about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml9
-rw-r--r--Cargo.lock443
-rw-r--r--RELEASES.md128
-rw-r--r--compiler/rustc_ast/src/ast.rs17
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs35
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs22
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs11
-rw-r--r--compiler/rustc_ast_ir/Cargo.toml1
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs27
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs11
-rw-r--r--compiler/rustc_ast_passes/messages.ftl5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs81
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs16
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs12
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs11
-rw-r--r--compiler/rustc_baked_icu_data/Cargo.toml1
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/nll.rs14
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs20
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs20
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl3
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/cmdline_attrs.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/rpath.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/rpath/tests.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs23
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs73
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs5
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs31
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs8
-rw-r--r--compiler/rustc_data_structures/Cargo.toml3
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs28
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs10
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0582.md34
-rw-r--r--compiler/rustc_expand/messages.ftl5
-rw-r--r--compiler/rustc_expand/src/base.rs100
-rw-r--r--compiler/rustc_expand/src/build.rs25
-rw-r--r--compiler/rustc_expand/src/errors.rs10
-rw-r--r--compiler/rustc_expand/src/expand.rs9
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs11
-rw-r--r--compiler/rustc_expand/src/module.rs5
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs26
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs47
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs63
-rw-r--r--compiler/rustc_feature/src/lib.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs3
-rw-r--r--compiler/rustc_feature/src/unstable.rs14
-rw-r--r--compiler/rustc_hir/src/def.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs39
-rw-r--r--compiler/rustc_hir/src/intravisit.rs19
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/errs.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs138
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs317
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs37
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs4
-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.rs8
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs111
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs104
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs49
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs76
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs170
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs15
-rw-r--r--compiler/rustc_index_macros/Cargo.toml3
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/at.rs4
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs27
-rw-r--r--compiler/rustc_infer/src/infer/canonical/instantiate.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs11
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs21
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs16
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs35
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs207
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs17
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/_match.rs (renamed from compiler/rustc_middle/src/ty/_match.rs)22
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs94
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs35
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs10
-rw-r--r--compiler/rustc_infer/src/infer/relate/higher_ranked.rs5
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs6
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs10
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs20
-rw-r--r--compiler/rustc_infer/src/infer/relate/type_relating.rs21
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs3
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/fudge.rs2
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs72
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs53
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs27
-rw-r--r--compiler/rustc_interface/src/interface.rs6
-rw-r--r--compiler/rustc_interface/src/passes.rs21
-rw-r--r--compiler/rustc_lint/messages.ftl18
-rw-r--r--compiler/rustc_lint/src/builtin.rs21
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs11
-rw-r--r--compiler/rustc_lint/src/lints.rs19
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs4
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs6
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs137
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs12
-rw-r--r--compiler/rustc_macros/src/extension.rs9
-rw-r--r--compiler/rustc_macros/src/query.rs21
-rw-r--r--compiler/rustc_metadata/src/creader.rs1
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs12
-rw-r--r--compiler/rustc_metadata/src/locator.rs34
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs12
-rw-r--r--compiler/rustc_middle/Cargo.toml4
-rw-r--r--compiler/rustc_middle/src/arena.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs54
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs16
-rw-r--r--compiler/rustc_middle/src/lib.rs11
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs83
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs26
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs38
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs51
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs10
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs24
-rw-r--r--compiler/rustc_middle/src/thir.rs4
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs4
-rw-r--r--compiler/rustc_middle/src/traits/query.rs9
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs6
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs179
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs222
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs127
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs9
-rw-r--r--compiler/rustc_middle/src/ty/context.rs98
-rw-r--r--compiler/rustc_middle/src/ty/error.rs183
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs28
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs20
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs6
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs12
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs38
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs76
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs139
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs844
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs76
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs141
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs4
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs5
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs45
-rw-r--r--compiler/rustc_mir_build/Cargo.toml2
-rw-r--r--compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs22
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs91
-rw-r--r--compiler/rustc_mir_build/src/errors.rs518
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs27
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs27
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs102
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs110
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs200
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs21
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs3
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs197
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs2
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs25
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs16
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs2
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs6
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs2
-rw-r--r--compiler/rustc_mir_transform/src/single_use_consts.rs199
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs6
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs34
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs1
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs68
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs2
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml16
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs52
-rw-r--r--compiler/rustc_next_trait_solver/src/resolve.rs15
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs9
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs4
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs50
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs75
-rw-r--r--compiler/rustc_parse/src/lib.rs158
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs37
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs26
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs40
-rw-r--r--compiler/rustc_parse/src/parser/item.rs43
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs58
-rw-r--r--compiler/rustc_parse/src/parser/mut_visit/tests.rs18
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs2
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs22
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs2
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs35
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs23
-rw-r--r--compiler/rustc_passes/src/check_const.rs10
-rw-r--r--compiler/rustc_passes/src/dead.rs142
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs11
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs8
-rw-r--r--compiler/rustc_passes/src/loops.rs7
-rw-r--r--compiler/rustc_passes/src/reachable.rs24
-rw-r--r--compiler/rustc_passes/src/stability.rs4
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs11
-rw-r--r--compiler/rustc_query_impl/Cargo.toml3
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs3
-rw-r--r--compiler/rustc_resolve/messages.ftl8
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs31
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs38
-rw-r--r--compiler/rustc_resolve/src/errors.rs17
-rw-r--r--compiler/rustc_resolve/src/ident.rs29
-rw-r--r--compiler/rustc_resolve/src/imports.rs28
-rw-r--r--compiler/rustc_resolve/src/late.rs58
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs41
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs2
-rw-r--r--compiler/rustc_session/src/filesearch.rs18
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs48
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs71
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs20
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mod.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs79
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs13
-rw-r--r--compiler/rustc_span/src/lib.rs32
-rw-r--r--compiler/rustc_span/src/span_encoding.rs188
-rw-r--r--compiler/rustc_span/src/symbol.rs5
-rw-r--r--compiler/rustc_span/src/tests.rs57
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs67
-rw-r--r--compiler/rustc_target/src/abi/mod.rs23
-rw-r--r--compiler/rustc_target/src/lib.rs12
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs6
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/regions.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs27
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs95
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs50
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs67
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs64
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs117
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs103
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs146
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs82
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs85
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs32
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs42
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/src/codegen.rs7
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs8
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs4
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs33
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs55
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs6
-rw-r--r--compiler/rustc_type_ir/src/debug.rs4
-rw-r--r--compiler/rustc_type_ir/src/error.rs106
-rw-r--r--compiler/rustc_type_ir/src/fold.rs2
-rw-r--r--compiler/rustc_type_ir/src/infcx.rs7
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs71
-rw-r--r--compiler/rustc_type_ir/src/interner.rs46
-rw-r--r--compiler/rustc_type_ir/src/lib.rs8
-rw-r--r--compiler/rustc_type_ir/src/macros.rs18
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs34
-rw-r--r--compiler/rustc_type_ir/src/relate.rs666
-rw-r--r--compiler/rustc_type_ir/src/solve.rs6
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs93
-rw-r--r--compiler/stable_mir/Cargo.toml1
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs22
-rw-r--r--compiler/stable_mir/src/mir/body.rs10
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs16
-rw-r--r--compiler/stable_mir/src/mir/visit.rs25
-rw-r--r--compiler/stable_mir/src/ty.rs95
-rw-r--r--compiler/stable_mir/src/visitor.rs30
-rw-r--r--config.example.toml4
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs3
-rw-r--r--library/alloc/src/collections/linked_list.rs4
-rw-r--r--library/alloc/src/collections/linked_list/tests.rs39
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/vec_deque_alloc_error.rs1
m---------library/backtrace0
-rw-r--r--library/core/src/cell.rs17
-rw-r--r--library/core/src/cell/once.rs4
-rw-r--r--library/core/src/error.rs16
-rw-r--r--library/core/src/fmt/num.rs33
-rw-r--r--library/core/src/intrinsics.rs1
-rw-r--r--library/core/src/intrinsics/mir.rs58
-rw-r--r--library/core/src/iter/adapters/chain.rs37
-rw-r--r--library/core/src/iter/adapters/mod.rs3
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/macros/mod.rs7
-rw-r--r--library/core/src/mem/maybe_uninit.rs17
-rw-r--r--library/core/src/num/f128.rs7
-rw-r--r--library/core/src/num/f16.rs6
-rw-r--r--library/core/src/num/f32.rs5
-rw-r--r--library/core/src/num/f64.rs5
-rw-r--r--library/core/src/num/nonzero.rs42
-rw-r--r--library/core/src/option.rs4
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/prelude/common.rs3
-rw-r--r--library/core/src/ptr/mod.rs2
-rw-r--r--library/core/src/slice/raw.rs1
-rw-r--r--library/core/src/sync/atomic.rs3
-rw-r--r--library/core/tests/iter/adapters/chain.rs8
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs2
-rw-r--r--library/proc_macro/src/bridge/fxhash.rs1
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/src/collections/hash/map.rs2
-rw-r--r--library/std/src/ffi/os_str.rs19
-rw-r--r--library/std/src/ffi/os_str/tests.rs9
-rw-r--r--library/std/src/io/error/repr_bitpacked.rs1
-rw-r--r--library/std/src/io/stdio.rs5
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/unix/net/ancillary.rs2
-rw-r--r--library/std/src/path.rs19
-rw-r--r--library/std/src/path/tests.rs10
-rw-r--r--library/std/src/prelude/common.rs3
-rw-r--r--library/std/src/prelude/mod.rs4
-rw-r--r--library/std/src/sync/lazy_lock.rs36
-rw-r--r--library/std/src/sync/mod.rs5
-rw-r--r--library/std/src/sync/once_lock.rs93
-rw-r--r--library/std/src/sys/os_str/bytes.rs5
-rw-r--r--library/std/src/sys/os_str/wtf8.rs5
-rw-r--r--library/std/src/sys/pal/sgx/thread.rs18
-rw-r--r--library/std/src/sys/pal/uefi/thread.rs2
-rw-r--r--library/std/src/sys/pal/unix/fs.rs29
-rw-r--r--library/std/src/sys/pal/unix/os.rs20
-rw-r--r--library/std/src/sys/pal/unix/process/process_unix.rs4
-rw-r--r--library/std/src/sys/pal/unsupported/thread.rs2
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs2
-rw-r--r--library/std/src/sys/pal/wasm/atomics/thread.rs2
-rw-r--r--library/std/src/sys/pal/windows/api.rs36
-rw-r--r--library/std/src/sys/pal/windows/c/README.md2
-rw-r--r--library/std/src/sys/pal/windows/fs.rs30
-rw-r--r--library/std/src/sys/pal/windows/futex.rs4
-rw-r--r--library/std/src/sys/pal/windows/os.rs7
-rw-r--r--library/std/src/sys/pal/windows/pipe.rs10
-rw-r--r--library/std/src/sys/pal/windows/process.rs8
-rw-r--r--library/std/src/sys/pal/windows/stdio.rs4
-rw-r--r--library/std/src/sys/thread_local/fast_local/eager.rs34
-rw-r--r--library/std/src/sys/thread_local/fast_local/lazy.rs46
-rw-r--r--library/std/src/sys/thread_local/fast_local/mod.rs79
-rw-r--r--library/std/src/sys/thread_local/os_local.rs63
-rw-r--r--library/std/src/sys/thread_local/static_local.rs53
-rw-r--r--library/std/src/sys_common/wtf8.rs5
-rw-r--r--library/std/src/thread/local.rs12
-rw-r--r--library/std/src/thread/mod.rs5
-rw-r--r--library/test/Cargo.toml2
-rw-r--r--rustfmt.toml31
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/bootstrap.py18
-rw-r--r--src/bootstrap/mk/Makefile.in7
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs15
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs40
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs17
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs58
-rw-r--r--src/bootstrap/src/core/builder.rs28
-rw-r--r--src/bootstrap/src/core/config/config.rs60
-rw-r--r--src/bootstrap/src/core/config/tests.rs28
-rw-r--r--src/bootstrap/src/core/download.rs22
-rw-r--r--src/bootstrap/src/core/sanity.rs50
-rw-r--r--src/ci/docker/README.md2
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig2
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh2
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/rfl/Dockerfile40
-rw-r--r--src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile10
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile3
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh101
-rwxr-xr-xsrc/ci/docker/run.sh1
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh68
-rwxr-xr-xsrc/ci/docker/scripts/x86_64-gnu-llvm.sh16
-rw-r--r--src/ci/github-actions/jobs.yml18
-rwxr-xr-xsrc/ci/publish_toolstate.sh4
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/SUMMARY.md18
-rw-r--r--src/doc/rustc/src/check-cfg/cargo-specifics.md14
-rw-r--r--src/doc/rustc/src/command-line-arguments.md40
-rw-r--r--src/doc/rustc/src/json.md8
-rw-r--r--src/doc/rustc/src/platform-support.md8
-rw-r--r--src/doc/rustc/src/platform-support/arm-none-eabi.md28
-rw-r--r--src/doc/rustc/src/platform-support/armv4t-none-eabi.md22
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md4
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/codegen-backend.md5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/print-check-cfg.md3
-rw-r--r--src/doc/unstable-book/src/language-features/abi-vectorcall.md19
-rw-r--r--src/librustdoc/clean/cfg/tests.rs6
-rw-r--r--src/librustdoc/clean/inline.rs28
-rw-r--r--src/librustdoc/clean/mod.rs40
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs2
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/librustdoc/clean/utils.rs7
-rw-r--r--src/librustdoc/config.rs26
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/doctest.rs1040
-rw-r--r--src/librustdoc/doctest/make.rs393
-rw-r--r--src/librustdoc/doctest/markdown.rs125
-rw-r--r--src/librustdoc/doctest/rust.rs200
-rw-r--r--src/librustdoc/doctest/tests.rs59
-rw-r--r--src/librustdoc/fold.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs19
-rw-r--r--src/librustdoc/html/markdown.rs44
-rw-r--r--src/librustdoc/html/render/print_item.rs17
-rw-r--r--src/librustdoc/html/static/.eslintrc.js2
-rw-r--r--src/librustdoc/html/static/js/externs.js3
-rw-r--r--src/librustdoc/html/static/js/search.js168
-rw-r--r--src/librustdoc/json/conversions.rs7
-rw-r--r--src/librustdoc/json/mod.rs2
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/librustdoc/markdown.rs48
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs8
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs8
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs8
-rw-r--r--src/librustdoc/scrape_examples.rs2
-rw-r--r--src/librustdoc/visit.rs2
m---------src/llvm-project0
-rw-r--r--src/rustdoc-json-types/lib.rs11
-rw-r--r--src/tools/build_helper/README.md1
-rw-r--r--src/tools/build_helper/src/lib.rs25
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.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/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs26
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr32
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed6
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs6
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.fixed4
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.rs2
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unicode.stderr2
-rw-r--r--src/tools/compiletest/src/header.rs30
-rw-r--r--src/tools/compiletest/src/header/needs.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs64
-rw-r--r--src/tools/compiletest/src/util.rs16
-rw-r--r--src/tools/jsondoclint/src/item_kind.rs2
-rw-r--r--src/tools/jsondoclint/src/validator.rs9
-rw-r--r--src/tools/libcxx-version/main.cpp26
-rw-r--r--src/tools/miri/CONTRIBUTING.md21
-rw-r--r--src/tools/miri/README.md21
-rw-r--r--src/tools/miri/bench-cargo-miri/big-allocs/Cargo.lock7
-rw-r--r--src/tools/miri/bench-cargo-miri/big-allocs/Cargo.toml8
-rw-r--r--src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs13
-rw-r--r--src/tools/miri/cargo-miri/src/main.rs5
-rw-r--r--src/tools/miri/cargo-miri/src/util.rs25
-rwxr-xr-xsrc/tools/miri/ci/ci.sh4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs13
-rw-r--r--src/tools/miri/src/bin/miri.rs3
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs13
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs6
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs39
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs1
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs43
-rw-r--r--src/tools/miri/src/clock.rs59
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs50
-rw-r--r--src/tools/miri/src/concurrency/init_once.rs9
-rw-r--r--src/tools/miri/src/concurrency/mod.rs3
-rw-r--r--src/tools/miri/src/concurrency/sync.rs84
-rw-r--r--src/tools/miri/src/concurrency/thread.rs111
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs43
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/src/helpers.rs105
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs38
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs12
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs131
-rw-r--r--src/tools/miri/src/lib.rs19
-rw-r--r--src/tools/miri/src/machine.rs76
-rw-r--r--src/tools/miri/src/operator.rs6
-rw-r--r--src/tools/miri/src/provenance_gc.rs14
-rw-r--r--src/tools/miri/src/shims/alloc.rs28
-rw-r--r--src/tools/miri/src/shims/backtrace.rs16
-rw-r--r--src/tools/miri/src/shims/extern_static.rs2
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs22
-rw-r--r--src/tools/miri/src/shims/native_lib.rs13
-rw-r--r--src/tools/miri/src/shims/os_str.rs42
-rw-r--r--src/tools/miri/src/shims/panic.rs12
-rw-r--r--src/tools/miri/src/shims/time.rs59
-rw-r--r--src/tools/miri/src/shims/tls.rs18
-rw-r--r--src/tools/miri/src/shims/unix/android/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/env.rs35
-rw-r--r--src/tools/miri/src/shims/unix/fd.rs18
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs118
-rw-r--r--src/tools/miri/src/shims/unix/linux/epoll.rs29
-rw-r--r--src/tools/miri/src/shims/unix/linux/eventfd.rs121
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/mem.rs10
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs43
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/mem.rs18
-rw-r--r--src/tools/miri/src/shims/unix/socket.rs14
-rw-r--r--src/tools/miri/src/shims/unix/solarish/foreign_items.rs34
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs170
-rw-r--r--src/tools/miri/src/shims/unix/thread.rs30
-rw-r--r--src/tools/miri/src/shims/wasi/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/windows/env.rs39
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/windows/handle.rs6
-rw-r--r--src/tools/miri/src/shims/windows/sync.rs51
-rw-r--r--src/tools/miri/src/shims/windows/thread.rs16
-rw-r--r--src/tools/miri/src/shims/x86/aesni.rs14
-rw-r--r--src/tools/miri/src/shims/x86/avx.rs8
-rw-r--r--src/tools/miri/src/shims/x86/avx2.rs8
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs225
-rw-r--r--src/tools/miri/src/shims/x86/sse.rs8
-rw-r--r--src/tools/miri/src/shims/x86/sse2.rs8
-rw-r--r--src/tools/miri/src/shims/x86/sse3.rs8
-rw-r--r--src/tools/miri/src/shims/x86/sse41.rs8
-rw-r--r--src/tools/miri/src/shims/x86/ssse3.rs8
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.lock4
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.toml2
-rwxr-xr-xsrc/tools/miri/test-cargo-miri/run-test.py4
-rw-r--r--src/tools/miri/test-cargo-miri/run.local_crate.stderr.ref0
-rw-r--r--src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref1
-rw-r--r--src/tools/miri/test-cargo-miri/test-local-crate-detection/Cargo.toml4
-rw-r--r--src/tools/miri/test-cargo-miri/test-local-crate-detection/src/main.rs5
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.rs11
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.stderr14
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.rs21
-rw-r--r--src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.stderr14
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs10
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs10
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs10
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr4
-rw-r--r--src/tools/miri/tests/fail/issue-miri-2432.rs19
-rw-r--r--src/tools/miri/tests/fail/issue-miri-2432.stderr15
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs108
-rw-r--r--src/tools/miri/tests/pass/drop_in_place.rs4
-rw-r--r--src/tools/miri/tests/pass/function_calls/abi_compat.rs16
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs100
-rw-r--r--src/tools/miri/tests/pass/shims/env/var.rs3
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs48
-rw-r--r--src/tools/opt-dist/src/environment.rs7
-rw-r--r--src/tools/opt-dist/src/main.rs6
-rw-r--r--src/tools/opt-dist/src/training.rs36
-rw-r--r--src/tools/run-make-support/src/cc.rs18
-rw-r--r--src/tools/run-make-support/src/clang.rs19
-rw-r--r--src/tools/run-make-support/src/command.rs151
-rw-r--r--src/tools/run-make-support/src/lib.rs158
-rw-r--r--src/tools/run-make-support/src/llvm_readobj.rs14
-rw-r--r--src/tools/run-make-support/src/run.rs41
-rw-r--r--src/tools/run-make-support/src/rustc.rs64
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs52
-rw-r--r--src/tools/rust-installer/src/compression.rs12
-rw-r--r--src/tools/rustbook/Cargo.toml1
-rw-r--r--src/tools/rustbook/src/main.rs13
m---------src/tools/rustc-perf0
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs4
-rw-r--r--src/tools/rustdoc-gui/.eslintrc.js2
-rw-r--r--src/tools/rustdoc-js/.eslintrc.js2
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs4
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs27
-rw-r--r--src/tools/rustfmt/src/utils.rs1
-rw-r--r--src/tools/rustfmt/tests/source/attrib.rs4
-rw-r--r--src/tools/rustfmt/tests/target/attrib.rs4
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt9
-rw-r--r--src/tools/tidy/src/deps.rs69
-rw-r--r--src/tools/tidy/src/ext_tool_checks.rs2
-rw-r--r--src/tools/tidy/src/extdeps.rs6
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--src/tools/tidy/src/walk.rs1
-rw-r--r--src/version2
-rw-r--r--tests/assembly/asm/global_asm.rs4
-rw-r--r--tests/codegen-units/item-collection/generic-impl.rs10
-rw-r--r--tests/codegen-units/item-collection/overloaded-operators.rs24
-rw-r--r--tests/codegen/consts.rs4
-rw-r--r--tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs17
-rw-r--r--tests/codegen/pattern_type_symbols.rs4
-rw-r--r--tests/codegen/riscv-abi/call-llvm-intrinsics.rs2
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64d-abi.rs25
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs21
-rw-r--r--tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs6
-rw-r--r--tests/codegen/simd/packed-simd.rs23
-rw-r--r--tests/codegen/virtual-function-elimination.rs4
-rw-r--r--tests/coverage/closure_macro.cov-map8
-rw-r--r--tests/coverage/closure_macro_async.cov-map8
-rw-r--r--tests/crashes/119830.rs11
-rw-r--r--tests/crashes/121134.rs20
-rw-r--r--tests/crashes/122908.rs4
-rw-r--r--tests/crashes/123917.rs41
-rw-r--r--tests/crashes/124342.rs6
-rw-r--r--tests/crashes/124347.rs4
-rw-r--r--tests/crashes/124490.rs16
-rw-r--r--tests/crashes/124552.rs12
-rw-r--r--tests/crashes/125013-1.rs5
-rw-r--r--tests/crashes/125013-2.rs16
-rw-r--r--tests/crashes/125556.rs14
-rw-r--r--tests/crashes/125655.rs8
-rw-r--r--tests/crashes/125680.rs15
-rw-r--r--tests/crashes/125758.rs26
-rw-r--r--tests/crashes/125768.rs15
-rw-r--r--tests/crashes/125769.rs14
-rw-r--r--tests/crashes/125772.rs17
-rw-r--r--tests/crashes/125799.rs22
-rw-r--r--tests/crashes/125801.rs20
-rw-r--r--tests/crashes/125810.rs10
-rw-r--r--tests/crashes/125811.rs34
-rw-r--r--tests/crashes/125841.rs14
-rw-r--r--tests/crashes/125843.rs4
-rw-r--r--tests/crashes/125874.rs22
-rw-r--r--tests/crashes/125879.rs18
-rw-r--r--tests/crashes/125881.rs8
-rw-r--r--tests/crashes/125888.rs17
-rw-r--r--tests/crashes/125914.rs20
-rw-r--r--tests/crashes/125957.rs20
-rw-r--r--tests/crashes/125992.rs19
-rw-r--r--tests/debuginfo/function-names.rs5
-rw-r--r--tests/mir-opt/address_of.rs2
-rw-r--r--tests/mir-opt/array_index_is_temporary.rs1
-rw-r--r--tests/mir-opt/building/custom/aggregate_exprs.rs12
-rw-r--r--tests/mir-opt/building/custom/arbitrary_let.rs4
-rw-r--r--tests/mir-opt/building/custom/arrays.rs14
-rw-r--r--tests/mir-opt/building/custom/as_cast.rs12
-rw-r--r--tests/mir-opt/building/custom/assume.rs12
-rw-r--r--tests/mir-opt/building/custom/composite_return.rs4
-rw-r--r--tests/mir-opt/building/custom/consts.consts.built.after.mir2
-rw-r--r--tests/mir-opt/building/custom/consts.rs30
-rw-r--r--tests/mir-opt/building/custom/debuginfo.rs24
-rw-r--r--tests/mir-opt/building/custom/enums.rs34
-rw-r--r--tests/mir-opt/building/custom/operators.rs60
-rw-r--r--tests/mir-opt/building/custom/projections.rs62
-rw-r--r--tests/mir-opt/building/custom/references.rs30
-rw-r--r--tests/mir-opt/building/custom/simple_assign.rs16
-rw-r--r--tests/mir-opt/building/custom/terminators.rs25
-rw-r--r--tests/mir-opt/building/custom/unwind_action.rs16
-rw-r--r--tests/mir-opt/building/custom/unwind_terminate.rs8
-rw-r--r--tests/mir-opt/building/enum_cast.rs24
-rw-r--r--tests/mir-opt/building/logical_or_in_conditional.rs8
-rw-r--r--tests/mir-opt/building/match/simple_match.rs1
-rw-r--r--tests/mir-opt/building/match/sort_candidates.rs6
-rw-r--r--tests/mir-opt/building/shifts.rs13
-rw-r--r--tests/mir-opt/building/storage_live_dead_in_statics.rs5
-rw-r--r--tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff (renamed from tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff)46
-rw-r--r--tests/mir-opt/const_debuginfo.rs6
-rw-r--r--tests/mir-opt/const_prop/control_flow_simplification.rs2
-rw-r--r--tests/mir-opt/const_prop/invalid_constant.rs10
-rw-r--r--tests/mir-opt/const_prop/offset_of.rs2
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_provenance.rs2
-rw-r--r--tests/mir-opt/const_prop/scalar_literal_propagation.rs2
-rw-r--r--tests/mir-opt/const_prop/switch_int.rs2
-rw-r--r--tests/mir-opt/const_prop/transmute.rs5
-rw-r--r--tests/mir-opt/const_prop/tuple_literal_propagation.rs2
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs18
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.rs22
-rw-r--r--tests/mir-opt/copy-prop/move_projection.rs8
-rw-r--r--tests/mir-opt/copy-prop/mutate_through_pointer.rs18
-rw-r--r--tests/mir-opt/copy-prop/non_dominate.rs24
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.rs31
-rw-r--r--tests/mir-opt/dataflow-const-prop/mult_by_zero.rs6
-rw-r--r--tests/mir-opt/dataflow-const-prop/transmute.rs5
-rw-r--r--tests/mir-opt/dead-store-elimination/call_arg_copy.rs4
-rw-r--r--tests/mir-opt/dead-store-elimination/cycle.rs4
-rw-r--r--tests/mir-opt/derefer_complex_case.rs4
-rw-r--r--tests/mir-opt/derefer_terminator_test.rs4
-rw-r--r--tests/mir-opt/derefer_test.rs2
-rw-r--r--tests/mir-opt/derefer_test_multiple.rs2
-rw-r--r--tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff2
-rw-r--r--tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff2
-rw-r--r--tests/mir-opt/enum_opt.rs62
-rw-r--r--tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff60
-rw-r--r--tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff60
-rw-r--r--tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff32
-rw-r--r--tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff32
-rw-r--r--tests/mir-opt/gvn.rs64
-rw-r--r--tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff48
-rw-r--r--tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff48
-rw-r--r--tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff51
-rw-r--r--tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff51
-rw-r--r--tests/mir-opt/inline/inline_cycle.rs1
-rw-r--r--tests/mir-opt/inline/inline_cycle_generic.rs1
-rw-r--r--tests/mir-opt/inline/inline_options.rs12
-rw-r--r--tests/mir-opt/inline/inline_specialization.rs6
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/issue_106141.rs6
-rw-r--r--tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs5
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.rs4
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.rs7
-rw-r--r--tests/mir-opt/instsimplify/duplicate_switch_targets.rs4
-rw-r--r--tests/mir-opt/issue_104451_unwindable_intrinsics.rs4
-rw-r--r--tests/mir-opt/issue_41110.rs8
-rw-r--r--tests/mir-opt/issue_41697.rs5
-rw-r--r--tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir4
-rw-r--r--tests/mir-opt/issue_41888.rs6
-rw-r--r--tests/mir-opt/issue_72181.rs12
-rw-r--r--tests/mir-opt/issue_72181_1.rs4
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff4
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff4
-rw-r--r--tests/mir-opt/issue_91633.rs44
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.32bit.mir2
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.64bit.mir2
-rw-r--r--tests/mir-opt/issues/issue_75439.rs6
-rw-r--r--tests/mir-opt/jump_threading.rs36
-rw-r--r--tests/mir-opt/lower_array_len.rs6
-rw-r--r--tests/mir-opt/lower_slice_len.rs6
-rw-r--r--tests/mir-opt/matches_reduce_branches.rs8
-rw-r--r--tests/mir-opt/matches_u8.rs9
-rw-r--r--tests/mir-opt/nll/named_lifetimes_basic.rs7
-rw-r--r--tests/mir-opt/nrvo_miscompile_111005.rs14
-rw-r--r--tests/mir-opt/nrvo_simple.rs4
-rw-r--r--tests/mir-opt/packed_struct_drop_aligned.rs1
-rw-r--r--tests/mir-opt/pre-codegen/intrinsics.rs4
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff32
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff32
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.rs2
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir10
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir10
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir102
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir102
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir88
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir88
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir96
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir96
-rw-r--r--tests/mir-opt/pre-codegen/try_identity.rs12
-rw-r--r--tests/mir-opt/reference_prop.rs23
-rw-r--r--tests/mir-opt/retag.rs4
-rw-r--r--tests/mir-opt/return_an_array.rs6
-rw-r--r--tests/mir-opt/set_no_discriminant.rs8
-rw-r--r--tests/mir-opt/simplify_dead_blocks.rs4
-rw-r--r--tests/mir-opt/simplify_locals.rs10
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.rs4
-rw-r--r--tests/mir-opt/simplify_match.rs7
-rw-r--r--tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-abort.diff12
-rw-r--r--tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-unwind.diff12
-rw-r--r--tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-abort.diff31
-rw-r--r--tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-unwind.diff31
-rw-r--r--tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff46
-rw-r--r--tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff46
-rw-r--r--tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-abort.diff14
-rw-r--r--tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-unwind.diff14
-rw-r--r--tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff36
-rw-r--r--tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff36
-rw-r--r--tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff47
-rw-r--r--tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff47
-rw-r--r--tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-abort.diff21
-rw-r--r--tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-unwind.diff21
-rw-r--r--tests/mir-opt/single_use_consts.rs80
-rw-r--r--tests/mir-opt/sroa/lifetimes.rs5
-rw-r--r--tests/mir-opt/switch_to_self.rs4
-rw-r--r--tests/mir-opt/uninhabited_enum.rs8
-rw-r--r--tests/mir-opt/unnamed-fields/field_access.rs6
-rw-r--r--tests/mir-opt/unreachable.rs4
-rw-r--r--tests/mir-opt/unusual_item_types.rs3
-rw-r--r--tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir4
-rw-r--r--tests/pretty/ast-stmt-expr-attr.rs18
-rw-r--r--tests/pretty/hir-fn-variadic.pp2
-rw-r--r--tests/pretty/stmt_expr_attributes.rs19
-rw-r--r--tests/run-make-fulldeps/hotplug_codegen_backend/Makefile25
-rw-r--r--tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs2
-rw-r--r--tests/run-make-fulldeps/issue-19371/Makefile9
-rw-r--r--tests/run-make-fulldeps/obtain-borrowck/Makefile26
-rw-r--r--tests/run-make-fulldeps/pretty-expanded/Makefile4
-rw-r--r--tests/run-make-fulldeps/pretty-expanded/input.rs8
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs12
-rw-r--r--tests/run-make/README.md43
-rw-r--r--tests/run-make/alloc-no-oom-handling/rmake.rs4
-rw-r--r--tests/run-make/alloc-no-rc/rmake.rs4
-rw-r--r--tests/run-make/alloc-no-sync/rmake.rs4
-rw-r--r--tests/run-make/allow-warnings-cmdline-stability/rmake.rs12
-rw-r--r--tests/run-make/arguments-non-c-like-enum/rmake.rs4
-rw-r--r--tests/run-make/artifact-incr-cache-no-obj/rmake.rs6
-rw-r--r--tests/run-make/artifact-incr-cache/rmake.rs6
-rw-r--r--tests/run-make/bare-outfile/Makefile9
-rw-r--r--tests/run-make/bare-outfile/rmake.rs11
-rw-r--r--tests/run-make/box-struct-no-segfault/rmake.rs4
-rw-r--r--tests/run-make/c-link-to-rust-dylib/rmake.rs14
-rw-r--r--tests/run-make/c-link-to-rust-staticlib/rmake.rs6
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/rmake.rs4
-rw-r--r--tests/run-make/cdylib/rmake.rs12
-rw-r--r--tests/run-make/compiler-builtins/Cargo.toml7
-rw-r--r--tests/run-make/compiler-builtins/lib.rs1
-rw-r--r--tests/run-make/compiler-builtins/rmake.rs36
-rw-r--r--tests/run-make/const-prop-lint/rmake.rs6
-rw-r--r--tests/run-make/core-no-fp-fmt-parse/rmake.rs4
-rw-r--r--tests/run-make/core-no-oom-handling/rmake.rs6
-rw-r--r--tests/run-make/crate-data-smoke/rmake.rs35
-rw-r--r--tests/run-make/cross-lang-lto-clang/Makefile2
-rw-r--r--tests/run-make/cross-lang-lto-pgo-smoketest/Makefile5
-rw-r--r--tests/run-make/cross-lang-lto-riscv-abi/rmake.rs11
-rw-r--r--tests/run-make/deref-impl-rustdoc-ice/rmake.rs4
-rw-r--r--tests/run-make/doctests-keep-binaries/rmake.rs14
-rw-r--r--tests/run-make/doctests-runtool/rmake.rs8
-rw-r--r--tests/run-make/emit-named-files/rmake.rs4
-rw-r--r--tests/run-make/emit/Makefile22
-rw-r--r--tests/run-make/emit/rmake.rs19
-rw-r--r--tests/run-make/exit-code/rmake.rs17
-rw-r--r--tests/run-make/external-crate-panic-handle-no-lint/rmake.rs4
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/Makefile19
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/rmake.rs27
-rw-r--r--tests/run-make/issue-107495-archive-permissions/rmake.rs4
-rw-r--r--tests/run-make/issue-125484-used-dependencies/dependency.rs1
-rw-r--r--tests/run-make/issue-125484-used-dependencies/main.rs9
-rw-r--r--tests/run-make/issue-125484-used-dependencies/rmake.rs18
-rw-r--r--tests/run-make/issue-84395-lto-embed-bitcode/Makefile5
-rw-r--r--tests/run-make/issue-88756-default-output/output-default.stdout2
-rw-r--r--tests/run-make/llvm-outputs/Makefile5
-rw-r--r--tests/run-make/llvm-outputs/rmake.rs20
-rw-r--r--tests/run-make/manual-crate-name/Makefile5
-rw-r--r--tests/run-make/manual-crate-name/rmake.rs7
-rw-r--r--tests/run-make/mixing-formats/Makefile75
-rw-r--r--tests/run-make/mixing-formats/rmake.rs87
-rw-r--r--tests/run-make/multiple-emits/Makefile7
-rw-r--r--tests/run-make/multiple-emits/rmake.rs13
-rw-r--r--tests/run-make/no-input-file/no-input-file.stderr2
-rw-r--r--tests/run-make/no-input-file/rmake.rs10
-rw-r--r--tests/run-make/no-intermediate-extras/rmake.rs4
-rw-r--r--tests/run-make/non-pie-thread-local/rmake.rs6
-rw-r--r--tests/run-make/non-unicode-env/rmake.rs3
-rw-r--r--tests/run-make/non-unicode-in-incremental-dir/rmake.rs8
-rw-r--r--tests/run-make/notify-all-emit-artifacts/lib.rs21
-rw-r--r--tests/run-make/notify-all-emit-artifacts/rmake.rs43
-rw-r--r--tests/run-make/panic-impl-transitive/rmake.rs9
-rw-r--r--tests/run-make/print-cfg/rmake.rs11
-rw-r--r--tests/run-make/print-check-cfg/rmake.rs16
-rw-r--r--tests/run-make/print-native-static-libs/rmake.rs4
-rw-r--r--tests/run-make/print-to-output/rmake.rs13
-rw-r--r--tests/run-make/reachable-extern-fn-available-lto/rmake.rs4
-rw-r--r--tests/run-make/repr128-dwarf/rmake.rs8
-rw-r--r--tests/run-make/reset-codegen-1/rmake.rs4
-rw-r--r--tests/run-make/resolve-rename/Makefile7
-rw-r--r--tests/run-make/resolve-rename/rmake.rs15
-rw-r--r--tests/run-make/run-in-tmpdir-self-test/rmake.rs38
-rw-r--r--tests/run-make/rust-lld-by-default/rmake.rs11
-rw-r--r--tests/run-make/rust-lld-custom-target/rmake.rs11
-rw-r--r--tests/run-make/rust-lld/rmake.rs15
-rw-r--r--tests/run-make/rustdoc-determinism/rmake.rs7
-rw-r--r--tests/run-make/rustdoc-error-lines/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-map-file/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-output-path/rmake.rs5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-macros/rmake.rs30
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/scrape.rs7
-rw-r--r--tests/run-make/rustdoc-shared-flags/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-target-spec-json-path/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-test-args/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-themes/rmake.rs9
-rw-r--r--tests/run-make/rustdoc-verify-output-files/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-with-out-dir-option/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-with-output-option/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs4
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/bar.rs3
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/foo.rs1
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/rmake.rs28
-rw-r--r--tests/run-make/stdin-rustc/rmake.rs15
-rw-r--r--tests/run-make/stdin-rustdoc/rmake.rs6
-rw-r--r--tests/run-make/suspicious-library/Makefile8
-rw-r--r--tests/run-make/suspicious-library/rmake.rs14
-rw-r--r--tests/run-make/wasm-abi/rmake.rs4
-rw-r--r--tests/run-make/wasm-custom-section/rmake.rs4
-rw-r--r--tests/run-make/wasm-custom-sections-opt/rmake.rs4
-rw-r--r--tests/run-make/wasm-export-all-symbols/rmake.rs9
-rw-r--r--tests/run-make/wasm-import-module/rmake.rs4
-rw-r--r--tests/run-make/wasm-override-linker/Makefile5
-rw-r--r--tests/run-make/wasm-panic-small/rmake.rs4
-rw-r--r--tests/run-make/wasm-spurious-import/rmake.rs4
-rw-r--r--tests/run-make/wasm-stringify-ints-small/rmake.rs4
-rw-r--r--tests/run-make/wasm-symbols-different-module/rmake.rs5
-rw-r--r--tests/run-make/wasm-symbols-not-exported/rmake.rs10
-rw-r--r--tests/run-make/wasm-symbols-not-imported/rmake.rs10
-rw-r--r--tests/run-make/windows-binary-no-external-deps/rmake.rs7
-rw-r--r--tests/run-make/windows-spawn/rmake.rs5
-rw-r--r--tests/run-make/windows-ws2_32/rmake.rs5
-rw-r--r--tests/run-pass-valgrind/cast-enum-with-dtor.rs6
-rw-r--r--tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs9
-rw-r--r--tests/run-pass-valgrind/coerce-match-calls.rs10
-rw-r--r--tests/run-pass-valgrind/coerce-match.rs15
-rw-r--r--tests/run-pass-valgrind/down-with-thread-dtors.rs8
-rw-r--r--tests/run-pass-valgrind/dst-dtor-1.rs10
-rw-r--r--tests/run-pass-valgrind/dst-dtor-2.rs6
-rw-r--r--tests/run-pass-valgrind/dst-dtor-3.rs8
-rw-r--r--tests/run-pass-valgrind/dst-dtor-4.rs4
-rw-r--r--tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs1
-rw-r--r--tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs5
-rw-r--r--tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs1
-rw-r--r--tests/rustdoc-js-std/parser-errors.js23
-rw-r--r--tests/rustdoc-js/assoc-type-backtrack.rs21
-rw-r--r--tests/rustdoc-js/assoc-type-loop.rs9
-rw-r--r--tests/rustdoc-js/auxiliary/interner.rs67
-rw-r--r--tests/rustdoc-js/basic.js2
-rw-r--r--tests/rustdoc-js/doc-alias.js22
-rw-r--r--tests/rustdoc-js/doc-alias.rs27
-rw-r--r--tests/rustdoc-js/enum-variant-not-type.rs10
-rw-r--r--tests/rustdoc-js/foreign-type-path.rs3
-rw-r--r--tests/rustdoc-js/full-path-function.rs20
-rw-r--r--tests/rustdoc-js/gat.rs16
-rw-r--r--tests/rustdoc-js/generics-impl.rs7
-rw-r--r--tests/rustdoc-js/generics-trait.rs16
-rw-r--r--tests/rustdoc-js/generics.rs37
-rw-r--r--tests/rustdoc-js/hof.rs8
-rw-r--r--tests/rustdoc-js/macro-search.rs4
-rw-r--r--tests/rustdoc-js/never-search.rs28
-rw-r--r--tests/rustdoc-js/non-english-identifier.js163
-rw-r--r--tests/rustdoc-js/non-english-identifier.rs47
-rw-r--r--tests/rustdoc-js/path-maxeditdistance.rs2
-rw-r--r--tests/rustdoc-js/prototype.rs2
-rw-r--r--tests/rustdoc-js/reexport-dedup-macro.rs2
-rw-r--r--tests/rustdoc-js/reexport-dedup-method.rs4
-rw-r--r--tests/rustdoc-js/reexport-dedup.rs4
-rw-r--r--tests/rustdoc-js/reexport.rs2
-rw-r--r--tests/rustdoc-js/reference.rs16
-rw-r--r--tests/rustdoc-js/slice-array.rs16
-rw-r--r--tests/rustdoc-js/struct-like-variant.rs4
-rw-r--r--tests/rustdoc-js/summaries.rs1
-rw-r--r--tests/rustdoc-js/tuple-unit.rs18
-rw-r--r--tests/rustdoc-js/type-parameters.rs20
-rw-r--r--tests/rustdoc-js/underscoredtype.js62
-rw-r--r--tests/rustdoc-js/underscoredtype.rs8
-rw-r--r--tests/rustdoc-js/where-clause.rs29
-rw-r--r--tests/rustdoc-json/lifetime/longest.rs6
-rw-r--r--tests/rustdoc-json/non_lifetime_binders.rs6
-rw-r--r--tests/rustdoc-json/output_generics.rs13
-rw-r--r--tests/rustdoc-json/type/extern.rs2
-rw-r--r--tests/rustdoc-json/unions/impl.rs2
-rw-r--r--tests/rustdoc-json/unions/union.rs1
-rw-r--r--tests/rustdoc-ui/ice-blanket-impl-119792.rs19
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.rs14
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.stdout21
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-invalid-doctest.rs13
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout22
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.rs14
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.stdout6
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.rs13
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.stderr31
-rw-r--r--tests/rustdoc/async-fn.rs2
-rw-r--r--tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html3
-rw-r--r--tests/rustdoc/decl-trailing-whitespace.declaration.html4
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs2
-rw-r--r--tests/rustdoc/line-breaks.rs2
-rw-r--r--tests/rustdoc/reexports-priv.rs2
-rw-r--r--tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs (renamed from tests/run-make-fulldeps/obtain-borrowck/test.rs)2
-rw-r--r--tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs (renamed from tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs)15
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout4
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout3
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout1
-rw-r--r--tests/ui-fulldeps/codegen-backend/hotplug.rs20
-rw-r--r--tests/ui-fulldeps/mod_dir_path_canonicalized.rs4
-rw-r--r--tests/ui-fulldeps/obtain-borrowck.rs (renamed from tests/run-make-fulldeps/obtain-borrowck/driver.rs)7
-rw-r--r--tests/ui-fulldeps/obtain-borrowck.run.stdout (renamed from tests/run-make-fulldeps/obtain-borrowck/output.stdout)0
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs7
-rw-r--r--tests/ui-fulldeps/run-compiler-twice.rs (renamed from tests/run-make-fulldeps/issue-19371/foo.rs)38
-rw-r--r--tests/ui-fulldeps/stable-mir/check_instance.rs11
-rw-r--r--tests/ui-fulldeps/stable-mir/check_transform.rs6
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.rs2
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.with_gate.stderr17
-rw-r--r--tests/ui/associated-inherent-types/issue-109299.rs1
-rw-r--r--tests/ui/associated-inherent-types/issue-109299.stderr11
-rw-r--r--tests/ui/async-await/coroutine-desc.stderr4
-rw-r--r--tests/ui/async-await/no-async-const.rs2
-rw-r--r--tests/ui/async-await/no-async-const.stderr4
-rw-r--r--tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs7
-rw-r--r--tests/ui/attributes/unsafe/derive-unsafe-attributes.rs6
-rw-r--r--tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr8
-rw-r--r--tests/ui/attributes/unsafe/double-unsafe-attributes.rs9
-rw-r--r--tests/ui/attributes/unsafe/double-unsafe-attributes.stderr27
-rw-r--r--tests/ui/attributes/unsafe/unsafe-attributes.rs7
-rw-r--r--tests/ui/attributes/unsafe/unsafe-safe-attribute.rs6
-rw-r--r--tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr10
-rw-r--r--tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs8
-rw-r--r--tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr10
-rw-r--r--tests/ui/borrowck/generic_const_early_param.rs1
-rw-r--r--tests/ui/borrowck/generic_const_early_param.stderr10
-rw-r--r--tests/ui/coherence/coherence-impls-copy.stderr22
-rw-r--r--tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr21
-rw-r--r--tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr21
-rw-r--r--tests/ui/coherence/orphan-check-opaque-types-not-covering.rs31
-rw-r--r--tests/ui/coherence/re-rebalance-coherence.rs1
-rw-r--r--tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs3
-rw-r--r--tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr16
-rw-r--r--tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs1
-rw-r--r--tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr19
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr14
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr14
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param.rs1
-rw-r--r--tests/ui/const-generics/defaults/repr-c-issue-82792.rs1
-rw-r--r--tests/ui/const-generics/generic_const_exprs/associated-consts.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/error_in_ty.rs21
-rw-r--r--tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr45
-rw-r--r--tests/ui/const-generics/generic_const_exprs/eval-privacy.rs6
-rw-r--r--tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr15
-rw-r--r--tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs5
-rw-r--r--tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr35
-rw-r--r--tests/ui/const-generics/issues/issue-71381.full.stderr18
-rw-r--r--tests/ui/const-generics/issues/issue-71381.min.stderr34
-rw-r--r--tests/ui/const-generics/issues/issue-71381.rs3
-rw-r--r--tests/ui/const-generics/issues/issue-71611.min.stderr10
-rw-r--r--tests/ui/const-generics/issues/issue-71611.rs1
-rw-r--r--tests/ui/const-generics/not_wf_param_in_rpitit.rs14
-rw-r--r--tests/ui/const-generics/not_wf_param_in_rpitit.stderr113
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr2
-rw-r--r--tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs1
-rw-r--r--tests/ui/const-generics/type_not_in_scope.rs3
-rw-r--r--tests/ui/const-generics/type_not_in_scope.stderr14
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs1
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr8
-rw-r--r--tests/ui/consts/issue-103790.rs2
-rw-r--r--tests/ui/consts/issue-103790.stderr27
-rw-r--r--tests/ui/coroutine/async_gen_fn.none.stderr4
-rw-r--r--tests/ui/coroutine/async_gen_fn.rs2
-rw-r--r--tests/ui/coroutine/gen_fn.none.stderr4
-rw-r--r--tests/ui/coroutine/gen_fn.rs2
-rw-r--r--tests/ui/cross-crate/auxiliary/static_init_aux.rs6
-rw-r--r--tests/ui/cross-crate/static-init.rs2
-rw-r--r--tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs1
-rw-r--r--tests/ui/delegation/ice-issue-124342.rs12
-rw-r--r--tests/ui/delegation/ice-issue-124342.stderr20
-rw-r--r--tests/ui/delegation/ice-issue-124347.rs12
-rw-r--r--tests/ui/delegation/ice-issue-124347.stderr14
-rw-r--r--tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs4
-rw-r--r--tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr16
-rw-r--r--tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs13
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs27
-rw-r--r--tests/ui/extern-flag/empty-extern-arg.stderr9
-rw-r--r--tests/ui/extern-flag/no-nounused.rs2
-rw-r--r--tests/ui/extern-flag/no-nounused.stderr3
-rw-r--r--tests/ui/feature-gates/feature-gate-extern_prelude.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-extern_prelude.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-offset-of-slice.rs26
-rw-r--r--tests/ui/feature-gates/feature-gate-offset-of-slice.stderr35
-rw-r--r--tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs14
-rw-r--r--tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr49
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-attributes.rs8
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs5
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-vectorcall.stderr7
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs1
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr11
-rw-r--r--tests/ui/generic-associated-types/issue-70304.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-70304.stderr18
-rw-r--r--tests/ui/generic-associated-types/issue-71176.rs3
-rw-r--r--tests/ui/generic-associated-types/issue-71176.stderr55
-rw-r--r--tests/ui/generic-associated-types/issue-80433.rs3
-rw-r--r--tests/ui/generic-associated-types/issue-80433.stderr28
-rw-r--r--tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr9
-rw-r--r--tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.rs30
-rw-r--r--tests/ui/impl-header-lifetime-elision/assoc-type.rs2
-rw-r--r--tests/ui/impl-header-lifetime-elision/assoc-type.stderr4
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs38
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr15
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr17
-rw-r--r--tests/ui/impl-trait/issues/issue-67830.rs7
-rw-r--r--tests/ui/impl-trait/issues/issue-67830.stderr31
-rw-r--r--tests/ui/impl-trait/issues/issue-88236-2.rs5
-rw-r--r--tests/ui/impl-trait/issues/issue-88236-2.stderr60
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.rs2
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.stderr34
-rw-r--r--tests/ui/imports/cycle-import-in-diff-module-0.rs14
-rw-r--r--tests/ui/imports/cycle-import-in-diff-module-1.rs14
-rw-r--r--tests/ui/imports/cycle-import-in-std-1.rs9
-rw-r--r--tests/ui/imports/cycle-import-in-std-1.stderr13
-rw-r--r--tests/ui/imports/cycle-import-in-std-2.rs9
-rw-r--r--tests/ui/imports/cycle-import-in-std-2.stderr13
-rw-r--r--tests/ui/imports/shadow-glob-module-resolution-1.rs17
-rw-r--r--tests/ui/imports/shadow-glob-module-resolution-1.stderr23
-rw-r--r--tests/ui/imports/shadow-glob-module-resolution-2.rs19
-rw-r--r--tests/ui/imports/shadow-glob-module-resolution-2.stderr26
-rw-r--r--tests/ui/inline-const/const_block_pat_liveness.rs18
-rw-r--r--tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr4
-rw-r--r--tests/ui/issues/issue-28344.stderr2
-rw-r--r--tests/ui/issues/issue-50781.rs8
-rw-r--r--tests/ui/issues/issue-50781.stderr50
-rw-r--r--tests/ui/issues/issue-53498.rs17
-rw-r--r--tests/ui/issues/issue-5708.rs1
-rw-r--r--tests/ui/layout/issue-84108.rs3
-rw-r--r--tests/ui/layout/issue-84108.stderr36
-rw-r--r--tests/ui/lifetimes/issue-69314.fixed2
-rw-r--r--tests/ui/lifetimes/issue-69314.rs2
-rw-r--r--tests/ui/lifetimes/issue-69314.stderr18
-rw-r--r--tests/ui/lifetimes/no_lending_iterators.rs35
-rw-r--r--tests/ui/lifetimes/no_lending_iterators.stderr30
-rw-r--r--tests/ui/lifetimes/noisy-follow-up-erro.rs23
-rw-r--r--tests/ui/lifetimes/noisy-follow-up-erro.stderr27
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.rs6
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr37
-rw-r--r--tests/ui/linkage-attr/linkage-attr-mutable-static.rs15
-rw-r--r--tests/ui/linkage-attr/linkage-attr-mutable-static.stderr10
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-1.rs5
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-1.stderr26
-rw-r--r--tests/ui/lint/dead-code/unused-assoc-const.rs20
-rw-r--r--tests/ui/lint/dead-code/unused-assoc-const.stderr16
-rw-r--r--tests/ui/lint/dead-code/unused-pub-struct.rs48
-rw-r--r--tests/ui/lint/dead-code/unused-pub-struct.stderr14
-rw-r--r--tests/ui/lint/non-local-defs/consts.stderr19
-rw-r--r--tests/ui/lint/unreachable_pub.rs10
-rw-r--r--tests/ui/lint/unreachable_pub.stderr32
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.rs4
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr14
-rw-r--r--tests/ui/macros/expand-full-no-resolution.stderr4
-rw-r--r--tests/ui/macros/issue-61053-missing-repetition.rs6
-rw-r--r--tests/ui/macros/issue-61053-missing-repetition.stderr6
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs2
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr2
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs15
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs39
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr160
-rw-r--r--tests/ui/match/ref_pat_everywhere-fail.rs12
-rw-r--r--tests/ui/match/ref_pat_everywhere-fail.stderr38
-rw-r--r--tests/ui/match/ref_pat_everywhere.rs24
-rw-r--r--tests/ui/mir/lint/assignment-overlap.rs4
-rw-r--r--tests/ui/mir/lint/call-overlap.rs4
-rw-r--r--tests/ui/mir/lint/no-storage.rs4
-rw-r--r--tests/ui/mir/lint/storage-live.rs4
-rw-r--r--tests/ui/mir/lint/storage-return.rs4
-rw-r--r--tests/ui/mir/mir_codegen_ssa.rs4
-rw-r--r--tests/ui/mir/ssa_call_ret.rs4
-rw-r--r--tests/ui/mir/validate/critical-edge.rs4
-rw-r--r--tests/ui/mir/validate/noncleanup-cleanup.rs5
-rw-r--r--tests/ui/mir/validate/noncleanup-resume.rs4
-rw-r--r--tests/ui/mir/validate/noncleanup-terminate.rs4
-rw-r--r--tests/ui/object-safety/issue-106247.rs2
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.rs4
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr11
-rw-r--r--tests/ui/offset-of/offset-of-slice.rs26
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed15
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.rs15
-rw-r--r--tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr46
-rw-r--r--tests/ui/parser/duplicate-visibility.rs4
-rw-r--r--tests/ui/parser/duplicate-visibility.stderr4
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.rs7
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.stderr14
-rw-r--r--tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs1
-rw-r--r--tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr17
-rw-r--r--tests/ui/parser/issues/issue-76437-async.rs2
-rw-r--r--tests/ui/parser/issues/issue-76437-async.stderr4
-rw-r--r--tests/ui/parser/issues/issue-76437-const-async.rs2
-rw-r--r--tests/ui/parser/issues/issue-76437-const-async.stderr4
-rw-r--r--tests/ui/parser/issues/issue-76437-const.rs2
-rw-r--r--tests/ui/parser/issues/issue-76437-const.stderr4
-rw-r--r--tests/ui/parser/issues/issue-86895.rs2
-rw-r--r--tests/ui/parser/issues/issue-86895.stderr4
-rw-r--r--tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs4
-rw-r--r--tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr4
-rw-r--r--tests/ui/parser/issues/issue-87694-duplicated-pub.rs4
-rw-r--r--tests/ui/parser/issues/issue-87694-duplicated-pub.stderr4
-rw-r--r--tests/ui/parser/issues/issue-87694-misplaced-pub.rs4
-rw-r--r--tests/ui/parser/issues/issue-87694-misplaced-pub.stderr4
-rw-r--r--tests/ui/parser/macro/macro-repeat.stderr4
-rw-r--r--tests/ui/parser/no-const-fn-in-extern-block.rs2
-rw-r--r--tests/ui/parser/no-const-fn-in-extern-block.stderr8
-rw-r--r--tests/ui/parser/recover/recover-range-pats.stderr9
-rw-r--r--tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed3
-rw-r--r--tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs3
-rw-r--r--tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr10
-rw-r--r--tests/ui/parser/unsafe-foreign-mod-2.rs6
-rw-r--r--tests/ui/parser/unsafe-foreign-mod-2.stderr6
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs14
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr31
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.fixed2
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.rs2
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2021.rs2
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024.rs2
-rw-r--r--tests/ui/pattern/no_ref_mut_behind_and.rs9
-rw-r--r--tests/ui/polymorphization/abi_mismatch.rs20
-rw-r--r--tests/ui/polymorphization/abi_mismatch.stderr11
-rw-r--r--tests/ui/privacy/ufc-method-call.different_name.stderr15
-rw-r--r--tests/ui/privacy/ufc-method-call.rs30
-rw-r--r--tests/ui/privacy/ufc-method-call.same_name.stderr (renamed from tests/ui/issues/issue-53498.stderr)2
-rw-r--r--tests/ui/privacy/where-priv-type.rs46
-rw-r--r--tests/ui/privacy/where-priv-type.stderr37
-rw-r--r--tests/ui/proc-macro/issue-81555.rs3
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.local.stderr183
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.local.stdout44
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr183
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout44
-rw-r--r--tests/ui/pub/pub-ident-struct-4.fixed3
-rw-r--r--tests/ui/pub/pub-ident-struct-4.rs3
-rw-r--r--tests/ui/pub/pub-ident-struct-4.stderr6
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.rs2
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.stderr6
-rw-r--r--tests/ui/regions/regions-issue-21422.rs1
-rw-r--r--tests/ui/resolve/filter-intrinsics.rs4
-rw-r--r--tests/ui/resolve/filter-intrinsics.stderr8
-rw-r--r--tests/ui/resolve/issue-82865.stderr7
-rw-r--r--tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs22
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr61
-rw-r--r--tests/ui/rust-2018/macro-use-warned-against.rs2
-rw-r--r--tests/ui/rust-2018/macro-use-warned-against.stderr3
-rw-r--r--tests/ui/rust-2024/unsafe-env.e2021.stderr27
-rw-r--r--tests/ui/rust-2024/unsafe-env.e2024.stderr49
-rw-r--r--tests/ui/rust-2024/unsafe-env.rs12
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs25
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr12
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs20
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs18
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr20
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr32
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs20
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr25
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr19
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs25
-rw-r--r--tests/ui/specialization/anyid-repro-125197.rs17
-rw-r--r--tests/ui/specialization/auxiliary/anyid-repro-125197.rs26
-rw-r--r--tests/ui/specialization/dont-drop-upcast-candidate.rs13
-rw-r--r--tests/ui/specialization/dont-drop-upcast-candidate.stderr11
-rw-r--r--tests/ui/static/duplicated-fields-issue-124464.rs (renamed from tests/crashes/124464.rs)6
-rw-r--r--tests/ui/static/duplicated-fields-issue-124464.stderr22
-rw-r--r--tests/ui/static/duplicated-fields-issue-125842.rs21
-rw-r--r--tests/ui/static/duplicated-fields-issue-125842.stderr11
-rw-r--r--tests/ui/structs-enums/newtype-struct-with-dtor.rs2
-rw-r--r--tests/ui/structs-enums/uninstantiable-struct.rs3
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.fixed1
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.rs1
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.stderr4
-rw-r--r--tests/ui/suggestions/ice-unwrap-probe-many-result-125876.rs11
-rw-r--r--tests/ui/suggestions/ice-unwrap-probe-many-result-125876.stderr40
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.rs22
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.stderr90
-rw-r--r--tests/ui/suggestions/option-content-move.fixed2
-rw-r--r--tests/ui/suggestions/option-content-move.rs2
-rw-r--r--tests/ui/suggestions/option-content-move.stderr4
-rw-r--r--tests/ui/suggestions/silenced-binding-typo.stderr4
-rw-r--r--tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs2
-rw-r--r--tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr32
-rw-r--r--tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs27
-rw-r--r--tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr19
-rw-r--r--tests/ui/traits/issue-78372.stderr12
-rw-r--r--tests/ui/traits/item-privacy.stderr9
-rw-r--r--tests/ui/traits/next-solver/generalize/bivariant-alias.rs20
-rw-r--r--tests/ui/traits/object/generics.rs1
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.rs1
-rw-r--r--tests/ui/traits/vtable/vtable-vacant.stderr2
-rw-r--r--tests/ui/transmutability/issue-101739-2.rs1
-rw-r--r--tests/ui/transmutability/issue-101739-2.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.classic.stderr (renamed from tests/ui/type-alias-impl-trait/coherence.stderr)2
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.next.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr13
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.rs4
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.rs5
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout8
-rw-r--r--tests/ui/unused-crate-deps/deny-attr.rs2
-rw-r--r--tests/ui/unused-crate-deps/deny-attr.stderr3
-rw-r--r--tests/ui/unused-crate-deps/deny-cmdline.rs2
-rw-r--r--tests/ui/unused-crate-deps/deny-cmdline.stderr3
-rw-r--r--tests/ui/unused-crate-deps/libfib.rs2
-rw-r--r--tests/ui/unused-crate-deps/libfib.stderr3
-rw-r--r--tests/ui/unused-crate-deps/unused-aliases.rs2
-rw-r--r--tests/ui/unused-crate-deps/unused-aliases.stderr3
-rw-r--r--tests/ui/unused-crate-deps/warn-attr.rs2
-rw-r--r--tests/ui/unused-crate-deps/warn-attr.stderr3
-rw-r--r--tests/ui/unused-crate-deps/warn-cmdline-static.rs2
-rw-r--r--tests/ui/unused-crate-deps/warn-cmdline-static.stderr3
-rw-r--r--tests/ui/unused-crate-deps/warn-cmdline.rs2
-rw-r--r--tests/ui/unused-crate-deps/warn-cmdline.stderr3
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs27
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr44
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs16
-rw-r--r--tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr93
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.rs1
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.stderr4
-rw-r--r--triagebot.toml16
1417 files changed, 18751 insertions, 12558 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c9d6c56076a..521f8ef0f5a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,6 +38,8 @@ concurrency:
   cancel-in-progress: true
 env:
   TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
+  # This will be empty in PR jobs.
+  TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}
 jobs:
   # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml.
   # It calculates which jobs should be executed, based on the data of the ${{ github }} context.
@@ -154,12 +156,6 @@ jobs:
 
       - name: checkout submodules
         run: src/ci/scripts/checkout-submodules.sh
-      
-      - name: Setup Python
-        uses: actions/setup-python@v5
-        with:
-          python-version: '3.x'
-        if: runner.environment == 'github-hosted'
 
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
@@ -242,6 +238,5 @@ jobs:
         shell: bash
         if: needs.calculate_matrix.outputs.run_type == 'auto'
         env:
-          TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}
           TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues
           TOOLSTATE_PUBLISH: 1
diff --git a/Cargo.lock b/Cargo.lock
index 1018eac13ff..ba8b2c27005 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -131,9 +131,9 @@ dependencies = [
 
 [[package]]
 name = "annotate-snippets"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5a59f105fb9635e9eebdc1e29d53e764fa5795b9cf899a638a53e61567ef61"
+checksum = "086b0afab3b349e5691143adbfb26983821e3eec4ba4c51957104d372c2e1b7d"
 dependencies = [
  "anstyle",
  "unicode-width",
@@ -189,9 +189,9 @@ dependencies = [
 
 [[package]]
 name = "anstyle-query"
-version = "1.0.3"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
 dependencies = [
  "windows-sys 0.52.0",
 ]
@@ -266,7 +266,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -372,7 +372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
 dependencies = [
  "memchr",
- "regex-automata 0.3.9",
+ "regex-automata 0.3.7",
  "serde",
 ]
 
@@ -501,9 +501,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.97"
+version = "1.0.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
+checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
 
 [[package]]
 name = "cfg-if"
@@ -568,9 +568,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.4"
+version = "4.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -588,9 +588,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.2"
+version = "4.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df"
 dependencies = [
  "anstream",
  "anstyle",
@@ -601,30 +601,30 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.2"
+version = "4.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e"
+checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.4"
+version = "4.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
 name = "clap_lex"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
 
 [[package]]
 name = "clippy"
@@ -644,7 +644,7 @@ dependencies = [
  "regex",
  "rustc_tools_util",
  "serde",
- "syn 2.0.64",
+ "syn 2.0.66",
  "tempfile",
  "termize",
  "tokio",
@@ -754,7 +754,7 @@ dependencies = [
  "nom",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -878,18 +878,18 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.4.0"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.12"
+version = "0.5.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
 dependencies = [
  "crossbeam-utils",
 ]
@@ -915,9 +915,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.19"
+version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
 
 [[package]]
 name = "crypto-common"
@@ -990,7 +990,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1001,7 +1001,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1027,7 +1027,7 @@ version = "0.1.80"
 dependencies = [
  "itertools 0.12.1",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1068,7 +1068,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1078,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
 dependencies = [
  "derive_builder_core",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1101,7 +1101,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1196,7 +1196,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1516,7 +1516,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1588,9 +1588,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1757,7 +1757,7 @@ dependencies = [
  "markup5ever 0.12.1",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -1800,9 +1800,9 @@ dependencies = [
 
 [[package]]
 name = "icu_list"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe6c04ec71ad1bacdbfb47164d4801f80a0533d9340f94f1a880f521eff59f54"
+checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365"
 dependencies = [
  "displaydoc",
  "icu_list_data",
@@ -1814,15 +1814,15 @@ dependencies = [
 
 [[package]]
 name = "icu_list_data"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f6afcf7a9a7fedece70b7f17d7a7ecdfb8df145d37ae46d0277cd1e3932532"
+checksum = "e1825170d2c6679cb20dbd96a589d034e49f698aed9a2ef4fafc9a0101ed298f"
 
 [[package]]
 name = "icu_locid"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c0aa2536adc14c07e2a521e95512b75ed8ef832f0fdf9299d4a0a45d2be2a9d"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
 dependencies = [
  "displaydoc",
  "litemap",
@@ -1833,9 +1833,9 @@ dependencies = [
 
 [[package]]
 name = "icu_locid_transform"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c17d8f6524fdca4471101dd71f0a132eb6382b5d6d7f2970441cb25f6f435a"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
 dependencies = [
  "displaydoc",
  "icu_locid",
@@ -1847,15 +1847,15 @@ dependencies = [
 
 [[package]]
 name = "icu_locid_transform_data"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "545c6c3e8bf9580e2dafee8de6f9ec14826aaf359787789c7724f1f85f47d3dc"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
 
 [[package]]
 name = "icu_provider"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba58e782287eb6950247abbf11719f83f5d4e4a5c1f2cd490d30a334bc47c2f4"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
 dependencies = [
  "displaydoc",
  "icu_locid",
@@ -1870,9 +1870,9 @@ dependencies = [
 
 [[package]]
 name = "icu_provider_adapters"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a229f978260da7c3aabb68cb7dc7316589936680570fe55e50fdd3f97711a4dd"
+checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc"
 dependencies = [
  "icu_locid",
  "icu_locid_transform",
@@ -1883,13 +1883,13 @@ dependencies = [
 
 [[package]]
 name = "icu_provider_macros"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -2196,9 +2196,9 @@ dependencies = [
 
 [[package]]
 name = "libz-sys"
-version = "1.1.16"
+version = "1.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9"
+checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e"
 dependencies = [
  "cc",
  "libc",
@@ -2207,6 +2207,21 @@ dependencies = [
 ]
 
 [[package]]
+name = "line-wrap"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e"
+
+[[package]]
+name = "linereader"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d921fea6860357575519aca014c6e22470585accdd543b370c404a8a72d0dd1d"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "linkchecker"
 version = "0.1.0"
 dependencies = [
@@ -2215,6 +2230,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
 name = "lint-docs"
 version = "0.1.0"
 dependencies = [
@@ -2231,9 +2252,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
 [[package]]
 name = "litemap"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d642685b028806386b2b6e75685faadd3eb65a85fff7df711ce18446a422da"
+checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
 
 [[package]]
 name = "lld-wrapper"
@@ -2365,6 +2386,25 @@ dependencies = [
 ]
 
 [[package]]
+name = "mdbook-i18n-helpers"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1f71f5961d6f3376e1ff3e5989c2e3ecccc3e8a00f3a3acde446847f84852e4"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "mdbook",
+ "polib",
+ "pulldown-cmark 0.10.3",
+ "pulldown-cmark-to-cmark",
+ "regex",
+ "semver",
+ "serde_json",
+ "syntect",
+ "textwrap",
+]
+
+[[package]]
 name = "mdbook-trpl-listing"
 version = "0.1.0"
 dependencies = [
@@ -2375,7 +2415,7 @@ dependencies = [
  "pulldown-cmark-to-cmark",
  "serde_json",
  "thiserror",
- "toml 0.8.13",
+ "toml 0.8.14",
  "xmlparser",
 ]
 
@@ -2568,9 +2608,9 @@ dependencies = [
 
 [[package]]
 name = "nu-ansi-term"
-version = "0.49.0"
+version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68"
+checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14"
 dependencies = [
  "windows-sys 0.48.0",
 ]
@@ -2612,14 +2652,11 @@ version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
- "compiler_builtins",
  "crc32fast",
  "flate2",
  "hashbrown",
  "indexmap",
  "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
  "ruzstd 0.5.0",
  "wasmparser",
 ]
@@ -2636,6 +2673,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "object"
+version = "0.36.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
+dependencies = [
+ "compiler_builtins",
+ "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
 name = "odht"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2651,6 +2700,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
+name = "onig"
+version = "6.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+ "once_cell",
+ "onig_sys",
+]
+
+[[package]]
+name = "onig_sys"
+version = "69.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
 name = "opener"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2778,9 +2849,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.12.2"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -2860,7 +2931,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -2969,6 +3040,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
 
 [[package]]
+name = "plist"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9"
+dependencies = [
+ "base64",
+ "indexmap",
+ "line-wrap",
+ "quick-xml",
+ "serde",
+ "time",
+]
+
+[[package]]
+name = "polib"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b393b155cf9be86249cba1b56cc81be0e6212c66d94ac0d76d37a1761f3bb1b"
+dependencies = [
+ "linereader",
+]
+
+[[package]]
 name = "polonius-engine"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3048,9 +3142,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.82"
+version = "1.0.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
+checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
 dependencies = [
  "unicode-ident",
 ]
@@ -3127,6 +3221,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"
 
 [[package]]
+name = "quick-xml"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "quine-mc_cluskey"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3143,9 +3246,9 @@ dependencies = [
 
 [[package]]
 name = "r-efi"
-version = "4.4.0"
+version = "4.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c47196f636c4cc0634b73b0405323d177753c2e15e866952c64ea22902567a34"
+checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -3261,12 +3364,13 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.8.4"
+version = "1.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29"
 dependencies = [
  "aho-corasick",
  "memchr",
+ "regex-automata 0.3.7",
  "regex-syntax 0.7.5",
 ]
 
@@ -3290,9 +3394,14 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.3.9"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
+checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.7.5",
+]
 
 [[package]]
 name = "regex-lite"
@@ -3367,6 +3476,7 @@ dependencies = [
  "clap",
  "env_logger",
  "mdbook",
+ "mdbook-i18n-helpers",
  "mdbook-trpl-listing",
  "mdbook-trpl-note",
 ]
@@ -3517,7 +3627,6 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
- "smallvec",
 ]
 
 [[package]]
@@ -3598,7 +3707,6 @@ dependencies = [
  "icu_locid",
  "icu_locid_transform",
  "icu_provider",
- "icu_provider_adapters",
  "zerovec",
 ]
 
@@ -3779,7 +3887,6 @@ dependencies = [
  "portable-atomic",
  "rustc-hash",
  "rustc-rayon",
- "rustc-rayon-core",
  "rustc_arena",
  "rustc_graphviz",
  "rustc_index",
@@ -3820,7 +3927,6 @@ dependencies = [
  "rustc_expand",
  "rustc_feature",
  "rustc_fluent_macro",
- "rustc_hir",
  "rustc_hir_analysis",
  "rustc_hir_pretty",
  "rustc_hir_typeck",
@@ -3948,7 +4054,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "unic-langid",
 ]
 
@@ -4082,8 +4188,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
- "synstructure",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -4100,6 +4205,7 @@ dependencies = [
  "rustc_middle",
  "rustc_span",
  "rustc_target",
+ "rustc_type_ir",
  "smallvec",
  "tracing",
 ]
@@ -4230,7 +4336,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "synstructure",
 ]
 
@@ -4274,7 +4380,6 @@ dependencies = [
  "field-offset",
  "gsgdt",
  "polonius-engine",
- "rustc-rayon",
  "rustc-rayon-core",
  "rustc_apfloat",
  "rustc_arena",
@@ -4291,7 +4396,6 @@ dependencies = [
  "rustc_hir_pretty",
  "rustc_index",
  "rustc_macros",
- "rustc_next_trait_solver",
  "rustc_query_system",
  "rustc_serialize",
  "rustc_session",
@@ -4307,7 +4411,6 @@ dependencies = [
 name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
- "either",
  "itertools 0.12.1",
  "rustc_apfloat",
  "rustc_arena",
@@ -4326,7 +4429,6 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "rustc_trait_selection",
- "smallvec",
  "tracing",
 ]
 
@@ -4401,13 +4503,7 @@ dependencies = [
 name = "rustc_next_trait_solver"
 version = "0.0.0"
 dependencies = [
- "derivative",
- "rustc_ast_ir",
- "rustc_data_structures",
- "rustc_macros",
- "rustc_serialize",
  "rustc_type_ir",
- "rustc_type_ir_macros",
 ]
 
 [[package]]
@@ -4512,7 +4608,6 @@ version = "0.0.0"
 dependencies = [
  "field-offset",
  "measureme",
- "rustc-rayon-core",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
@@ -4809,7 +4904,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "synstructure",
 ]
 
@@ -4907,7 +5002,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -5043,22 +5138,22 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.202"
+version = "1.0.203"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
+checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.202"
+version = "1.0.203"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
+checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -5170,9 +5265,9 @@ dependencies = [
 
 [[package]]
 name = "spanned"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccdf4f5590b7e6fbd4f2e80d442789079a6fff7c12ef921a9de358b7b353098e"
+checksum = "ed14ba8b4b82241bd5daba2c49185d4a0581a0058355fe96537338f002b8605d"
 dependencies = [
  "bstr",
  "color-eyre",
@@ -5218,7 +5313,6 @@ name = "stable_mir"
 version = "0.1.0-preview"
 dependencies = [
  "scoped-tls",
- "tracing",
 ]
 
 [[package]]
@@ -5255,7 +5349,7 @@ dependencies = [
  "hermit-abi",
  "libc",
  "miniz_oxide",
- "object 0.32.2",
+ "object 0.36.0",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -5352,9 +5446,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.64"
+version = "2.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5369,7 +5463,29 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
+]
+
+[[package]]
+name = "syntect"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
+dependencies = [
+ "bincode",
+ "bitflags 1.3.2",
+ "flate2",
+ "fnv",
+ "once_cell",
+ "onig",
+ "plist",
+ "regex-syntax 0.8.3",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "thiserror",
+ "walkdir",
+ "yaml-rust",
 ]
 
 [[package]]
@@ -5407,9 +5523,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.40"
+version = "0.4.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
+checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909"
 dependencies = [
  "filetime",
  "libc",
@@ -5492,12 +5608,16 @@ dependencies = [
  "core",
  "getopts",
  "libc",
- "panic_abort",
- "panic_unwind",
  "std",
 ]
 
 [[package]]
+name = "textwrap"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+
+[[package]]
 name = "thin-vec"
 version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5520,7 +5640,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -5605,9 +5725,9 @@ dependencies = [
 
 [[package]]
 name = "tinystr"
-version = "0.7.5"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
 dependencies = [
  "displaydoc",
  "zerovec",
@@ -5630,9 +5750,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.37.0"
+version = "1.38.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
+checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
 dependencies = [
  "backtrace",
  "bytes",
@@ -5662,14 +5782,14 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.13"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba"
+checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
 dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "toml_edit 0.22.13",
+ "toml_edit 0.22.14",
 ]
 
 [[package]]
@@ -5696,15 +5816,15 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.22.13"
+version = "0.22.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
+checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
 dependencies = [
  "indexmap",
  "serde",
  "serde_spanned",
  "toml_datetime",
- "winnow 0.6.8",
+ "winnow 0.6.13",
 ]
 
 [[package]]
@@ -5733,7 +5853,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
@@ -5788,11 +5908,11 @@ dependencies = [
 
 [[package]]
 name = "tracing-tree"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65139ecd2c3f6484c3b99bc01c77afe21e95473630747c7aca525e78b0666675"
+checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe"
 dependencies = [
- "nu-ansi-term 0.49.0",
+ "nu-ansi-term 0.50.0",
  "tracing-core",
  "tracing-log",
  "tracing-subscriber",
@@ -5872,7 +5992,7 @@ version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "29e5f4ffcbab82453958fbf59990e981b8e8a177dcd60c2bd8f9b52c3036a6e1"
 dependencies = [
- "annotate-snippets 0.11.2",
+ "annotate-snippets 0.11.3",
  "anyhow",
  "bstr",
  "cargo-platform",
@@ -5933,7 +6053,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "unic-langid-impl",
 ]
 
@@ -6004,9 +6124,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.12"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -6083,9 +6203,9 @@ checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
 
 [[package]]
 name = "utf8parse"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "uuid"
@@ -6165,7 +6285,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "wasm-bindgen-shared",
 ]
 
@@ -6187,7 +6307,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6268,7 +6388,7 @@ dependencies = [
  "rayon",
  "serde",
  "serde_json",
- "syn 2.0.64",
+ "syn 2.0.66",
  "windows-metadata",
 ]
 
@@ -6437,18 +6557,18 @@ dependencies = [
 
 [[package]]
 name = "winnow"
-version = "0.6.8"
+version = "0.6.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "writeable"
-version = "0.5.4"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dad7bb64b8ef9c0aa27b6da38b452b0ee9fd82beaf276a87dd796fb55cbae14e"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 
 [[package]]
 name = "xattr"
@@ -6477,6 +6597,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
 name = "yansi-term"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6487,9 +6616,9 @@ dependencies = [
 
 [[package]]
 name = "yoke"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4"
+checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
 dependencies = [
  "serde",
  "stable_deref_trait",
@@ -6499,13 +6628,13 @@ dependencies = [
 
 [[package]]
 name = "yoke-derive"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8"
+checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "synstructure",
 ]
 
@@ -6526,35 +6655,35 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
 
 [[package]]
 name = "zerofrom"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7"
+checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3"
+checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
  "synstructure",
 ]
 
 [[package]]
 name = "zerovec"
-version = "0.10.1"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff4439ae91fb5c72b8abc12f3f2dbf51bd27e6eadb9f8a5bc8898dddb0e27ea"
+checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c"
 dependencies = [
  "yoke",
  "zerofrom",
@@ -6563,11 +6692,11 @@ dependencies = [
 
 [[package]]
 name = "zerovec-derive"
-version = "0.10.1"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20"
+checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.64",
+ "syn 2.0.66",
 ]
diff --git a/RELEASES.md b/RELEASES.md
index 3080f03c721..c1311ab14c5 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,131 @@
+Version 1.79.0 (2024-06-13)
+==========================
+
+<a id="1.79.0-Language"></a>
+
+Language
+--------
+- [Stabilize inline `const {}` expressions.](https://github.com/rust-lang/rust/pull/104087/)
+- [Prevent opaque types being instantiated twice with different regions within the same function.](https://github.com/rust-lang/rust/pull/116935/)
+- [Stabilize WebAssembly target features that are in phase 4 and 5.](https://github.com/rust-lang/rust/pull/117457/)
+- [Add the `redundant_lifetimes` lint to detect lifetimes which are semantically redundant.](https://github.com/rust-lang/rust/pull/118391/)
+- [Stabilize the `unnameable_types` lint for public types that can't be named.](https://github.com/rust-lang/rust/pull/120144/)
+- [Enable debuginfo in macros, and stabilize `-C collapse-macro-debuginfo` and `#[collapse_debuginfo]`.](https://github.com/rust-lang/rust/pull/120845/)
+- [Propagate temporary lifetime extension into `if` and `match` expressions.](https://github.com/rust-lang/rust/pull/121346/)
+- [Restrict promotion of `const fn` calls.](https://github.com/rust-lang/rust/pull/121557/)
+- [Warn against refining impls of crate-private traits with `refining_impl_trait` lint.](https://github.com/rust-lang/rust/pull/121720/)
+- [Stabilize associated type bounds (RFC 2289).](https://github.com/rust-lang/rust/pull/122055/)
+- [Stabilize importing `main` from other modules or crates.](https://github.com/rust-lang/rust/pull/122060/)
+- [Check return types of function types for well-formedness](https://github.com/rust-lang/rust/pull/115538)
+- [Rework `impl Trait` lifetime inference](https://github.com/rust-lang/rust/pull/116891/)
+- [Change inductive trait solver cycles to be ambiguous](https://github.com/rust-lang/rust/pull/122791)
+
+<a id="1.79.0-Compiler"></a>
+
+Compiler
+--------
+- [Define `-C strip` to only affect binaries, not artifacts like `.pdb`.](https://github.com/rust-lang/rust/pull/115120/)
+- [Stabilize `-Crelro-level` for controlling runtime link hardening.](https://github.com/rust-lang/rust/pull/121694/)
+- [Stabilize checking of `cfg` names and values at compile-time with `--check-cfg`.](https://github.com/rust-lang/rust/pull/123501/)
+  *Note that this only stabilizes the compiler part, the Cargo part is still unstable in this release.*
+- [Add `aarch64-apple-visionos` and `aarch64-apple-visionos-sim` tier 3 targets.](https://github.com/rust-lang/rust/pull/121419/)
+- [Add `riscv32ima-unknown-none-elf` tier 3 target.](https://github.com/rust-lang/rust/pull/122696/)
+- [Promote several Windows targets to tier 2](https://github.com/rust-lang/rust/pull/121712): `aarch64-pc-windows-gnullvm`, `i686-pc-windows-gnullvm`, and `x86_64-pc-windows-gnullvm`.
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.79.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Implement `FromIterator` for `(impl Default + Extend, impl Default + Extend)`.](https://github.com/rust-lang/rust/pull/107462/)
+- [Implement `{Div,Rem}Assign<NonZero<X>>` on `X`.](https://github.com/rust-lang/rust/pull/121952/)
+- [Document overrides of `clone_from()` in core/std.](https://github.com/rust-lang/rust/pull/122201/)
+- [Link MSVC default lib in core.](https://github.com/rust-lang/rust/pull/122268/)
+- [Caution against using `transmute` between pointers and integers.](https://github.com/rust-lang/rust/pull/122379/)
+- [Enable frame pointers for the standard library.](https://github.com/rust-lang/rust/pull/122646/)
+
+<a id="1.79.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`{integer}::unchecked_add`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_add)
+- [`{integer}::unchecked_mul`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_mul)
+- [`{integer}::unchecked_sub`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_sub)
+- [`<[T]>::split_at_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_unchecked)
+- [`<[T]>::split_at_mut_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_unchecked)
+- [`<[u8]>::utf8_chunks`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.utf8_chunks)
+- [`str::Utf8Chunks`](https://doc.rust-lang.org/stable/core/str/struct.Utf8Chunks.html)
+- [`str::Utf8Chunk`](https://doc.rust-lang.org/stable/core/str/struct.Utf8Chunk.html)
+- [`<*const T>::is_aligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_aligned)
+- [`<*mut T>::is_aligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_aligned-1)
+- [`NonNull::is_aligned`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.is_aligned)
+- [`<*const [T]>::len`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.len)
+- [`<*mut [T]>::len`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.len-1)
+- [`<*const [T]>::is_empty`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_empty)
+- [`<*mut [T]>::is_empty`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_empty-1)
+- [`NonNull::<[T]>::is_empty`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.is_empty)
+- [`CStr::count_bytes`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes)
+- [`io::Error::downcast`](https://doc.rust-lang.org/stable/std/io/struct.Error.html#method.downcast)
+- [`num::NonZero<T>`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html)
+- [`path::absolute`](https://doc.rust-lang.org/stable/std/path/fn.absolute.html)
+- [`proc_macro::Literal::byte_character`](https://doc.rust-lang.org/stable/proc_macro/struct.Literal.html#method.byte_character)
+- [`proc_macro::Literal::c_string`](https://doc.rust-lang.org/stable/proc_macro/struct.Literal.html#method.c_string)
+
+These APIs are now stable in const contexts:
+
+- [`Atomic*::into_inner`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicUsize.html#method.into_inner)
+- [`io::Cursor::new`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.new)
+- [`io::Cursor::get_ref`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_ref)
+- [`io::Cursor::position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.position)
+- [`io::empty`](https://doc.rust-lang.org/stable/std/io/fn.empty.html)
+- [`io::repeat`](https://doc.rust-lang.org/stable/std/io/fn.repeat.html)
+- [`io::sink`](https://doc.rust-lang.org/stable/std/io/fn.sink.html)
+- [`panic::Location::caller`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.caller)
+- [`panic::Location::file`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.file)
+- [`panic::Location::line`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.line)
+- [`panic::Location::column`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.column)
+
+<a id="1.79.0-Cargo"></a>
+
+Cargo
+-----
+
+- [Prevent dashes in `lib.name`, always normalizing to `_`.](https://github.com/rust-lang/cargo/pull/12783/)
+- [Stabilize MSRV-aware version requirement selection in `cargo add`.](https://github.com/rust-lang/cargo/pull/13608/)
+- [Switch to using `gitoxide` by default for listing files.](https://github.com/rust-lang/cargo/pull/13696/)
+- [Error on `[project]` in Edition 2024; `cargo fix --edition` will change it to `[package]`.](https://github.com/rust-lang/cargo/pull/13747/)
+
+<a id="1.79.0-Rustdoc"></a>
+
+Rustdoc
+-----
+
+- [Always display stability version even if it's the same as the containing item.](https://github.com/rust-lang/rust/pull/118441/)
+- [Show a single search result for items with multiple paths.](https://github.com/rust-lang/rust/pull/119912/)
+- [Support typing `/` in docs to begin a search.](https://github.com/rust-lang/rust/pull/123355/)
+
+<a id="1.79.0-Misc"></a>
+
+Misc
+----
+
+<a id="1.79.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Update the minimum external LLVM to 17.](https://github.com/rust-lang/rust/pull/122649/)
+- [`RustcEncodable` and `RustcDecodable` are soft-destabilized, to be removed
+  from the prelude in next edition.](https://github.com/rust-lang/rust/pull/116016/)
+- [The `wasm_c_abi` future-incompatibility lint will warn about use of the
+  non-spec-compliant C ABI.](https://github.com/rust-lang/rust/pull/117918/)
+  Use `wasm-bindgen v0.2.88` to generate forward-compatible bindings.
+- [Check return types of function types for well-formedness](https://github.com/rust-lang/rust/pull/115538)
+
 Version 1.78.0 (2024-05-02)
 ==========================
 
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 7a45d909d07..9cb193b4a67 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -488,6 +488,7 @@ pub struct Crate {
 /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MetaItem {
+    pub unsafety: Safety,
     pub path: Path,
     pub kind: MetaItemKind,
     pub span: Span,
@@ -1392,7 +1393,7 @@ pub enum ExprKind {
     /// An array (e.g, `[a, b, c, d]`).
     Array(ThinVec<P<Expr>>),
     /// Allow anonymous constants from an inline `const` block
-    ConstBlock(P<Expr>),
+    ConstBlock(AnonConst),
     /// A function call
     ///
     /// The first field resolves to the function itself,
@@ -2501,6 +2502,8 @@ pub enum IsAuto {
 pub enum Safety {
     /// `unsafe` an item is explicitly marked as `unsafe`.
     Unsafe(Span),
+    /// `safe` an item is explicitly marked as `safe`.
+    Safe(Span),
     /// Default means no value was provided, it will take a default value given the context in
     /// which is used.
     Default,
@@ -2821,7 +2824,12 @@ pub struct NormalAttr {
 impl NormalAttr {
     pub fn from_ident(ident: Ident) -> Self {
         Self {
-            item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
+            item: AttrItem {
+                unsafety: Safety::Default,
+                path: Path::from_ident(ident),
+                args: AttrArgs::Empty,
+                tokens: None,
+            },
             tokens: None,
         }
     }
@@ -2829,6 +2837,7 @@ impl NormalAttr {
 
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct AttrItem {
+    pub unsafety: Safety,
     pub path: Path,
     pub args: AttrArgs,
     // Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.
@@ -3162,6 +3171,7 @@ pub struct DelegationMac {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StaticItem {
     pub ty: P<Ty>,
+    pub safety: Safety,
     pub mutability: Mutability,
     pub expr: Option<P<Expr>>,
 }
@@ -3171,6 +3181,7 @@ pub struct StaticItem {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StaticForeignItem {
     pub ty: P<Ty>,
+    pub safety: Safety,
     pub mutability: Mutability,
     pub expr: Option<P<Expr>>,
 }
@@ -3179,6 +3190,7 @@ impl From<StaticItem> for StaticForeignItem {
     fn from(static_item: StaticItem) -> StaticForeignItem {
         StaticForeignItem {
             ty: static_item.ty,
+            safety: static_item.safety,
             mutability: static_item.mutability,
             expr: static_item.expr,
         }
@@ -3189,6 +3201,7 @@ impl From<StaticForeignItem> for StaticItem {
     fn from(static_item: StaticForeignItem) -> StaticItem {
         StaticItem {
             ty: static_item.ty,
+            safety: static_item.safety,
             mutability: static_item.mutability,
             expr: static_item.expr,
         }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index d5c9fc960c8..676a2377c3b 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -1,6 +1,8 @@
 //! Functions dealing with attributes and meta items.
 
-use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
+use crate::ast::{
+    AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, Safety,
+};
 use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
 use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
 use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
@@ -238,7 +240,12 @@ impl AttrItem {
     }
 
     pub fn meta(&self, span: Span) -> Option<MetaItem> {
-        Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
+        Some(MetaItem {
+            unsafety: Safety::Default,
+            path: self.path.clone(),
+            kind: self.meta_kind()?,
+            span,
+        })
     }
 
     pub fn meta_kind(&self) -> Option<MetaItemKind> {
@@ -371,7 +378,10 @@ impl MetaItem {
             _ => path.span.hi(),
         };
         let span = path.span.with_hi(hi);
-        Some(MetaItem { path, kind, span })
+        // FIXME: This parses `unsafe()` not as unsafe attribute syntax in `MetaItem`,
+        // but as a parenthesized list. This (and likely `MetaItem`) should be changed in
+        // such a way that builtin macros don't accept extraneous `unsafe()`.
+        Some(MetaItem { unsafety: Safety::Default, path, kind, span })
     }
 }
 
@@ -555,11 +565,12 @@ pub fn mk_doc_comment(
 pub fn mk_attr(
     g: &AttrIdGenerator,
     style: AttrStyle,
+    unsafety: Safety,
     path: Path,
     args: AttrArgs,
     span: Span,
 ) -> Attribute {
-    mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
+    mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
 }
 
 pub fn mk_attr_from_item(
@@ -577,15 +588,22 @@ pub fn mk_attr_from_item(
     }
 }
 
-pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
+pub fn mk_attr_word(
+    g: &AttrIdGenerator,
+    style: AttrStyle,
+    unsafety: Safety,
+    name: Symbol,
+    span: Span,
+) -> Attribute {
     let path = Path::from_ident(Ident::new(name, span));
     let args = AttrArgs::Empty;
-    mk_attr(g, style, path, args, span)
+    mk_attr(g, style, unsafety, path, args, span)
 }
 
 pub fn mk_attr_nested_word(
     g: &AttrIdGenerator,
     style: AttrStyle,
+    unsafety: Safety,
     outer: Symbol,
     inner: Symbol,
     span: Span,
@@ -601,12 +619,13 @@ pub fn mk_attr_nested_word(
         delim: Delimiter::Parenthesis,
         tokens: inner_tokens,
     });
-    mk_attr(g, style, path, attr_args, span)
+    mk_attr(g, style, unsafety, path, attr_args, span)
 }
 
 pub fn mk_attr_name_value_str(
     g: &AttrIdGenerator,
     style: AttrStyle,
+    unsafety: Safety,
     name: Symbol,
     val: Symbol,
     span: Span,
@@ -621,7 +640,7 @@ pub fn mk_attr_name_value_str(
     });
     let path = Path::from_ident(Ident::new(name, span));
     let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
-    mk_attr(g, style, path, args, span)
+    mk_attr(g, style, unsafety, path, args, span)
 }
 
 pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 5c581c270e4..cc33ce2cb56 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -647,8 +647,10 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
     let Attribute { kind, id: _, style: _, span } = attr;
     match kind {
         AttrKind::Normal(normal) => {
-            let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } =
-                &mut **normal;
+            let NormalAttr {
+                item: AttrItem { unsafety: _, path, args, tokens },
+                tokens: attr_tokens,
+            } = &mut **normal;
             vis.visit_path(path);
             visit_attr_args(args, vis);
             visit_lazy_tts(tokens, vis);
@@ -678,7 +680,7 @@ fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T
 }
 
 fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
-    let MetaItem { path: _, kind, span } = mi;
+    let MetaItem { unsafety: _, path: _, kind, span } = mi;
     match kind {
         MetaItemKind::Word => {}
         MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
@@ -840,7 +842,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
         token::NtTy(ty) => vis.visit_ty(ty),
         token::NtLiteral(expr) => vis.visit_expr(expr),
         token::NtMeta(item) => {
-            let AttrItem { path, args, tokens } = item.deref_mut();
+            let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
             vis.visit_path(path);
             visit_attr_args(args, vis);
             visit_lazy_tts(tokens, vis);
@@ -862,6 +864,7 @@ fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T)
 fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) {
     match safety {
         Safety::Unsafe(span) => vis.visit_span(span),
+        Safety::Safe(span) => vis.visit_span(span),
         Safety::Default => {}
     }
 }
@@ -1079,7 +1082,7 @@ impl NoopVisitItemKind for ItemKind {
         match self {
             ItemKind::ExternCrate(_orig_name) => {}
             ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-            ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
+            ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
                 vis.visit_ty(ty);
                 visit_opt(expr, |expr| vis.visit_expr(expr));
             }
@@ -1289,7 +1292,12 @@ pub fn noop_flat_map_item<K: NoopVisitItemKind>(
 impl NoopVisitItemKind for ForeignItemKind {
     fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
         match self {
-            ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => {
+            ForeignItemKind::Static(box StaticForeignItem {
+                ty,
+                mutability: _,
+                expr,
+                safety: _,
+            }) => {
                 visitor.visit_ty(ty);
                 visit_opt(expr, |expr| visitor.visit_expr(expr));
             }
@@ -1411,7 +1419,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
     match kind {
         ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
         ExprKind::ConstBlock(anon_const) => {
-            vis.visit_expr(anon_const);
+            vis.visit_anon_const(anon_const);
         }
         ExprKind::Repeat(expr, count) => {
             vis.visit_expr(expr);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 099a6096d0b..109c401bb6a 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -210,6 +210,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> boo
             kw::Unsafe,
             kw::While,
             kw::Yield,
+            kw::Safe,
             kw::Static,
         ]
         .contains(&name)
@@ -577,6 +578,7 @@ impl Token {
                 kw::Impl,
                 kw::Unsafe,
                 kw::Const,
+                kw::Safe,
                 kw::Static,
                 kw::Union,
                 kw::Macro,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index b2f3b27c77e..fa97c8db326 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -334,7 +334,7 @@ impl WalkItemKind for ItemKind {
         match self {
             ItemKind::ExternCrate(_) => {}
             ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
-            ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
+            ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
             }
@@ -658,7 +658,12 @@ impl WalkItemKind for ForeignItemKind {
     ) -> V::Result {
         let &Item { id, span, ident, ref vis, .. } = item;
         match self {
-            ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => {
+            ForeignItemKind::Static(box StaticForeignItem {
+                ty,
+                mutability: _,
+                expr,
+                safety: _,
+            }) => {
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
             }
@@ -954,7 +959,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_expr(anon_const)),
+        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
         ExprKind::Repeat(element, count) => {
             try_visit!(visitor.visit_expr(element));
             try_visit!(visitor.visit_anon_const(count));
diff --git a/compiler/rustc_ast_ir/Cargo.toml b/compiler/rustc_ast_ir/Cargo.toml
index e761b7adad3..a78c91e0615 100644
--- a/compiler/rustc_ast_ir/Cargo.toml
+++ b/compiler/rustc_ast_ir/Cargo.toml
@@ -9,7 +9,6 @@ rustc_data_structures = { path = "../rustc_data_structures", optional = true }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
-smallvec = { version = "1.8.1" }
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 27f8a6eae02..d9dd0b3bca5 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -67,7 +67,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return false;
         };
         if let Some(local_sig_id) = sig_id.as_local() {
-            self.resolver.delegation_fn_sigs[&local_sig_id].has_self
+            // The value may be missing due to recursive delegation.
+            // Error will be emmited later during HIR ty lowering.
+            self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
         } else {
             match self.tcx.def_kind(sig_id) {
                 DefKind::Fn => false,
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index eb206a09be3..77f95869e9d 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -75,8 +75,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
                 ExprKind::ConstBlock(c) => {
-                    self.has_inline_consts = true;
-                    hir::ExprKind::ConstBlock(self.lower_expr(c))
+                    let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
+                        def_id: this.local_def_id(c.id),
+                        hir_id: this.lower_node_id(c.id),
+                        body: this.lower_const_body(c.value.span, Some(&c.value)),
+                    });
+                    hir::ExprKind::ConstBlock(c)
                 }
                 ExprKind::Repeat(expr, count) => {
                     let expr = self.lower_expr(expr);
@@ -1801,6 +1805,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let attr = attr::mk_attr_nested_word(
             &self.tcx.sess.psess.attr_id_generator,
             AttrStyle::Outer,
+            Safety::Default,
             sym::allow,
             sym::unreachable_code,
             self.lower_span(span),
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 741a44eb0c5..44f37b5533a 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -236,6 +236,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
+    fn visit_inline_const(&mut self, constant: &'hir ConstBlock) {
+        self.insert(DUMMY_SP, constant.hir_id, Node::ConstBlock(constant));
+
+        self.with_parent(constant.hir_id, |this| {
+            intravisit::walk_inline_const(this, constant);
+        });
+    }
+
     fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
         self.insert(expr.span, expr.hir_id, Node::Expr(expr));
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index a15449409df..8c963e9f890 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -181,7 +181,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
             }
-            ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
+            ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
                 let (ty, body_id) =
                     self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
                 hir::ItemKind::Static(ty, *m, body_id)
@@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
                 };
                 hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
-                    safety: self.lower_safety(*safety),
+                    safety: self.lower_safety(*safety, hir::Safety::Safe),
                     polarity,
                     defaultness,
                     defaultness_span,
@@ -418,7 +418,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         let items = this.arena.alloc_from_iter(
                             items.iter().map(|item| this.lower_trait_item_ref(item)),
                         );
-                        let safety = this.lower_safety(*safety);
+                        let safety = this.lower_safety(*safety, hir::Safety::Safe);
                         (safety, items, bounds)
                     },
                 );
@@ -660,13 +660,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                 this.lower_fn_params_to_names(fdec),
                             )
                         });
+                    let safety = self.lower_safety(sig.header.safety, hir::Safety::Unsafe);
 
-                    hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
+                    hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety)
                 }
-                ForeignItemKind::Static(box StaticForeignItem { ty, mutability, expr: _ }) => {
+                ForeignItemKind::Static(box StaticForeignItem {
+                    ty,
+                    mutability,
+                    expr: _,
+                    safety,
+                }) => {
                     let ty = self
                         .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
-                    hir::ForeignItemKind::Static(ty, *mutability)
+                    let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
+
+                    hir::ForeignItemKind::Static(ty, *mutability, safety)
                 }
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
                 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
@@ -1360,7 +1368,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             hir::IsAsync::NotAsync
         };
         hir::FnHeader {
-            safety: self.lower_safety(h.safety),
+            safety: self.lower_safety(h.safety, hir::Safety::Safe),
             asyncness: asyncness,
             constness: self.lower_constness(h.constness),
             abi: self.lower_extern(h.ext),
@@ -1410,10 +1418,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    pub(super) fn lower_safety(&mut self, s: Safety) -> hir::Safety {
+    pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety {
         match s {
             Safety::Unsafe(_) => hir::Safety::Unsafe,
-            Safety::Default => hir::Safety::Safe,
+            Safety::Default => default,
+            Safety::Safe(_) => hir::Safety::Safe,
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5a80fa803f8..1c6b5b9af19 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -96,8 +96,6 @@ struct LoweringContext<'a, 'hir> {
 
     /// Bodies inside the owner being lowered.
     bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
-    /// Whether there were inline consts that typeck will split out into bodies
-    has_inline_consts: bool,
     /// Attributes inside the owner being lowered.
     attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
     /// Collect items that were created by lowering the current owner.
@@ -160,7 +158,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             item_local_id_counter: hir::ItemLocalId::ZERO,
             node_id_to_local_id: Default::default(),
             trait_map: Default::default(),
-            has_inline_consts: false,
 
             // Lowering state.
             catch_scope: None,
@@ -570,7 +567,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let current_attrs = std::mem::take(&mut self.attrs);
         let current_bodies = std::mem::take(&mut self.bodies);
-        let current_has_inline_consts = std::mem::take(&mut self.has_inline_consts);
         let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
         let current_trait_map = std::mem::take(&mut self.trait_map);
         let current_owner =
@@ -597,7 +593,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         self.attrs = current_attrs;
         self.bodies = current_bodies;
-        self.has_inline_consts = current_has_inline_consts;
         self.node_id_to_local_id = current_node_ids;
         self.trait_map = current_trait_map;
         self.current_hir_id_owner = current_owner;
@@ -634,7 +629,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let attrs = std::mem::take(&mut self.attrs);
         let mut bodies = std::mem::take(&mut self.bodies);
         let trait_map = std::mem::take(&mut self.trait_map);
-        let has_inline_consts = std::mem::take(&mut self.has_inline_consts);
 
         #[cfg(debug_assertions)]
         for (id, attrs) in attrs.iter() {
@@ -652,7 +646,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.tcx.hash_owner_nodes(node, &bodies, &attrs);
         let num_nodes = self.item_local_id_counter.as_usize();
         let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
-        let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies, has_inline_consts };
+        let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
         let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
 
         self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
@@ -911,6 +905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let kind = match attr.kind {
             AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
                 item: AttrItem {
+                    unsafety: normal.item.unsafety,
                     path: normal.item.path.clone(),
                     args: self.lower_attr_args(&normal.item.args),
                     tokens: None,
@@ -1321,7 +1316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
                 hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
                     generic_params,
-                    safety: self.lower_safety(f.safety),
+                    safety: self.lower_safety(f.safety, hir::Safety::Safe),
                     abi: self.lower_extern(f.ext),
                     decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
                     param_names: self.lower_fn_params_to_names(&f.decl),
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 3a4c95b250c..9a8689e27c0 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -67,6 +67,9 @@ ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have quali
     .label = in this `extern` block
     .suggestion = remove this qualifier
 
+ast_passes_extern_invalid_safety = items in unadorned `extern` blocks cannot have safety qualifiers
+    .suggestion = add unsafe to this `extern` block
+
 ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
     .label = in this `extern` block
     .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
@@ -174,6 +177,8 @@ ast_passes_match_arm_with_no_body =
     `match` arm with no body
     .suggestion = add a body after the pattern
 
+ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
+
 ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
     .help = consider using the `#[path]` attribute to specify filesystem path
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 435b0b6a956..0fbb288cc96 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -15,7 +15,8 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_feature::Features;
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{
-    DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
+    DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
+    PATTERNS_IN_FNS_WITHOUT_BODY,
 };
 use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
 use rustc_session::Session;
@@ -86,6 +87,9 @@ struct AstValidator<'a> {
     /// or `Foo::Bar<impl Trait>`
     is_impl_trait_banned: bool,
 
+    /// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
+    extern_mod_safety: Option<Safety>,
+
     lint_buffer: &'a mut LintBuffer,
 }
 
@@ -116,6 +120,12 @@ impl<'a> AstValidator<'a> {
         self.outer_trait_or_trait_impl = old;
     }
 
+    fn with_in_extern_mod(&mut self, extern_mod_safety: Safety, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
+        f(self);
+        self.extern_mod_safety = old;
+    }
+
     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.is_impl_trait_banned, true);
         f(self);
@@ -429,6 +439,18 @@ impl<'a> AstValidator<'a> {
         }
     }
 
+    fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) {
+        if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
+            && (self.extern_mod_safety == Some(Safety::Default)
+                || !self.features.unsafe_extern_blocks)
+        {
+            self.dcx().emit_err(errors::InvalidSafetyOnExtern {
+                item_span,
+                block: self.current_extern_span(),
+            });
+        }
+    }
+
     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
         if let Defaultness::Default(def_span) = defaultness {
             let span = self.session.source_map().guess_head_span(span);
@@ -518,7 +540,7 @@ impl<'a> AstValidator<'a> {
     fn check_foreign_fn_headerless(
         &self,
         // Deconstruct to ensure exhaustiveness
-        FnHeader { safety, coroutine_kind, constness, ext }: FnHeader,
+        FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader,
     ) {
         let report_err = |span| {
             self.dcx().emit_err(errors::FnQualifierInExtern {
@@ -526,10 +548,6 @@ impl<'a> AstValidator<'a> {
                 block: self.current_extern_span(),
             });
         };
-        match safety {
-            Safety::Unsafe(span) => report_err(span),
-            Safety::Default => (),
-        }
         match coroutine_kind {
             Some(knd) => report_err(knd.span()),
             None => (),
@@ -1017,19 +1035,39 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 return; // Avoid visiting again.
             }
             ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
-                let old_item = mem::replace(&mut self.extern_mod, Some(item));
-                self.visibility_not_permitted(
-                    &item.vis,
-                    errors::VisibilityNotPermittedNote::IndividualForeignItems,
-                );
-                if let &Safety::Unsafe(span) = safety {
-                    self.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
-                }
-                if abi.is_none() {
-                    self.maybe_lint_missing_abi(item.span, item.id);
-                }
-                visit::walk_item(self, item);
-                self.extern_mod = old_item;
+                self.with_in_extern_mod(*safety, |this| {
+                    let old_item = mem::replace(&mut this.extern_mod, Some(item));
+                    this.visibility_not_permitted(
+                        &item.vis,
+                        errors::VisibilityNotPermittedNote::IndividualForeignItems,
+                    );
+
+                    if this.features.unsafe_extern_blocks {
+                        if &Safety::Default == safety {
+                            if item.span.at_least_rust_2024() {
+                                this.dcx()
+                                    .emit_err(errors::MissingUnsafeOnExtern { span: item.span });
+                            } else {
+                                this.lint_buffer.buffer_lint(
+                                    MISSING_UNSAFE_ON_EXTERN,
+                                    item.id,
+                                    item.span,
+                                    BuiltinLintDiag::MissingUnsafeOnExtern {
+                                        suggestion: item.span.shrink_to_lo(),
+                                    },
+                                );
+                            }
+                        }
+                    } else if let &Safety::Unsafe(span) = safety {
+                        this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
+                    }
+
+                    if abi.is_none() {
+                        this.maybe_lint_missing_abi(item.span, item.id);
+                    }
+                    visit::walk_item(this, item);
+                    this.extern_mod = old_item;
+                });
                 return; // Avoid visiting again.
             }
             ItemKind::Enum(def, _) => {
@@ -1161,6 +1199,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
             ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+                self.check_foreign_item_safety(fi.span, sig.header.safety);
                 self.check_defaultness(fi.span, *defaultness);
                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
                 self.check_foreign_fn_headerless(sig.header);
@@ -1180,7 +1219,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.check_foreign_ty_genericless(generics, where_clauses);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
-            ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability: _, expr }) => {
+            ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => {
+                self.check_foreign_item_safety(fi.span, *safety);
                 self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
                 self.check_foreign_item_ascii_only(fi.ident);
             }
@@ -1736,6 +1776,7 @@ pub fn check_crate(
         outer_impl_trait: None,
         disallow_tilde_const: Some(DisallowTildeConstContext::Item),
         is_impl_trait_banned: false,
+        extern_mod_safety: None,
         lint_buffer: lints,
     };
     visit::walk_crate(&mut validator, krate);
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index c07fbe5b016..260c182bd9e 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -217,6 +217,15 @@ pub enum ExternBlockSuggestion {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_extern_invalid_safety)]
+pub struct InvalidSafetyOnExtern {
+    #[primary_span]
+    pub item_span: Span,
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub block: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_bound_in_context)]
 pub struct BoundInContext<'a> {
     #[primary_span]
@@ -486,6 +495,13 @@ pub struct UnsafeItem {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_missing_unsafe_on_extern)]
+pub struct MissingUnsafeOnExtern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_fieldless_union)]
 pub struct FieldlessUnion {
     #[primary_span]
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index a9dca9b6a29..764d942836c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -561,6 +561,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(mut_ref, "mutable by-reference bindings are experimental");
     gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
     gate_all!(global_registration, "global registration is experimental");
+    gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
 
     if !visitor.features.never_patterns {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 4c29ca0ca46..f32b63a39f0 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -16,7 +16,7 @@ use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, To
 use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{Comment, CommentStyle};
-use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
+use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind, Safety};
 use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
 use rustc_ast::{GenericArg, GenericBound, SelfKind};
 use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@@ -249,6 +249,7 @@ pub fn print_crate<'a>(
         let fake_attr = attr::mk_attr_nested_word(
             g,
             ast::AttrStyle::Inner,
+            Safety::Default,
             sym::feature,
             sym::prelude_import,
             DUMMY_SP,
@@ -259,7 +260,13 @@ pub fn print_crate<'a>(
         // root, so this is not needed, and actually breaks things.
         if edition.is_rust_2015() {
             // `#![no_std]`
-            let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
+            let fake_attr = attr::mk_attr_word(
+                g,
+                ast::AttrStyle::Inner,
+                Safety::Default,
+                sym::no_std,
+                DUMMY_SP,
+            );
             s.print_attribute(&fake_attr);
         }
     }
@@ -1973,6 +1980,7 @@ impl<'a> State<'a> {
     fn print_safety(&mut self, s: ast::Safety) {
         match s {
             ast::Safety::Default => {}
+            ast::Safety::Safe(_) => self.word_nbsp("safe"),
             ast::Safety::Unsafe(_) => self.word_nbsp("unsafe"),
         }
     }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 993ccc5b956..1e117c46b6e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -380,9 +380,8 @@ impl<'a> State<'a> {
             ast::ExprKind::Array(exprs) => {
                 self.print_expr_vec(exprs);
             }
-            ast::ExprKind::ConstBlock(expr) => {
-                self.word_space("const");
-                self.print_expr(expr, FixupContext::default());
+            ast::ExprKind::ConstBlock(anon_const) => {
+                self.print_expr_anon_const(anon_const, attrs);
             }
             ast::ExprKind::Repeat(element, count) => {
                 self.print_expr_repeat(element, count);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 59d9b0c1a8e..474741fb067 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -31,7 +31,13 @@ impl<'a> State<'a> {
             ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
                 self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
             }
-            ast::ForeignItemKind::Static(box ast::StaticForeignItem { ty, mutability, expr }) => {
+            ast::ForeignItemKind::Static(box ast::StaticForeignItem {
+                ty,
+                mutability,
+                expr,
+                safety,
+            }) => {
+                self.print_safety(*safety);
                 self.print_item_const(
                     ident,
                     Some(*mutability),
@@ -165,7 +171,8 @@ impl<'a> State<'a> {
                 self.print_use_tree(tree);
                 self.word(";");
             }
-            ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
+            ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => {
+                self.print_safety(*safety);
                 self.print_item_const(
                     item.ident,
                     Some(*mutbl),
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index 48af4e6f600..e6cfb4887c9 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -9,7 +9,6 @@ icu_list = "1.2"
 icu_locid = "1.2"
 icu_locid_transform = "1.3.2"
 icu_provider = "1.2"
-icu_provider_adapters = "1.2"
 zerovec = "0.10.0"
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index ff11e4db121..97408fa20d7 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
+use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
 use rustc_span::Span;
 use std::fmt;
 use std::ops::Index;
@@ -97,7 +97,7 @@ pub struct OutlivesConstraint<'tcx> {
     pub category: ConstraintCategory<'tcx>,
 
     /// Variance diagnostic information
-    pub variance_info: VarianceDiagInfo<'tcx>,
+    pub variance_info: VarianceDiagInfo<TyCtxt<'tcx>>,
 
     /// If this constraint is promoted from closure requirements.
     pub from_closure: bool,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index cde7ac94e35..821a9036654 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1347,7 +1347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             return;
         };
         // Try to find predicates on *generic params* that would allow copying `ty`
-        let ocx = ObligationCtxt::new(self.infcx);
+        let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
         let cause = ObligationCause::misc(span, self.mir_def_id());
 
         ocx.register_bound(cause, self.param_env, ty, def_id);
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 88172c62a3b..1eb67ea367c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -11,7 +11,7 @@ use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::CoroutineKind;
 use rustc_index::IndexSlice;
 use rustc_infer::infer::BoundRegionConversionTime;
-use rustc_infer::traits::{FulfillmentErrorCode, SelectionError};
+use rustc_infer::traits::SelectionError;
 use rustc_middle::bug;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
@@ -29,7 +29,9 @@ use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
+use rustc_trait_selection::traits::{
+    type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
+};
 
 use crate::fluent_generated as fluent;
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 78798545c26..df1a1411cf5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -6,7 +6,6 @@ use hir::{ExprKind, Param};
 use rustc_errors::{Applicability, Diag};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, BindingMode, ByRef, Node};
-use rustc_infer::traits;
 use rustc_middle::bug;
 use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast};
@@ -18,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{sym, BytePos, DesugaringKind, Span};
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
 
 use crate::diagnostics::BorrowedContentSource;
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 49f50babdcb..5d7ce548469 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -125,8 +125,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         placeholder_indices,
         placeholder_index_to_region: _,
         liveness_constraints,
-        outlives_constraints,
-        member_constraints,
+        mut outlives_constraints,
+        mut member_constraints,
         universe_causes,
         type_tests,
     } = constraints;
@@ -144,6 +144,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
         &universal_region_relations,
     );
 
+    if let Some(guar) = universal_regions.tainted_by_errors() {
+        // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
+        // outlives bounds that we may end up checking.
+        outlives_constraints = Default::default();
+        member_constraints = Default::default();
+
+        // Also taint the entire scope.
+        infcx.set_tainted_by_errors(guar);
+    }
+
     let mut regioncx = RegionInferenceContext::new(
         infcx,
         var_origins,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index b57cf9066cf..0e3140ca98b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -2304,5 +2304,5 @@ pub struct BlameConstraint<'tcx> {
     pub category: ConstraintCategory<'tcx>,
     pub from_closure: bool,
     pub cause: ObligationCause<'tcx>,
-    pub variance_info: ty::VarianceDiagInfo<'tcx>,
+    pub variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index f601a9d7073..06adb686ed4 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -340,7 +340,7 @@ fn check_opaque_type_well_formed<'tcx>(
         .with_next_trait_solver(next_trait_solver)
         .with_opaque_type_inference(parent_def_id)
         .build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     let identity_args = GenericArgs::identity_for_item(tcx, def_id);
 
     // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index b23ad2e1584..0cb4b15b127 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -10,9 +10,9 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_span::Span;
-use rustc_trait_selection::solve::deeply_normalize;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
+use rustc_trait_selection::traits::ScrubbedTraitError;
 
 use crate::{
     constraints::OutlivesConstraint,
@@ -282,11 +282,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let result = CustomTypeOp::new(
             |ocx| {
-                deeply_normalize(
-                    ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
+                ocx.deeply_normalize(
+                    &ObligationCause::dummy_with_span(self.span),
+                    self.param_env,
                     ty,
                 )
-                .map_err(|_| NoSolution)
+                .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
             },
             "normalize type outlives obligation",
         )
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 291d2782c32..fcfb297d50a 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -346,7 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         } else {
             let tcx = self.tcx();
             let maybe_uneval = match constant.const_ {
-                Const::Ty(ct) => match ct.kind() {
+                Const::Ty(_, ct) => match ct.kind() {
                     ty::ConstKind::Unevaluated(_) => {
                         bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
                     }
@@ -1856,7 +1856,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         if let Operand::Constant(constant) = op {
             let maybe_uneval = match constant.const_ {
-                Const::Val(..) | Const::Ty(_) => None,
+                Const::Val(..) | Const::Ty(_, _) => None,
                 Const::Unevaluated(uv, _) => Some(uv),
             };
 
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index cbd8a4125cd..2c34fc583c8 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,14 +1,14 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
+use rustc_infer::infer::relate::{ObligationEmittingRelation, StructurallyRelateAliases};
+use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
 use rustc_infer::infer::NllRegionVariableOrigin;
-use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
 use rustc_infer::traits::{Obligation, PredicateObligations};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::span_bug;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
@@ -82,7 +82,7 @@ pub struct NllTypeRelating<'me, 'bccx, 'tcx> {
     /// - Bivariant means that it doesn't matter.
     ambient_variance: ty::Variance,
 
-    ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
+    ambient_variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
 }
 
 impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
@@ -193,7 +193,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
                 types: &mut |_bound_ty: ty::BoundTy| {
                     unreachable!("we only replace regions in nll_relate, not types")
                 },
-                consts: &mut |_bound_var: ty::BoundVar, _ty| {
+                consts: &mut |_bound_var: ty::BoundVar| {
                     unreachable!("we only replace regions in nll_relate, not consts")
                 },
             };
@@ -231,7 +231,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
             types: &mut |_bound_ty: ty::BoundTy| {
                 unreachable!("we only replace regions in nll_relate, not types")
             },
-            consts: &mut |_bound_var: ty::BoundVar, _ty| {
+            consts: &mut |_bound_var: ty::BoundVar| {
                 unreachable!("we only replace regions in nll_relate, not consts")
             },
         };
@@ -296,7 +296,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
         &mut self,
         sup: ty::Region<'tcx>,
         sub: ty::Region<'tcx>,
-        info: ty::VarianceDiagInfo<'tcx>,
+        info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
     ) {
         let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
         let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
@@ -314,7 +314,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
     }
 }
 
-impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
+impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.type_checker.infcx.tcx
     }
@@ -324,10 +324,10 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
     }
 
     #[instrument(skip(self, info), level = "trace", ret)]
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        info: ty::VarianceDiagInfo<'tcx>,
+        info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -445,7 +445,7 @@ impl<'bccx, 'tcx> TypeRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         // We want that
         //
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index f8123535e2d..9f5fb59e46c 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -29,7 +29,8 @@ use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, T
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{kw, sym};
-use rustc_span::Symbol;
+use rustc_span::{ErrorGuaranteed, Symbol};
+use std::cell::Cell;
 use std::iter;
 
 use crate::renumber::RegionCtxt;
@@ -186,6 +187,10 @@ struct UniversalRegionIndices<'tcx> {
 
     /// The vid assigned to `'static`. Used only for diagnostics.
     pub fr_static: RegionVid,
+
+    /// Whether we've encountered an error region. If we have, cancel all
+    /// outlives errors, as they are likely bogus.
+    pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
 }
 
 #[derive(Debug, PartialEq)]
@@ -408,6 +413,10 @@ impl<'tcx> UniversalRegions<'tcx> {
             }
         }
     }
+
+    pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
+        self.indices.tainted_by_errors.get()
+    }
 }
 
 struct UniversalRegionsBuilder<'cx, 'tcx> {
@@ -663,7 +672,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
         let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var()));
 
-        UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static }
+        UniversalRegionIndices {
+            indices: global_mapping.chain(arg_mapping).collect(),
+            fr_static,
+            tainted_by_errors: Cell::new(None),
+        }
     }
 
     fn compute_inputs_and_output(
@@ -868,7 +881,8 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
         if let ty::ReVar(..) = *r {
             r.as_var()
-        } else if r.is_error() {
+        } else if let ty::ReError(guar) = *r {
+            self.tainted_by_errors.set(Some(guar));
             // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
             // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
             // errors are being emitted and 2) it leaves the happy path unaffected.
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index a3d6a1c7360..2d1269e1b6a 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -110,6 +110,9 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
 builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
     .suggestion = remove the value
 
+builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
+    .suggestion = remove the `unsafe(...)`
+
 builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
     .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
     .custom = use `std::env::var({$var_expr})` to read the variable at run time
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 78144226114..a98cb6f0f76 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -57,7 +57,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
     /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to:
     ///
     /// ```rust
-    /// #![feature(generic_assert_internals)]
     /// let elem = 1;
     /// {
     ///   #[allow(unused_imports)]
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 5f63a8ae0a8..03aff6f9633 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -196,7 +196,7 @@ impl CfgEval<'_, '_> {
         // Re-parse the tokens, setting the `capture_cfg` flag to save extra information
         // to the captured `AttrTokenStream` (specifically, we capture
         // `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
-        let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.psess, orig_tokens, None);
+        let mut parser = Parser::new(&self.cfg.sess.psess, orig_tokens, None);
         parser.capture_cfg = true;
         match parse_annotatable_with(&mut parser) {
             Ok(a) => annotatable = a,
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index ada82e45712..16184ec7511 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -4,19 +4,20 @@ use crate::errors;
 use rustc_ast::attr::mk_attr;
 use rustc_ast::token;
 use rustc_ast::{self as ast, AttrItem, AttrStyle};
+use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use rustc_span::FileName;
 
 pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
     for raw_attr in attrs {
-        let mut parser = rustc_parse::new_parser_from_source_str(
+        let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
             psess,
             FileName::cli_crate_attr_source_code(raw_attr),
             raw_attr.clone(),
-        );
+        ));
 
         let start_span = parser.token.span;
-        let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
+        let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
             Ok(ai) => ai,
             Err(err) => {
                 err.emit();
@@ -32,6 +33,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
         krate.attrs.push(mk_attr(
             &psess.attr_id_generator,
             AttrStyle::Inner,
+            unsafety,
             path,
             args,
             start_span.to(end_span),
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index d14858e5c1d..b5cbfdf0ec6 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -2,7 +2,7 @@ use crate::cfg_eval::cfg_eval;
 use crate::errors;
 
 use rustc_ast as ast;
-use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, Safety, StmtKind};
 use rustc_expand::base::{
     Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
 };
@@ -60,6 +60,7 @@ impl MultiItemModifier for Expander {
                                 // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
                                 // paths.
                                 report_path_args(sess, meta);
+                                report_unsafe_args(sess, meta);
                                 meta.path.clone()
                             })
                             .map(|path| DeriveResolution {
@@ -159,3 +160,13 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
         }
     }
 }
+
+fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
+    match meta.unsafety {
+        Safety::Unsafe(span) => {
+            sess.dcx().emit_err(errors::DeriveUnsafePath { span });
+        }
+        Safety::Default => {}
+        Safety::Safe(_) => unreachable!(),
+    }
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 217fa5ff9f1..ba289f9552e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -412,6 +412,15 @@ fn find_type_parameters(
 
     impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
+            let stack_len = self.bound_generic_params_stack.len();
+            if let ast::TyKind::BareFn(bare_fn) = &ty.kind
+                && !bare_fn.generic_params.is_empty()
+            {
+                // Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so
+                // that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622
+                self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned());
+            }
+
             if let ast::TyKind::Path(_, path) = &ty.kind
                 && let Some(segment) = path.segments.first()
                 && self.ty_param_names.contains(&segment.ident.name)
@@ -422,7 +431,8 @@ fn find_type_parameters(
                 });
             }
 
-            visit::walk_ty(self, ty)
+            visit::walk_ty(self, ty);
+            self.bound_generic_params_stack.truncate(stack_len);
         }
 
         // Place bound generic params on a stack, to extract them when a type is encountered.
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d157703723b..b14eb2b5ee6 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -296,6 +296,13 @@ pub(crate) struct DerivePathArgsValue {
 }
 
 #[derive(Diagnostic)]
+#[diag(builtin_macros_derive_unsafe_path)]
+pub(crate) struct DeriveUnsafePath {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(builtin_macros_no_default_variant)]
 #[help]
 pub(crate) struct NoDefaultVariant {
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 29e991525a9..dc1d82df0c3 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -12,8 +12,8 @@ use rustc_expand::base::{
 };
 use rustc_expand::module::DirOwnership;
 use rustc_lint_defs::BuiltinLintDiag;
-use rustc_parse::new_parser_from_file;
 use rustc_parse::parser::{ForceCollect, Parser};
+use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
@@ -126,7 +126,7 @@ pub(crate) fn expand_include<'cx>(
             return ExpandResult::Ready(DummyResult::any(sp, guar));
         }
     };
-    let p = new_parser_from_file(cx.psess(), &file, Some(sp));
+    let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp)));
 
     // If in the included file we have e.g., `mod bar;`,
     // then the path of `bar.rs` should be relative to the directory of `file`.
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 38ac2f15fe7..ba4e5cfd130 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -203,6 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
                     let allow_dead_code = attr::mk_attr_nested_word(
                         &self.sess.psess.attr_id_generator,
                         ast::AttrStyle::Outer,
+                        ast::Safety::Default,
                         sym::allow,
                         sym::dead_code,
                         self.def_site,
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 963e5de91ce..6d26ca0b899 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -832,9 +832,10 @@ fn codegen_stmt<'tcx>(
                     let val = match null_op {
                         NullOp::SizeOf => layout.size.bytes(),
                         NullOp::AlignOf => layout.align.abi.bytes(),
-                        NullOp::OffsetOf(fields) => {
-                            layout.offset_of_subfield(fx, fields.iter()).bytes()
-                        }
+                        NullOp::OffsetOf(fields) => fx
+                            .tcx
+                            .offset_of_subfield(ParamEnv::reveal_all(), layout, fields.iter())
+                            .bytes(),
                         NullOp::UbChecks => {
                             let val = fx.tcx.sess.ub_checks();
                             let val = CValue::by_val(
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index ba98f2e772c..a53598018f4 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -110,7 +110,7 @@ pub(crate) fn codegen_const_value<'tcx>(
                 if fx.clif_type(layout.ty).is_some() {
                     return CValue::const_val(fx, layout, int);
                 } else {
-                    let raw_val = int.size().truncate(int.assert_bits(int.size()));
+                    let raw_val = int.size().truncate(int.to_bits(int.size()));
                     let val = match int.size().bytes() {
                         1 => fx.bcx.ins().iconst(types::I8, raw_val as i64),
                         2 => fx.bcx.ins().iconst(types::I16, raw_val as i64),
@@ -501,12 +501,12 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                                             Ordering::Equal => scalar_int,
                                             Ordering::Less => match ty.kind() {
                                                 ty::Uint(_) => ScalarInt::try_from_uint(
-                                                    scalar_int.assert_uint(scalar_int.size()),
+                                                    scalar_int.to_uint(scalar_int.size()),
                                                     fx.layout_of(*ty).size,
                                                 )
                                                 .unwrap(),
                                                 ty::Int(_) => ScalarInt::try_from_int(
-                                                    scalar_int.assert_int(scalar_int.size()),
+                                                    scalar_int.to_int(scalar_int.size()),
                                                     fx.layout_of(*ty).size,
                                                 )
                                                 .unwrap(),
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 394c810176a..dcafac21bc7 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -288,6 +288,29 @@ fn produce_final_output_artifacts(
         }
     }
 
+    if sess.opts.json_artifact_notifications {
+        if codegen_results.modules.len() == 1 {
+            codegen_results.modules[0].for_each_output(|_path, ty| {
+                if sess.opts.output_types.contains_key(&ty) {
+                    let descr = ty.shorthand();
+                    // for single cgu file is renamed to drop cgu specific suffix
+                    // so we regenerate it the same way
+                    let path = crate_output.path(ty);
+                    sess.dcx().emit_artifact_notification(path.as_path(), descr);
+                }
+            });
+        } else {
+            for module in &codegen_results.modules {
+                module.for_each_output(|path, ty| {
+                    if sess.opts.output_types.contains_key(&ty) {
+                        let descr = ty.shorthand();
+                        sess.dcx().emit_artifact_notification(&path, descr);
+                    }
+                });
+            }
+        }
+    }
+
     // We leave the following files around by default:
     //  - #crate#.o
     //  - #crate#.crate.metadata.o
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 27b55ecc72e..d454f3c1de7 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -902,7 +902,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                         .span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant");
                 };
 
-            let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
+            let imm8 = imm8.to_u8();
 
             codegen_inline_asm_inner(
                 fx,
@@ -955,7 +955,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                         .span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant");
                 };
 
-            let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
+            let imm8 = imm8.to_u8();
 
             codegen_inline_asm_inner(
                 fx,
@@ -1003,7 +1003,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                     );
                 };
 
-            let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
+            let imm8 = imm8.to_u8();
 
             codegen_inline_asm_inner(
                 fx,
@@ -1040,7 +1040,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                     );
                 };
 
-            let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8));
+            let imm8 = imm8.to_u8();
 
             codegen_inline_asm_inner(
                 fx,
@@ -1195,7 +1195,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
                     .span_fatal(span, "Func argument for `_mm_sha1rnds4_epu32` is not a constant");
             };
 
-            let func = func.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", func));
+            let func = func.to_u8();
 
             codegen_inline_asm_inner(
                 fx,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index b17f191ce26..ca910dccb0d 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -133,6 +133,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 .expect_const()
                 .eval(fx.tcx, ty::ParamEnv::reveal_all(), span)
                 .unwrap()
+                .1
                 .unwrap_branch();
 
             assert_eq!(x.layout(), y.layout());
@@ -146,8 +147,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let total_len = lane_count * 2;
 
-            let indexes =
-                idx.iter().map(|idx| idx.unwrap_leaf().try_to_u32().unwrap()).collect::<Vec<u32>>();
+            let indexes = idx.iter().map(|idx| idx.unwrap_leaf().to_u32()).collect::<Vec<u32>>();
 
             for &idx in &indexes {
                 assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
@@ -281,9 +281,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 fx.tcx.dcx().span_fatal(span, "Index argument for `simd_insert` is not a constant");
             };
 
-            let idx: u32 = idx_const
-                .try_to_u32()
-                .unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const));
+            let idx: u32 = idx_const.to_u32();
             let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
             if u64::from(idx) >= lane_count {
                 fx.tcx.dcx().span_fatal(
@@ -329,9 +327,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 return;
             };
 
-            let idx = idx_const
-                .try_to_u32()
-                .unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const));
+            let idx = idx_const.to_u32();
             let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
             if u64::from(idx) >= lane_count {
                 fx.tcx.dcx().span_fatal(
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 512a96450a4..1aa28daeafc 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -327,7 +327,7 @@ impl<'tcx> CValue<'tcx> {
 
         let val = match layout.ty.kind() {
             ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
-                let const_val = const_val.assert_bits(layout.size);
+                let const_val = const_val.to_bits(layout.size);
                 let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64);
                 let msb = fx.bcx.ins().iconst(types::I64, (const_val >> 64) as u64 as i64);
                 fx.bcx.ins().iconcat(lsb, msb)
@@ -339,7 +339,7 @@ impl<'tcx> CValue<'tcx> {
             | ty::Ref(..)
             | ty::RawPtr(..)
             | ty::FnPtr(..) => {
-                let raw_val = const_val.size().truncate(const_val.assert_bits(layout.size));
+                let raw_val = const_val.size().truncate(const_val.to_bits(layout.size));
                 fx.bcx.ins().iconst(clif_ty, raw_val as i64)
             }
             ty::Float(FloatTy::F32) => {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 78d943192db..548c23cc794 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -166,7 +166,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
         match cv {
             Scalar::Int(int) => {
-                let data = int.assert_bits(layout.size(self));
+                let data = int.to_bits(layout.size(self));
 
                 // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
                 // the paths for floating-point values.
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index fa7e7e5377a..a354f3d3536 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -128,11 +128,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
         is_direct_dependency: bool,
     ) -> PathBuf {
         let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
-        let output_path = {
-            let mut output_path: PathBuf = tmpdir.to_path_buf();
-            output_path.push(format!("{lib_name}{name_suffix}"));
-            output_path.with_extension("lib")
-        };
+        let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib"));
 
         let target = &sess.target;
         let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target);
@@ -157,8 +153,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
             // that loaded but crashed with an AV upon calling one of the imported
             // functions. Therefore, use binutils to create the import library instead,
             // by writing a .DEF file to the temp dir and calling binutils's dlltool.
-            let def_file_path =
-                tmpdir.join(format!("{lib_name}{name_suffix}")).with_extension("def");
+            let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def"));
 
             let def_file_content = format!(
                 "EXPORTS\n{}",
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ab8036a1410..4ffc92eb633 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -244,7 +244,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
         match cv {
             Scalar::Int(int) => {
-                let data = int.assert_bits(layout.size(self));
+                let data = int.to_bits(layout.size(self));
                 let llval = self.const_uint_big(self.type_ix(bitsize), data);
                 if matches!(layout.primitive(), Pointer(_)) {
                     unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 39bbf87bea7..b5b0086f740 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1109,10 +1109,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
-    // Vectors must be immediates (non-power-of-2 #[repr(packed)] are not)
-    for (ty, arg) in arg_tys.iter().zip(args) {
-        if ty.is_simd() && !matches!(arg.val, OperandValue::Immediate(_)) {
-            return_error!(InvalidMonomorphization::SimdArgument { span, name, ty: *ty });
+    // Sanity-check: all vector arguments must be immediates.
+    if cfg!(debug_assertions) {
+        for (ty, arg) in arg_tys.iter().zip(args) {
+            if ty.is_simd() {
+                assert!(matches!(arg.val, OperandValue::Immediate(_)));
+            }
         }
     }
 
@@ -1201,6 +1203,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             .expect_const()
             .eval(tcx, ty::ParamEnv::reveal_all(), span)
             .unwrap()
+            .1
             .unwrap_branch();
         let n = idx.len() as u64;
 
@@ -1220,7 +1223,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             .iter()
             .enumerate()
             .map(|(arg_idx, val)| {
-                let idx = val.unwrap_leaf().try_to_i32().unwrap();
+                let idx = val.unwrap_leaf().to_i32();
                 if idx >= i32::try_from(total_len).unwrap() {
                     bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
                         span,
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs
index 3114f1c38ae..f499bbcf853 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs
@@ -85,6 +85,11 @@ fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsStrin
     // Strip filenames
     let lib = lib.parent().unwrap();
     let output = config.out_filename.parent().unwrap();
+
+    // If output or lib is empty, just assume it locates in current path
+    let lib = if lib == Path::new("") { Path::new(".") } else { lib };
+    let output = if output == Path::new("") { Path::new(".") } else { output };
+
     let lib = try_canonicalize(lib).unwrap();
     let output = try_canonicalize(output).unwrap();
     let relative = path_relative_from(&lib, &output)
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
index ac2e54072c4..0de90a1036e 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
@@ -58,6 +58,22 @@ fn test_rpath_relative() {
 }
 
 #[test]
+fn test_rpath_relative_issue_119571() {
+    let config = &mut RPathConfig {
+        libs: &[],
+        out_filename: PathBuf::from("rustc"),
+        has_rpath: true,
+        is_like_osx: false,
+        linker_is_gnu: true,
+    };
+    // Should not panic when out_filename only contains filename.
+    // Issue 119571
+    let _ = get_rpath_relative_to_output(config, Path::new("lib/libstd.so"));
+    // Should not panic when lib only contains filename.
+    let _ = get_rpath_relative_to_output(config, Path::new("libstd.so"));
+}
+
+#[test]
 fn test_xlinker() {
     let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 79d6641a0da..a6df8950b35 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -400,7 +400,7 @@ fn upstream_monomorphizations_provider(
     tcx: TyCtxt<'_>,
     (): (),
 ) -> DefIdMap<UnordMap<GenericArgsRef<'_>, CrateNum>> {
-    let cnums = tcx.used_crates(());
+    let cnums = tcx.crates(());
 
     let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index d57f4ddf8aa..dec87db0fc5 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -717,6 +717,29 @@ fn produce_final_output_artifacts(
         }
     }
 
+    if sess.opts.json_artifact_notifications {
+        if compiled_modules.modules.len() == 1 {
+            compiled_modules.modules[0].for_each_output(|_path, ty| {
+                if sess.opts.output_types.contains_key(&ty) {
+                    let descr = ty.shorthand();
+                    // for single cgu file is renamed to drop cgu specific suffix
+                    // so we regenerate it the same way
+                    let path = crate_output.path(ty);
+                    sess.dcx().emit_artifact_notification(path.as_path(), descr);
+                }
+            });
+        } else {
+            for module in &compiled_modules.modules {
+                module.for_each_output(|path, ty| {
+                    if sess.opts.output_types.contains_key(&ty) {
+                        let descr = ty.shorthand();
+                        sess.dcx().emit_artifact_notification(&path, descr);
+                    }
+                });
+            }
+        }
+    }
+
     // We leave the following files around by default:
     //  - #crate#.o
     //  - #crate#.crate.metadata.o
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f372d3a0522..0b450c43924 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -541,7 +541,7 @@ pub fn collect_debugger_visualizers_transitive(
     tcx.debugger_visualizers(LOCAL_CRATE)
         .iter()
         .chain(
-            tcx.used_crates(())
+            tcx.crates(())
                 .iter()
                 .filter(|&cnum| {
                     let used_crate_source = tcx.used_crate_source(*cnum);
@@ -851,7 +851,7 @@ impl CrateInfo {
         // `compiler_builtins` are always placed last to ensure that they're linked correctly.
         used_crates.extend(compiler_builtins);
 
-        let crates = tcx.used_crates(());
+        let crates = tcx.crates(());
         let n_crates = crates.len();
         let mut info = CrateInfo {
             target_cpu,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 5d7257b15c4..15955170e87 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -324,21 +324,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
                     if tcx.is_foreign_item(did) {
                         codegen_fn_attrs.import_linkage = linkage;
+
+                        if tcx.is_mutable_static(did.into()) {
+                            let mut diag = tcx.dcx().struct_span_err(
+                                attr.span,
+                                "extern mutable statics are not allowed with `#[linkage]`",
+                            );
+                            diag.note(
+                                "marking the extern static mutable would allow changing which symbol \
+                                 the static references rather than make the target of the symbol \
+                                 mutable",
+                            );
+                            diag.emit();
+                        }
                     } else {
                         codegen_fn_attrs.linkage = linkage;
                     }
-                    if tcx.is_mutable_static(did.into()) {
-                        let mut diag = tcx.dcx().struct_span_err(
-                            attr.span,
-                            "mutable statics are not allowed with `#[linkage]`",
-                        );
-                        diag.note(
-                            "making the static mutable would allow changing which symbol the \
-                             static references rather than make the target of the symbol \
-                             mutable",
-                        );
-                        diag.emit();
-                    }
                 }
             }
             sym::link_section => {
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index e4a36b3f591..27b0f127e92 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -163,7 +163,7 @@ pub fn asm_const_to_str<'tcx>(
     let mir::ConstValue::Scalar(scalar) = const_value else {
         span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
     };
-    let value = scalar.assert_bits(ty_and_layout.size);
+    let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size);
     match ty_and_layout.ty.kind() {
         ty::Uint(_) => value.to_string(),
         ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 07473ee476b..c4e5c858240 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -263,7 +263,7 @@ fn push_debuginfo_type_name<'tcx>(
                         let ExistentialProjection { def_id: item_def_id, term, .. } =
                             tcx.instantiate_bound_regions_with_erased(bound);
                         // FIXME(associated_const_equality): allow for consts here
-                        (item_def_id, term.ty().unwrap())
+                        (item_def_id, term.expect_type())
                     })
                     .collect();
 
@@ -693,41 +693,46 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
         ty::ConstKind::Param(param) => {
             write!(output, "{}", param.name)
         }
-        _ => match ct.ty().kind() {
-            ty::Int(ity) => {
-                let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
-                let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
-                write!(output, "{val}")
-            }
-            ty::Uint(_) => {
-                let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
-                write!(output, "{val}")
-            }
-            ty::Bool => {
-                let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
-                write!(output, "{val}")
-            }
-            _ => {
-                // If we cannot evaluate the constant to a known type, we fall back
-                // to emitting a stable hash value of the constant. This isn't very pretty
-                // but we get a deterministic, virtually unique value for the constant.
-                //
-                // Let's only emit 64 bits of the hash value. That should be plenty for
-                // avoiding collisions and will make the emitted type names shorter.
-                let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
-                    let mut hasher = StableHasher::new();
-                    let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
-                    hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
-                    hasher.finish::<Hash64>()
-                });
-
-                if cpp_like_debuginfo(tcx) {
-                    write!(output, "CONST${hash_short:x}")
-                } else {
-                    write!(output, "{{CONST#{hash_short:x}}}")
+        ty::ConstKind::Value(ty, _) => {
+            match ty.kind() {
+                ty::Int(ity) => {
+                    // FIXME: directly extract the bits from a valtree instead of evaluating an
+                    // alreay evaluated `Const` in order to get the bits.
+                    let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
+                    let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
+                    write!(output, "{val}")
+                }
+                ty::Uint(_) => {
+                    let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
+                    write!(output, "{val}")
+                }
+                ty::Bool => {
+                    let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
+                    write!(output, "{val}")
+                }
+                _ => {
+                    // If we cannot evaluate the constant to a known type, we fall back
+                    // to emitting a stable hash value of the constant. This isn't very pretty
+                    // but we get a deterministic, virtually unique value for the constant.
+                    //
+                    // Let's only emit 64 bits of the hash value. That should be plenty for
+                    // avoiding collisions and will make the emitted type names shorter.
+                    let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
+                        let mut hasher = StableHasher::new();
+                        let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
+                        hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
+                        hasher.finish::<Hash64>()
+                    });
+
+                    if cpp_like_debuginfo(tcx) {
+                        write!(output, "CONST${hash_short:x}")
+                    } else {
+                        write!(output, "{{CONST#{hash_short:x}}}")
+                    }
                 }
             }
-        },
+        }
+        _ => bug!("Invalid `Const` during codegen: {:?}", ct),
     }
     .unwrap();
 }
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 1668104d7e2..3b1921d40e6 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -106,6 +106,24 @@ pub struct CompiledModule {
     pub llvm_ir: Option<PathBuf>,  // --emit=llvm-ir, llvm-bc is in bytecode
 }
 
+impl CompiledModule {
+    /// Call `emit` function with every artifact type currently compiled
+    pub fn for_each_output(&self, mut emit: impl FnMut(&Path, OutputType)) {
+        if let Some(path) = self.object.as_deref() {
+            emit(path, OutputType::Object);
+        }
+        if let Some(path) = self.bytecode.as_deref() {
+            emit(path, OutputType::Bitcode);
+        }
+        if let Some(path) = self.llvm_ir.as_deref() {
+            emit(path, OutputType::LlvmAssembly);
+        }
+        if let Some(path) = self.assembly.as_deref() {
+            emit(path, OutputType::Assembly);
+        }
+    }
+}
+
 pub struct CachedModuleCodegen {
     pub name: String,
     pub source: WorkProduct,
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index dba5fbefd8a..822f5c2c44a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -40,10 +40,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
         let uv = match self.monomorphize(constant.const_) {
             mir::Const::Unevaluated(uv, _) => uv.shrink(),
-            mir::Const::Ty(c) => match c.kind() {
+            mir::Const::Ty(_, c) => match c.kind() {
                 // A constant that came from a const generic but was then used as an argument to old-style
                 // simd_shuffle (passing as argument instead of as a generic param).
-                rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
+                rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)),
                 other => span_bug!(constant.span, "{other:#?}"),
             },
             // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index c23867be3a1..ad6b3f1159d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -680,7 +680,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         bx.cx().const_usize(val)
                     }
                     mir::NullOp::OffsetOf(fields) => {
-                        let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes();
+                        let val = bx
+                            .tcx()
+                            .offset_of_subfield(bx.param_env(), layout, fields.iter())
+                            .bytes();
                         bx.cx().const_usize(val)
                     }
                     mir::NullOp::UbChecks => {
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 5fbf5b41109..9e01c59a96f 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // which path expressions are getting called on and which path expressions are only used
                 // as function pointers. This is required for correctness.
                 let infcx = tcx.infer_ctxt().build();
-                let ocx = ObligationCtxt::new(&infcx);
+                let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
                 let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
                 let cause = ObligationCause::new(
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 5949444e599..9fd7219499b 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -357,15 +357,15 @@ where
 
     // Check the qualifs of the value of `const` items.
     let uneval = match constant.const_ {
-        Const::Ty(ct)
+        Const::Ty(_, ct)
             if matches!(
                 ct.kind(),
-                ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
+                ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
             ) =>
         {
             None
         }
-        Const::Ty(c) => {
+        Const::Ty(_, c) => {
             bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
         }
         Const::Unevaluated(uv, _) => Some(uv),
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 3c11d67e748..8c66888d100 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -38,6 +38,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
     match node {
         hir::Node::Ctor(_)
         | hir::Node::AnonConst(_)
+        | hir::Node::ConstBlock(_)
         | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
             hir::Constness::Const
         }
@@ -56,7 +57,6 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
             if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
         }
         hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
-        hir::Node::Expr(e) if let hir::ExprKind::ConstBlock(_) = e.kind => hir::Constness::Const,
         _ => {
             if let Some(fn_kind) = node.fn_kind() {
                 if fn_kind.constness() == hir::Constness::Const {
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 5312f1f946f..66993476bef 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -95,10 +95,10 @@ fn const_to_valtree_inner<'tcx>(
         }
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
             let val = ecx.read_immediate(place)?;
-            let val = val.to_scalar();
+            let val = val.to_scalar_int().unwrap();
             *num_nodes += 1;
 
-            Ok(ty::ValTree::Leaf(val.assert_int()))
+            Ok(ty::ValTree::Leaf(val))
         }
 
         ty::Pat(base, ..) => {
@@ -125,7 +125,7 @@ fn const_to_valtree_inner<'tcx>(
             let val = val.to_scalar();
             // We are in the CTFE machine, so ptr-to-int casts will fail.
             // This can only be `Ok` if `val` already is an integer.
-            let Ok(val) = val.try_to_int() else {
+            let Ok(val) = val.try_to_scalar_int() else {
                 return Err(ValTreeCreationError::NonSupportedType);
             };
             // It's just a ScalarInt!
@@ -411,7 +411,7 @@ fn valtree_into_mplace<'tcx>(
                 ty::Adt(def, _) if def.is_enum() => {
                     // First element of valtree corresponds to variant
                     let scalar_int = branches[0].unwrap_leaf();
-                    let variant_idx = VariantIdx::from_u32(scalar_int.try_to_u32().unwrap());
+                    let variant_idx = VariantIdx::from_u32(scalar_int.to_u32());
                     let variant = def.variant(variant_idx);
                     debug!(?variant);
 
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 67fbf9642bf..0dbee8c1d94 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -123,14 +123,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // (`tag_bits` itself is only used for error messages below.)
                 let tag_bits = tag_val
                     .to_scalar()
-                    .try_to_int()
+                    .try_to_scalar_int()
                     .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
-                    .assert_bits(tag_layout.size);
+                    .to_bits(tag_layout.size);
                 // Cast bits from tag layout to discriminant layout.
                 // After the checks we did above, this cannot fail, as
                 // discriminants are int-like.
                 let discr_val = self.int_to_int_or_float(&tag_val, discr_layout).unwrap();
-                let discr_bits = discr_val.to_scalar().assert_bits(discr_layout.size);
+                let discr_bits = discr_val.to_scalar().to_bits(discr_layout.size)?;
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match *ty.kind() {
                     ty::Adt(adt, _) => {
@@ -152,7 +152,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // discriminant (encoded in niche/tag) and variant index are the same.
                 let variants_start = niche_variants.start().as_u32();
                 let variants_end = niche_variants.end().as_u32();
-                let variant = match tag_val.try_to_int() {
+                let variant = match tag_val.try_to_scalar_int() {
                     Err(dbg_val) => {
                         // So this is a pointer then, and casting to an int failed.
                         // Can only happen during CTFE.
@@ -167,7 +167,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                         untagged_variant
                     }
                     Ok(tag_bits) => {
-                        let tag_bits = tag_bits.assert_bits(tag_layout.size);
+                        let tag_bits = tag_bits.to_bits(tag_layout.size);
                         // We need to use machine arithmetic to get the relative variant idx:
                         // variant_index_relative = tag_val - niche_start_val
                         let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
@@ -175,7 +175,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                         let variant_index_relative_val =
                             self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
                         let variant_index_relative =
-                            variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
+                            variant_index_relative_val.to_scalar().to_bits(tag_val.layout.size)?;
                         // Check if this is in the range that indicates an actual discriminant.
                         if variant_index_relative <= u128::from(variants_end - variants_start) {
                             let variant_index_relative = u32::try_from(variant_index_relative)
@@ -294,8 +294,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     ImmTy::from_uint(variant_index_relative, tag_layout);
                 let tag = self
                     .binary_op(mir::BinOp::Add, &variant_index_relative_val, &niche_start_val)?
-                    .to_scalar()
-                    .assert_int();
+                    .to_scalar_int()?;
                 Ok(Some((tag, tag_field)))
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 8d0b267e1a9..3066e0933d9 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -102,7 +102,7 @@ fn intern_as_new_static<'tcx>(
     let feed = tcx.create_def(
         static_id,
         sym::nested,
-        DefKind::Static { mutability: alloc.0.mutability, nested: true },
+        DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
     );
     tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 18b76443cd9..dac5c10addc 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -519,7 +519,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
         // First, check x % y != 0 (or if that computation overflows).
         let rem = self.binary_op(BinOp::Rem, a, b)?;
-        if rem.to_scalar().assert_bits(a.layout.size) != 0 {
+        if rem.to_scalar().to_bits(a.layout.size)? != 0 {
             throw_ub_custom!(
                 fluent::const_eval_exact_div_has_remainder,
                 a = format!("{a}"),
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 521f28b7123..7eb73e9b52f 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1344,7 +1344,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Test if this value might be null.
     /// If the machine does not support ptr-to-int casts, this is conservative.
     pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {
-        Ok(match scalar.try_to_int() {
+        Ok(match scalar.try_to_scalar_int() {
             Ok(int) => int.is_null(),
             Err(_) => {
                 // Can only happen during CTFE.
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index bbb2c2f3938..0a7e9853763 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -89,6 +89,12 @@ impl<Prov: Provenance> Immediate<Prov> {
 
     #[inline]
     #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
+    pub fn to_scalar_int(self) -> ScalarInt {
+        self.to_scalar().try_to_scalar_int().unwrap()
+    }
+
+    #[inline]
+    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
     pub fn to_scalar_pair(self) -> (Scalar<Prov>, Scalar<Prov>) {
         match self {
             Immediate::ScalarPair(val1, val2) => (val1, val2),
@@ -220,19 +226,11 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     }
 
     #[inline]
-    pub fn try_from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
-        Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
-    }
-    #[inline]
     pub fn from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Self {
         Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
     }
 
     #[inline]
-    pub fn try_from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
-        Some(Self::from_scalar(Scalar::try_from_int(i, layout.size)?, layout))
-    }
-    #[inline]
     pub fn from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Self {
         Self::from_scalar(Scalar::from_int(i, layout.size), layout)
     }
@@ -276,7 +274,8 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
     #[inline]
     pub fn to_const_int(self) -> ConstInt {
         assert!(self.layout.ty.is_integral());
-        let int = self.to_scalar().assert_int();
+        let int = self.imm.to_scalar_int();
+        assert_eq!(int.size(), self.layout.size);
         ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 6d005dfcd86..c821c98073d 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -95,10 +95,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let l = left.to_scalar_int()?;
         let r = right.to_scalar_int()?;
         // Prepare to convert the values to signed or unsigned form.
-        let l_signed = || l.assert_int(left.layout.size);
-        let l_unsigned = || l.assert_uint(left.layout.size);
-        let r_signed = || r.assert_int(right.layout.size);
-        let r_unsigned = || r.assert_uint(right.layout.size);
+        let l_signed = || l.to_int(left.layout.size);
+        let l_unsigned = || l.to_uint(left.layout.size);
+        let r_signed = || r.to_int(right.layout.size);
+        let r_unsigned = || r.to_uint(right.layout.size);
 
         let throw_ub_on_overflow = match bin_op {
             AddUnchecked => Some(sym::unchecked_add),
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 4a86ec3f57a..046ff34e3d0 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -499,13 +499,14 @@ where
         &self,
         mplace: &MPlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> {
-        // Basically we just transmute this place into an array following simd_size_and_type.
-        // (Transmuting is okay since this is an in-memory place. We also double-check the size
-        // stays the same.)
+        // Basically we want to transmute this place into an array following simd_size_and_type.
         let (len, e_ty) = mplace.layout.ty.simd_size_and_type(*self.tcx);
-        let array = Ty::new_array(self.tcx.tcx, e_ty, len);
-        let layout = self.layout_of(array)?;
-        let mplace = mplace.transmute(layout, self)?;
+        // Some SIMD types have padding, so `len` many `e_ty` does not cover the entire place.
+        // Therefore we cannot transmute, and instead we project at offset 0, which side-steps
+        // the size check.
+        let array_layout = self.layout_of(Ty::new_array(self.tcx.tcx, e_ty, len))?;
+        assert!(array_layout.size <= mplace.layout.size);
+        let mplace = mplace.offset(Size::ZERO, array_layout, self)?;
         Ok((mplace, len))
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 0e594914c3a..09e1a59dfa1 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -81,6 +81,8 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
         ecx: &InterpCx<'tcx, M>,
     ) -> InterpResult<'tcx, Self> {
         assert!(layout.is_sized());
+        // We sometimes do pointer arithmetic with this function, disregarding the source type.
+        // So we don't check the sizes here.
         self.offset_with_meta(offset, OffsetMode::Inbounds, MemPlaceMeta::None, layout, ecx)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index d0bb821862a..1baf62baa81 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -253,7 +253,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                         Scalar::from_target_usize(val, self)
                     }
                     mir::NullOp::OffsetOf(fields) => {
-                        let val = layout.offset_of_subfield(self, fields.iter()).bytes();
+                        let val = self
+                            .tcx
+                            .offset_of_subfield(self.param_env, layout, fields.iter())
+                            .bytes();
                         Scalar::from_target_usize(val, self)
                     }
                     mir::NullOp::UbChecks => Scalar::from_bool(self.tcx.sess.ub_checks()),
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 0649bb5617c..cbfe25ca8df 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
     /// Unwrap types that are guaranteed a null-pointer-optimization
     fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
-        // Check if this is `Option` wrapping some type.
-        let inner = match layout.ty.kind() {
-            ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
-                args[0].as_type().unwrap()
-            }
-            _ => {
-                // Not an `Option`.
-                return Ok(layout);
+        // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
+        // another type.
+        let ty::Adt(def, args) = layout.ty.kind() else {
+            // Not an ADT, so definitely no NPO.
+            return Ok(layout);
+        };
+        let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
+            // The wrapped type is the only arg.
+            self.layout_of(args[0].as_type().unwrap())?
+        } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
+            // We want to extract which (if any) of the args is not a 1-ZST.
+            let lhs = self.layout_of(args[0].as_type().unwrap())?;
+            let rhs = self.layout_of(args[1].as_type().unwrap())?;
+            if lhs.is_1zst() {
+                rhs
+            } else if rhs.is_1zst() {
+                lhs
+            } else {
+                return Ok(layout); // no NPO
             }
+        } else {
+            return Ok(layout); // no NPO
         };
-        let inner = self.layout_of(inner)?;
+
         // Check if the inner type is one of the NPO-guaranteed ones.
         // For that we first unpeel transparent *structs* (but not unions).
         let is_npo = |def: AdtDef<'tcx>| {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index e35ce9ef28d..f532f6bbe37 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -653,8 +653,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         let WrappingRange { start, end } = valid_range;
         let max_value = size.unsigned_int_max();
         assert!(end <= max_value);
-        let bits = match scalar.try_to_int() {
-            Ok(int) => int.assert_bits(size),
+        let bits = match scalar.try_to_scalar_int() {
+            Ok(int) => int.to_bits(size),
             Err(_) => {
                 // So this is a pointer then, and casting to an int failed.
                 // Can only happen during CTFE.
@@ -711,7 +711,9 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
     // We're not using `try_global_alloc` since dangling pointers have already been handled.
     match ecx.tcx.global_alloc(alloc_id) {
         GlobalAlloc::Static(did) => {
-            let DefKind::Static { mutability, nested } = ecx.tcx.def_kind(did) else { bug!() };
+            let DefKind::Static { safety: _, mutability, nested } = ecx.tcx.def_kind(did) else {
+                bug!()
+            };
             if nested {
                 assert!(
                     ecx.memory.alloc_map.get(alloc_id).is_none(),
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 2b61e17efa2..6876046a583 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -16,7 +16,6 @@ libc = "0.2"
 measureme = "11"
 rustc-hash = "1.1.0"
 rustc-rayon = { version = "0.5.0", optional = true }
-rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_arena = { path = "../rustc_arena" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
@@ -52,5 +51,5 @@ portable-atomic = "1.5.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"]
+rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 5f7504add8d..91cbffcd707 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -19,7 +19,6 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_hir = { path = "../rustc_hir" }
 rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_hir_typeck = { path = "../rustc_hir_typeck" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 08b97b4953e..93a65290602 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -32,6 +32,7 @@ use rustc_interface::{interface, Queries};
 use rustc_lint::unerased_lint_store;
 use rustc_metadata::creader::MetadataLoader;
 use rustc_metadata::locator;
+use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
 use rustc_session::getopts::{self, Matches};
@@ -814,13 +815,17 @@ fn print_crate_info(
                     match expected_values {
                         ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")),
                         ExpectedValues::Some(values) => {
-                            check_cfgs.extend(values.iter().map(|value| {
-                                if let Some(value) = value {
-                                    format!("{name}=\"{value}\"")
-                                } else {
-                                    name.to_string()
-                                }
-                            }))
+                            if !values.is_empty() {
+                                check_cfgs.extend(values.iter().map(|value| {
+                                    if let Some(value) = value {
+                                        format!("{name}=\"{value}\"")
+                                    } else {
+                                        name.to_string()
+                                    }
+                                }))
+                            } else {
+                                check_cfgs.push(format!("{name}="))
+                            }
                         }
                     }
                 }
@@ -1260,12 +1265,13 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
 }
 
 fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
-    match &sess.io.input {
-        Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.psess),
+    let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
+        Input::File(file) => new_parser_from_file(&sess.psess, file, None),
         Input::Str { name, input } => {
-            rustc_parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.psess)
+            new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
         }
-    }
+    });
+    parser.parse_inner_attributes()
 }
 
 /// Runs a closure and catches unwinds triggered by fatal errors.
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 8acba57b7a6..31de0a747b2 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -3,7 +3,6 @@
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust as pprust_ast;
 use rustc_errors::FatalError;
-use rustc_hir as hir;
 use rustc_hir_pretty as pprust_hir;
 use rustc_middle::bug;
 use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
@@ -70,11 +69,7 @@ struct HirIdentifiedAnn<'tcx> {
 
 impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
     fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
-        pprust_hir::PpAnn::nested(
-            &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>),
-            state,
-            nested,
-        )
+        self.tcx.nested(state, nested)
     }
 
     fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
@@ -152,8 +147,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
         if let pprust_hir::Nested::Body(id) = nested {
             self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
         }
-        let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
-        pprust_hir::PpAnn::nested(pp_ann, state, nested);
+        self.tcx.nested(state, nested);
         self.maybe_typeck_results.set(old_maybe_typeck_results);
     }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md
index e50cc60ea33..b2cdb509c95 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0582.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0582.md
@@ -27,6 +27,40 @@ fn bar<F, G>(t: F, u: G)
 fn main() { }
 ```
 
+This error also includes the use of associated types with lifetime parameters.
+```compile_fail,E0582
+trait Foo {
+    type Assoc<'a>;
+}
+
+struct Bar<X, F>
+where
+    X: Foo,
+    F: for<'a> Fn(X::Assoc<'a>) -> &'a i32
+{
+    x: X,
+    f: F
+}
+```
+The latter scenario encounters this error because `Foo::Assoc<'a>` could be
+implemented by a type that does not use the `'a` parameter, so there is no
+guarentee that `X::Assoc<'a>` actually uses `'a`.
+
+To fix this we can pass a dummy parameter:
+```
+# trait Foo {
+#     type Assoc<'a>;
+# }
+struct Bar<X, F>
+where
+    X: Foo,
+    F: for<'a> Fn(X::Assoc<'a>, /* dummy */ &'a ()) -> &'a i32
+{
+    x: X,
+    f: F
+}
+```
+
 Note: The examples above used to be (erroneously) accepted by the
 compiler, but this was since corrected. See [issue #33685] for more
 details.
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 530b37aadb1..2e150f7bb27 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -124,6 +124,9 @@ expand_not_a_meta_item =
 expand_only_one_word =
     must only be one word
 
+expand_proc_macro_back_compat = using an old version of `{$crate_name}`
+    .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
+
 expand_proc_macro_derive_panicked =
     proc-macro derive panicked
     .help = message: {$message}
@@ -154,7 +157,7 @@ expand_unsupported_key_value =
     key-value macro attributes are not supported
 
 expand_var_still_repeating =
-    variable '{$ident}' is still repeating at this depth
+    variable `{$ident}` is still repeating at this depth
 
 expand_wrong_fragment_kind =
     non-{$kind} macro in {$kind} position: {$name}
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 91af8758e51..b3f6a35f3a4 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -14,9 +14,8 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult};
 use rustc_feature::Features;
-use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
-use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools};
-use rustc_parse::{parser, MACRO_ARGUMENTS};
+use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
+use rustc_parse::{parser::Parser, MACRO_ARGUMENTS};
 use rustc_session::config::CollapseMacroDebuginfo;
 use rustc_session::{parse::ParseSess, Limit, Session};
 use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
@@ -1150,8 +1149,8 @@ impl<'a> ExtCtxt<'a> {
     pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
         expand::MacroExpander::new(self, true)
     }
-    pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> {
-        rustc_parse::stream_to_parser(&self.sess.psess, stream, MACRO_ARGUMENTS)
+    pub fn new_parser_from_tts(&self, stream: TokenStream) -> Parser<'a> {
+        Parser::new(&self.sess.psess, stream, MACRO_ARGUMENTS)
     }
     pub fn source_map(&self) -> &'a SourceMap {
         self.sess.psess.source_map()
@@ -1330,80 +1329,63 @@ pub fn parse_macro_name_and_helper_attrs(
     Some((trait_ident.name, proc_attrs))
 }
 
-/// This nonterminal looks like some specific enums from
-/// `proc-macro-hack` and `procedural-masquerade` crates.
-/// We need to maintain some special pretty-printing behavior for them due to incorrect
-/// asserts in old versions of those crates and their wide use in the ecosystem.
-/// See issue #73345 for more details.
+/// If this item looks like a specific enums from `rental`, emit a fatal error.
+/// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
-fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
+fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
     let name = item.ident.name;
-    if name == sym::ProceduralMasqueradeDummyType {
-        if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
-            if let [variant] = &*enum_def.variants {
-                if variant.ident.name == sym::Input {
-                    let filename = sess.source_map().span_to_filename(item.ident.span);
-                    if let FileName::Real(real) = filename {
-                        if let Some(c) = real
-                            .local_path()
-                            .unwrap_or(Path::new(""))
-                            .components()
-                            .flat_map(|c| c.as_os_str().to_str())
-                            .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
-                        {
-                            let crate_matches = if c.starts_with("allsorts-rental") {
-                                true
-                            } else {
-                                let mut version = c.trim_start_matches("rental-").split('.');
-                                version.next() == Some("0")
-                                    && version.next() == Some("5")
-                                    && version
-                                        .next()
-                                        .and_then(|c| c.parse::<u32>().ok())
-                                        .is_some_and(|v| v < 6)
-                            };
-
-                            if crate_matches {
-                                sess.psess.buffer_lint(
-                                    PROC_MACRO_BACK_COMPAT,
-                                    item.ident.span,
-                                    ast::CRATE_NODE_ID,
-                                    BuiltinLintDiag::ProcMacroBackCompat {
-                                        crate_name: "rental".to_string(),
-                                        fixed_version: "0.5.6".to_string(),
-                                    },
-                                );
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
+    if name == sym::ProceduralMasqueradeDummyType
+        && let ast::ItemKind::Enum(enum_def, _) = &item.kind
+        && let [variant] = &*enum_def.variants
+        && variant.ident.name == sym::Input
+        && let FileName::Real(real) = sess.source_map().span_to_filename(item.ident.span)
+        && let Some(c) = real
+            .local_path()
+            .unwrap_or(Path::new(""))
+            .components()
+            .flat_map(|c| c.as_os_str().to_str())
+            .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
+    {
+        let crate_matches = if c.starts_with("allsorts-rental") {
+            true
+        } else {
+            let mut version = c.trim_start_matches("rental-").split('.');
+            version.next() == Some("0")
+                && version.next() == Some("5")
+                && version.next().and_then(|c| c.parse::<u32>().ok()).is_some_and(|v| v < 6)
+        };
+
+        if crate_matches {
+            // FIXME: make this translatable
+            #[allow(rustc::untranslatable_diagnostic)]
+            sess.psess.dcx.emit_fatal(errors::ProcMacroBackCompat {
+                crate_name: "rental".to_string(),
+                fixed_version: "0.5.6".to_string(),
+            });
         }
     }
-    false
 }
 
-pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool {
+pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) {
     let item = match ann {
         Annotatable::Item(item) => item,
         Annotatable::Stmt(stmt) => match &stmt.kind {
             ast::StmtKind::Item(item) => item,
-            _ => return false,
+            _ => return,
         },
-        _ => return false,
+        _ => return,
     };
     pretty_printing_compatibility_hack(item, sess)
 }
 
-pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool {
+pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) {
     let item = match nt {
         Nonterminal::NtItem(item) => item,
         Nonterminal::NtStmt(stmt) => match &stmt.kind {
             ast::StmtKind::Item(item) => item,
-            _ => return false,
+            _ => return,
         },
-        _ => return false,
+        _ => return,
     };
     pretty_printing_compatibility_hack(item, sess)
 }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 1b6e191c2eb..37dfd830512 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -631,7 +631,10 @@ impl<'a> ExtCtxt<'a> {
             span,
             name,
             AttrVec::new(),
-            ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()),
+            ast::ItemKind::Static(
+                ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) }
+                    .into(),
+            ),
         )
     }
 
@@ -663,7 +666,7 @@ impl<'a> ExtCtxt<'a> {
     // Builds `#[name]`.
     pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
         let g = &self.sess.psess.attr_id_generator;
-        attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
+        attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span)
     }
 
     // Builds `#[name = val]`.
@@ -671,12 +674,26 @@ impl<'a> ExtCtxt<'a> {
     // Note: `span` is used for both the identifier and the value.
     pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
         let g = &self.sess.psess.attr_id_generator;
-        attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
+        attr::mk_attr_name_value_str(
+            g,
+            ast::AttrStyle::Outer,
+            ast::Safety::Default,
+            name,
+            val,
+            span,
+        )
     }
 
     // Builds `#[outer(inner)]`.
     pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
         let g = &self.sess.psess.attr_id_generator;
-        attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
+        attr::mk_attr_nested_word(
+            g,
+            ast::AttrStyle::Outer,
+            ast::Safety::Default,
+            outer,
+            inner,
+            span,
+        )
     }
 }
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index a5fc9e9d89c..3f8b4661e5f 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -440,3 +440,13 @@ pub(crate) struct EmptyDelegationList {
     #[primary_span]
     pub span: Span,
 }
+
+// This used to be the `proc_macro_back_compat` lint (#83125). It was later
+// turned into a hard error.
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_back_compat)]
+#[note]
+pub struct ProcMacroBackCompat {
+    pub crate_name: String,
+    pub fixed_version: String,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index d8f0f221189..c28a09eb57c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -778,7 +778,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
-                    let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
+                    // The `MetaItem` representing the trait to derive can't
+                    // have an unsafe around it (as of now).
+                    let meta = ast::MetaItem {
+                        unsafety: ast::Safety::Default,
+                        kind: MetaItemKind::Word,
+                        span,
+                        path,
+                    };
                     let items = match expander.expand(self.cx, span, &meta, item, is_const) {
                         ExpandResult::Ready(items) => items,
                         ExpandResult::Retry(item) => {
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index e1f50876b05..25e961d6009 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -30,11 +30,11 @@ impl MutVisitor for Marker {
         // it's some advanced case with macro-generated macros. So if we cache the marked version
         // of that context once, we'll typically have a 100% cache hit rate after that.
         let Marker(expn_id, transparency, ref mut cache) = *self;
-        let data = span.data();
-        let marked_ctxt = *cache
-            .entry(data.ctxt)
-            .or_insert_with(|| data.ctxt.apply_mark(expn_id.to_expn_id(), transparency));
-        *span = data.with_ctxt(marked_ctxt);
+        span.update_ctxt(|ctxt| {
+            *cache
+                .entry(ctxt)
+                .or_insert_with(|| ctxt.apply_mark(expn_id.to_expn_id(), transparency))
+        });
     }
 }
 
@@ -267,7 +267,6 @@ pub(super) fn transcribe<'a>(
                 // some of the unnecessary whitespace.
                 let ident = MacroRulesNormalizedIdent::new(original_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
-                    // njn: explain the use of alone here
                     let tt = match cur_matched {
                         MatchedSingle(ParseNtResult::Tt(tt)) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index c8983619e70..506bd445be3 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -5,8 +5,8 @@ use crate::errors::{
 use rustc_ast::ptr::P;
 use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
 use rustc_errors::{Diag, ErrorGuaranteed};
-use rustc_parse::new_parser_from_file;
 use rustc_parse::validate_attr;
+use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
@@ -66,7 +66,8 @@ pub(crate) fn parse_external_mod(
         }
 
         // Actually parse the external file as a module.
-        let mut parser = new_parser_from_file(&sess.psess, &mp.file_path, Some(span));
+        let mut parser =
+            unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span)));
         let (inner_attrs, items, inner_span) =
             parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
         attrs.extend(inner_attrs);
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 530059e53c2..96145affe0a 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -4,14 +4,12 @@ use crate::proc_macro_server;
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
-use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorGuaranteed;
-use rustc_parse::parser::ForceCollect;
+use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::config::ProcMacroExecutionStrategy;
 use rustc_span::profiling::SpannedEventArgRecorder;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 
 struct MessagePipe<T> {
     tx: std::sync::mpsc::SyncSender<T>,
@@ -120,18 +118,13 @@ impl MultiItemModifier for DeriveProcMacro {
         // We need special handling for statement items
         // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
         let is_stmt = matches!(item, Annotatable::Stmt(..));
-        let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
-        let input = if hack {
-            let nt = match item {
-                Annotatable::Item(item) => token::NtItem(item),
-                Annotatable::Stmt(stmt) => token::NtStmt(stmt),
-                _ => unreachable!(),
-            };
-            TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
-        } else {
-            item.to_tokens()
-        };
 
+        // We used to have an alternative behaviour for crates that needed it.
+        // We had a lint for a long time, but now we just emit a hard error.
+        // Eventually we might remove the special case hard error check
+        // altogether. See #73345.
+        crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
+        let input = item.to_tokens();
         let stream = {
             let _timer =
                 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
@@ -161,8 +154,7 @@ impl MultiItemModifier for DeriveProcMacro {
         };
 
         let error_count_before = ecx.dcx().err_count();
-        let mut parser =
-            rustc_parse::stream_to_parser(&ecx.sess.psess, stream, Some("proc-macro derive"));
+        let mut parser = Parser::new(&ecx.sess.psess, stream, Some("proc-macro derive"));
         let mut items = vec![];
 
         loop {
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index ec7e4416b91..93f8682090d 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -13,7 +13,8 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
 use rustc_parse::lexer::nfc_normalize;
-use rustc_parse::parse_stream_from_source_str;
+use rustc_parse::parser::Parser;
+use rustc_parse::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use rustc_span::def_id::CrateNum;
 use rustc_span::symbol::{self, sym, Symbol};
@@ -276,21 +277,20 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
 
                 Interpolated(nt) => {
                     let stream = TokenStream::from_nonterminal_ast(&nt);
-                    // A hack used to pass AST fragments to attribute and derive
-                    // macros as a single nonterminal token instead of a token
-                    // stream. Such token needs to be "unwrapped" and not
-                    // represented as a delimited group.
-                    // FIXME: It needs to be removed, but there are some
-                    // compatibility issues (see #73345).
-                    if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess) {
-                        trees.extend(Self::from_internal((stream, rustc)));
-                    } else {
-                        trees.push(TokenTree::Group(Group {
-                            delimiter: pm::Delimiter::None,
-                            stream: Some(stream),
-                            span: DelimSpan::from_single(span),
-                        }))
-                    }
+                    // We used to have an alternative behaviour for crates that
+                    // needed it: a hack used to pass AST fragments to
+                    // attribute and derive macros as a single nonterminal
+                    // token instead of a token stream. Such token needs to be
+                    // "unwrapped" and not represented as a delimited group. We
+                    // had a lint for a long time, but now we just emit a hard
+                    // error. Eventually we might remove the special case hard
+                    // error check altogether. See #73345.
+                    crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess);
+                    trees.push(TokenTree::Group(Group {
+                        delimiter: pm::Delimiter::None,
+                        stream: Some(stream),
+                        span: DelimSpan::from_single(span),
+                    }))
                 }
 
                 OpenDelim(..) | CloseDelim(..) => unreachable!(),
@@ -467,7 +467,8 @@ impl server::FreeFunctions for Rustc<'_, '_> {
 
     fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
         let name = FileName::proc_macro_source_code(s);
-        let mut parser = rustc_parse::new_parser_from_source_str(self.psess(), name, s.to_owned());
+        let mut parser =
+            unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned()));
 
         let first_span = parser.token.span.data();
         let minus_present = parser.eat(&token::BinOp(token::Minus));
@@ -539,12 +540,12 @@ impl server::TokenStream for Rustc<'_, '_> {
     }
 
     fn from_str(&mut self, src: &str) -> Self::TokenStream {
-        parse_stream_from_source_str(
+        unwrap_or_emit_fatal(source_str_to_stream(
+            self.psess(),
             FileName::proc_macro_source_code(src),
             src.to_string(),
-            self.psess(),
             Some(self.call_site),
-        )
+        ))
     }
 
     fn to_string(&mut self, stream: &Self::TokenStream) -> String {
@@ -554,11 +555,7 @@ impl server::TokenStream for Rustc<'_, '_> {
     fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
         // Parse the expression from our tokenstream.
         let expr: PResult<'_, _> = try {
-            let mut p = rustc_parse::stream_to_parser(
-                self.psess(),
-                stream.clone(),
-                Some("proc_macro expand expr"),
-            );
+            let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr"));
             let expr = p.parse_expr()?;
             if p.token != token::Eof {
                 p.unexpected()?;
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 8b7e93fd555..9b5e4e50d3c 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -59,6 +59,16 @@ pub enum AttributeType {
     CrateLevel,
 }
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum AttributeSafety {
+    /// Normal attribute that does not need `#[unsafe(...)]`
+    Normal,
+
+    /// Unsafe attribute that requires safety obligations
+    /// to be discharged
+    Unsafe,
+}
+
 #[derive(Clone, Copy)]
 pub enum AttributeGate {
     /// Is gated by a given feature gate, reason
@@ -172,11 +182,23 @@ macro_rules! template {
 }
 
 macro_rules! ungated {
+    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
+        BuiltinAttribute {
+            name: sym::$attr,
+            encode_cross_crate: $encode_cross_crate,
+            type_: $typ,
+            safety: AttributeSafety::Unsafe,
+            template: $tpl,
+            gate: Ungated,
+            duplicates: $duplicates,
+        }
+    };
     ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
             type_: $typ,
+            safety: AttributeSafety::Normal,
             template: $tpl,
             gate: Ungated,
             duplicates: $duplicates,
@@ -185,11 +207,34 @@ macro_rules! ungated {
 }
 
 macro_rules! gated {
+    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
+        BuiltinAttribute {
+            name: sym::$attr,
+            encode_cross_crate: $encode_cross_crate,
+            type_: $typ,
+            safety: AttributeSafety::Unsafe,
+            template: $tpl,
+            duplicates: $duplicates,
+            gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
+        }
+    };
+    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
+        BuiltinAttribute {
+            name: sym::$attr,
+            encode_cross_crate: $encode_cross_crate,
+            type_: $typ,
+            safety: AttributeSafety::Unsafe,
+            template: $tpl,
+            duplicates: $duplicates,
+            gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
+        }
+    };
     ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
             type_: $typ,
+            safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
             gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
@@ -200,6 +245,7 @@ macro_rules! gated {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
             type_: $typ,
+            safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
             gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
@@ -228,6 +274,7 @@ macro_rules! rustc_attr {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
             type_: $typ,
+            safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
             gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
@@ -258,6 +305,7 @@ pub struct BuiltinAttribute {
     /// Otherwise, it can only be used in the local crate.
     pub encode_cross_crate: EncodeCrossCrate,
     pub type_: AttributeType,
+    pub safety: AttributeSafety,
     pub template: AttributeTemplate,
     pub duplicates: AttributeDuplicates,
     pub gate: AttributeGate,
@@ -375,9 +423,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
     ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
-    ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
-    ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
-    ungated!(no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
+    ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
+    ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
+    ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
     ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
     ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
 
@@ -486,11 +534,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     gated!(
-        ffi_pure, Normal, template!(Word), WarnFollowing,
+        unsafe ffi_pure, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::No, experimental!(ffi_pure)
     ),
     gated!(
-        ffi_const, Normal, template!(Word), WarnFollowing,
+        unsafe ffi_const, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::No, experimental!(ffi_const)
     ),
     gated!(
@@ -850,6 +898,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
         encode_cross_crate: EncodeCrossCrate::Yes,
         type_: Normal,
+        safety: AttributeSafety::Normal,
         template: template!(NameValueStr: "name"),
         duplicates: ErrorFollowing,
         gate: Gated(
@@ -1096,6 +1145,10 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
     })
 }
 
+pub fn is_unsafe_attr(name: Symbol) -> bool {
+    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
+}
+
 pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
     LazyLock::new(|| {
         let mut map = FxHashMap::default();
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 9cbf836ec76..9db9073e2f0 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -123,8 +123,8 @@ pub use accepted::ACCEPTED_FEATURES;
 pub use builtin_attrs::AttributeDuplicates;
 pub use builtin_attrs::{
     deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
-    is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
-    GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+    is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
+    BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
 };
 pub use removed::REMOVED_FEATURES;
 pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index eaaf7ca34e0..aea447b2aff 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -128,6 +128,8 @@ declare_features! (
     /// Allows the use of type alias impl trait in function return positions
     (removed, min_type_alias_impl_trait, "1.56.0", Some(63063),
      Some("removed in favor of full type_alias_impl_trait")),
+    /// Make `mut` not reset the binding mode on edition >= 2024.
+    (removed, mut_preserve_binding_mode_2024, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`")),
     (removed, needs_allocator, "1.4.0", Some(27389),
      Some("subsumed by `#![feature(allocator_internals)]`")),
     /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
@@ -181,6 +183,7 @@ declare_features! (
     (removed, pushpop_unsafe, "1.2.0", None, None),
     (removed, quad_precision_float, "1.0.0", None, None),
     (removed, quote, "1.33.0", Some(29601), None),
+    (removed, ref_pat_everywhere, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024")),
     (removed, reflect, "1.0.0", Some(27749), None),
     /// Allows using the `#[register_attr]` attribute.
     (removed, register_attr, "1.65.0", Some(66080),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 2a4859a2478..2410019868a 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -177,8 +177,6 @@ declare_features! (
 
     /// Allows using the `unadjusted` ABI; perma-unstable.
     (internal, abi_unadjusted, "1.16.0", None),
-    /// Allows using the `vectorcall` ABI.
-    (unstable, abi_vectorcall, "1.7.0", None),
     /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
     (internal, allocator_internals, "1.20.0", None),
     /// Allows using `#[allow_internal_unsafe]`. This is an
@@ -243,6 +241,8 @@ declare_features! (
     // feature-group-start: internal feature gates
     // -------------------------------------------------------------------------
 
+    /// Allows using the `vectorcall` ABI.
+    (unstable, abi_vectorcall, "1.7.0", Some(124485)),
     /// Allows features specific to auto traits.
     /// Renamed from `optin_builtin_traits`.
     (unstable, auto_traits, "1.50.0", Some(13231)),
@@ -529,8 +529,6 @@ declare_features! (
     (unstable, more_qualified_paths, "1.54.0", Some(86935)),
     /// Allows the `#[must_not_suspend]` attribute.
     (unstable, must_not_suspend, "1.57.0", Some(83310)),
-    /// Make `mut` not reset the binding mode on edition >= 2024.
-    (incomplete, mut_preserve_binding_mode_2024, "1.79.0", Some(123076)),
     /// Allows `mut ref` and `mut ref mut` identifier patterns.
     (incomplete, mut_ref, "1.79.0", Some(123076)),
     /// Allows using `#[naked]` on functions.
@@ -561,6 +559,8 @@ declare_features! (
     (unstable, offset_of_enum, "1.75.0", Some(120141)),
     /// Allows using multiple nested field accesses in offset_of!
     (unstable, offset_of_nested, "1.77.0", Some(120140)),
+    /// Allows using fields with slice type in offset_of!
+    (unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows postfix match `expr.match { ... }`
@@ -573,8 +573,6 @@ declare_features! (
     (unstable, raw_ref_op, "1.41.0", Some(64490)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
     (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
-    /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
-    (incomplete, ref_pat_everywhere, "1.79.0", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
     (unstable, register_tool, "1.41.0", Some(66079)),
     /// Allows the `#[repr(i128)]` attribute for enums.
@@ -624,6 +622,10 @@ declare_features! (
     (unstable, type_changing_struct_update, "1.58.0", Some(86555)),
     /// Allows unnamed fields of struct and union type
     (incomplete, unnamed_fields, "1.74.0", Some(49804)),
+    /// Allows unsafe attributes.
+    (unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
+    /// Allows unsafe on extern declarations and safety qualifiers over internal items.
+    (unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
     /// Allows unsized fn parameters.
     (unstable, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 649a08b6972..b1854923247 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -76,6 +76,8 @@ pub enum DefKind {
     /// Constant generic parameter: `struct Foo<const N: usize> { ... }`
     ConstParam,
     Static {
+        /// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`.
+        safety: hir::Safety,
         /// Whether it's a `static mut` or just a `static`.
         mutability: ast::Mutability,
         /// Whether it's an anonymous static generated for nested allocations.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e971d0e3c14..87ff39a8294 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -907,9 +907,6 @@ pub struct OwnerNodes<'tcx> {
     pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
     /// Content of local bodies.
     pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
-    /// Whether the body contains inline constants that are created for the query system during typeck
-    /// of the body.
-    pub has_inline_consts: bool,
 }
 
 impl<'tcx> OwnerNodes<'tcx> {
@@ -1626,6 +1623,14 @@ pub struct AnonConst {
     pub span: Span,
 }
 
+/// An inline constant expression `const { something }`.
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
+pub struct ConstBlock {
+    pub hir_id: HirId,
+    pub def_id: LocalDefId,
+    pub body: BodyId,
+}
+
 /// An expression.
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Expr<'hir> {
@@ -1912,7 +1917,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum ExprKind<'hir> {
     /// Allow anonymous constants from an inline `const` block
-    ConstBlock(&'hir Expr<'hir>),
+    ConstBlock(ConstBlock),
     /// An array (e.g., `[a, b, c, d]`).
     Array(&'hir [Expr<'hir>]),
     /// A function call.
@@ -2345,7 +2350,9 @@ impl ImplItemId {
     }
 }
 
-/// Represents anything within an `impl` block.
+/// Represents an associated item within an impl block.
+///
+/// Refer to [`Impl`] for an impl block declaration.
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct ImplItem<'hir> {
     pub ident: Ident,
@@ -3327,6 +3334,10 @@ pub enum ItemKind<'hir> {
     Impl(&'hir Impl<'hir>),
 }
 
+/// Represents an impl block declaration.
+///
+/// E.g., `impl $Type { .. }` or `impl $Trait for $Type { .. }`
+/// Refer to [`ImplItem`] for an associated item within an impl block.
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Impl<'hir> {
     pub safety: Safety,
@@ -3475,9 +3486,9 @@ impl ForeignItem<'_> {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum ForeignItemKind<'hir> {
     /// A foreign function.
-    Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>),
+    Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>, Safety),
     /// A foreign static item (`static ext: u8`).
-    Static(&'hir Ty<'hir>, Mutability),
+    Static(&'hir Ty<'hir>, Mutability, Safety),
     /// A foreign type.
     Type,
 }
@@ -3545,7 +3556,7 @@ impl<'hir> OwnerNode<'hir> {
             | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
             | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
             OwnerNode::ForeignItem(ForeignItem {
-                kind: ForeignItemKind::Fn(fn_decl, _, _),
+                kind: ForeignItemKind::Fn(fn_decl, _, _, _),
                 ..
             }) => Some(fn_decl),
             _ => None,
@@ -3644,6 +3655,7 @@ pub enum Node<'hir> {
     Variant(&'hir Variant<'hir>),
     Field(&'hir FieldDef<'hir>),
     AnonConst(&'hir AnonConst),
+    ConstBlock(&'hir ConstBlock),
     Expr(&'hir Expr<'hir>),
     ExprField(&'hir ExprField<'hir>),
     Stmt(&'hir Stmt<'hir>),
@@ -3704,6 +3716,7 @@ impl<'hir> Node<'hir> {
             Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
             Node::Param(..)
             | Node::AnonConst(..)
+            | Node::ConstBlock(..)
             | Node::Expr(..)
             | Node::Stmt(..)
             | Node::Block(..)
@@ -3728,9 +3741,9 @@ impl<'hir> Node<'hir> {
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
             | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
             Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. })
-            | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
-                Some(fn_decl)
-            }
+            | Node::ForeignItem(ForeignItem {
+                kind: ForeignItemKind::Fn(fn_decl, _, _, _), ..
+            }) => Some(fn_decl),
             _ => None,
         }
     }
@@ -3801,6 +3814,7 @@ impl<'hir> Node<'hir> {
             }
 
             Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
+            Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
 
             _ => None,
         }
@@ -3813,7 +3827,7 @@ impl<'hir> Node<'hir> {
     pub fn generics(self) -> Option<&'hir Generics<'hir>> {
         match self {
             Node::ForeignItem(ForeignItem {
-                kind: ForeignItemKind::Fn(_, _, generics), ..
+                kind: ForeignItemKind::Fn(_, _, generics, _), ..
             })
             | Node::TraitItem(TraitItem { generics, .. })
             | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
@@ -3869,6 +3883,7 @@ impl<'hir> Node<'hir> {
         expect_variant,       &'hir Variant<'hir>,      Node::Variant(n),      n;
         expect_field,         &'hir FieldDef<'hir>,     Node::Field(n),        n;
         expect_anon_const,    &'hir AnonConst,          Node::AnonConst(n),    n;
+        expect_inline_const,  &'hir ConstBlock,         Node::ConstBlock(n),   n;
         expect_expr,          &'hir Expr<'hir>,         Node::Expr(n),         n;
         expect_expr_field,    &'hir ExprField<'hir>,    Node::ExprField(n),    n;
         expect_stmt,          &'hir Stmt<'hir>,         Node::Stmt(n),         n;
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 9bc2bbe0c64..5a16f266dab 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -344,6 +344,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
+    fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
+        walk_inline_const(self, c)
+    }
     fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
         walk_expr(self, ex)
     }
@@ -608,12 +611,14 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
     try_visit!(visitor.visit_ident(foreign_item.ident));
 
     match foreign_item.kind {
-        ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
+        ForeignItemKind::Fn(ref function_declaration, param_names, ref generics, _) => {
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(function_declaration));
             walk_list!(visitor, visit_ident, param_names.iter().copied());
         }
-        ForeignItemKind::Static(ref typ, _) => try_visit!(visitor.visit_ty(typ)),
+        ForeignItemKind::Static(ref typ, _, _) => {
+            try_visit!(visitor.visit_ty(typ));
+        }
         ForeignItemKind::Type => (),
     }
     V::Result::output()
@@ -716,6 +721,14 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
     visitor.visit_nested_body(constant.body)
 }
 
+pub fn walk_inline_const<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    constant: &'v ConstBlock,
+) -> V::Result {
+    try_visit!(visitor.visit_id(constant.hir_id));
+    visitor.visit_nested_body(constant.body)
+}
+
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
     try_visit!(visitor.visit_id(expression.hir_id));
     match expression.kind {
@@ -723,7 +736,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprKind::ConstBlock(ref const_block) => {
-            try_visit!(visitor.visit_expr(const_block))
+            try_visit!(visitor.visit_inline_const(const_block))
         }
         ExprKind::Repeat(ref element, ref count) => {
             try_visit!(visitor.visit_expr(element));
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 1ebd4b80e18..baa1635f731 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -93,8 +93,7 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'
         // `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
         // the body satisfies the condition of two nodes being different have different
         // `hash_stable` results.
-        let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _, has_inline_consts: _ } =
-            *self;
+        let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
         opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3904f14b0f6..72e5995e892 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -15,6 +15,7 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
+use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
@@ -342,7 +343,7 @@ fn check_opaque_meets_bounds<'tcx>(
     let param_env = tcx.param_env(defining_use_anchor);
 
     let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let args = match *origin {
         hir::OpaqueTyOrigin::FnReturn(parent)
@@ -801,7 +802,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
                         let item = tcx.hir().foreign_item(item.id);
                         match &item.kind {
-                            hir::ForeignItemKind::Fn(fn_decl, _, _) => {
+                            hir::ForeignItemKind::Fn(fn_decl, _, _, _) => {
                                 require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
                             }
                             hir::ForeignItemKind::Static(..) => {
@@ -1727,7 +1728,7 @@ pub(super) fn check_coroutine_obligations(
         .with_opaque_type_inference(def_id)
         .build();
 
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
         ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
     }
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 db749ef3f81..82b57cdd106 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -10,7 +10,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::{util, FulfillmentError};
+use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::util::ExplicitSelf;
@@ -25,7 +25,7 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
-    self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
+    self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
 };
 use std::borrow::Cow;
 use std::iter;
@@ -225,7 +225,7 @@ fn compare_method_predicate_entailment<'tcx>(
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
 
     let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
 
@@ -493,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     );
 
     let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     // Normalize the impl signature with fresh variables for lifetime inference.
     let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
@@ -764,17 +764,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     Ok(&*tcx.arena.alloc(remapped_types))
 }
 
-struct ImplTraitInTraitCollector<'a, 'tcx> {
-    ocx: &'a ObligationCtxt<'a, 'tcx>,
+struct ImplTraitInTraitCollector<'a, 'tcx, E> {
+    ocx: &'a ObligationCtxt<'a, 'tcx, E>,
     types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
 }
 
-impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
+impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
+where
+    E: 'tcx,
+{
     fn new(
-        ocx: &'a ObligationCtxt<'a, 'tcx>,
+        ocx: &'a ObligationCtxt<'a, 'tcx, E>,
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
@@ -783,7 +786,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
     }
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
+impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
+where
+    E: 'tcx,
+{
     fn interner(&self) -> TyCtxt<'tcx> {
         self.ocx.infcx.tcx
     }
@@ -1777,7 +1783,7 @@ fn compare_const_predicate_entailment<'tcx>(
     );
 
     let infcx = tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
     for (predicate, span) in impl_ct_own_bounds {
@@ -1910,7 +1916,7 @@ fn compare_type_predicate_entailment<'tcx>(
     let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
     let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
     let infcx = tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
 
@@ -1977,7 +1983,7 @@ pub(super) fn check_type_bounds<'tcx>(
     let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
 
     let infcx = tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
     // span for an impl's associated type. Instead, for these, use the def_span for the synthesized
@@ -2192,9 +2198,6 @@ fn param_env_with_gat_bounds<'tcx>(
                         tcx,
                         ty::INNERMOST,
                         ty::BoundVar::from_usize(bound_vars.len() - 1),
-                        tcx.type_of(param.def_id)
-                            .no_bound_vars()
-                            .expect("const parameter types cannot be generic"),
                     )
                     .into()
                 }
@@ -2275,7 +2278,7 @@ fn try_report_async_mismatch<'tcx>(
             && let Some(proj) = proj.no_bound_vars()
             && infcx.can_eq(
                 error.root_obligation.param_env,
-                proj.term.ty().unwrap(),
+                proj.term.expect_type(),
                 impl_sig.output(),
             )
         {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index ca08eeea227..10b097a1060 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -267,7 +267,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
             .explicit_item_bounds(future_ty.def_id)
             .iter_instantiated_copied(tcx, future_ty.args)
             .find_map(|(clause, _)| match clause.kind().no_bound_vars()? {
-                ty::ClauseKind::Projection(proj) => proj.term.ty(),
+                ty::ClauseKind::Projection(proj) => proj.term.as_type(),
                 _ => None,
             })
         else {
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index be412dde968..8ec6dd12a78 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -123,7 +123,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     adt_to_impl_args: GenericArgsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let infcx = tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     // Take the param-env of the adt and instantiate the args that show up in
     // the implementation's self type. This gives us the assumptions that the
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index 25ac31c16c7..cc52a765802 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -133,7 +133,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             main_diagnostics_def_id,
             ObligationCauseCode::MainFunctionType,
         );
-        let ocx = traits::ObligationCtxt::new(&infcx);
+        let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
         let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
         ocx.register_bound(cause, param_env, norm_return_ty, term_did);
         let errors = ocx.select_all_or_error();
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
index a49626eed35..2cdcc06f53c 100644
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -41,7 +41,8 @@ fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
     if let hir::ExprKind::Path(qpath) = expr.kind
         && let hir::QPath::Resolved(_, path) = qpath
         && let hir::def::Res::Def(def_kind, _) = path.res
-        && let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
+        && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
+            def_kind
     {
         return Some(qpath_to_string(&tcx, &qpath));
     }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index f7989aeab41..13180fa2673 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -29,7 +29,7 @@ fn equate_intrinsic_type<'tcx>(
     let (own_counts, span) = match tcx.hir_node_by_def_id(def_id) {
         hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
         | hir::Node::ForeignItem(hir::ForeignItem {
-            kind: hir::ForeignItemKind::Fn(.., generics),
+            kind: hir::ForeignItemKind::Fn(.., generics, _),
             ..
         }) => {
             let own_counts = tcx.generics_of(def_id).own_counts();
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 149e7737e30..4d1b96d9c1b 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -441,7 +441,9 @@ fn fn_sig_suggestion<'tcx>(
         output = if let ty::Alias(_, alias_ty) = *output.kind() {
             tcx.explicit_item_super_predicates(alias_ty.def_id)
                 .iter_instantiated_copied(tcx, alias_ty.args)
-                .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
+                .find_map(|(bound, _)| {
+                    bound.as_projection_clause()?.no_bound_vars()?.term.as_type()
+                })
                 .unwrap_or_else(|| {
                     span_bug!(
                         ident.span,
@@ -599,7 +601,7 @@ pub fn check_function_signature<'tcx>(
     let param_env = ty::ParamEnv::empty();
 
     let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
 
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 30b03b43872..72e431926ca 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -407,14 +407,11 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
     match expr.kind {
         // Manually recurse over closures and inline consts, because they are the only
         // case of nested bodies that share the parent environment.
-        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+        hir::ExprKind::Closure(&hir::Closure { body, .. })
+        | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) => {
             let body = visitor.tcx.hir().body(body);
             visitor.visit_body(body);
         }
-        hir::ExprKind::ConstBlock(expr) => visitor.enter_body(expr.hir_id, |this| {
-            this.cx.var_parent = None;
-            resolve_local(this, None, Some(expr));
-        }),
         hir::ExprKind::AssignOp(_, left_expr, right_expr) => {
             debug!(
                 "resolve_expr - enabling pessimistic_yield, was previously {}",
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 81e3d8c7ece..b206d8046ee 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -37,7 +37,7 @@ use rustc_trait_selection::traits::misc::{
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
-    self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
+    self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
 };
 use rustc_type_ir::TypeFlags;
 
@@ -45,13 +45,13 @@ use std::cell::LazyCell;
 use std::ops::{ControlFlow, Deref};
 
 pub(super) struct WfCheckingCtxt<'a, 'tcx> {
-    pub(super) ocx: ObligationCtxt<'a, 'tcx>,
+    pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
     span: Span,
     body_def_id: LocalDefId,
     param_env: ty::ParamEnv<'tcx>,
 }
 impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {
-    type Target = ObligationCtxt<'a, 'tcx>;
+    type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;
     fn deref(&self) -> &Self::Target {
         &self.ocx
     }
@@ -106,7 +106,7 @@ where
 {
     let param_env = tcx.param_env(body_def_id);
     let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
     let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
 
@@ -881,7 +881,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
         _ => {}
     }
     if !trait_should_be_self.is_empty() {
-        if tcx.check_is_object_safe(trait_def_id) {
+        if tcx.is_object_safe(trait_def_id) {
             return;
         }
         let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 84771978a46..61adb7a3cba 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -267,7 +267,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
                         .join(", "),
                 }));
             } else {
-                let ocx = ObligationCtxt::new(&infcx);
+                let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
                 for field in coerced_fields {
                     ocx.register_obligation(Obligation::new(
                         tcx,
@@ -480,7 +480,7 @@ pub fn coerce_unsized_info<'tcx>(
     };
 
     // Register an obligation for `A: Trait<B>`.
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     let cause = traits::ObligationCause::misc(span, impl_did);
     let obligation = Obligation::new(
         tcx,
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 480318acca8..eae41d28e89 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -191,7 +191,7 @@ fn check_object_overlap<'tcx>(
         });
 
         for component_def_id in component_def_ids {
-            if !tcx.check_is_object_safe(component_def_id) {
+            if !tcx.is_object_safe(component_def_id) {
                 // Without the 'object_safe_for_dispatch' feature this is an error
                 // which will be reported by wfcheck. Ignore it here.
                 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index bdac0d9b0b4..61ac4af0151 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -14,7 +14,6 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
 use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
-use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt};
 
 #[instrument(level = "debug", skip(tcx))]
 pub(crate) fn orphan_check_impl(
@@ -317,12 +316,12 @@ fn orphan_check<'tcx>(
         }
 
         let ty = if infcx.next_trait_solver() {
-            let mut fulfill_cx = <dyn traits::TraitEngine<'_>>::new(&infcx);
-            infcx
-                .at(&cause, ty::ParamEnv::empty())
-                .structurally_normalize(ty, &mut *fulfill_cx)
-                .map(|ty| infcx.resolve_vars_if_possible(ty))
-                .unwrap_or(ty)
+            ocx.structurally_normalize(
+                &cause,
+                ty::ParamEnv::empty(),
+                infcx.resolve_vars_if_possible(ty),
+            )
+            .unwrap_or(ty)
         } else {
             ty
         };
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 7e746006148..c6e8759327f 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -18,11 +18,11 @@ use rustc_ast::Recovered;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
-use rustc_hir as hir;
+use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::intravisit::{self, walk_generics, Visitor};
+use rustc_hir::{self as hir};
 use rustc_hir::{GenericParamKind, Node};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
@@ -44,7 +44,7 @@ use std::ops::Bound;
 
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::errors;
-use crate::hir_ty_lowering::HirTyLowerer;
+use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
 pub use type_of::test_opaque_hidden_types;
 
 mod generics_of;
@@ -370,32 +370,34 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
         self.tcx
     }
 
-    fn item_def_id(&self) -> DefId {
-        self.item_def_id.to_def_id()
+    fn item_def_id(&self) -> LocalDefId {
+        self.item_def_id
     }
 
-    fn allow_infer(&self) -> bool {
-        false
-    }
-
-    fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
-        None
+    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
+        if let RegionInferReason::BorrowedObjectLifetimeDefault = reason {
+            let e = struct_span_code_err!(
+                self.tcx().dcx(),
+                span,
+                E0228,
+                "the lifetime bound for this object type cannot be deduced \
+                from context; please supply an explicit bound"
+            )
+            .emit();
+            self.set_tainted_by_errors(e);
+            ty::Region::new_error(self.tcx(), e)
+        } else {
+            // This indicates an illegal lifetime in a non-assoc-trait position
+            ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
+        }
     }
 
     fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
         Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
     }
 
-    fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
-        let ty = self.tcx.fold_regions(ty, |r, _| match *r {
-            rustc_type_ir::RegionKind::ReStatic => r,
-
-            // This is never reached in practice. If it ever is reached,
-            // `ReErased` should be changed to `ReStatic`, and any other region
-            // left alone.
-            r => bug!("unexpected region: {r:?}"),
-        });
-        ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
+    fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
+        ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
     }
 
     fn probe_ty_param_bounds(
@@ -510,6 +512,89 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
     fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
         self.tainted_by_errors.set(Some(err));
     }
+
+    fn lower_fn_sig(
+        &self,
+        decl: &hir::FnDecl<'tcx>,
+        generics: Option<&hir::Generics<'_>>,
+        hir_id: rustc_hir::HirId,
+        hir_ty: Option<&hir::Ty<'_>>,
+    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
+        let tcx = self.tcx();
+        // We proactively collect all the inferred type params to emit a single error per fn def.
+        let mut visitor = HirPlaceholderCollector::default();
+        let mut infer_replacements = vec![];
+
+        if let Some(generics) = generics {
+            walk_generics(&mut visitor, generics);
+        }
+
+        let input_tys = decl
+            .inputs
+            .iter()
+            .enumerate()
+            .map(|(i, a)| {
+                if let hir::TyKind::Infer = a.kind {
+                    if let Some(suggested_ty) =
+                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
+                    {
+                        infer_replacements.push((a.span, suggested_ty.to_string()));
+                        return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
+                    }
+                }
+
+                // Only visit the type looking for `_` if we didn't fix the type above
+                visitor.visit_ty(a);
+                self.lowerer().lower_arg_ty(a, None)
+            })
+            .collect();
+
+        let output_ty = match decl.output {
+            hir::FnRetTy::Return(output) => {
+                if let hir::TyKind::Infer = output.kind
+                    && let Some(suggested_ty) =
+                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
+                {
+                    infer_replacements.push((output.span, suggested_ty.to_string()));
+                    Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
+                } else {
+                    visitor.visit_ty(output);
+                    self.lower_ty(output)
+                }
+            }
+            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
+        };
+
+        if !(visitor.0.is_empty() && infer_replacements.is_empty()) {
+            // We check for the presence of
+            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
+
+            let mut diag = crate::collect::placeholder_type_error_diag(
+                tcx,
+                generics,
+                visitor.0,
+                infer_replacements.iter().map(|(s, _)| *s).collect(),
+                true,
+                hir_ty,
+                "function",
+            );
+
+            if !infer_replacements.is_empty() {
+                diag.multipart_suggestion(
+                    format!(
+                    "try replacing `_` with the type{} in the corresponding trait method signature",
+                    rustc_errors::pluralize!(infer_replacements.len()),
+                ),
+                    infer_replacements,
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            self.set_tainted_by_errors(diag.emit());
+        }
+
+        (input_tys, output_ty)
+    }
 }
 
 /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
@@ -1321,9 +1406,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
             icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
         }
 
-        ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
+        ForeignItem(&hir::ForeignItem {
+            kind: ForeignItemKind::Fn(fn_decl, _, _, safety), ..
+        }) => {
             let abi = tcx.hir().get_foreign_abi(hir_id);
-            compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+            compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, safety)
         }
 
         Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
@@ -1695,11 +1782,12 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     def_id: LocalDefId,
     decl: &'tcx hir::FnDecl<'tcx>,
     abi: abi::Abi,
+    safety: hir::Safety,
 ) -> ty::PolyFnSig<'tcx> {
     let safety = if abi == abi::Abi::RustIntrinsic {
         intrinsic_operation_unsafety(tcx, def_id)
     } else {
-        hir::Safety::Unsafe
+        safety
     };
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
     let fty =
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 9af959681fb..abdf85ad707 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -177,10 +177,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 }
             }
         }
-        Node::Expr(&hir::Expr {
-            kind: hir::ExprKind::Closure { .. } | hir::ExprKind::ConstBlock { .. },
-            ..
-        }) => Some(tcx.typeck_root_def_id(def_id.to_def_id())),
+        Node::ConstBlock(_)
+        | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
+            Some(tcx.typeck_root_def_id(def_id.to_def_id()))
+        }
         Node::Item(item) => match item.kind {
             ItemKind::OpaqueTy(&hir::OpaqueTy {
                 origin:
@@ -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::Expr(Expr { kind: ExprKind::ConstBlock(..), .. }) = node {
+    if let Node::ConstBlock(_) = node {
         own_params.push(ty::GenericParamDef {
             index: next_index(),
             name: Symbol::intern("<const_ty>"),
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 072bb727901..40204961e9c 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,7 +1,7 @@
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
-use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
+use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
 use hir::{HirId, Node};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
@@ -117,7 +117,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     let mut is_trait = None;
     let mut is_default_impl_trait = None;
 
-    // FIXME: Should ItemCtxt take a LocalDefId?
     let icx = ItemCtxt::new(tcx, def_id);
 
     const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
@@ -197,7 +196,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                     .type_of(param.def_id.to_def_id())
                     .no_bound_vars()
                     .expect("const parameters cannot be generic");
-                let ct = icx.lowerer().lower_const_param(param.hir_id, ct_ty);
+                let ct = icx.lowerer().lower_const_param(param.hir_id);
                 predicates
                     .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
             }
@@ -244,12 +243,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
-                let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None);
+                let r1 = icx
+                    .lowerer()
+                    .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
                 predicates.extend(region_pred.bounds.iter().map(|bound| {
                     let (r2, span) = match bound {
-                        hir::GenericBound::Outlives(lt) => {
-                            (icx.lowerer().lower_lifetime(lt, None), lt.ident.span)
-                        }
+                        hir::GenericBound::Outlives(lt) => (
+                            icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
+                            lt.ident.span,
+                        ),
                         bound => {
                             span_bug!(
                                 bound.span(),
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 c1850f78f2f..abc3bb838db 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -603,7 +603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         match item.kind {
-            hir::ForeignItemKind::Fn(_, _, generics) => {
+            hir::ForeignItemKind::Fn(_, _, generics, _) => {
                 self.visit_early_late(item.hir_id(), generics, |this| {
                     intravisit::walk_foreign_item(this, item);
                 })
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c677fa92261..2684467a438 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -464,7 +464,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                 let args = ty::GenericArgs::identity_for_item(tcx, def_id);
                 Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
-            ForeignItemKind::Static(t, _) => icx.lower_ty(t),
+            ForeignItemKind::Static(t, _, _) => icx.lower_ty(t),
             ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
         },
 
@@ -485,7 +485,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
         }
 
         Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
-        Node::Expr(&Expr { kind: ExprKind::ConstBlock(..), .. }) => {
+
+        Node::ConstBlock(_) => {
             let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
             args.as_inline_const().ty()
         }
@@ -502,7 +503,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
             bug!("unexpected sort of node in type_of(): {:?}", x);
         }
     };
-    if let Err(e) = icx.check_tainted_by_errors() {
+    if let Err(e) = icx.check_tainted_by_errors()
+        && !output.references_error()
+    {
         ty::EarlyBinder::bind(Ty::new_error(tcx, e))
     } else {
         ty::EarlyBinder::bind(output)
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 b6a1799c03f..7f6f57907c2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -18,6 +18,8 @@ use crate::bounds::Bounds;
 use crate::errors;
 use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
 
+use super::RegionInferReason;
+
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// Add a `Sized` bound to the `bounds` if appropriate.
     ///
@@ -166,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     );
                 }
                 hir::GenericBound::Outlives(lifetime) => {
-                    let region = self.lower_lifetime(lifetime, None);
+                    let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
                     bounds.push_region_bound(
                         self.tcx(),
                         ty::Binder::bind_with_vars(
@@ -366,11 +368,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                     },
                                 )
                             });
-                            let ty = tcx
-                                .type_of(param.def_id)
-                                .no_bound_vars()
-                                .expect("ct params cannot have early bound vars");
-                            ty::Const::new_error(tcx, guar, ty).into()
+                            ty::Const::new_error(tcx, guar).into()
                         }
                     };
                     num_bound_vars += 1;
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 821c5653040..3a9ef244fd3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -15,7 +15,6 @@ use rustc_errors::{
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_infer::traits::FulfillmentError;
 use rustc_middle::bug;
 use rustc_middle::query::Key;
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -28,6 +27,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::BytePos;
 use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_trait_selection::traits::FulfillmentError;
 use rustc_trait_selection::traits::{
     object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
 };
@@ -702,7 +702,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     pub(crate) fn complain_about_missing_assoc_tys(
         &self,
         associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
-        potential_assoc_types: Vec<Span>,
+        potential_assoc_types: Vec<usize>,
         trait_bounds: &[hir::PolyTraitRef<'_>],
     ) {
         if associated_types.values().all(|v| v.is_empty()) {
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 d641e33b299..26cabb69d25 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -214,10 +214,11 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
             if let Some(&param) = params.peek() {
                 if param.index == 0 {
                     if let GenericParamDefKind::Type { .. } = param.kind {
+                        assert_eq!(&args[..], &[]);
                         args.push(
                             self_ty
                                 .map(|ty| ty.into())
-                                .unwrap_or_else(|| ctx.inferred_kind(None, param, true)),
+                                .unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
                         );
                         params.next();
                     }
@@ -267,7 +268,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
                             // Since this is a const impl, we need to insert a host arg at the end of
                             // `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
                             // To work around this, we infer all arguments until we reach the host param.
-                            args.push(ctx.inferred_kind(Some(&args), param, infer_args));
+                            args.push(ctx.inferred_kind(&args, param, infer_args));
                             params.next();
                         }
                         (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
@@ -281,7 +282,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
                             GenericParamDefKind::Const { .. },
                             _,
                         ) => {
-                            args.push(ctx.provided_kind(param, arg));
+                            args.push(ctx.provided_kind(&args, param, arg));
                             args_iter.next();
                             params.next();
                         }
@@ -292,7 +293,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
                         ) => {
                             // We expected a lifetime argument, but got a type or const
                             // argument. That means we're inferring the lifetimes.
-                            args.push(ctx.inferred_kind(None, param, infer_args));
+                            args.push(ctx.inferred_kind(&args, param, infer_args));
                             force_infer_lt = Some((arg, param));
                             params.next();
                         }
@@ -388,7 +389,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
                 (None, Some(&param)) => {
                     // If there are fewer arguments than parameters, it means
                     // we're inferring the remaining arguments.
-                    args.push(ctx.inferred_kind(Some(&args), param, infer_args));
+                    args.push(ctx.inferred_kind(&args, param, infer_args));
                     params.next();
                 }
 
@@ -474,16 +475,9 @@ pub(crate) fn check_generic_arg_count(
             return Ok(());
         }
 
-        if provided_args > max_expected_args {
-            invalid_args.extend(
-                gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()),
-            );
-        };
+        invalid_args.extend(min_expected_args..provided_args);
 
         let gen_args_info = if provided_args > min_expected_args {
-            invalid_args.extend(
-                gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()),
-            );
             let num_redundant_args = provided_args - min_expected_args;
             GenericArgsInfo::ExcessLifetimes { num_redundant_args }
         } else {
@@ -538,11 +532,7 @@ pub(crate) fn check_generic_arg_count(
         let num_default_params = expected_max - expected_min;
 
         let gen_args_info = if provided > expected_max {
-            invalid_args.extend(
-                gen_args.args[args_offset + expected_max..args_offset + provided]
-                    .iter()
-                    .map(|arg| arg.span()),
-            );
+            invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
             let num_redundant_args = provided - expected_max;
 
             // Provide extra note if synthetic arguments like `impl Trait` are specified.
@@ -610,7 +600,7 @@ pub(crate) fn check_generic_arg_count(
         explicit_late_bound,
         correct: lifetimes_correct
             .and(args_correct)
-            .map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }),
+            .map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index b4305f6efb9..240a749de96 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -182,7 +182,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             // For recursive traits, don't downgrade the error. (#119652)
                             is_downgradable = false;
                         }
-                        tcx.check_is_object_safe(id)
+                        tcx.is_object_safe(id)
                     }
                     _ => false,
                 })
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 54b7f7f36ed..7ec64f1feda 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -20,7 +20,6 @@ mod lint;
 mod object_safety;
 
 use crate::bounds::Bounds;
-use crate::collect::HirPlaceholderCollector;
 use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
 use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
@@ -34,7 +33,6 @@ use rustc_errors::{
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::{GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
@@ -82,6 +80,20 @@ pub enum PredicateFilter {
     SelfAndAssociatedTypeBounds,
 }
 
+#[derive(Debug)]
+pub enum RegionInferReason<'a> {
+    /// Lifetime on a trait object behind a reference.
+    /// This allows inferring information from the reference.
+    BorrowedObjectLifetimeDefault,
+    /// A trait object's lifetime.
+    ObjectLifetimeDefault,
+    /// Generic lifetime parameter
+    Param(&'a ty::GenericParamDef),
+    RegionPredicate,
+    Reference,
+    OutlivesBound,
+}
+
 /// A context which can lower type-system entities from the [HIR][hir] to
 /// the [`rustc_middle::ty`] representation.
 ///
@@ -89,26 +101,17 @@ pub enum PredicateFilter {
 pub trait HirTyLowerer<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx>;
 
-    /// Returns the [`DefId`] of the overarching item whose constituents get lowered.
-    fn item_def_id(&self) -> DefId;
-
-    /// Returns `true` if the current context allows the use of inference variables.
-    fn allow_infer(&self) -> bool;
+    /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered.
+    fn item_def_id(&self) -> LocalDefId;
 
     /// Returns the region to use when a lifetime is omitted (and not elided).
-    fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
-    -> Option<ty::Region<'tcx>>;
+    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>;
 
     /// Returns the type to use when a type is omitted.
     fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
 
     /// Returns the const to use when a const is omitted.
-    fn ct_infer(
-        &self,
-        ty: Ty<'tcx>,
-        param: Option<&ty::GenericParamDef>,
-        span: Span,
-    ) -> Const<'tcx>;
+    fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;
 
     /// Probe bounds in scope where the bounded type coincides with the given type parameter.
     ///
@@ -151,6 +154,14 @@ pub trait HirTyLowerer<'tcx> {
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx>;
 
+    fn lower_fn_sig(
+        &self,
+        decl: &hir::FnDecl<'tcx>,
+        generics: Option<&hir::Generics<'_>>,
+        hir_id: HirId,
+        hir_ty: Option<&hir::Ty<'_>>,
+    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>);
+
     /// Returns `AdtDef` if `ty` is an ADT.
     ///
     /// Note that `ty` might be a alias type that needs normalization.
@@ -215,12 +226,11 @@ pub(crate) enum GenericArgPosition {
 
 /// A marker denoting that the generic arguments that were
 /// provided did not match the respective generic parameters.
-#[derive(Clone, Default, Debug)]
+#[derive(Clone, Debug)]
 pub struct GenericArgCountMismatch {
-    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
-    pub reported: Option<ErrorGuaranteed>,
-    /// A list of spans of arguments provided that were not valid.
-    pub invalid_args: Vec<Span>,
+    pub reported: ErrorGuaranteed,
+    /// A list of indices of arguments provided that were not valid.
+    pub invalid_args: Vec<usize>,
 }
 
 /// Decorates the result of a generic argument count mismatch
@@ -240,13 +250,14 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
 
     fn provided_kind(
         &mut self,
+        preceding_args: &[ty::GenericArg<'tcx>],
         param: &ty::GenericParamDef,
         arg: &GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx>;
 
     fn inferred_kind(
         &mut self,
-        args: Option<&[ty::GenericArg<'tcx>]>,
+        preceding_args: &[ty::GenericArg<'tcx>],
         param: &ty::GenericParamDef,
         infer_args: bool,
     ) -> ty::GenericArg<'tcx>;
@@ -258,7 +269,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     pub fn lower_lifetime(
         &self,
         lifetime: &hir::Lifetime,
-        def: Option<&ty::GenericParamDef>,
+        reason: RegionInferReason<'_>,
     ) -> ty::Region<'tcx> {
         let tcx = self.tcx();
         let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
@@ -292,21 +303,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar),
 
-            None => {
-                self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
-                    debug!(?lifetime, "unelided lifetime in signature");
-
-                    // This indicates an illegal lifetime
-                    // elision. `resolve_lifetime` should have
-                    // reported an error in this case -- but if
-                    // not, let's error out.
-                    ty::Region::new_error_with_message(
-                        tcx,
-                        lifetime.ident.span,
-                        "unelided lifetime in signature",
-                    )
-                })
-            }
+            None => self.re_infer(lifetime.ident.span, reason),
         }
     }
 
@@ -404,10 +401,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             self_ty.is_some(),
         );
 
-        if let Err(err) = &arg_count.correct
-            && let Some(reported) = err.reported
-        {
-            self.set_tainted_by_errors(reported);
+        if let Err(err) = &arg_count.correct {
+            self.set_tainted_by_errors(err.reported);
         }
 
         // Skip processing if type has no generic parameters.
@@ -423,8 +418,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             def_id: DefId,
             generic_args: &'a GenericArgs<'tcx>,
             span: Span,
-            inferred_params: Vec<Span>,
             infer_args: bool,
+            incorrect_args: &'a Result<(), GenericArgCountMismatch>,
         }
 
         impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> {
@@ -439,12 +434,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             fn provided_kind(
                 &mut self,
+                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 let tcx = self.lowerer.tcx();
 
-                let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
+                if let Err(incorrect) = self.incorrect_args {
+                    if incorrect.invalid_args.contains(&(param.index as usize)) {
+                        return param.to_error(tcx);
+                    }
+                }
+
+                let handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
                     if has_default {
                         tcx.check_optional_stability(
                             param.def_id,
@@ -461,17 +463,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             },
                         );
                     }
-                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.lowerer.allow_infer()) {
-                        self.inferred_params.push(ty.span);
-                        Ty::new_misc_error(tcx).into()
-                    } else {
-                        self.lowerer.lower_ty(ty).into()
-                    }
+                    self.lowerer.lower_ty(ty).into()
                 };
 
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        self.lowerer.lower_lifetime(lt, Some(param)).into()
+                        self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into()
                     }
                     (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
                         handle_ty_args(has_default, ty)
@@ -485,17 +482,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         ty::Const::from_anon_const(tcx, did).into()
                     }
                     (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
-                        let ty = tcx
-                            .at(self.span)
-                            .type_of(param.def_id)
-                            .no_bound_vars()
-                            .expect("const parameter types cannot be generic");
-                        if self.lowerer.allow_infer() {
-                            self.lowerer.ct_infer(ty, Some(param), inf.span).into()
-                        } else {
-                            self.inferred_params.push(inf.span);
-                            ty::Const::new_misc_error(tcx, ty).into()
-                        }
+                        self.lowerer.ct_infer(Some(param), inf.span).into()
                     }
                     (kind, arg) => span_bug!(
                         self.span,
@@ -506,38 +493,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             fn inferred_kind(
                 &mut self,
-                args: Option<&[ty::GenericArg<'tcx>]>,
+                preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 infer_args: bool,
             ) -> ty::GenericArg<'tcx> {
                 let tcx = self.lowerer.tcx();
+
+                if let Err(incorrect) = self.incorrect_args {
+                    if incorrect.invalid_args.contains(&(param.index as usize)) {
+                        return param.to_error(tcx);
+                    }
+                }
                 match param.kind {
-                    GenericParamDefKind::Lifetime => self
-                        .lowerer
-                        .re_infer(Some(param), self.span)
-                        .unwrap_or_else(|| {
-                            debug!(?param, "unelided lifetime in signature");
-
-                            // This indicates an illegal lifetime in a non-assoc-trait position
-                            ty::Region::new_error_with_message(
-                                tcx,
-                                self.span,
-                                "unelided lifetime in signature",
-                            )
-                        })
-                        .into(),
+                    GenericParamDefKind::Lifetime => {
+                        self.lowerer.re_infer(self.span, RegionInferReason::Param(param)).into()
+                    }
                     GenericParamDefKind::Type { has_default, .. } => {
                         if !infer_args && has_default {
                             // No type parameter provided, but a default exists.
-                            let args = args.unwrap();
-                            if args.iter().any(|arg| match arg.unpack() {
-                                GenericArgKind::Type(ty) => ty.references_error(),
-                                _ => false,
-                            }) {
+                            if let Some(prev) =
+                                preceding_args.iter().find_map(|arg| match arg.unpack() {
+                                    GenericArgKind::Type(ty) => ty.error_reported().err(),
+                                    _ => None,
+                                })
+                            {
                                 // Avoid ICE #86756 when type error recovery goes awry.
-                                return Ty::new_misc_error(tcx).into();
+                                return Ty::new_error(tcx, prev).into();
                             }
-                            tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into()
+                            tcx.at(self.span)
+                                .type_of(param.def_id)
+                                .instantiate(tcx, preceding_args)
+                                .into()
                         } else if infer_args {
                             self.lowerer.ty_infer(Some(param), self.span).into()
                         } else {
@@ -552,46 +538,45 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             .no_bound_vars()
                             .expect("const parameter types cannot be generic");
                         if let Err(guar) = ty.error_reported() {
-                            return ty::Const::new_error(tcx, guar, ty).into();
+                            return ty::Const::new_error(tcx, guar).into();
                         }
                         // FIXME(effects) see if we should special case effect params here
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id)
-                                .instantiate(tcx, args.unwrap())
+                                .instantiate(tcx, preceding_args)
                                 .into()
                         } else {
                             if infer_args {
-                                self.lowerer.ct_infer(ty, Some(param), self.span).into()
+                                self.lowerer.ct_infer(Some(param), self.span).into()
                             } else {
                                 // We've already errored above about the mismatch.
-                                ty::Const::new_misc_error(tcx, ty).into()
+                                ty::Const::new_misc_error(tcx).into()
                             }
                         }
                     }
                 }
             }
         }
-
-        let mut args_ctx = GenericArgsCtxt {
-            lowerer: self,
-            def_id,
-            span,
-            generic_args: segment.args(),
-            inferred_params: vec![],
-            infer_args: segment.infer_args,
-        };
         if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
             && generics.has_self
             && !tcx.has_attr(def_id, sym::const_trait)
         {
-            let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
+            let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
                 span,
                 modifier: constness.as_str(),
             });
-            self.set_tainted_by_errors(e);
-            arg_count.correct =
-                Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
+            self.set_tainted_by_errors(reported);
+            arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] });
         }
+
+        let mut args_ctx = GenericArgsCtxt {
+            lowerer: self,
+            def_id,
+            span,
+            generic_args: segment.args(),
+            infer_args: segment.infer_args,
+            incorrect_args: &arg_count.correct,
+        };
         let args = lower_generic_args(
             tcx,
             def_id,
@@ -1298,7 +1283,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .copied()
             .filter(|&(impl_, _)| {
                 infcx.probe(|_| {
-                    let ocx = ObligationCtxt::new(infcx);
+                    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
                     let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
 
                     let impl_args = infcx.fresh_args_for_item(span, impl_);
@@ -1477,16 +1462,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             let def_id = self.item_def_id();
             debug!(item_def_id = ?def_id);
 
-            let parent_def_id = def_id
-                .as_local()
-                .map(|def_id| tcx.local_def_id_to_hir_id(def_id))
-                .map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id());
+            // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
+            let parent_def_id =
+                tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
             debug!(?parent_def_id);
 
             // If the trait in segment is the same as the trait defining the item,
             // use the `<Self as ..>` syntax in the error.
-            let is_part_of_self_trait_constraints = def_id == trait_def_id;
-            let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
+            let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
+            let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
 
             let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
                 vec!["Self".to_string()]
@@ -1914,7 +1898,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
     /// and late-bound ones to [`ty::ConstKind::Bound`].
-    pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
+    pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> {
         let tcx = self.tcx();
         match tcx.named_bound_var(hir_id) {
             Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@@ -1924,12 +1908,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.item_name(def_id);
-                ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)
+                ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
             }
             Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
-                ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty)
+                ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
             }
-            Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty),
+            Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
             arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
         }
     }
@@ -1967,7 +1951,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
 
         let sig_generics = self.tcx().generics_of(sig_id);
-        let parent = self.tcx().parent(self.item_def_id());
+        let parent = self.tcx().local_parent(self.item_def_id());
         let parent_generics = self.tcx().generics_of(parent);
 
         let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
@@ -2006,7 +1990,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let sig = self.tcx().fn_sig(sig_id);
         let sig_generics = self.tcx().generics_of(sig_id);
 
-        let parent = self.tcx().parent(self.item_def_id());
+        let parent = self.tcx().local_parent(self.item_def_id());
         let parent_def_kind = self.tcx().def_kind(parent);
 
         let sig = if let DefKind::Impl { .. } = parent_def_kind
@@ -2054,7 +2038,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
             hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
             hir::TyKind::Ref(region, mt) => {
-                let r = self.lower_lifetime(region, None);
+                let r = self.lower_lifetime(region, RegionInferReason::Reference);
                 debug!(?r);
                 let t = self.lower_ty_common(mt.ty, true, false);
                 Ty::new_ref(tcx, r, t, mt.mutbl)
@@ -2145,7 +2129,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
             hir::TyKind::Array(ty, length) => {
                 let length = match length {
-                    hir::ArrayLen::Infer(inf) => self.ct_infer(tcx.types.usize, None, inf.span),
+                    hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
                     hir::ArrayLen::Body(constant) => {
                         ty::Const::from_anon_const(tcx, constant.def_id)
                     }
@@ -2176,17 +2160,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 }
                                 _ => (expr, None),
                             };
-                            let c = match &expr.kind {
+                            let (c, c_ty) = match &expr.kind {
                                 hir::ExprKind::Lit(lit) => {
                                     let lit_input =
                                         LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
-                                    match tcx.lit_to_const(lit_input) {
+                                    let ct = match tcx.lit_to_const(lit_input) {
                                         Ok(c) => c,
                                         Err(LitToConstError::Reported(err)) => {
-                                            ty::Const::new_error(tcx, err, ty)
+                                            ty::Const::new_error(tcx, err)
                                         }
                                         Err(LitToConstError::TypeError) => todo!(),
-                                    }
+                                    };
+                                    (ct, ty)
                                 }
 
                                 hir::ExprKind::Path(hir::QPath::Resolved(
@@ -2204,19 +2189,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                         .type_of(def_id)
                                         .no_bound_vars()
                                         .expect("const parameter types cannot be generic");
-                                    self.lower_const_param(expr.hir_id, ty)
+                                    let ct = self.lower_const_param(expr.hir_id);
+                                    (ct, ty)
                                 }
 
                                 _ => {
                                     let err = tcx
                                         .dcx()
                                         .emit_err(crate::errors::NonConstRange { span: expr.span });
-                                    ty::Const::new_error(tcx, err, ty)
+                                    (ty::Const::new_error(tcx, err), Ty::new_error(tcx, err))
                                 }
                             };
-                            self.record_ty(expr.hir_id, c.ty(), expr.span);
+                            self.record_ty(expr.hir_id, c_ty, expr.span);
                             if let Some((id, span)) = neg {
-                                self.record_ty(id, c.ty(), span);
+                                self.record_ty(id, c_ty, span);
                             }
                             c
                         };
@@ -2283,7 +2269,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         &lifetimes[i]
                     )
                 };
-                self.lower_lifetime(lifetime, None).into()
+                self.lower_lifetime(lifetime, RegionInferReason::Param(&param)).into()
             } else {
                 tcx.mk_param_from_def(param)
             }
@@ -2322,92 +2308,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let bound_vars = tcx.late_bound_vars(hir_id);
         debug!(?bound_vars);
 
-        // We proactively collect all the inferred type params to emit a single error per fn def.
-        let mut visitor = HirPlaceholderCollector::default();
-        let mut infer_replacements = vec![];
-
-        if let Some(generics) = generics {
-            walk_generics(&mut visitor, generics);
-        }
-
-        let input_tys: Vec<_> = decl
-            .inputs
-            .iter()
-            .enumerate()
-            .map(|(i, a)| {
-                if let hir::TyKind::Infer = a.kind
-                    && !self.allow_infer()
-                {
-                    if let Some(suggested_ty) =
-                        self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
-                    {
-                        infer_replacements.push((a.span, suggested_ty.to_string()));
-                        return Ty::new_error_with_message(
-                            self.tcx(),
-                            a.span,
-                            suggested_ty.to_string(),
-                        );
-                    }
-                }
-
-                // Only visit the type looking for `_` if we didn't fix the type above
-                visitor.visit_ty(a);
-                self.lower_arg_ty(a, None)
-            })
-            .collect();
-
-        let output_ty = match decl.output {
-            hir::FnRetTy::Return(output) => {
-                if let hir::TyKind::Infer = output.kind
-                    && !self.allow_infer()
-                    && let Some(suggested_ty) =
-                        self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
-                {
-                    infer_replacements.push((output.span, suggested_ty.to_string()));
-                    Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string())
-                } else {
-                    visitor.visit_ty(output);
-                    self.lower_ty(output)
-                }
-            }
-            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
-        };
+        let (input_tys, output_ty) = self.lower_fn_sig(decl, generics, hir_id, hir_ty);
 
         debug!(?output_ty);
 
         let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
         let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
 
-        if !self.allow_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
-            // We always collect the spans for placeholder types when evaluating `fn`s, but we
-            // only want to emit an error complaining about them if infer types (`_`) are not
-            // allowed. `allow_infer` gates this behavior. We check for the presence of
-            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
-
-            let mut diag = crate::collect::placeholder_type_error_diag(
-                tcx,
-                generics,
-                visitor.0,
-                infer_replacements.iter().map(|(s, _)| *s).collect(),
-                true,
-                hir_ty,
-                "function",
-            );
-
-            if !infer_replacements.is_empty() {
-                diag.multipart_suggestion(
-                    format!(
-                    "try replacing `_` with the type{} in the corresponding trait method signature",
-                    rustc_errors::pluralize!(infer_replacements.len()),
-                ),
-                    infer_replacements,
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            self.set_tainted_by_errors(diag.emit());
-        }
-
         // Find any late-bound regions declared in return type that do
         // not appear in the arguments. These are not well-formed.
         //
@@ -2437,7 +2344,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// corresponding function in the trait that the impl implements, if it exists.
     /// If arg_idx is Some, then it corresponds to an input type index, otherwise it
     /// corresponds to the return type.
-    fn suggest_trait_fn_ty_for_impl_fn_infer(
+    pub(super) fn suggest_trait_fn_ty_for_impl_fn_infer(
         &self,
         fn_hir_id: HirId,
         arg_idx: Option<usize>,
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 4f7a39d0250..34924f09d09 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
@@ -1,5 +1,7 @@
 use crate::bounds::Bounds;
-use crate::hir_ty_lowering::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
+use crate::hir_ty_lowering::{
+    GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds, RegionInferReason,
+};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
@@ -141,9 +143,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         // `trait_object_dummy_self`, so check for that.
                         let references_self = match pred.skip_binder().term.unpack() {
                             ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
-                            ty::TermKind::Const(c) => {
-                                c.ty().walk().any(|arg| arg == dummy_self.into())
-                            }
+                            // FIXME(associated_const_equality): We should walk the const instead of not doing anything
+                            ty::TermKind::Const(_) => false,
                         };
 
                         // If the projection output contains `Self`, force the user to
@@ -321,30 +322,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         // Use explicitly-specified region bound.
         let region_bound = if !lifetime.is_elided() {
-            self.lower_lifetime(lifetime, None)
+            self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault)
         } else {
             self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
                 if tcx.named_bound_var(lifetime.hir_id).is_some() {
-                    self.lower_lifetime(lifetime, None)
+                    self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault)
                 } else {
-                    self.re_infer(None, span).unwrap_or_else(|| {
-                        let err = struct_span_code_err!(
-                            tcx.dcx(),
-                            span,
-                            E0228,
-                            "the lifetime bound for this object type cannot be deduced \
-                             from context; please supply an explicit bound"
-                        );
-                        let e = if borrowed {
-                            // We will have already emitted an error E0106 complaining about a
-                            // missing named lifetime in `&dyn Trait`, so we elide this one.
-                            err.delay_as_bug()
+                    self.re_infer(
+                        span,
+                        if borrowed {
+                            RegionInferReason::ObjectLifetimeDefault
                         } else {
-                            err.emit()
-                        };
-                        self.set_tainted_by_errors(e);
-                        ty::Region::new_error(tcx, e)
-                    })
+                            RegionInferReason::BorrowedObjectLifetimeDefault
+                        },
+                    )
                 }
             })
         };
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 10101aa046e..13993a1992b 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -67,7 +67,7 @@ fn diagnostic_hir_wf_check<'tcx>(
     impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
             let infcx = self.tcx.infer_ctxt().build();
-            let ocx = ObligationCtxt::new(&infcx);
+            let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
             let tcx_ty = self.icx.lower_ty(ty);
             // This visitor can walk into binders, resulting in the `tcx_ty` to
@@ -158,7 +158,7 @@ fn diagnostic_hir_wf_check<'tcx>(
             },
             hir::Node::Field(field) => vec![field.ty],
             hir::Node::ForeignItem(ForeignItem {
-                kind: ForeignItemKind::Static(ty, _), ..
+                kind: ForeignItemKind::Static(ty, _, _), ..
             }) => vec![*ty],
             hir::Node::GenericParam(hir::GenericParam {
                 kind: hir::GenericParamKind::Type { default: Some(ty), .. },
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 002be61196a..5cc1ec71757 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -86,6 +86,8 @@ fn enforce_impl_params_are_constrained(
     let impl_predicates = tcx.predicates_of(impl_def_id);
     let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
 
+    impl_trait_ref.error_reported()?;
+
     let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
     cgp::identify_constrained_generic_params(
         tcx,
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 6967cb4d9d0..f3ce3ab6655 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
@@ -196,7 +196,7 @@ fn get_impl_args(
     impl2_node: Node,
 ) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
     let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
     let param_env = tcx.param_env(impl1_def_id);
     let impl1_span = tcx.def_span(impl1_def_id);
     let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 65b02a2ec56..8fe81851f93 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -190,6 +190,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         }
     });
 
+    // Freeze definitions as we don't add new ones at this point. This improves performance by
+    // allowing lock-free access to them.
+    tcx.untracked().definitions.freeze();
+
     // FIXME: Remove this when we implement creating `DefId`s
     // for anon constants during their parents' typeck.
     // Typeck all body owners in parallel will produce queries
@@ -201,10 +205,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         }
     });
 
-    // Freeze definitions as we don't add new ones at this point. This improves performance by
-    // allowing lock-free access to them.
-    tcx.untracked().definitions.freeze();
-
     tcx.ensure().check_unused_traits(());
 }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a8e0b3fc079..6f2febd86b0 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -84,6 +84,7 @@ impl<'a> State<'a> {
             Node::ImplItem(a) => self.print_impl_item(a),
             Node::Variant(a) => self.print_variant(a),
             Node::AnonConst(a) => self.print_anon_const(a),
+            Node::ConstBlock(a) => self.print_inline_const(a),
             Node::Expr(a) => self.print_expr(a),
             Node::ExprField(a) => self.print_expr_field(a),
             Node::Stmt(a) => self.print_stmt(a),
@@ -345,12 +346,12 @@ impl<'a> State<'a> {
         self.maybe_print_comment(item.span.lo());
         self.print_outer_attributes(self.attrs(item.hir_id()));
         match item.kind {
-            hir::ForeignItemKind::Fn(decl, arg_names, generics) => {
+            hir::ForeignItemKind::Fn(decl, arg_names, generics, safety) => {
                 self.head("");
                 self.print_fn(
                     decl,
                     hir::FnHeader {
-                        safety: hir::Safety::Safe,
+                        safety,
                         constness: hir::Constness::NotConst,
                         abi: Abi::Rust,
                         asyncness: hir::IsAsync::NotAsync,
@@ -364,7 +365,8 @@ impl<'a> State<'a> {
                 self.word(";");
                 self.end() // end the outer fn box
             }
-            hir::ForeignItemKind::Static(t, m) => {
+            hir::ForeignItemKind::Static(t, m, safety) => {
+                self.print_safety(safety);
                 self.head("static");
                 if m.is_mut() {
                     self.word_space("mut");
@@ -1048,10 +1050,10 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    fn print_inline_const(&mut self, constant: &hir::Expr<'_>) {
+    fn print_inline_const(&mut self, constant: &hir::ConstBlock) {
         self.ibox(INDENT_UNIT);
         self.word_space("const");
-        self.print_expr(constant);
+        self.ann.nested(self, Nested::Body(constant.body));
         self.end()
     }
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 14a6177141c..ac7ed3e26f9 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -485,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Since this is a return parameter type it is safe to unwrap.
-        let ret_param_ty = projection.skip_binder().term.ty().unwrap();
+        let ret_param_ty = projection.skip_binder().term.expect_type();
         let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty);
         debug!(?ret_param_ty);
 
@@ -956,7 +956,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let output_ty = self.resolve_vars_if_possible(predicate.term);
         debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty);
         // This is a projection on a Fn trait so will always be a type.
-        Some(output_ty.ty().unwrap())
+        Some(output_ty.expect_type())
     }
 
     /// Converts the types that the user supplied, in case that doing
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 93726ce2b3e..dbaa6e398c8 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -41,6 +41,7 @@ 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_analysis::hir_ty_lowering::HirTyLowerer;
+use rustc_infer::infer::relate::RelateResult;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
 use rustc_infer::traits::{Obligation, PredicateObligation};
@@ -51,7 +52,6 @@ use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
 };
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
 use rustc_session::parse::feature_err;
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index fa147f9bfcf..d2a5924c8bb 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -350,7 +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(), DUMMY_SP)
+                    self.next_const_var(DUMMY_SP)
                 } else {
                     ct
                 }
@@ -827,7 +827,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ) else {
             return;
         };
-        let in_scope_methods = self.probe_for_name_many(
+
+        let Ok(in_scope_methods) = self.probe_for_name_many(
             probe::Mode::MethodCall,
             path.ident,
             Some(expected),
@@ -835,11 +836,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self_ty,
             deref.hir_id,
             probe::ProbeScope::TraitsInScope,
-        );
+        ) else {
+            return;
+        };
+
         let other_methods_in_scope: Vec<_> =
             in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
 
-        let all_methods = self.probe_for_name_many(
+        let Ok(all_methods) = self.probe_for_name_many(
             probe::Mode::MethodCall,
             path.ident,
             Some(expected),
@@ -847,7 +851,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self_ty,
             deref.hir_id,
             probe::ProbeScope::AllTraits,
-        );
+        ) else {
+            return;
+        };
+
         let suggestions: Vec<_> = all_methods
             .into_iter()
             .filter(|c| c.item.def_id != pick.item.def_id)
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2f92a304bf0..5b27ebe3416 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -13,7 +13,6 @@ use crate::errors::{
     YieldExprOutsideOfCoroutine,
 };
 use crate::fatally_break_rust;
-use crate::method::SelfSource;
 use crate::type_error_struct;
 use crate::CoroutineTypes;
 use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
@@ -32,6 +31,7 @@ use rustc_errors::{
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
@@ -41,7 +41,7 @@ use rustc_infer::infer::InferOk;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
-use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
@@ -223,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = ensure_sufficient_stack(|| match &expr.kind {
             hir::ExprKind::Path(
                 qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),
-            ) => self.check_expr_path(qpath, expr, args, call),
+            ) => self.check_expr_path(qpath, expr, Some(args), call),
             _ => self.check_expr_kind(expr, expected),
         });
         let ty = self.resolve_vars_if_possible(ty);
@@ -290,7 +290,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Path(QPath::LangItem(lang_item, _)) => {
                 self.check_lang_item_path(lang_item, expr)
             }
-            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[], None),
+            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None, None),
             ExprKind::InlineAsm(asm) => {
                 // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
                 self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
@@ -335,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
             ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
-            ExprKind::ConstBlock(ref block) => self.check_expr_with_expectation(block, expected),
+            ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected),
             ExprKind::Repeat(element, ref count) => {
                 self.check_expr_repeat(element, count, expected, expr)
             }
@@ -502,12 +502,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         qpath: &'tcx hir::QPath<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
-        args: &'tcx [hir::Expr<'tcx>],
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
         call: Option<&'tcx hir::Expr<'tcx>>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
+            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
         let ty = match res {
             Res::Err => {
                 self.suggest_assoc_method_call(segs);
@@ -564,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We just want to check sizedness, so instead of introducing
                     // placeholder lifetimes with probing, we just replace higher lifetimes
                     // with fresh vars.
-                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
+                    let span = args.and_then(|args| args.get(i)).map_or(expr.span, |arg| arg.span);
                     let input = self.instantiate_binder_with_fresh_vars(
                         span,
                         infer::BoundRegionConversionTime::FnCall,
@@ -683,7 +683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.suggest_mismatched_types_on_tail(
                                 &mut err, expr, ty, e_ty, target_id,
                             );
-                            let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
+                            let error =
+                                Some(TypeError::Sorts(ExpectedFound { expected: ty, found: e_ty }));
                             self.annotate_loop_expected_due_to_inference(err, expr, error);
                             if let Some(val) =
                                 self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
@@ -1331,9 +1332,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let rcvr_t = self.check_expr(rcvr);
         // no need to check for bot/err -- callee does that
         let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
-        let span = segment.ident.span;
 
-        let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
+        let method = match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args)
+        {
             Ok(method) => {
                 // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
                 // trigger this codepath causing `structurally_resolve_type` to emit an error.
@@ -1342,18 +1343,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Err(error) => {
                 if segment.ident.name != kw::Empty {
-                    if let Some(err) = self.report_method_error(
-                        span,
-                        Some(rcvr),
-                        rcvr_t,
-                        segment.ident,
-                        expr.hir_id,
-                        SelfSource::MethodCall(rcvr),
-                        error,
-                        Some(args),
-                        expected,
-                        false,
-                    ) {
+                    if let Some(err) =
+                        self.report_method_error(expr.hir_id, rcvr_t, error, expected, false)
+                    {
                         err.emit();
                     }
                 }
@@ -1362,7 +1354,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Call the generic checker.
-        self.check_method_argument_types(span, expr, method, args, DontTupleArguments, expected)
+        self.check_method_argument_types(
+            segment.ident.span,
+            expr,
+            method,
+            args,
+            DontTupleArguments,
+            expected,
+        )
     }
 
     fn check_expr_cast(
@@ -1459,6 +1458,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn check_expr_const_block(
+        &self,
+        block: &'tcx hir::ConstBlock,
+        expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        let body = self.tcx.hir().body(block.body);
+
+        // Create a new function context.
+        let def_id = block.def_id;
+        let fcx = FnCtxt::new(self, self.param_env, def_id);
+        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, ObligationCauseCode::ConstSized);
+        fcx.write_ty(block.hir_id, ty);
+        ty
+    }
+
     fn check_expr_repeat(
         &self,
         element: &'tcx hir::Expr<'tcx>,
@@ -1674,6 +1691,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut error_happened = false;
 
+        if variant.fields.len() != remaining_fields.len() {
+            // Some field is defined more than once. Make sure we don't try to
+            // instantiate this struct in static/const context.
+            let guar =
+                self.dcx().span_delayed_bug(expr.span, "struct fields have non-unique names");
+            self.set_tainted_by_errors(guar);
+            error_happened = true;
+        }
+
         // Type-check each field.
         for (idx, field) in hir_fields.iter().enumerate() {
             let ident = tcx.adjust_ident(field.ident, variant.def_id);
@@ -3049,7 +3075,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.commit_if_ok(|snapshot| {
             let outer_universe = self.universe();
 
-            let ocx = ObligationCtxt::new(self);
+            let ocx = ObligationCtxt::new_with_diagnostics(self);
             let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
             let impl_trait_ref =
                 self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);
@@ -3337,7 +3363,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     let field_ty = self.field_ty(expr.span, field, args);
 
-                    // FIXME: DSTs with static alignment should be allowed
+                    // Enums are anyway always sized. But just to safeguard against future
+                    // language extensions, let's double-check.
                     self.require_type_is_sized(field_ty, expr.span, ObligationCauseCode::Misc);
 
                     if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
@@ -3365,8 +3392,19 @@ 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, ObligationCauseCode::Misc);
+                        if self.tcx.features().offset_of_slice {
+                            self.require_type_has_static_alignment(
+                                field_ty,
+                                expr.span,
+                                ObligationCauseCode::Misc,
+                            );
+                        } else {
+                            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);
@@ -3386,10 +3424,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if let Ok(index) = field.as_str().parse::<usize>()
                         && field.name == sym::integer(index)
                     {
-                        for ty in tys.iter().take(index + 1) {
-                            self.require_type_is_sized(ty, expr.span, ObligationCauseCode::Misc);
-                        }
                         if let Some(&field_ty) = tys.get(index) {
+                            if self.tcx.features().offset_of_slice {
+                                self.require_type_has_static_alignment(
+                                    field_ty,
+                                    expr.span,
+                                    ObligationCauseCode::Misc,
+                                );
+                            } else {
+                                self.require_type_is_sized(
+                                    field_ty,
+                                    expr.span,
+                                    ObligationCauseCode::Misc,
+                                );
+                            }
+
                             field_indices.push((FIRST_VARIANT, index.into()));
                             current_container = field_ty;
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 0c10c67db8c..e354e1ec59c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1,6 +1,6 @@
 use crate::callee::{self, DeferredCallResolution};
 use crate::errors::{self, CtorIsPrivate};
-use crate::method::{self, MethodCallee, SelfSource};
+use crate::method::{self, MethodCallee};
 use crate::rvalue_scopes;
 use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
 use rustc_data_structures::fx::FxHashSet;
@@ -16,7 +16,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
 };
 use rustc_hir_analysis::hir_ty_lowering::{
     ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
-    GenericPathSegment, HirTyLowerer, IsMethodCall,
+    GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
 };
 use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
@@ -386,6 +386,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub fn require_type_has_static_alignment(
+        &self,
+        ty: Ty<'tcx>,
+        span: Span,
+        code: traits::ObligationCauseCode<'tcx>,
+    ) {
+        if !ty.references_error() {
+            let tail =
+                self.tcx.struct_tail_with_normalize(ty, |ty| self.normalize(span, ty), || {});
+            // Sized types have static alignment, and so do slices.
+            if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) {
+                // Nothing else is required here.
+            } else {
+                // We can't be sure, let's required full `Sized`.
+                let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
+                self.require_type_meets(ty, span, code, lang_item);
+            }
+        }
+    }
+
     pub fn register_bound(
         &self,
         ty: Ty<'tcx>,
@@ -436,7 +456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
         match length {
-            hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span),
+            hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
             hir::ArrayLen::Body(anon_const) => {
                 let span = self.tcx.def_span(anon_const.def_id);
                 let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
@@ -735,7 +755,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &'tcx QPath<'tcx>,
         hir_id: HirId,
         span: Span,
-        args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
         debug!(
             "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
@@ -828,14 +847,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 if item_name.name != kw::Empty {
                     if let Some(e) = self.report_method_error(
-                        span,
-                        None,
-                        ty.normalized,
-                        item_name,
                         hir_id,
-                        SelfSource::QPath(qself),
+                        ty.normalized,
                         error,
-                        args,
                         Expectation::NoExpectation,
                         trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
@@ -1072,7 +1086,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::ImplContainer => {
                         if segments.len() == 1 {
                             // `<T>::assoc` will end up here, and so
-                            // can `T::assoc`. It this came from an
+                            // can `T::assoc`. If this came from an
                             // inherent impl, we need to record the
                             // `T` for posterity (see `UserSelfTy` for
                             // details).
@@ -1118,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
 
-        let mut infer_args_for_err = FxHashSet::default();
+        let mut infer_args_for_err = None;
 
         let mut explicit_late_bound = ExplicitLateBound::No;
         for &GenericPathSegment(def_id, index) in &generic_segments {
@@ -1136,9 +1150,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 explicit_late_bound = ExplicitLateBound::Yes;
             }
 
-            if let Err(GenericArgCountMismatch { reported: Some(e), .. }) = arg_count.correct {
-                infer_args_for_err.insert(index);
-                self.set_tainted_by_errors(e); // See issue #53251.
+            if let Err(GenericArgCountMismatch { reported, .. }) = arg_count.correct {
+                infer_args_for_err
+                    .get_or_insert_with(|| (reported, FxHashSet::default()))
+                    .1
+                    .insert(index);
+                self.set_tainted_by_errors(reported); // See issue #53251.
             }
         }
 
@@ -1232,15 +1249,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         let def_id = res.def_id();
 
-        let arg_count = GenericArgCountResult {
-            explicit_late_bound,
-            correct: if infer_args_for_err.is_empty() {
-                Ok(())
-            } else {
-                Err(GenericArgCountMismatch::default())
-            },
+        let (correct, infer_args_for_err) = match infer_args_for_err {
+            Some((reported, args)) => {
+                (Err(GenericArgCountMismatch { reported, invalid_args: vec![] }), args)
+            }
+            None => (Ok(()), Default::default()),
         };
 
+        let arg_count = GenericArgCountResult { explicit_late_bound, correct };
+
         struct CtorGenericArgsCtxt<'a, 'tcx> {
             fcx: &'a FnCtxt<'a, 'tcx>,
             span: Span,
@@ -1272,13 +1289,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             fn provided_kind(
                 &mut self,
+                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
-                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        self.fcx.lowerer().lower_lifetime(lt, Some(param)).into()
-                    }
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => self
+                        .fcx
+                        .lowerer()
+                        .lower_lifetime(lt, RegionInferReason::Param(param))
+                        .into(),
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                         self.fcx.lower_ty(ty).raw.into()
                     }
@@ -1292,20 +1312,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         &GenericParamDefKind::Const { has_default, is_host_effect },
                         GenericArg::Infer(inf),
                     ) => {
-                        let tcx = self.fcx.tcx();
-
                         if has_default && is_host_effect {
                             self.fcx.var_for_effect(param)
                         } else {
-                            self.fcx
-                                .ct_infer(
-                                    tcx.type_of(param.def_id)
-                                        .no_bound_vars()
-                                        .expect("const parameter types cannot be generic"),
-                                    Some(param),
-                                    inf.span,
-                                )
-                                .into()
+                            self.fcx.ct_infer(Some(param), inf.span).into()
                         }
                     }
                     _ => unreachable!(),
@@ -1314,21 +1324,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             fn inferred_kind(
                 &mut self,
-                args: Option<&[ty::GenericArg<'tcx>]>,
+                preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 infer_args: bool,
             ) -> ty::GenericArg<'tcx> {
                 let tcx = self.fcx.tcx();
                 match param.kind {
-                    GenericParamDefKind::Lifetime => {
-                        self.fcx.re_infer(Some(param), self.span).unwrap().into()
-                    }
+                    GenericParamDefKind::Lifetime => self
+                        .fcx
+                        .re_infer(
+                            self.span,
+                            rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param),
+                        )
+                        .into(),
                     GenericParamDefKind::Type { has_default, .. } => {
                         if !infer_args && has_default {
                             // If we have a default, then it doesn't matter that we're not
                             // inferring the type arguments: we provide the default where any
                             // is missing.
-                            tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into()
+                            tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into()
                         } else {
                             // If no type arguments were provided, we have to infer them.
                             // This case also occurs as a result of some malformed input, e.g.
@@ -1353,7 +1367,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             } else if !infer_args {
                                 return tcx
                                     .const_param_default(param.def_id)
-                                    .instantiate(tcx, args.unwrap())
+                                    .instantiate(tcx, preceding_args)
                                     .into();
                             }
                         }
@@ -1412,11 +1426,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ) {
                 Ok(ok) => self.register_infer_ok_obligations(ok),
                 Err(_) => {
-                    self.dcx().span_delayed_bug(
+                    self.dcx().span_bug(
                         span,
                         format!(
-                        "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
-                    ),
+                            "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
+                        ),
                     );
                 }
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index afba812a8e7..f02b0f95390 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -15,7 +15,7 @@ use hir::def_id::CRATE_DEF_ID;
 use rustc_errors::DiagCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
+use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
 use rustc_infer::infer;
 use rustc_infer::infer::error_reporting::sub_relations::SubRelations;
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
@@ -213,25 +213,21 @@ impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn item_def_id(&self) -> DefId {
-        self.body_id.to_def_id()
+    fn item_def_id(&self) -> LocalDefId {
+        self.body_id
     }
 
-    fn allow_infer(&self) -> bool {
-        true
-    }
-
-    fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>> {
-        let v = match def {
-            Some(def) => infer::RegionParameterDefinition(span, def.name),
-            None => infer::MiscVariable(span),
+    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
+        let v = match reason {
+            RegionInferReason::Param(def) => infer::RegionParameterDefinition(span, def.name),
+            _ => infer::MiscVariable(span),
         };
-        Some(self.next_region_var(v))
+        self.next_region_var(v)
     }
 
     fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
@@ -241,12 +237,7 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn ct_infer(
-        &self,
-        ty: Ty<'tcx>,
-        param: Option<&ty::GenericParamDef>,
-        span: Span,
-    ) -> Const<'tcx> {
+    fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
         // FIXME ideally this shouldn't use unwrap
         match param {
             Some(
@@ -256,7 +247,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, span),
+            None => self.next_const_var(span),
         }
     }
 
@@ -350,6 +341,22 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> {
     fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
         self.infcx.set_tainted_by_errors(e)
     }
+
+    fn lower_fn_sig(
+        &self,
+        decl: &rustc_hir::FnDecl<'tcx>,
+        _generics: Option<&rustc_hir::Generics<'_>>,
+        _hir_id: rustc_hir::HirId,
+        _hir_ty: Option<&hir::Ty<'_>>,
+    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
+        let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_arg_ty(a, None)).collect();
+
+        let output_ty = match decl.output {
+            hir::FnRetTy::Return(output) => self.lowerer().lower_ty(output),
+            hir::FnRetTy::DefaultReturn(..) => self.tcx().types.unit,
+        };
+        (input_tys, output_ty)
+    }
 }
 
 /// The `ty` representation of a user-provided type. Depending on the use-site
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 5723b73a328..9ab89f3444c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -22,7 +22,6 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::traits;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
@@ -36,6 +35,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
 use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -1051,10 +1051,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .take_while(|(_, node)| {
                     // look at parents until we find the first body owner
                     node.body_id().is_none()
-                        && !matches!(
-                            node,
-                            Node::Expr(Expr { kind: ExprKind::ConstBlock { .. }, .. })
-                        )
                 })
                 .any(|(parent_id, _)| self.is_loop(parent_id));
 
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 9c64f9475cf..3c9a49e91a3 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -7,7 +7,9 @@ use rustc_hir::GenericArg;
 use rustc_hir_analysis::hir_ty_lowering::generics::{
     check_generic_arg_count_for_call, lower_generic_args,
 };
-use rustc_hir_analysis::hir_ty_lowering::{GenericArgsLowerer, HirTyLowerer, IsMethodCall};
+use rustc_hir_analysis::hir_ty_lowering::{
+    GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason,
+};
 use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
 use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@@ -383,13 +385,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
             fn provided_kind(
                 &mut self,
+                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
                 match (&param.kind, arg) {
-                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                        self.cfcx.fcx.lowerer().lower_lifetime(lt, Some(param)).into()
-                    }
+                    (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => self
+                        .cfcx
+                        .fcx
+                        .lowerer()
+                        .lower_lifetime(lt, RegionInferReason::Param(param))
+                        .into(),
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                         self.cfcx.lower_ty(ty).raw.into()
                     }
@@ -400,16 +406,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                         self.cfcx.ty_infer(Some(param), inf.span).into()
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
-                        let tcx = self.cfcx.tcx();
-                        self.cfcx
-                            .ct_infer(
-                                tcx.type_of(param.def_id)
-                                    .no_bound_vars()
-                                    .expect("const parameter types cannot be generic"),
-                                Some(param),
-                                inf.span,
-                            )
-                            .into()
+                        self.cfcx.ct_infer(Some(param), inf.span).into()
                     }
                     (kind, arg) => {
                         bug!("mismatched method arg kind {kind:?} in turbofish: {arg:?}")
@@ -419,7 +416,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
             fn inferred_kind(
                 &mut self,
-                _args: Option<&[ty::GenericArg<'tcx>]>,
+                _preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 _infer_args: bool,
             ) -> ty::GenericArg<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 4165ccb1b80..1f90d5e4c88 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,7 +7,6 @@ mod prelude_edition_lints;
 pub mod probe;
 mod suggest;
 
-pub use self::suggest::SelfSource;
 pub use self::MethodError::*;
 
 use crate::FnCtxt;
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 97a74b55c53..e842bba34bf 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -41,6 +41,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
 use rustc_trait_selection::traits::query::CanonicalTyGoal;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCause};
+use std::cell::Cell;
 use std::cell::RefCell;
 use std::cmp::max;
 use std::iter;
@@ -76,8 +77,12 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
     /// requested name (by edit distance)
     allow_similar_names: bool,
 
+    /// List of potential private candidates. Will be trimmed to ones that
+    /// actually apply and then the result inserted into `private_candidate`
+    private_candidates: Vec<Candidate<'tcx>>,
+
     /// Some(candidate) if there is a private candidate
-    private_candidate: Option<(DefKind, DefId)>,
+    private_candidate: Cell<Option<(DefKind, DefId)>>,
 
     /// Collects near misses when the candidate functions are missing a `self` keyword and is only
     /// used for error reporting
@@ -301,7 +306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self_ty: Ty<'tcx>,
         scope_expr_id: HirId,
         scope: ProbeScope,
-    ) -> Vec<Candidate<'tcx>> {
+    ) -> Result<Vec<Candidate<'tcx>>, MethodError<'tcx>> {
         self.probe_op(
             item_name.span,
             mode,
@@ -319,7 +324,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .collect())
             },
         )
-        .unwrap()
     }
 
     pub(crate) fn probe_op<OP, R>(
@@ -581,7 +585,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             orig_steps_var_values,
             steps,
             allow_similar_names: false,
-            private_candidate: None,
+            private_candidates: Vec::new(),
+            private_candidate: Cell::new(None),
             static_candidates: RefCell::new(Vec::new()),
             unsatisfied_predicates: RefCell::new(Vec::new()),
             scope_expr_id,
@@ -593,7 +598,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         self.inherent_candidates.clear();
         self.extension_candidates.clear();
         self.impl_dups.clear();
-        self.private_candidate = None;
+        self.private_candidates.clear();
+        self.private_candidate.set(None);
         self.static_candidates.borrow_mut().clear();
         self.unsatisfied_predicates.borrow_mut().clear();
     }
@@ -617,9 +623,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             } else {
                 self.extension_candidates.push(candidate);
             }
-        } else if self.private_candidate.is_none() {
-            self.private_candidate =
-                Some((candidate.item.kind.as_def_kind(), candidate.item.def_id));
+        } else {
+            self.private_candidates.push(candidate);
         }
     }
 
@@ -1171,7 +1176,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let mut possibly_unsatisfied_predicates = Vec::new();
 
         for (kind, candidates) in
-            &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
+            [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
         {
             debug!("searching {} candidates", kind);
             let res = self.consider_candidates(
@@ -1185,6 +1190,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             }
         }
 
+        if self.private_candidate.get().is_none() {
+            if let Some(Ok(pick)) =
+                self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None)
+            {
+                self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
+            }
+        }
+
         // `pick_method` may be called twice for the same self_ty if no stable methods
         // match. Only extend once.
         if unstable_candidates.is_some() {
@@ -1390,7 +1403,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
             let mut result = ProbeResult::Match;
             let cause = &self.misc(self.span);
-            let ocx = ObligationCtxt::new(self);
+            let ocx = ObligationCtxt::new_with_diagnostics(self);
 
             let mut trait_predicate = None;
             let (mut xform_self_ty, mut xform_ret_ty);
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index daaaf630f2c..bbe4a8791c6 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -16,11 +16,11 @@ use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, MultiSpan, StashKey,
 };
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::PathSegment;
+use rustc_hir::{self as hir, HirId};
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::{self, RegionVariableOrigin};
 use rustc_middle::bug;
@@ -187,37 +187,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn report_method_error(
         &self,
-        span: Span,
-        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
+        call_id: HirId,
         rcvr_ty: Ty<'tcx>,
-        item_name: Ident,
-        expr_id: hir::HirId,
-        source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
-        args: Option<&'tcx [hir::Expr<'tcx>]>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
     ) -> Option<Diag<'_>> {
+        let (span, sugg_span, source, item_name, args) = match self.tcx.hir_node(call_id) {
+            hir::Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::MethodCall(segment, rcvr, args, _),
+                span,
+                ..
+            }) => {
+                (segment.ident.span, span, SelfSource::MethodCall(rcvr), segment.ident, Some(args))
+            }
+            hir::Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Path(QPath::TypeRelative(rcvr, segment)),
+                span,
+                ..
+            })
+            | hir::Node::Pat(&hir::Pat {
+                kind:
+                    hir::PatKind::Path(QPath::TypeRelative(rcvr, segment))
+                    | hir::PatKind::Struct(QPath::TypeRelative(rcvr, segment), ..)
+                    | hir::PatKind::TupleStruct(QPath::TypeRelative(rcvr, segment), ..),
+                span,
+                ..
+            }) => {
+                let args = match self.tcx.parent_hir_node(call_id) {
+                    hir::Node::Expr(&hir::Expr {
+                        kind: hir::ExprKind::Call(callee, args), ..
+                    }) if callee.hir_id == call_id => Some(args),
+                    _ => None,
+                };
+                (segment.ident.span, span, SelfSource::QPath(rcvr), segment.ident, args)
+            }
+            node => unreachable!("{node:?}"),
+        };
+
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
             return None;
         }
 
-        let sugg_span = if let SelfSource::MethodCall(expr) = source {
-            // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
-            self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id)).span
-        } else {
-            span
-        };
-
         match error {
             MethodError::NoMatch(mut no_match_data) => {
                 return self.report_no_match_method_error(
                     span,
-                    rcvr_opt,
                     rcvr_ty,
                     item_name,
-                    expr_id,
+                    call_id,
                     source,
                     args,
                     sugg_span,
@@ -362,7 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn suggest_use_shadowed_binding_with_method(
         &self,
-        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
+        self_source: SelfSource<'tcx>,
         method_name: Ident,
         ty_str_reported: &str,
         err: &mut Diag<'_>,
@@ -502,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        if let Some(rcvr) = rcvr_opt
+        if let SelfSource::MethodCall(rcvr) = self_source
             && let hir::ExprKind::Path(QPath::Resolved(_, path)) = rcvr.kind
             && let hir::def::Res::Local(recv_id) = path.res
             && let Some(segment) = path.segments.first()
@@ -548,7 +567,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn report_no_match_method_error(
         &self,
         mut span: Span,
-        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         expr_id: hir::HirId,
@@ -658,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             if is_method {
                 self.suggest_use_shadowed_binding_with_method(
-                    rcvr_opt,
+                    source,
                     item_name,
                     &ty_str_reported,
                     &mut err,
@@ -1622,10 +1640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .unwrap_or(Ty::new_misc_error(self.tcx)),
                 );
 
-                // FIXME: `probe_for_name_many` searches for methods in inherent implementations,
-                // so it may return a candidate that doesn't belong to this `revr_ty`. We need to
-                // check whether the instantiated type matches the received one.
-                for _matched_method in self.probe_for_name_many(
+                let Ok(candidates) = self.probe_for_name_many(
                     Mode::MethodCall,
                     item_name,
                     None,
@@ -1633,7 +1648,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     rcvr_ty,
                     source_expr.hir_id,
                     ProbeScope::TraitsInScope,
-                ) {
+                ) else {
+                    return;
+                };
+
+                // FIXME: `probe_for_name_many` searches for methods in inherent implementations,
+                // so it may return a candidate that doesn't belong to this `revr_ty`. We need to
+                // check whether the instantiated type matches the received one.
+                for _matched_method in candidates {
                     // found a match, push to stack
                     stack_methods.push(rcvr_ty);
                 }
@@ -2078,9 +2100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
                                 .into(),
                             GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
-                            GenericArgKind::Const(arg) => {
-                                self.next_const_var(arg.ty(), DUMMY_SP).into()
-                            }
+                            GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
                         }
                     } else {
                         arg
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 25b74dca12f..d774ae2146a 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -928,7 +928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let (obligation, _) =
                     self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
                 // FIXME: This should potentially just add the obligation to the `FnCtxt`
-                let ocx = ObligationCtxt::new(&self.infcx);
+                let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
                 ocx.register_obligation(obligation);
                 Err(ocx.select_all_or_error())
             }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b37aba38619..9476dc70483 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
-use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
+use rustc_session::{lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS, parse::feature_err};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::Spanned;
@@ -223,9 +223,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
 
         let path_res = match &pat.kind {
-            PatKind::Path(qpath) => Some(
-                self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None),
-            ),
+            PatKind::Path(qpath) => {
+                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
+            }
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
@@ -335,9 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match adjust_mode {
             AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
             AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
-            AdjustMode::Peel => {
-                self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl)
-            }
+            AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
         }
     }
 
@@ -408,8 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
         mut def_br: ByRef,
-        max_peelable_mutability: Mutability,
-        mut max_ref_mutability: MutblCap,
+        mut max_ref_mutbl: MutblCap,
     ) -> (Ty<'tcx>, ByRef, MutblCap) {
         let mut expected = self.try_structurally_resolve_type(pat.span, expected);
         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
@@ -421,9 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // See the examples in `ui/match-defbm*.rs`.
         let mut pat_adjustments = vec![];
-        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
-            && inner_mutability <= max_peelable_mutability
-        {
+        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
             debug!("inspecting {:?}", expected);
 
             debug!("current discriminant is Ref, inserting implicit deref");
@@ -443,10 +438,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
         }
 
-        if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
-            def_br = def_br.cap_ref_mutability(max_ref_mutability.as_mutbl());
+        if self.tcx.features().ref_pat_eat_one_layer_2024 {
+            def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
             if def_br == ByRef::Yes(Mutability::Not) {
-                max_ref_mutability = MutblCap::Not;
+                max_ref_mutbl = MutblCap::Not;
             }
         }
 
@@ -458,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .insert(pat.hir_id, pat_adjustments);
         }
 
-        (expected, def_br, max_ref_mutability)
+        (expected, def_br, max_ref_mutbl)
     }
 
     fn check_pat_lit(
@@ -674,17 +669,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Determine the binding mode...
         let bm = match user_bind_annot {
-            // `mut` resets binding mode on edition <= 2021
-            BindingMode(ByRef::No, Mutability::Mut)
-                if !(pat.span.at_least_rust_2024()
-                    && self.tcx.features().mut_preserve_binding_mode_2024)
-                    && matches!(def_br, ByRef::Yes(_)) =>
-            {
-                self.typeck_results
-                    .borrow_mut()
-                    .rust_2024_migration_desugared_pats_mut()
-                    .insert(pat_info.top_info.hir_id);
-                BindingMode(ByRef::No, Mutability::Mut)
+            BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
+                if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+                    if !self.tcx.features().mut_ref {
+                        feature_err(
+                            &self.tcx.sess,
+                            sym::mut_ref,
+                            pat.span.until(ident.span),
+                            "binding cannot be both mutable and by-reference",
+                        )
+                        .emit();
+                    }
+
+                    BindingMode(def_br, Mutability::Mut)
+                } else {
+                    // `mut` resets binding mode on edition <= 2021
+                    self.typeck_results
+                        .borrow_mut()
+                        .rust_2024_migration_desugared_pats_mut()
+                        .insert(pat_info.top_info.hir_id);
+                    BindingMode(ByRef::No, Mutability::Mut)
+                }
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
             BindingMode(ByRef::Yes(_), _) => user_bind_annot,
@@ -1184,7 +1189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Resolve the path and check the definition for errors.
         let (res, opt_ty, segments) =
-            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
+            self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
         if res == Res::Err {
             let e = tcx.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
             self.set_tainted_by_errors(e);
@@ -2126,57 +2131,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         mut expected: Ty<'tcx>,
         mut pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        // FIXME: repace with `bool` once final decision on 1 vs 2 layers is made
-        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-        enum MatchErgonomicsMode {
-            EatOneLayer,
-            EatTwoLayers,
-            Legacy,
-        }
+        let no_ref_mut_behind_and = self.tcx.features().ref_pat_eat_one_layer_2024;
+        let new_match_ergonomics = pat.span.at_least_rust_2024() && no_ref_mut_behind_and;
 
-        let match_ergonomics_mode =
-            if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
-                MatchErgonomicsMode::EatOneLayer
-            } else if self.tcx.features().ref_pat_everywhere {
-                MatchErgonomicsMode::EatTwoLayers
-            } else {
-                MatchErgonomicsMode::Legacy
-            };
+        let pat_prefix_span =
+            inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end));
 
-        let mut inherited_ref_mutbl_match = false;
-        if match_ergonomics_mode != MatchErgonomicsMode::Legacy {
+        if no_ref_mut_behind_and {
             if pat_mutbl == Mutability::Not {
                 // Prevent the inner pattern from binding with `ref mut`.
-                pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(
-                    inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)),
-                );
+                pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
             }
+        } else {
+            pat_info.max_ref_mutbl = MutblCap::Mut;
+        }
 
+        if new_match_ergonomics {
             if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
-                inherited_ref_mutbl_match = pat_mutbl <= inh_mut;
-            }
+                // ref pattern consumes inherited reference
+
+                if pat_mutbl > inh_mut {
+                    // Tried to match inherited `ref` with `&mut`, which is an error
+                    let err_msg = "cannot match inherited `&` with `&mut` pattern";
+                    let err = if let Some(span) = pat_prefix_span {
+                        let mut err = self.dcx().struct_span_err(span, err_msg);
+                        err.span_suggestion_verbose(
+                            span,
+                            "replace this `&mut` pattern with `&`",
+                            "&",
+                            Applicability::MachineApplicable,
+                        );
+                        err
+                    } else {
+                        self.dcx().struct_span_err(pat.span, err_msg)
+                    };
+                    err.emit();
+                }
 
-            if inherited_ref_mutbl_match {
                 pat_info.binding_mode = ByRef::No;
-                if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer {
-                    self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
-                    self.check_pat(inner, expected, pat_info);
-                    return expected;
-                }
-            } else if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer
-                && pat_mutbl == Mutability::Mut
-            {
-                // `&mut` patterns pell off `&` references
-                let (new_expected, new_bm, max_ref_mutbl) = self.peel_off_references(
-                    pat,
-                    expected,
-                    pat_info.binding_mode,
-                    Mutability::Not,
-                    pat_info.max_ref_mutbl,
-                );
-                expected = new_expected;
-                pat_info.binding_mode = new_bm;
-                pat_info.max_ref_mutbl = max_ref_mutbl;
+                self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+                self.check_pat(inner, expected, pat_info);
+                return expected;
             }
         } else {
             // Reset binding mode on old editions
@@ -2189,8 +2184,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .rust_2024_migration_desugared_pats_mut()
                     .insert(pat_info.top_info.hir_id);
             }
-
-            pat_info.max_ref_mutbl = MutblCap::Mut;
         }
 
         let tcx = self.tcx;
@@ -2205,34 +2198,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // the bad interactions of the given hack detailed in (note_1).
                 debug!("check_pat_ref: expected={:?}", expected);
                 match *expected.kind() {
-                    ty::Ref(_, r_ty, r_mutbl) if r_mutbl == pat_mutbl => {
-                        if r_mutbl == Mutability::Not
-                            && match_ergonomics_mode != MatchErgonomicsMode::Legacy
-                        {
+                    ty::Ref(_, r_ty, r_mutbl)
+                        if (new_match_ergonomics && r_mutbl >= pat_mutbl)
+                            || r_mutbl == pat_mutbl =>
+                    {
+                        if no_ref_mut_behind_and && r_mutbl == Mutability::Not {
                             pat_info.max_ref_mutbl = MutblCap::Not;
                         }
 
                         (expected, r_ty)
                     }
 
-                    // `&` pattern eats `&mut` reference
-                    ty::Ref(_, r_ty, Mutability::Mut)
-                        if pat_mutbl == Mutability::Not
-                            && match_ergonomics_mode != MatchErgonomicsMode::Legacy =>
-                    {
-                        (expected, r_ty)
-                    }
-
-                    _ if inherited_ref_mutbl_match
-                        && match_ergonomics_mode == MatchErgonomicsMode::EatTwoLayers =>
-                    {
-                        // We already matched against a match-ergonmics inserted reference,
-                        // so we don't need to match against a reference from the original type.
-                        // Save this info for use in lowering later
-                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
-                        (expected, expected)
-                    }
-
                     _ => {
                         let inner_ty = self.next_ty_var(inner.span);
                         let ref_ty = self.new_ref_ty(pat.span, pat_mutbl, inner_ty);
@@ -2409,10 +2385,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         min_len: u64,
     ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
         let len = match len.eval(self.tcx, self.param_env, span) {
-            Ok(val) => val
+            Ok((_, val)) => val
                 .try_to_scalar()
-                .and_then(|scalar| scalar.try_to_int().ok())
-                .and_then(|int| int.try_to_target_usize(self.tcx).ok()),
+                .and_then(|scalar| scalar.try_to_scalar_int().ok())
+                .map(|int| int.to_target_usize(self.tcx)),
             Err(ErrorHandled::Reported(..)) => {
                 let guar = self.error_scrutinee_unfixed_length(span);
                 return (Some(Ty::new_error(self.tcx, guar)), arr_ty);
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 19d6481cc1b..28745af3a53 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -11,7 +11,9 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefIdMap;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
+use rustc_trait_selection::traits::{
+    self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _,
+};
 
 use std::cell::RefCell;
 use std::ops::Deref;
@@ -34,7 +36,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
 
     pub(super) locals: RefCell<HirIdMap<Ty<'tcx>>>,
 
-    pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
+    pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
 
     /// Some additional `Sized` obligations badly affect type inference.
     /// These obligations are added in a later stage of typeck.
@@ -83,7 +85,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
 
         TypeckRootCtxt {
             typeck_results,
-            fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
+            fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
             infcx,
             locals: RefCell::new(Default::default()),
             deferred_sized_obligations: RefCell::new(Vec::new()),
@@ -158,7 +160,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
         {
             // If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
             // we need to make it into one.
-            if let Some(vid) = predicate.term.ty().and_then(|ty| ty.ty_vid()) {
+            if let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid()) {
                 debug!("infer_var_info: {:?}.output = true", vid);
                 infer_var_info.entry(vid).or_default().output = true;
             }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 4386e68ce86..466397817da 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -149,6 +149,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
                 self.visit_body(body);
                 self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
             }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.fcx.tcx.hir().body(anon_const.body);
+                self.visit_body(body);
+            }
             _ => {}
         }
 
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index e337105f011..b67d29fce92 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -3,7 +3,6 @@
 // generic parameters.
 
 use crate::FnCtxt;
-use hir::def::DefKind;
 use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
@@ -17,7 +16,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::TypeSuperFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::solve;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -296,11 +295,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
                 self.visit_field_id(e.hir_id);
             }
-            hir::ExprKind::ConstBlock(_) => {
-                let feed = self.tcx().create_def(self.fcx.body_id, kw::Empty, DefKind::InlineConst);
-                feed.def_span(e.span);
-                feed.local_def_id_to_hir_id(e.hir_id);
-                self.typeck_results.inline_consts.insert(e.hir_id.local_id, feed.def_id());
+            hir::ExprKind::ConstBlock(anon_const) => {
+                self.visit_node_id(e.span, anon_const.hir_id);
+
+                let body = self.tcx().hir().body(anon_const.body);
+                self.visit_body(body);
             }
             _ => {}
         }
@@ -863,7 +862,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
-            ty::Const::new_error(tcx, guar, ct.ty())
+            ty::Const::new_error(tcx, guar)
         })
         .super_fold_with(self)
     }
diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml
index c4ca29db3c2..07ee81788ce 100644
--- a/compiler/rustc_index_macros/Cargo.toml
+++ b/compiler/rustc_index_macros/Cargo.toml
@@ -7,11 +7,10 @@ edition = "2021"
 proc-macro = true
 
 [dependencies]
-synstructure = "0.13.0"
 syn = { version = "2.0.9", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
 
 [features]
 default = ["nightly"]
-nightly = []
\ No newline at end of file
+nightly = []
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index c1565a7d40f..5136ab79a0f 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -18,6 +18,7 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
+rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 17e6d6250ad..046d908d148 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -27,8 +27,8 @@
 
 use super::*;
 
+use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
 use rustc_middle::bug;
-use rustc_middle::ty::relate::{Relate, TypeRelation};
 use rustc_middle::ty::{Const, ImplSubject};
 
 /// Whether we should define opaque types or just treat them opaquely.
@@ -90,7 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 }
 
-pub trait ToTrace<'tcx>: Relate<'tcx> + Copy {
+pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {
     fn to_trace(
         cause: &ObligationCause<'tcx>,
         a_is_expected: bool,
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 27b06c4b73e..bc2592b43f3 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -462,7 +462,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 // any equated inference vars correctly!
                 let root_vid = self.infcx.unwrap().root_const_var(vid);
                 if root_vid != vid {
-                    ct = ty::Const::new_var(self.tcx, root_vid, ct.ty());
+                    ct = ty::Const::new_var(self.tcx, root_vid);
                     vid = root_vid;
                 }
 
@@ -481,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                             ui = ty::UniverseIndex::ROOT;
                         }
                         return self.canonicalize_const_var(
-                            CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty()) },
+                            CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
                             ct,
                         );
                     }
@@ -510,9 +510,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
             }
             ty::ConstKind::Placeholder(placeholder) => {
                 return self.canonicalize_const_var(
-                    CanonicalVarInfo {
-                        kind: CanonicalVarKind::PlaceholderConst(placeholder, ct.ty()),
-                    },
+                    CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
                     ct,
                 );
             }
@@ -719,9 +717,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
                     CanonicalVarKind::Region(u) => {
                         CanonicalVarKind::Region(reverse_universe_map[&u])
                     }
-                    CanonicalVarKind::Const(u, t) => {
-                        CanonicalVarKind::Const(reverse_universe_map[&u], t)
-                    }
+                    CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
                     CanonicalVarKind::PlaceholderTy(placeholder) => {
                         CanonicalVarKind::PlaceholderTy(ty::Placeholder {
                             universe: reverse_universe_map[&placeholder.universe],
@@ -734,14 +730,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
                             ..placeholder
                         })
                     }
-                    CanonicalVarKind::PlaceholderConst(placeholder, t) => {
-                        CanonicalVarKind::PlaceholderConst(
-                            ty::Placeholder {
-                                universe: reverse_universe_map[&placeholder.universe],
-                                ..placeholder
-                            },
-                            t,
-                        )
+                    CanonicalVarKind::PlaceholderConst(placeholder) => {
+                        CanonicalVarKind::PlaceholderConst(ty::Placeholder {
+                            universe: reverse_universe_map[&placeholder.universe],
+                            ..placeholder
+                        })
                     }
                 },
             })
@@ -806,6 +799,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
         );
         let var = self.canonical_var(info, const_var.into());
-        ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))
+        ty::Const::new_bound(self.tcx, self.binder_index, var)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
index de0e15ef3de..153de3d4c09 100644
--- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs
+++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
@@ -70,7 +70,7 @@ where
                 GenericArgKind::Type(ty) => ty,
                 r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
             },
-            consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
+            consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].unpack() {
                 GenericArgKind::Const(ct) => ct,
                 c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
             },
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 1abb8086d41..8ad4f7926ca 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -143,8 +143,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
             }
 
-            CanonicalVarKind::Const(ui, ty) => {
-                self.next_const_var_in_universe(ty, span, universe_map(ui)).into()
+            CanonicalVarKind::Const(ui) => {
+                self.next_const_var_in_universe(span, universe_map(ui)).into()
             }
             CanonicalVarKind::Effect => {
                 let vid = self
@@ -153,13 +153,12 @@ impl<'tcx> InferCtxt<'tcx> {
                     .effect_unification_table()
                     .new_key(EffectVarValue::Unknown)
                     .vid;
-                ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool)
-                    .into()
+                ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into()
             }
-            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => {
+            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
                 let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
-                ty::Const::new_placeholder(self.tcx, placeholder_mapped, ty).into()
+                ty::Const::new_placeholder(self.tcx, placeholder_mapped).into()
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 1732913e191..d7dd6a1e7cf 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -16,7 +16,7 @@ use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
 use crate::traits::query::NoSolution;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
-use crate::traits::{TraitEngine, TraitEngineExt};
+use crate::traits::{ScrubbedTraitError, TraitEngine};
 use rustc_data_structures::captures::Captures;
 use rustc_index::Idx;
 use rustc_index::IndexVec;
@@ -54,7 +54,7 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
     ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -101,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         inference_vars: CanonicalVarValues<'tcx>,
         answer: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>,
     ) -> Result<QueryResponse<'tcx, T>, NoSolution>
     where
         T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -109,19 +109,13 @@ impl<'tcx> InferCtxt<'tcx> {
         let tcx = self.tcx;
 
         // Select everything, returning errors.
-        let true_errors = fulfill_cx.select_where_possible(self);
-        debug!("true_errors = {:#?}", true_errors);
+        let errors = fulfill_cx.select_all_or_error(self);
 
-        if !true_errors.is_empty() {
-            // FIXME -- we don't indicate *why* we failed to solve
-            debug!("make_query_response: true_errors={:#?}", true_errors);
+        // True error!
+        if errors.iter().any(|e| e.is_true_error()) {
             return Err(NoSolution);
         }
 
-        // Anything left unselected *now* must be an ambiguity.
-        let ambig_errors = fulfill_cx.select_all_or_error(self);
-        debug!("ambig_errors = {:#?}", ambig_errors);
-
         let region_obligations = self.take_registered_region_obligations();
         debug!(?region_obligations);
         let region_constraints = self.with_region_constraints(|region_constraints| {
@@ -135,8 +129,7 @@ impl<'tcx> InferCtxt<'tcx> {
         });
         debug!(?region_constraints);
 
-        let certainty =
-            if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
+        let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
 
         let opaque_types = self.take_opaque_types_for_query_response();
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 95fbc1e66ce..ed483c6cbeb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -58,6 +58,7 @@ use crate::traits::{
     PredicateObligation,
 };
 
+use crate::infer::relate::{self, RelateResult, TypeRelation};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
@@ -71,8 +72,8 @@ use rustc_hir::lang_items::LangItem;
 use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
+use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
-use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::Upcast;
 use rustc_middle::ty::{
     self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
@@ -425,7 +426,7 @@ impl<'tcx> InferCtxt<'tcx> {
                         ty::ClauseKind::Projection(projection_predicate)
                             if projection_predicate.projection_term.def_id == item_def_id =>
                         {
-                            projection_predicate.term.ty()
+                            projection_predicate.term.as_type()
                         }
                         _ => None,
                     })
@@ -2686,7 +2687,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
     /// FloatVar inference type are compatible with themselves or their concrete types (Int and
     /// Float types, respectively). When comparing two ADTs, these rules apply recursively.
-    pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
+    pub fn same_type_modulo_infer<T: relate::Relate<TyCtxt<'tcx>>>(&self, a: T, b: T) -> bool {
         let (a, b) = self.resolve_vars_if_possible((a, b));
         SameTypeModuloInfer(self).relate(a, b).is_ok()
     }
@@ -2694,7 +2695,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
 struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
 
-impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.0.tcx
     }
@@ -2703,10 +2704,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         "SameTypeModuloInfer"
     }
 
-    fn relate_with_variance<T: relate::Relate<'tcx>>(
+    fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
         &mut self,
         _variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> relate::RelateResult<'tcx, T> {
@@ -2754,7 +2755,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: relate::Relate<'tcx>,
+        T: relate::Relate<TyCtxt<'tcx>>,
     {
         Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
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 fb8c843f309..cb0e13652e8 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
@@ -543,9 +543,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             match arg.unpack() {
                                 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
                                 GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
-                                GenericArgKind::Const(arg) => {
-                                    self.next_const_var(arg.ty(), DUMMY_SP).into()
-                                }
+                                GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
                             }
                         }))
                         .unwrap();
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 19ef2d61fca..effb4090692 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
@@ -21,18 +21,26 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         sp: Span,
         body_owner_def_id: DefId,
     ) {
-        use ty::error::TypeError::*;
         debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
 
         let tcx = self.tcx;
 
         match err {
-            ArgumentSorts(values, _) | Sorts(values) => {
+            TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
                 match (*values.expected.kind(), *values.found.kind()) {
                     (ty::Closure(..), ty::Closure(..)) => {
                         diag.note("no two closures, even if identical, have the same type");
                         diag.help("consider boxing your closure and/or using it as a trait object");
                     }
+                    (ty::Coroutine(def_id1, ..), ty::Coroutine(def_id2, ..))
+                        if self.tcx.coroutine_is_async(def_id1)
+                            && self.tcx.coroutine_is_async(def_id2) =>
+                    {
+                        diag.note("no two async blocks, even if identical, have the same type");
+                        diag.help(
+                            "consider pinning your async block and casting it to a trait object",
+                        );
+                    }
                     (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
                         // Issue #63167
                         diag.note("distinct uses of `impl Trait` result in different opaque types");
@@ -483,7 +491,7 @@ impl<T> Trait<T> for X {
                     values.found.kind(),
                 );
             }
-            CyclicTy(ty) => {
+            TypeError::CyclicTy(ty) => {
                 // Watch out for various cases of cyclic types and try to explain.
                 if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
                     diag.note(
@@ -494,7 +502,7 @@ impl<T> Trait<T> for X {
                     );
                 }
             }
-            TargetFeatureCast(def_id) => {
+            TypeError::TargetFeatureCast(def_id) => {
                 let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
                 diag.note(
                     "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index b2d89523ea8..4bb59bd9037 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -33,7 +33,6 @@
 use super::InferCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::bug;
-use rustc_middle::infer::unify_key::ToType;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt};
 use std::collections::hash_map::Entry;
@@ -80,7 +79,6 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
         &mut self,
         input: Result<ty::Const<'tcx>, ty::InferConst>,
         freshener: F,
-        ty: Ty<'tcx>,
     ) -> ty::Const<'tcx>
     where
         F: FnOnce(u32) -> ty::InferConst,
@@ -92,7 +90,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
                 Entry::Vacant(entry) => {
                     let index = self.const_freshen_count;
                     self.const_freshen_count += 1;
-                    let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
+                    let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index));
                     entry.insert(ct);
                     ct
                 }
@@ -150,7 +148,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
                         ty::InferConst::Var(inner.const_unification_table().find(v).vid)
                     });
                 drop(inner);
-                self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
+                self.freshen_const(input, ty::InferConst::Fresh)
             }
             ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
                 let mut inner = self.infcx.inner.borrow_mut();
@@ -159,7 +157,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
                         ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
                     });
                 drop(inner);
-                self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
+                self.freshen_const(input, ty::InferConst::Fresh)
             }
             ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
                 if i >= self.const_freshen_count {
@@ -178,7 +176,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
             }
 
             ty::ConstKind::Param(_)
-            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Value(_, _)
             | ty::ConstKind::Unevaluated(..)
             | ty::ConstKind::Expr(..)
             | ty::ConstKind::Error(_) => ct.super_fold_with(self),
@@ -204,22 +202,27 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
 
             ty::IntVar(v) => {
                 let mut inner = self.infcx.inner.borrow_mut();
-                let input = inner
-                    .int_unification_table()
-                    .probe_value(v)
-                    .map(|v| v.to_type(self.infcx.tcx))
-                    .ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v)));
+                let value = inner.int_unification_table().probe_value(v);
+                let input = match value {
+                    ty::IntVarValue::IntType(ty) => Ok(Ty::new_int(self.infcx.tcx, ty)),
+                    ty::IntVarValue::UintType(ty) => Ok(Ty::new_uint(self.infcx.tcx, ty)),
+                    ty::IntVarValue::Unknown => {
+                        Err(ty::IntVar(inner.int_unification_table().find(v)))
+                    }
+                };
                 drop(inner);
                 Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)))
             }
 
             ty::FloatVar(v) => {
                 let mut inner = self.infcx.inner.borrow_mut();
-                let input = inner
-                    .float_unification_table()
-                    .probe_value(v)
-                    .map(|v| v.to_type(self.infcx.tcx))
-                    .ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v)));
+                let value = inner.float_unification_table().probe_value(v);
+                let input = match value {
+                    ty::FloatVarValue::Known(ty) => Ok(Ty::new_float(self.infcx.tcx, ty)),
+                    ty::FloatVarValue::Unknown => {
+                        Err(ty::FloatVar(inner.float_unification_table().find(v)))
+                    }
+                };
                 drop(inner);
                 Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)))
             }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c8bb6cf5f9b..c606ab808ef 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1,9 +1,6 @@
 pub use at::DefineOpaqueTypes;
 pub use freshen::TypeFreshener;
 pub use lexical_region_resolve::RegionResolutionError;
-pub use relate::combine::CombineFields;
-pub use relate::combine::ObligationEmittingRelation;
-pub use relate::StructurallyRelateAliases;
 pub use rustc_macros::{TypeFoldable, TypeVisitable};
 pub use rustc_middle::ty::IntVarValue;
 pub use BoundRegionConversionTime::*;
@@ -11,8 +8,9 @@ pub use RegionVariableOrigin::*;
 pub use SubregionOrigin::*;
 pub use ValuePairs::*;
 
+use crate::infer::relate::{CombineFields, RelateResult};
 use crate::traits::{
-    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
+    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
 };
 use error_reporting::TypeErrCtxt;
 use free_regions::RegionRelations;
@@ -29,9 +27,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::extension;
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
+use rustc_middle::infer::unify_key::ConstVariableOrigin;
 use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ToType};
 use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
@@ -39,9 +37,8 @@ use rustc_middle::traits::select;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
 use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
 use rustc_middle::{bug, span_bug};
@@ -62,7 +59,7 @@ pub mod opaque_types;
 pub mod outlives;
 mod projection;
 pub mod region_constraints;
-mod relate;
+pub mod relate;
 pub mod resolve;
 pub(crate) mod snapshot;
 pub mod type_variable;
@@ -392,18 +389,18 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
         self.opportunistic_resolve_float_var(vid)
     }
 
-    fn opportunistic_resolve_ct_var(&self, vid: ConstVid, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ty::Const<'tcx> {
         match self.probe_const_var(vid) {
             Ok(ct) => ct,
-            Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid), ty),
+            Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)),
         }
     }
 
-    fn opportunistic_resolve_effect_var(&self, vid: EffectVid, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+    fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> ty::Const<'tcx> {
         match self.probe_effect_var(vid) {
             Some(ct) => ct,
             None => {
-                ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)), ty)
+                ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)))
             }
         }
     }
@@ -424,8 +421,8 @@ pub enum ValuePairs<'tcx> {
 impl<'tcx> ValuePairs<'tcx> {
     pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
         if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
-            && let Some(expected) = expected.ty()
-            && let Some(found) = found.ty()
+            && let Some(expected) = expected.as_type()
+            && let Some(found) = found.as_type()
         {
             Some((expected, found))
         } else {
@@ -587,6 +584,7 @@ pub enum FixupError {
     UnresolvedFloatTy(FloatVid),
     UnresolvedTy(TyVid),
     UnresolvedConst(ConstVid),
+    UnresolvedEffect(EffectVid),
 }
 
 /// See the `region_obligations` field for more information.
@@ -614,6 +612,7 @@ impl fmt::Display for FixupError {
             ),
             UnresolvedTy(_) => write!(f, "unconstrained type"),
             UnresolvedConst(_) => write!(f, "unconstrained const value"),
+            UnresolvedEffect(_) => write!(f, "unconstrained effect value"),
         }
     }
 }
@@ -737,10 +736,10 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
 
 impl<'tcx, T> InferOk<'tcx, T> {
     /// Extracts `value`, registering any obligations into `fulfill_cx`.
-    pub fn into_value_registering_obligations(
+    pub fn into_value_registering_obligations<E: 'tcx>(
         self,
         infcx: &InferCtxt<'tcx>,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
     ) -> T {
         let InferOk { value, obligations } = self;
         fulfill_cx.register_predicate_obligations(infcx, obligations);
@@ -811,13 +810,13 @@ impl<'tcx> InferCtxt<'tcx> {
         vars.extend(
             (0..inner.int_unification_table().len())
                 .map(|i| ty::IntVid::from_u32(i as u32))
-                .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none())
+                .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
                 .map(|v| Ty::new_int_var(self.tcx, v)),
         );
         vars.extend(
             (0..inner.float_unification_table().len())
                 .map(|i| ty::FloatVid::from_u32(i as u32))
-                .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none())
+                .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
                 .map(|v| Ty::new_float_var(self.tcx, v)),
         );
         vars
@@ -830,9 +829,7 @@ impl<'tcx> InferCtxt<'tcx> {
         (0..table.len())
             .map(|i| ty::EffectVid::from_usize(i))
             .filter(|&vid| table.probe_value(vid).is_unknown())
-            .map(|v| {
-                ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool)
-            })
+            .map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v)))
             .collect()
     }
 
@@ -991,27 +988,22 @@ impl<'tcx> InferCtxt<'tcx> {
         Ty::new_var(self.tcx, vid)
     }
 
-    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(&self, span: Span) -> ty::Const<'tcx> {
+        self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None })
     }
 
-    pub fn next_const_var_with_origin(
-        &self,
-        ty: Ty<'tcx>,
-        origin: ConstVariableOrigin,
-    ) -> ty::Const<'tcx> {
+    pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
         let vid = self
             .inner
             .borrow_mut()
             .const_unification_table()
             .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
             .vid;
-        ty::Const::new_var(self.tcx, vid, ty)
+        ty::Const::new_var(self.tcx, vid)
     }
 
     pub fn next_const_var_in_universe(
         &self,
-        ty: Ty<'tcx>,
         span: Span,
         universe: ty::UniverseIndex,
     ) -> ty::Const<'tcx> {
@@ -1022,17 +1014,31 @@ impl<'tcx> InferCtxt<'tcx> {
             .const_unification_table()
             .new_key(ConstVariableValue::Unknown { origin, universe })
             .vid;
-        ty::Const::new_var(self.tcx, vid, ty)
+        ty::Const::new_var(self.tcx, vid)
+    }
+
+    pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid {
+        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(ty::IntVarValue::Unknown)
     }
 
     pub fn next_int_var(&self) -> Ty<'tcx> {
-        let vid = self.inner.borrow_mut().int_unification_table().new_key(None);
-        Ty::new_int_var(self.tcx, vid)
+        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(ty::FloatVarValue::Unknown)
     }
 
     pub fn next_float_var(&self) -> Ty<'tcx> {
-        let vid = self.inner.borrow_mut().float_unification_table().new_key(None);
-        Ty::new_float_var(self.tcx, vid)
+        Ty::new_float_var(self.tcx, self.next_float_var_id())
     }
 
     /// Creates a fresh region variable with the next available index.
@@ -1119,15 +1125,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .const_unification_table()
                     .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
                     .vid;
-                ty::Const::new_var(
-                    self.tcx,
-                    const_var_id,
-                    self.tcx
-                        .type_of(param.def_id)
-                        .no_bound_vars()
-                        .expect("const parameter types cannot be generic"),
-                )
-                .into()
+                ty::Const::new_var(self.tcx, const_var_id).into()
             }
         }
     }
@@ -1141,7 +1139,7 @@ impl<'tcx> InferCtxt<'tcx> {
             .no_bound_vars()
             .expect("const parameter types cannot be generic");
         debug_assert_eq!(self.tcx.types.bool, ty);
-        ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).into()
+        ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid)).into()
     }
 
     /// Given a set of generics defined on a type or impl, returns the generic parameters mapping each
@@ -1234,45 +1232,44 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 
     pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
-    }
-
-    // This is separate from `shallow_resolve` to keep that method small and inlinable.
-    #[inline(never)]
-    fn fold_infer_ty(&self, v: InferTy) -> Option<Ty<'tcx>> {
-        match v {
-            ty::TyVar(v) => {
-                // Not entirely obvious: if `typ` is a type variable,
-                // it can be resolved to an int/float variable, which
-                // can then be recursively resolved, hence the
-                // recursion. Note though that we prevent type
-                // variables from unifying to other type variables
-                // directly (though they may be embedded
-                // structurally), and we prevent cycles in any case,
-                // so this recursion should always be of very limited
-                // depth.
-                //
-                // Note: if these two lines are combined into one we get
-                // dynamic borrow errors on `self.inner`.
-                let known = self.inner.borrow_mut().type_variables().probe(v).known();
-                known.map(|t| self.shallow_resolve(t))
-            }
+        if let ty::Infer(v) = *ty.kind() {
+            match v {
+                ty::TyVar(v) => {
+                    // Not entirely obvious: if `typ` is a type variable,
+                    // it can be resolved to an int/float variable, which
+                    // can then be recursively resolved, hence the
+                    // recursion. Note though that we prevent type
+                    // variables from unifying to other type variables
+                    // directly (though they may be embedded
+                    // structurally), and we prevent cycles in any case,
+                    // so this recursion should always be of very limited
+                    // depth.
+                    //
+                    // Note: if these two lines are combined into one we get
+                    // dynamic borrow errors on `self.inner`.
+                    let known = self.inner.borrow_mut().type_variables().probe(v).known();
+                    known.map_or(ty, |t| self.shallow_resolve(t))
+                }
+
+                ty::IntVar(v) => {
+                    match self.inner.borrow_mut().int_unification_table().probe_value(v) {
+                        ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
+                        ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
+                        ty::IntVarValue::Unknown => ty,
+                    }
+                }
+
+                ty::FloatVar(v) => {
+                    match self.inner.borrow_mut().float_unification_table().probe_value(v) {
+                        ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
+                        ty::FloatVarValue::Unknown => ty,
+                    }
+                }
 
-            ty::IntVar(v) => self
-                .inner
-                .borrow_mut()
-                .int_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.tcx)),
-
-            ty::FloatVar(v) => self
-                .inner
-                .borrow_mut()
-                .float_unification_table()
-                .probe_value(v)
-                .map(|v| v.to_type(self.tcx)),
-
-            ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
+                ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => ty,
+            }
+        } else {
+            ty
         }
     }
 
@@ -1299,7 +1296,7 @@ impl<'tcx> InferCtxt<'tcx> {
             | ty::ConstKind::Bound(_, _)
             | ty::ConstKind::Placeholder(_)
             | ty::ConstKind::Unevaluated(_)
-            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Value(_, _)
             | ty::ConstKind::Error(_)
             | ty::ConstKind::Expr(_) => ct,
         }
@@ -1321,10 +1318,13 @@ impl<'tcx> InferCtxt<'tcx> {
     /// or else the root int var in the unification table.
     pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
         let mut inner = self.inner.borrow_mut();
-        if let Some(value) = inner.int_unification_table().probe_value(vid) {
-            value.to_type(self.tcx)
-        } else {
-            Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
+        let value = inner.int_unification_table().probe_value(vid);
+        match value {
+            ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
+            ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
+            ty::IntVarValue::Unknown => {
+                Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
+            }
         }
     }
 
@@ -1332,10 +1332,12 @@ impl<'tcx> InferCtxt<'tcx> {
     /// or else the root float var in the unification table.
     pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
         let mut inner = self.inner.borrow_mut();
-        if let Some(value) = inner.float_unification_table().probe_value(vid) {
-            value.to_type(self.tcx)
-        } else {
-            Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
+        let value = inner.float_unification_table().probe_value(vid);
+        match value {
+            ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
+            ty::FloatVarValue::Unknown => {
+                Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
+            }
         }
     }
 
@@ -1449,10 +1451,10 @@ impl<'tcx> InferCtxt<'tcx> {
                     .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> {
+            fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
                 self.map
                     .entry(bv)
-                    .or_insert_with(|| self.infcx.next_const_var(ty, self.span).into())
+                    .or_insert_with(|| self.infcx.next_const_var(self.span).into())
                     .expect_const()
             }
         }
@@ -1506,11 +1508,14 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         param_env: ty::ParamEnv<'tcx>,
         unevaluated: ty::UnevaluatedConst<'tcx>,
-        ty: Ty<'tcx>,
         span: Span,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
         match self.const_eval_resolve(param_env, unevaluated, span) {
-            Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)),
+            Ok(Some(val)) => Ok(ty::Const::new_value(
+                self.tcx,
+                val,
+                self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
+            )),
             Ok(None) => {
                 let tcx = self.tcx;
                 let def_id = unevaluated.def;
@@ -1626,7 +1631,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // If `inlined_probe_value` returns a value it's always a
                 // `ty::Int(_)` or `ty::UInt(_)`, which never matches a
                 // `ty::Infer(_)`.
-                self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some()
+                self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
             }
 
             TyOrConstInferVar::TyFloat(v) => {
@@ -1634,7 +1639,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // `ty::Float(_)`, which never matches a `ty::Infer(_)`.
                 //
                 // Not `inlined_probe_value(v)` because this call site is colder.
-                self.inner.borrow_mut().float_unification_table().probe_value(v).is_some()
+                self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
             }
 
             TyOrConstInferVar::Const(v) => {
@@ -1944,11 +1949,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 
         fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
             if let ty::ConstKind::Infer(_) = c.kind() {
-                let ty = c.ty();
-                // If the type references param or infer then ICE ICE ICE
-                if ty.has_non_region_param() || ty.has_non_region_infer() {
-                    bug!("const `{c}`'s type should not reference params or types");
-                }
                 ty::Const::new_placeholder(
                     self.tcx,
                     ty::PlaceholderConst {
@@ -1959,7 +1959,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
                             idx
                         }),
                     },
-                    ty,
                 )
             } else {
                 c.super_fold_with(self)
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 29c11d4247d..978b92fd898 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -1,15 +1,12 @@
 use std::collections::hash_map::Entry;
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{
-    self,
-    error::TypeError,
-    relate::{self, Relate, RelateResult, TypeRelation},
-    Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use crate::infer::region_constraints::VerifyIfEq;
+use crate::infer::relate::{self as relate, Relate, RelateResult, TypeRelation};
 
 /// Given a "verify-if-eq" type test like:
 ///
@@ -135,7 +132,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx> {
     fn tag(&self) -> &'static str {
         "MatchAgainstHigherRankedOutlives"
     }
@@ -145,10 +142,10 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
     }
 
     #[instrument(level = "trace", skip(self))]
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        _: ty::VarianceDiagInfo<'tcx>,
+        _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -208,7 +205,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
         value: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         self.pattern_depth.shift_in(1);
         let result = Ok(pattern.rebind(self.relate(pattern.skip_binder(), value.skip_binder())?));
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 255ca52d3e9..5b159d62731 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -1,11 +1,11 @@
 use super::*;
+use crate::infer::relate::RelateResult;
 use crate::infer::snapshot::CombinedSnapshot;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
 use rustc_index::Idx;
 use rustc_middle::span_bug;
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::relate::RelateResult;
 
 impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     /// Searches new universes created during `snapshot`, looking for
@@ -276,7 +276,7 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> {
         other_region: ty::Region<'tcx>,
     ) -> TypeError<'tcx> {
         debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
-        TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
+        TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound, other_region)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_infer/src/infer/relate/_match.rs
index f30270abd5c..30a066a265a 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_infer/src/infer/relate/_match.rs
@@ -1,8 +1,10 @@
-use crate::ty::error::TypeError;
-use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use crate::ty::{self, InferConst, Ty, TyCtxt};
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
 use tracing::{debug, instrument};
 
+use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation};
+use crate::infer::relate;
+
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// instantiated with values so as to make it equal to A. Matching is
 /// intended to be used only on freshened types, and it basically
@@ -29,7 +31,7 @@ impl<'tcx> MatchAgainstFreshVars<'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
     fn tag(&self) -> &'static str {
         "MatchAgainstFreshVars"
     }
@@ -38,10 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
         self.tcx
     }
 
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         _: ty::Variance,
-        _: ty::VarianceDiagInfo<'tcx>,
+        _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -72,12 +74,12 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
             ) => Ok(a),
 
             (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
-                Err(TypeError::Sorts(relate::expected_found(a, b)))
+                Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
             }
 
             (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
 
-            _ => relate::structurally_relate_tys(self, a, b),
+            _ => structurally_relate_tys(self, a, b),
         }
     }
 
@@ -97,7 +99,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
             }
 
             (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
-                return Err(TypeError::ConstMismatch(relate::expected_found(a, b)));
+                return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b)));
             }
 
             _ => {}
@@ -112,7 +114,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 04ca043e6fe..30cb2bab900 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -22,12 +22,13 @@ use super::glb::Glb;
 use super::lub::Lub;
 use super::type_relating::TypeRelating;
 use super::StructurallyRelateAliases;
+use super::{RelateResult, TypeRelation};
+use crate::infer::relate;
 use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
 use crate::traits::{Obligation, PredicateObligations};
 use rustc_middle::bug;
 use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::relate::{RelateResult, TypeRelation};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::Span;
@@ -68,40 +69,38 @@ impl<'tcx> InferCtxt<'tcx> {
         match (a.kind(), b.kind()) {
             // Relate integral variables to other types
             (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => {
-                self.inner
-                    .borrow_mut()
-                    .int_unification_table()
-                    .unify_var_var(a_id, b_id)
-                    .map_err(|e| int_unification_error(true, e))?;
+                self.inner.borrow_mut().int_unification_table().union(a_id, b_id);
                 Ok(a)
             }
             (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => {
-                self.unify_integral_variable(true, v_id, IntType(v))
+                self.unify_integral_variable(v_id, IntType(v));
+                Ok(b)
             }
             (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => {
-                self.unify_integral_variable(false, v_id, IntType(v))
+                self.unify_integral_variable(v_id, IntType(v));
+                Ok(a)
             }
             (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => {
-                self.unify_integral_variable(true, v_id, UintType(v))
+                self.unify_integral_variable(v_id, UintType(v));
+                Ok(b)
             }
             (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => {
-                self.unify_integral_variable(false, v_id, UintType(v))
+                self.unify_integral_variable(v_id, UintType(v));
+                Ok(a)
             }
 
             // Relate floating-point variables to other types
             (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => {
-                self.inner
-                    .borrow_mut()
-                    .float_unification_table()
-                    .unify_var_var(a_id, b_id)
-                    .map_err(|e| float_unification_error(true, e))?;
+                self.inner.borrow_mut().float_unification_table().union(a_id, b_id);
                 Ok(a)
             }
             (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => {
-                self.unify_float_variable(true, v_id, v)
+                self.unify_float_variable(v_id, ty::FloatVarValue::Known(v));
+                Ok(b)
             }
             (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => {
-                self.unify_float_variable(false, v_id, v)
+                self.unify_float_variable(v_id, ty::FloatVarValue::Known(v));
+                Ok(a)
             }
 
             // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
@@ -123,7 +122,7 @@ impl<'tcx> InferCtxt<'tcx> {
             (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
                 match relation.structurally_relate_aliases() {
                     StructurallyRelateAliases::Yes => {
-                        ty::relate::structurally_relate_tys(relation, a, b)
+                        relate::structurally_relate_tys(relation, a, b)
                     }
                     StructurallyRelateAliases::No => {
                         relation.register_type_relate_obligation(a, b);
@@ -134,7 +133,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
             // All other cases of inference are errors
             (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
-                Err(TypeError::Sorts(ty::relate::expected_found(a, b)))
+                Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
             }
 
             // During coherence, opaque types should be treated as *possibly*
@@ -146,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 Ok(a)
             }
 
-            _ => ty::relate::structurally_relate_tys(relation, a, b),
+            _ => relate::structurally_relate_tys(relation, a, b),
         }
     }
 
@@ -236,43 +235,22 @@ impl<'tcx> InferCtxt<'tcx> {
                         Ok(b)
                     }
                     StructurallyRelateAliases::Yes => {
-                        ty::relate::structurally_relate_consts(relation, a, b)
+                        relate::structurally_relate_consts(relation, a, b)
                     }
                 }
             }
-            _ => ty::relate::structurally_relate_consts(relation, a, b),
+            _ => relate::structurally_relate_consts(relation, a, b),
         }
     }
 
-    fn unify_integral_variable(
-        &self,
-        vid_is_expected: bool,
-        vid: ty::IntVid,
-        val: ty::IntVarValue,
-    ) -> RelateResult<'tcx, Ty<'tcx>> {
-        self.inner
-            .borrow_mut()
-            .int_unification_table()
-            .unify_var_value(vid, Some(val))
-            .map_err(|e| int_unification_error(vid_is_expected, e))?;
-        match val {
-            IntType(v) => Ok(Ty::new_int(self.tcx, v)),
-            UintType(v) => Ok(Ty::new_uint(self.tcx, v)),
-        }
+    #[inline(always)]
+    fn unify_integral_variable(&self, vid: ty::IntVid, val: ty::IntVarValue) {
+        self.inner.borrow_mut().int_unification_table().union_value(vid, val);
     }
 
-    fn unify_float_variable(
-        &self,
-        vid_is_expected: bool,
-        vid: ty::FloatVid,
-        val: ty::FloatTy,
-    ) -> RelateResult<'tcx, Ty<'tcx>> {
-        self.inner
-            .borrow_mut()
-            .float_unification_table()
-            .unify_var_value(vid, Some(ty::FloatVarValue(val)))
-            .map_err(|e| float_unification_error(vid_is_expected, e))?;
-        Ok(Ty::new_float(self.tcx, val))
+    #[inline(always)]
+    fn unify_float_variable(&self, vid: ty::FloatVid, val: ty::FloatVarValue) {
+        self.inner.borrow_mut().float_unification_table().union_value(vid, val);
     }
 
     fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> {
@@ -326,7 +304,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
     }
 }
 
-pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
+pub trait ObligationEmittingRelation<'tcx>: TypeRelation<TyCtxt<'tcx>> {
     fn span(&self) -> Span;
 
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
@@ -350,19 +328,3 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
     /// Register `AliasRelate` obligation(s) that both types must be related to each other.
     fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>);
 }
-
-fn int_unification_error<'tcx>(
-    a_is_expected: bool,
-    v: (ty::IntVarValue, ty::IntVarValue),
-) -> TypeError<'tcx> {
-    let (a, b) = v;
-    TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b))
-}
-
-fn float_unification_error<'tcx>(
-    a_is_expected: bool,
-    v: (ty::FloatVarValue, ty::FloatVarValue),
-) -> TypeError<'tcx> {
-    let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
-    TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
-}
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index d4c7d752c95..5478afda455 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -1,15 +1,16 @@
 use std::mem;
 
 use super::StructurallyRelateAliases;
+use super::{ObligationEmittingRelation, Relate, RelateResult, TypeRelation};
+use crate::infer::relate;
 use crate::infer::type_variable::TypeVariableValue;
-use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
+use crate::infer::{InferCtxt, RegionVariableOrigin};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::MaxUniverse;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{AliasRelationDirection, InferConst, Term, TypeVisitable, TypeVisitableExt};
@@ -228,7 +229,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Attempts to generalize `source_term` for the type variable `target_vid`.
     /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
-    fn generalize<T: Into<Term<'tcx>> + Relate<'tcx>>(
+    fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
         &self,
         span: Span,
         structurally_relate_aliases: StructurallyRelateAliases,
@@ -329,6 +330,14 @@ impl<'tcx> Generalizer<'_, 'tcx> {
         }
     }
 
+    /// Create a new type variable in the universe of the target when
+    /// generalizing an alias. This has to set `has_unconstrained_ty_var`
+    /// if we're currently in a bivariant context.
+    fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> {
+        self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant;
+        self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
+    }
+
     /// An occurs check failure inside of an alias does not mean
     /// that the types definitely don't unify. We may be able
     /// to normalize the alias after all.
@@ -358,7 +367,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
         //
         // 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));
+            return Ok(self.next_ty_var_for_alias());
         }
 
         let is_nested_alias = mem::replace(&mut self.in_alias, true);
@@ -378,7 +387,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
                     }
 
                     debug!("generalization failure in alias");
-                    Ok(self.infcx.next_ty_var_in_universe(self.span, self.for_universe))
+                    Ok(self.next_ty_var_for_alias())
                 }
             }
         };
@@ -387,7 +396,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
@@ -422,10 +431,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self, variance, b), ret)]
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -645,7 +654,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                             {
                                 variable_table.union(vid, new_var_id);
                             }
-                            Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty()))
+                            Ok(ty::Const::new_var(self.tcx(), new_var_id))
                         }
                     }
                 }
@@ -663,11 +672,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                     args,
                     args,
                 )?;
-                Ok(ty::Const::new_unevaluated(
-                    self.tcx(),
-                    ty::UnevaluatedConst { def, args },
-                    c.ty(),
-                ))
+                Ok(ty::Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst { def, args }))
             }
             ty::ConstKind::Placeholder(placeholder) => {
                 if self.for_universe.can_name(placeholder.universe) {
@@ -691,7 +696,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
         _: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         let result = self.relate(a.skip_binder(), a.skip_binder())?;
         Ok(a.rebind(result))
diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
index a224a86492a..98e8f07c7a2 100644
--- a/compiler/rustc_infer/src/infer/relate/glb.rs
+++ b/compiler/rustc_infer/src/infer/relate/glb.rs
@@ -1,6 +1,6 @@
 //! Greatest lower bound. See [`lattice`].
 
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use super::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 
@@ -21,7 +21,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
     fn tag(&self) -> &'static str {
         "Glb"
     }
@@ -30,10 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         self.fields.tcx()
     }
 
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         // GLB of a binder and itself is just itself
         if a == b {
diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
index 70ed7cf9af1..cfce28aca5d 100644
--- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
+++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
@@ -1,10 +1,10 @@
 //! Helper routines for higher-ranked things. See the `doc` module at
 //! the end of the file for details.
 
+use super::RelateResult;
 use crate::infer::snapshot::CombinedSnapshot;
 use crate::infer::InferCtxt;
 use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -43,11 +43,10 @@ impl<'tcx> InferCtxt<'tcx> {
                     ty::PlaceholderType { universe: next_universe, bound: bound_ty },
                 )
             },
-            consts: &mut |bound_var: ty::BoundVar, ty| {
+            consts: &mut |bound_var: ty::BoundVar| {
                 ty::Const::new_placeholder(
                     self.tcx,
                     ty::PlaceholderConst { universe: next_universe, bound: bound_var },
-                    ty,
                 )
             },
         };
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 38e25b0d9b6..f05b984142a 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -21,7 +21,7 @@ use super::combine::ObligationEmittingRelation;
 use crate::infer::{DefineOpaqueTypes, InferCtxt};
 use crate::traits::ObligationCause;
 
-use rustc_middle::ty::relate::RelateResult;
+use super::RelateResult;
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty};
 
@@ -64,8 +64,8 @@ where
 
     let infcx = this.infcx();
 
-    let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
-    let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
+    let a = infcx.shallow_resolve(a);
+    let b = infcx.shallow_resolve(b);
 
     match (a.kind(), b.kind()) {
         // If one side is known to be a variable and one is not,
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index 83ab7770770..28dbaa94f95 100644
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -6,7 +6,7 @@ use super::StructurallyRelateAliases;
 use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
 use crate::traits::{ObligationCause, PredicateObligations};
 
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use super::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
 
@@ -21,7 +21,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
     fn tag(&self) -> &'static str {
         "Lub"
     }
@@ -30,10 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         self.fields.tcx()
     }
 
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         // LUB of a binder and itself is just itself
         if a == b {
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index 86a01130167..627c527cba1 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -1,6 +1,14 @@
 //! This module contains the definitions of most `TypeRelation`s in the type system
 //! (except for some relations used for diagnostics and heuristics in the compiler).
+//! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
 
+pub use rustc_middle::ty::relate::*;
+
+pub use self::_match::MatchAgainstFreshVars;
+pub use self::combine::CombineFields;
+pub use self::combine::ObligationEmittingRelation;
+
+pub mod _match;
 pub(super) mod combine;
 mod generalize;
 mod glb;
@@ -8,15 +16,3 @@ mod higher_ranked;
 mod lattice;
 mod lub;
 mod type_relating;
-
-/// Whether aliases should be related structurally or not. Used
-/// to adjust the behavior of generalization and combine.
-///
-/// This should always be `No` unless in a few special-cases when
-/// instantiating canonical responses and in the new solver. Each
-/// such case should have a comment explaining why it is used.
-#[derive(Debug, Copy, Clone)]
-pub enum StructurallyRelateAliases {
-    Yes,
-    No,
-}
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index 21064fff97f..fd0bc9f44f7 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -1,12 +1,11 @@
 use super::combine::CombineFields;
 use crate::infer::BoundRegionConversionTime::HigherRankedType;
-use crate::infer::{
-    DefineOpaqueTypes, ObligationEmittingRelation, StructurallyRelateAliases, SubregionOrigin,
-};
+use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
 use crate::traits::{Obligation, PredicateObligations};
 
-use rustc_middle::ty::relate::{
-    relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
+use super::{
+    relate_args_invariantly, relate_args_with_variances, ObligationEmittingRelation, Relate,
+    RelateResult, StructurallyRelateAliases, TypeRelation,
 };
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -29,7 +28,7 @@ impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
     fn tag(&self) -> &'static str {
         "TypeRelating"
     }
@@ -56,10 +55,10 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
         }
     }
 
-    fn relate_with_variance<T: Relate<'tcx>>(
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
         variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -80,8 +79,8 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
         }
 
         let infcx = self.fields.infcx;
-        let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
-        let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
+        let a = infcx.shallow_resolve(a);
+        let b = infcx.shallow_resolve(b);
 
         match (a.kind(), b.kind()) {
             (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
@@ -226,7 +225,7 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
         b: ty::Binder<'tcx, T>,
     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
     where
-        T: Relate<'tcx>,
+        T: Relate<TyCtxt<'tcx>>,
     {
         if a == b {
             // Do nothing
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 21ef2e89523..830d79f52b9 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -167,6 +167,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
                 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                     bug!("Unexpected const in full const resolver: {:?}", c);
                 }
+                ty::ConstKind::Infer(InferConst::EffectVar(evid)) => {
+                    return Err(FixupError::UnresolvedEffect(evid));
+                }
                 _ => {}
             }
             c.try_super_fold_with(self)
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index 4408251c99d..a086c82c92e 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -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_with_origin(ct.ty(), origin)
+                self.infcx.next_const_var_with_origin(origin)
             } else {
                 ct
             }
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index e27e6a0a4a1..026b2c1b905 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -1,13 +1,38 @@
+use std::fmt::Debug;
+
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
 use rustc_hir::def_id::DefId;
-use rustc_macros::extension;
 use rustc_middle::ty::{self, Ty, Upcast};
 
-use super::FulfillmentError;
 use super::{ObligationCause, PredicateObligation};
 
-pub trait TraitEngine<'tcx>: 'tcx {
+/// A trait error with most of its information removed. This is the error
+/// returned by an `ObligationCtxt` by default, and suitable if you just
+/// want to see if a predicate holds, and don't particularly care about the
+/// error itself (except for if it's an ambiguity or true error).
+///
+/// use `ObligationCtxt::new_with_diagnostics` to get a `FulfillmentError`.
+#[derive(Clone, Debug)]
+pub enum ScrubbedTraitError<'tcx> {
+    /// A real error. This goal definitely does not hold.
+    TrueError,
+    /// An ambiguity. This goal may hold if further inference is done.
+    Ambiguity,
+    /// An old-solver-style cycle error, which will fatal.
+    Cycle(Vec<PredicateObligation<'tcx>>),
+}
+
+impl<'tcx> ScrubbedTraitError<'tcx> {
+    pub fn is_true_error(&self) -> bool {
+        match self {
+            ScrubbedTraitError::TrueError => true,
+            ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false,
+        }
+    }
+}
+
+pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
     /// Requires that `ty` must implement the trait with `def_id` in
     /// the given environment. This trait must not have any type
     /// parameters (except for `Self`).
@@ -37,28 +62,10 @@ pub trait TraitEngine<'tcx>: 'tcx {
         obligation: PredicateObligation<'tcx>,
     );
 
-    #[must_use]
-    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
-
-    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
-
-    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
-
-    /// Among all pending obligations, collect those are stalled on a inference variable which has
-    /// changed since the last call to `select_where_possible`. Those obligations are marked as
-    /// successful and returned.
-    fn drain_unstalled_obligations(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-    ) -> Vec<PredicateObligation<'tcx>>;
-}
-
-#[extension(pub trait TraitEngineExt<'tcx>)]
-impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T {
     fn register_predicate_obligations(
         &mut self,
         infcx: &InferCtxt<'tcx>,
-        obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
+        obligations: Vec<PredicateObligation<'tcx>>,
     ) {
         for obligation in obligations {
             self.register_predicate_obligation(infcx, obligation);
@@ -66,7 +73,12 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T {
     }
 
     #[must_use]
-    fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
+
+    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
+
+    #[must_use]
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         let errors = self.select_where_possible(infcx);
         if !errors.is_empty() {
             return errors;
@@ -74,4 +86,18 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T {
 
         self.collect_remaining_errors(infcx)
     }
+
+    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
+
+    /// Among all pending obligations, collect those are stalled on a inference variable which has
+    /// changed since the last call to `select_where_possible`. Those obligations are marked as
+    /// successful and returned.
+    fn drain_unstalled_obligations(
+        &mut self,
+        infcx: &InferCtxt<'tcx>,
+    ) -> Vec<PredicateObligation<'tcx>>;
+}
+
+pub trait FromSolverError<'tcx, E>: Debug + 'tcx {
+    fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
 }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 0ae4340098b..ca6c6570e07 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -15,15 +15,14 @@ use hir::def_id::LocalDefId;
 use rustc_hir as hir;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::Certainty;
-use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, Const, Ty, TyCtxt, Upcast};
+use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::Span;
 
 pub use self::ImplSource::*;
 pub use self::SelectionError::*;
 use crate::infer::InferCtxt;
 
-pub use self::engine::{TraitEngine, TraitEngineExt};
+pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
 pub use self::project::MismatchedProjectionTypes;
 pub(crate) use self::project::UndoLog;
 pub use self::project::{
@@ -124,32 +123,6 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
 pub type ObligationInspector<'tcx> =
     fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
 
-pub struct FulfillmentError<'tcx> {
-    pub obligation: PredicateObligation<'tcx>,
-    pub code: FulfillmentErrorCode<'tcx>,
-    /// Diagnostics only: the 'root' obligation which resulted in
-    /// the failure to process `obligation`. This is the obligation
-    /// that was initially passed to `register_predicate_obligation`
-    pub root_obligation: PredicateObligation<'tcx>,
-}
-
-#[derive(Clone)]
-pub enum FulfillmentErrorCode<'tcx> {
-    /// Inherently impossible to fulfill; this trait is implemented if and only
-    /// if it is already implemented.
-    Cycle(Vec<PredicateObligation<'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
-        /// emitting a fatal error instead.
-        overflow: Option<bool>,
-    },
-}
-
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
@@ -198,28 +171,6 @@ impl<'tcx, O> Obligation<'tcx, O> {
     }
 }
 
-impl<'tcx> FulfillmentError<'tcx> {
-    pub fn new(
-        obligation: PredicateObligation<'tcx>,
-        code: FulfillmentErrorCode<'tcx>,
-        root_obligation: PredicateObligation<'tcx>,
-    ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation, code, root_obligation }
-    }
-
-    pub fn is_true_error(&self) -> bool {
-        match self.code {
-            FulfillmentErrorCode::Select(_)
-            | FulfillmentErrorCode::Project(_)
-            | FulfillmentErrorCode::Subtype(_, _)
-            | FulfillmentErrorCode::ConstEquate(_, _) => true,
-            FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
-                false
-            }
-        }
-    }
-}
-
 impl<'tcx> PolyTraitObligation<'tcx> {
     pub fn polarity(&self) -> ty::PredicatePolarity {
         self.predicate.skip_binder().polarity
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index b616d37e5b5..b26734a296f 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -29,33 +29,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
     }
 }
 
-impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
-    }
-}
-
-impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::FulfillmentErrorCode::*;
-        match *self {
-            Select(ref e) => write!(f, "{e:?}"),
-            Project(ref e) => write!(f, "{e:?}"),
-            Subtype(ref a, ref b) => {
-                write!(f, "CodeSubtypeError({a:?}, {b:?})")
-            }
-            ConstEquate(ref a, ref b) => {
-                write!(f, "CodeConstEquateError({a:?}, {b:?})")
-            }
-            Ambiguity { overflow: None } => write!(f, "Ambiguity"),
-            Ambiguity { overflow: Some(suggest_increasing_limit) } => {
-                write!(f, "Overflow({suggest_increasing_limit})")
-            }
-            Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
-        }
-    }
-}
-
 impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "MismatchedProjectionTypes({:?})", self.err)
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 5254a6576f9..c95a10f4e8d 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -14,7 +14,7 @@ use rustc_lint::LintStore;
 use rustc_middle::ty;
 use rustc_middle::ty::CurrentGcx;
 use rustc_middle::util::Providers;
-use rustc_parse::maybe_new_parser_from_source_str;
+use rustc_parse::new_parser_from_source_str;
 use rustc_query_impl::QueryCtxt;
 use rustc_query_system::query::print_query_stack;
 use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
@@ -67,7 +67,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
                 };
             }
 
-            match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) {
+            match new_parser_from_source_str(&psess, filename, s.to_string()) {
                 Ok(mut parser) => match parser.parse_meta_item() {
                     Ok(meta_item) if parser.token == token::Eof => {
                         if meta_item.path.segments.len() != 1 {
@@ -166,7 +166,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
             error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
         };
 
-        let mut parser = match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) {
+        let mut parser = match new_parser_from_source_str(&psess, filename, s.to_string()) {
             Ok(parser) => parser,
             Err(errs) => {
                 errs.into_iter().for_each(|err| err.cancel());
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 33995f80162..d52286d5887 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -19,7 +19,9 @@ use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_middle::util::Providers;
-use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
+use rustc_parse::{
+    new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
+};
 use rustc_passes::{abi_test, hir_stats, layout_test};
 use rustc_resolve::Resolver;
 use rustc_session::code_stats::VTableSizeInfo;
@@ -42,11 +44,14 @@ use std::{env, fs, iter};
 use tracing::{info, instrument};
 
 pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
-    let krate = sess.time("parse_crate", || match &sess.io.input {
-        Input::File(file) => parse_crate_from_file(file, &sess.psess),
-        Input::Str { input, name } => {
-            parse_crate_from_source_str(name.clone(), input.clone(), &sess.psess)
-        }
+    let krate = sess.time("parse_crate", || {
+        let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
+            Input::File(file) => new_parser_from_file(&sess.psess, file, None),
+            Input::Str { input, name } => {
+                new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
+            }
+        });
+        parser.parse_crate_mod()
     })?;
 
     if sess.opts.unstable_opts.input_stats {
@@ -459,7 +464,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
                 }
             }
 
-            for &cnum in tcx.crates_including_speculative(()) {
+            for &cnum in tcx.crates(()) {
                 let source = tcx.used_crate_source(cnum);
                 if let Some((path, _)) = &source.dylib {
                     files.push(escape_dep_filename(&path.display().to_string()));
@@ -832,7 +837,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
         let traits = tcx.traits(LOCAL_CRATE);
 
         for &tr in traits {
-            if !tcx.check_is_object_safe(tr) {
+            if !tcx.is_object_safe(tr) {
                 continue;
             }
 
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index fb71cb60140..733c73bc3d0 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -445,7 +445,8 @@ lint_macro_is_private = macro `{$ident}` is private
 lint_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used
 
 lint_macro_use_deprecated =
-    deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
+    applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
+    .help = remove it and import macros at use sites with a `use` item instead
 
 lint_malformed_attribute = malformed lint attribute input
 
@@ -456,12 +457,15 @@ lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
     .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
     .suggestion = you might have meant to use `Iterator::for_each`
 
-lint_metavariable_still_repeating = variable '{$name}' is still repeating at this depth
+lint_metavariable_still_repeating = variable `{$name}` is still repeating at this depth
 
 lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
 
 lint_missing_fragment_specifier = missing fragment specifier
 
+lint_missing_unsafe_on_extern = extern blocks should be unsafe
+    .suggestion = needs `unsafe` before the extern keyword
+
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
     .includes_note = the usage includes {$includes}
@@ -632,11 +636,8 @@ lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies
 lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations
     .label = pattern not allowed in foreign function
 
-lint_private_extern_crate_reexport =
-    extern crate `{$ident}` is private, and cannot be re-exported, consider declaring with `pub`
-
-lint_proc_macro_back_compat = using an old version of `{$crate_name}`
-    .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
+lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported
+    .suggestion = consider making the `extern crate` item publicly accessible
 
 lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope
     .label = names from parent modules are not accessible without an explicit import
@@ -847,7 +848,8 @@ lint_unused_coroutine =
     }{$post} that must be used
     .note = coroutines are lazy and do nothing unless resumed
 
-lint_unused_crate_dependency = external crate `{$extern_crate}` unused in `{$local_crate}`: remove the dependency or add `use {$extern_crate} as _;`
+lint_unused_crate_dependency = extern crate `{$extern_crate}` is unused in crate `{$local_crate}`
+    .help = remove the dependency or add `use {$extern_crate} as _;` to the crate root
 
 lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
     .suggestion = use `let _ = ...` to ignore the resulting value
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 87c433a5dc0..8c9abeafacf 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -51,7 +51,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::intravisit::FnKind as HirFnKind;
-use rustc_hir::{Body, FnDecl, GenericParamKind, Node, PatKind, PredicateOrigin};
+use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin};
 use rustc_middle::bug;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::layout::LayoutOf;
@@ -1423,11 +1423,20 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
         self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
     }
 
-    fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
-        if matches!(cx.tcx.parent_hir_node(field.hir_id), Node::Variant(_)) {
-            return;
-        }
-        self.perform_lint(cx, "field", field.def_id, field.vis_span, false);
+    fn check_field_def(&mut self, _cx: &LateContext<'_>, _field: &hir::FieldDef<'_>) {
+        // - If an ADT definition is reported then we don't need to check fields
+        //   (as it would add unnecessary complexity to the source code, the struct
+        //   definition is in the immediate proximity to give the "real" visibility).
+        // - If an ADT is not reported because it's not `pub` - we don't need to
+        //   check fields.
+        // - If an ADT is not reported because it's reachable - we also don't need
+        //   to check fields because then they are reachable by construction if they
+        //   are pub.
+        //
+        // Therefore in no case we check the fields.
+        //
+        // cf. https://github.com/rust-lang/rust/pull/126013#issuecomment-2152839205
+        // cf. https://github.com/rust-lang/rust/pull/126040#issuecomment-2152944506
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 26f34486a3d..83640d7210f 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -159,9 +159,6 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
         BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
             lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
         }
-        BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => {
-            lints::ProcMacroBackCompat { crate_name, fixed_version }.decorate_lint(diag);
-        }
         BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
             lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag);
         }
@@ -205,6 +202,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
             };
             lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
         }
+        BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
+            lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
+        }
         BuiltinLintDiag::SingleUseLifetime {
             param_span,
             use_span: Some((use_span, elide)),
@@ -340,8 +340,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
             lints::MacroUseDeprecated.decorate_lint(diag);
         }
         BuiltinLintDiag::UnusedMacroUse => lints::UnusedMacroUse.decorate_lint(diag),
-        BuiltinLintDiag::PrivateExternCrateReexport(ident) => {
-            lints::PrivateExternCrateReexport { ident }.decorate_lint(diag);
+        BuiltinLintDiag::PrivateExternCrateReexport { source: ident, extern_crate_span } => {
+            lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() }
+                .decorate_lint(diag);
         }
         BuiltinLintDiag::UnusedLabel => lints::UnusedLabel.decorate_lint(diag),
         BuiltinLintDiag::MacroIsPrivate(ident) => {
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 84d46ef3b65..b377da31a58 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2313,6 +2313,7 @@ pub mod unexpected_cfg_value {
 
 #[derive(LintDiagnostic)]
 #[diag(lint_macro_use_deprecated)]
+#[help]
 pub struct MacroUseDeprecated;
 
 #[derive(LintDiagnostic)]
@@ -2323,6 +2324,8 @@ pub struct UnusedMacroUse;
 #[diag(lint_private_extern_crate_reexport, code = E0365)]
 pub struct PrivateExternCrateReexport {
     pub ident: Ident,
+    #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")]
+    pub sugg: Span,
 }
 
 #[derive(LintDiagnostic)]
@@ -2416,6 +2419,7 @@ pub struct UnknownMacroVariable {
 
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_crate_dependency)]
+#[help]
 pub struct UnusedCrateDependency {
     pub extern_crate: Symbol,
     pub local_crate: Symbol,
@@ -2650,14 +2654,6 @@ pub struct LegacyDeriveHelpers {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_proc_macro_back_compat)]
-#[note]
-pub struct ProcMacroBackCompat {
-    pub crate_name: String,
-    pub fixed_version: String,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(lint_or_patterns_back_compat)]
 pub struct OrPatternsBackCompat {
     #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
@@ -2739,6 +2735,13 @@ pub enum DeprecatedWhereClauseLocationSugg {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_missing_unsafe_on_extern)]
+pub struct MissingUnsafeOnExtern {
+    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
+    pub suggestion: Span,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_single_use_lifetime)]
 pub struct SingleUseLifetime {
     #[label(lint_label_param)]
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index 48d140c6b7f..aa1d94228ea 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -38,10 +38,10 @@ declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTAB
 impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         let def_id = item.owner_id.to_def_id();
-        // NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because
+        // NOTE(nbdd0121): use `object_safety_violations` instead of `is_object_safe` because
         // the latter will report `where_clause_object_safety` lint.
         if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
-            && cx.tcx.object_safety_violations(def_id).is_empty()
+            && cx.tcx.is_object_safe(def_id)
         {
             let direct_super_traits_iter = cx
                 .tcx
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index eda40e4a011..6098da990c0 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 };
                 // Only check types, since those are the only things that may
                 // have opaques in them anyways.
-                let Some(proj_term) = proj.term.ty() else { return };
+                let Some(proj_term) = proj.term.as_type() else { return };
 
                 // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"...
                 if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind()
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 9d3a838666a..f3a904022e9 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1741,13 +1741,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
         let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
 
         match it.kind {
-            hir::ForeignItemKind::Fn(decl, _, _) if !vis.is_internal_abi(abi) => {
+            hir::ForeignItemKind::Fn(decl, _, _, _) if !vis.is_internal_abi(abi) => {
                 vis.check_foreign_fn(it.owner_id.def_id, decl);
             }
-            hir::ForeignItemKind::Static(ty, _) if !vis.is_internal_abi(abi) => {
+            hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => {
                 vis.check_foreign_static(it.owner_id, ty.span);
             }
-            hir::ForeignItemKind::Fn(decl, _, _) => vis.check_fn(it.owner_id.def_id, decl),
+            hir::ForeignItemKind::Fn(decl, _, _, _) => vis.check_fn(it.owner_id.def_id, decl),
             hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (),
         }
     }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 93995fe60a3..726bd0de129 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -66,6 +66,7 @@ declare_lint_pass! {
         META_VARIABLE_MISUSE,
         MISSING_ABI,
         MISSING_FRAGMENT_SPECIFIER,
+        MISSING_UNSAFE_ON_EXTERN,
         MUST_NOT_SUSPEND,
         NAMED_ARGUMENTS_USED_POSITIONALLY,
         NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
@@ -76,7 +77,6 @@ declare_lint_pass! {
         PATTERNS_IN_FNS_WITHOUT_BODY,
         PRIVATE_BOUNDS,
         PRIVATE_INTERFACES,
-        PROC_MACRO_BACK_COMPAT,
         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
         PUB_USE_OF_PRIVATE_EXTERN_CRATE,
         REDUNDANT_LIFETIMES,
@@ -136,7 +136,6 @@ declare_lint_pass! {
         USELESS_DEPRECATED,
         WARNINGS,
         WASM_C_ABI,
-        WHERE_CLAUSES_OBJECT_SAFETY,
         WRITES_THROUGH_IMMUTABLE_POINTER,
         // tidy-alphabetical-end
     ]
@@ -512,8 +511,9 @@ declare_lint! {
     /// This will produce:
     ///
     /// ```text
-    /// error: external crate `regex` unused in `lint_example`: remove the dependency or add `use regex as _;`
+    /// error: extern crate `regex` is unused in crate `lint_example`
     ///   |
+    ///   = help: remove the dependency or add `use regex as _;` to the crate root
     /// note: the lint level is defined here
     ///  --> src/lib.rs:1:9
     ///   |
@@ -2094,47 +2094,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `where_clauses_object_safety` lint detects for [object safety] of
-    /// [where clauses].
-    ///
-    /// [object safety]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
-    /// [where clauses]: https://doc.rust-lang.org/reference/items/generics.html#where-clauses
-    ///
-    /// ### Example
-    ///
-    /// ```rust,no_run
-    /// trait Trait {}
-    ///
-    /// trait X { fn foo(&self) where Self: Trait; }
-    ///
-    /// impl X for () { fn foo(&self) {} }
-    ///
-    /// impl Trait for dyn X {}
-    ///
-    /// // Segfault at opt-level 0, SIGILL otherwise.
-    /// pub fn main() { <dyn X as X>::foo(&()); }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// The compiler previously allowed these object-unsafe bounds, which was
-    /// incorrect. This is a [future-incompatible] lint to transition this to
-    /// a hard error in the future. See [issue #51443] for more details.
-    ///
-    /// [issue #51443]: https://github.com/rust-lang/rust/issues/51443
-    /// [future-incompatible]: ../index.md#future-incompatible-lints
-    pub WHERE_CLAUSES_OBJECT_SAFETY,
-    Warn,
-    "checks the object safety of where clauses",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
-    };
-}
-
-declare_lint! {
     /// The `proc_macro_derive_resolution_fallback` lint detects proc macro
     /// derives using inaccessible names from parent modules.
     ///
@@ -2202,8 +2161,7 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `macro_use_extern_crate` lint detects the use of the
-    /// [`macro_use` attribute].
+    /// The `macro_use_extern_crate` lint detects the use of the [`macro_use` attribute].
     ///
     /// ### Example
     ///
@@ -2221,12 +2179,13 @@ declare_lint! {
     /// This will produce:
     ///
     /// ```text
-    /// error: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
+    /// error: applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
     ///  --> src/main.rs:3:1
     ///   |
     /// 3 | #[macro_use]
     ///   | ^^^^^^^^^^^^
     ///   |
+    ///   = help: remove it and import macros at use sites with a `use` item instead
     /// note: the lint level is defined here
     ///  --> src/main.rs:1:9
     ///   |
@@ -3707,53 +3666,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `proc_macro_back_compat` lint detects uses of old versions of certain
-    /// proc-macro crates, which have hardcoded workarounds in the compiler.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,ignore (needs-dependency)
-    ///
-    /// use time_macros_impl::impl_macros;
-    /// struct Foo;
-    /// impl_macros!(Foo);
-    /// ```
-    ///
-    /// This will produce:
-    ///
-    /// ```text
-    /// warning: using an old version of `time-macros-impl`
-    ///   ::: $DIR/group-compat-hack.rs:27:5
-    ///    |
-    /// LL |     impl_macros!(Foo);
-    ///    |     ------------------ in this macro invocation
-    ///    |
-    ///    = note: `#[warn(proc_macro_back_compat)]` on by default
-    ///    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    ///    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-    ///    = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
-    ///    = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-    /// ```
-    ///
-    /// ### Explanation
-    ///
-    /// Eventually, the backwards-compatibility hacks present in the compiler will be removed,
-    /// causing older versions of certain crates to stop compiling.
-    /// This is a [future-incompatible] lint to ease the transition to an error.
-    /// See [issue #83125] for more details.
-    ///
-    /// [issue #83125]: https://github.com/rust-lang/rust/issues/83125
-    /// [future-incompatible]: ../index.md#future-incompatible-lints
-    pub PROC_MACRO_BACK_COMPAT,
-    Deny,
-    "detects usage of old versions of certain proc-macro crates",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
-        reference: "issue #83125 <https://github.com/rust-lang/rust/issues/83125>",
-    };
-}
-
-declare_lint! {
     /// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns.
     ///
     /// ### Example
@@ -4893,3 +4805,40 @@ declare_lint! {
         reference: "issue #27970 <https://github.com/rust-lang/rust/issues/27970>",
     };
 }
+
+declare_lint! {
+    /// The `missing_unsafe_on_extern` lint detects missing unsafe keyword on extern declarations.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(unsafe_extern_blocks)]
+    /// #![warn(missing_unsafe_on_extern)]
+    /// #![allow(dead_code)]
+    ///
+    /// extern "C" {
+    ///     fn foo(_: i32);
+    /// }
+    ///
+    /// fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Declaring extern items, even without ever using them, can cause Undefined Behavior. We
+    /// should consider all sources of Undefined Behavior to be unsafe.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a
+    /// hard error in the future.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub MISSING_UNSAFE_ON_EXTERN,
+    Allow,
+    "detects missing unsafe keyword on extern declarations",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index c8a9fb02bf2..8bf25024afe 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -618,10 +618,6 @@ pub enum BuiltinLintDiag {
         is_foreign: bool,
     },
     LegacyDeriveHelpers(Span),
-    ProcMacroBackCompat {
-        crate_name: String,
-        fixed_version: String,
-    },
     OrPatternsBackCompat(Span, String),
     ReservedPrefix(Span, String),
     TrailingMacro(bool, Ident),
@@ -630,6 +626,9 @@ pub enum BuiltinLintDiag {
     UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
     UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
     DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
+    MissingUnsafeOnExtern {
+        suggestion: Span,
+    },
     SingleUseLifetime {
         /// Span of the parameter which declares this lifetime.
         param_span: Span,
@@ -707,7 +706,10 @@ pub enum BuiltinLintDiag {
     },
     MacroUseDeprecated,
     UnusedMacroUse,
-    PrivateExternCrateReexport(Ident),
+    PrivateExternCrateReexport {
+        source: Ident,
+        extern_crate_span: Span,
+    },
     UnusedLabel,
     MacroIsPrivate(Ident),
     UnusedMacroDefinition(Symbol),
diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs
index 5377bbdfeab..bbaa477237b 100644
--- a/compiler/rustc_macros/src/extension.rs
+++ b/compiler/rustc_macros/src/extension.rs
@@ -6,6 +6,7 @@ use syn::spanned::Spanned;
 use syn::{
     braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature,
     Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility,
+    WhereClause,
 };
 
 pub(crate) fn extension(
@@ -13,7 +14,7 @@ pub(crate) fn extension(
     input: proc_macro::TokenStream,
 ) -> proc_macro::TokenStream {
     let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr);
-    let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl);
+    let Impl { attrs, generics, self_ty, items, wc } = parse_macro_input!(input as Impl);
     let headers: Vec<_> = items
         .iter()
         .map(|item| match item {
@@ -59,7 +60,7 @@ pub(crate) fn extension(
             #(#headers)*
         }
 
-        impl #generics #trait_ for #self_ty {
+        impl #generics #trait_ for #self_ty #wc {
             #(#items)*
         }
     }
@@ -133,6 +134,7 @@ struct Impl {
     generics: Generics,
     self_ty: Type,
     items: Vec<ImplItem>,
+    wc: Option<WhereClause>,
 }
 
 impl Parse for Impl {
@@ -141,6 +143,7 @@ impl Parse for Impl {
         let _: Token![impl] = input.parse()?;
         let generics = input.parse()?;
         let self_ty = input.parse()?;
+        let wc = input.parse()?;
 
         let content;
         let _brace_token = braced!(content in input);
@@ -149,6 +152,6 @@ impl Parse for Impl {
             items.push(content.parse()?);
         }
 
-        Ok(Impl { attrs, generics, self_ty, items })
+        Ok(Impl { attrs, generics, self_ty, items, wc })
     }
 }
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 25675e06e38..ceff1da9763 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -314,6 +314,17 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
     let mut query_description_stream = quote! {};
     let mut query_cached_stream = quote! {};
     let mut feedable_queries = quote! {};
+    let mut errors = quote! {};
+
+    macro_rules! assert {
+        ( $cond:expr, $span:expr, $( $tt:tt )+ ) => {
+            if !$cond {
+                errors.extend(
+                    Error::new($span, format!($($tt)+)).into_compile_error(),
+                );
+            }
+        }
+    }
 
     for query in queries.0 {
         let Query { name, arg, modifiers, .. } = &query;
@@ -369,10 +380,15 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             [#attribute_stream] fn #name(#arg) #result,
         });
 
-        if modifiers.feedable.is_some() {
-            assert!(modifiers.anon.is_none(), "Query {name} cannot be both `feedable` and `anon`.");
+        if let Some(feedable) = &modifiers.feedable {
+            assert!(
+                modifiers.anon.is_none(),
+                feedable.span(),
+                "Query {name} cannot be both `feedable` and `anon`."
+            );
             assert!(
                 modifiers.eval_always.is_none(),
+                feedable.span(),
                 "Query {name} cannot be both `feedable` and `eval_always`."
             );
             feedable_queries.extend(quote! {
@@ -407,5 +423,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             use super::*;
             #query_cached_stream
         }
+        #errors
     })
 }
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 44a3e9760e1..ad283117d7e 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -581,7 +581,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
                 hash,
                 extra_filename,
-                false, // is_host
                 path_kind,
             );
 
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index bf9bbfb8cfa..9c69ab2344e 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -144,7 +144,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                     && sess.crt_static(Some(ty))
                     && !sess.target.crt_static_allows_dylibs)
             {
-                for &cnum in tcx.used_crates(()).iter() {
+                for &cnum in tcx.crates(()).iter() {
                     if tcx.dep_kind(cnum).macros_only() {
                         continue;
                     }
@@ -165,7 +165,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     // Sweep all crates for found dylibs. Add all dylibs, as well as their
     // dependencies, ensuring there are no conflicts. The only valid case for a
     // dependency to be relied upon twice is for both cases to rely on a dylib.
-    for &cnum in tcx.used_crates(()).iter() {
+    for &cnum in tcx.crates(()).iter() {
         if tcx.dep_kind(cnum).macros_only() {
             continue;
         }
@@ -183,7 +183,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     }
 
     // Collect what we've got so far in the return vector.
-    let last_crate = tcx.used_crates(()).len();
+    let last_crate = tcx.crates(()).len();
     let mut ret = (1..last_crate + 1)
         .map(|cnum| match formats.get(&CrateNum::new(cnum)) {
             Some(&RequireDynamic) => Linkage::Dynamic,
@@ -197,7 +197,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     //
     // If the crate hasn't been included yet and it's not actually required
     // (e.g., it's an allocator) then we skip it here as well.
-    for &cnum in tcx.used_crates(()).iter() {
+    for &cnum in tcx.crates(()).iter() {
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_none()
             && !formats.contains_key(&cnum)
@@ -285,7 +285,7 @@ fn add_library(
 
 fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<DependencyList> {
     let all_crates_available_as_rlib = tcx
-        .used_crates(())
+        .crates(())
         .iter()
         .copied()
         .filter_map(|cnum| {
@@ -306,7 +306,7 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<De
     // All crates are available in an rlib format, so we're just going to link
     // everything in explicitly so long as it's actually required.
     let mut ret = tcx
-        .used_crates(())
+        .crates(())
         .iter()
         .map(|&cnum| match tcx.dep_kind(cnum) {
             CrateDepKind::Explicit => Linkage::Static,
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 73443de3553..90fe52a3438 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -222,7 +222,6 @@ use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_fs_util::try_canonicalize;
-use rustc_session::config;
 use rustc_session::cstore::CrateSource;
 use rustc_session::filesearch::FileSearch;
 use rustc_session::search_paths::PathKind;
@@ -309,7 +308,6 @@ impl<'a> CrateLocator<'a> {
         is_rlib: bool,
         hash: Option<Svh>,
         extra_filename: Option<&'a str>,
-        is_host: bool,
         path_kind: PathKind,
     ) -> CrateLocator<'a> {
         let needs_object_code = sess.opts.output_types.should_codegen();
@@ -340,17 +338,9 @@ impl<'a> CrateLocator<'a> {
             },
             hash,
             extra_filename,
-            target: if is_host { &sess.host } else { &sess.target },
-            triple: if is_host {
-                TargetTriple::from_triple(config::host_triple())
-            } else {
-                sess.opts.target_triple.clone()
-            },
-            filesearch: if is_host {
-                sess.host_filesearch(path_kind)
-            } else {
-                sess.target_filesearch(path_kind)
-            },
+            target: &sess.target,
+            triple: sess.opts.target_triple.clone(),
+            filesearch: sess.target_filesearch(path_kind),
             is_proc_macro: false,
             crate_rejections: CrateRejections::default(),
         }
@@ -424,12 +414,18 @@ impl<'a> CrateLocator<'a> {
                 debug!("testing {}", spf.path.display());
 
                 let f = &spf.file_name_str;
-                let (hash, kind) = if f.starts_with(rlib_prefix) && f.ends_with(rlib_suffix) {
-                    (&f[rlib_prefix.len()..(f.len() - rlib_suffix.len())], CrateFlavor::Rlib)
-                } else if f.starts_with(rmeta_prefix) && f.ends_with(rmeta_suffix) {
-                    (&f[rmeta_prefix.len()..(f.len() - rmeta_suffix.len())], CrateFlavor::Rmeta)
-                } else if f.starts_with(dylib_prefix) && f.ends_with(dylib_suffix.as_ref()) {
-                    (&f[dylib_prefix.len()..(f.len() - dylib_suffix.len())], CrateFlavor::Dylib)
+                let (hash, kind) = if let Some(f) = f.strip_prefix(rlib_prefix)
+                    && let Some(f) = f.strip_suffix(rlib_suffix)
+                {
+                    (f, CrateFlavor::Rlib)
+                } else if let Some(f) = f.strip_prefix(rmeta_prefix)
+                    && let Some(f) = f.strip_suffix(rmeta_suffix)
+                {
+                    (f, CrateFlavor::Rmeta)
+                } else if let Some(f) = f.strip_prefix(dylib_prefix)
+                    && let Some(f) = f.strip_suffix(dylib_suffix.as_ref())
+                {
+                    (f, CrateFlavor::Dylib)
                 } else {
                     if f.starts_with(staticlib_prefix) && f.ends_with(staticlib_suffix.as_ref()) {
                         self.crate_rejections.via_kind.push(CrateMismatch {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index f6b9c7ed992..1cef35f082b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -314,6 +314,7 @@ provide! { tcx, def_id, other, cdata,
     extern_crate => { cdata.extern_crate.map(|c| &*tcx.arena.alloc(c)) }
     is_no_builtins => { cdata.root.no_builtins }
     symbol_mangling_version => { cdata.root.symbol_mangling_version }
+    specialization_enabled_in => { cdata.root.specialization_enabled_in }
     reachable_non_generics => {
         let reachable_non_generics = tcx
             .exported_symbols(cdata.cnum)
@@ -439,7 +440,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
             // traversal, but not globally minimal across all crates.
             let bfs_queue = &mut VecDeque::new();
 
-            for &cnum in tcx.crates_including_speculative(()) {
+            for &cnum in tcx.crates(()) {
                 // Ignore crates without a corresponding local `extern crate` item.
                 if tcx.missing_extern_crate_item(cnum) {
                     continue;
@@ -509,7 +510,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
             tcx.arena
                 .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
         },
-        crates_including_speculative: |tcx, ()| {
+        crates: |tcx, ()| {
             // The list of loaded crates is now frozen in query cache,
             // so make sure cstore is not mutably accessed from here on.
             tcx.untracked().cstore.freeze();
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 4f186981a76..89da0df8575 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -741,6 +741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 expn_data,
                 expn_hashes,
                 def_path_hash_map,
+                specialization_enabled_in: tcx.specialization_enabled_in(LOCAL_CRATE),
             })
         });
 
@@ -1899,7 +1900,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let deps = self
             .tcx
-            .crates_including_speculative(())
+            .crates(())
             .iter()
             .map(|&cnum| {
                 let dep = CrateDep {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index c2cf5b6b712..87900c23d8d 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -290,6 +290,8 @@ pub(crate) struct CrateRoot {
     panic_runtime: bool,
     profiler_runtime: bool,
     symbol_mangling_version: SymbolManglingVersion,
+
+    specialization_enabled_in: bool,
 }
 
 /// On-disk representation of `DefId`.
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 23a6ceb4d3e..dcbddad2dbc 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -156,10 +156,14 @@ fixed_size_enum! {
         ( Impl { of_trait: false }                 )
         ( Impl { of_trait: true }                  )
         ( Closure                                  )
-        ( Static { mutability: ast::Mutability::Not, nested: false } )
-        ( Static { mutability: ast::Mutability::Mut, nested: false } )
-        ( Static { mutability: ast::Mutability::Not, nested: true } )
-        ( Static { mutability: ast::Mutability::Mut, nested: true } )
+        ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } )
+        ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } )
+        ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } )
+        ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: false } )
+        ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: true } )
+        ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: true } )
+        ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: true } )
+        ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: true } )
         ( Ctor(CtorOf::Struct, CtorKind::Fn)       )
         ( Ctor(CtorOf::Struct, CtorKind::Const)    )
         ( Ctor(CtorOf::Variant, CtorKind::Fn)      )
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index ab0c598ea0c..3dc592980fd 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -11,7 +11,6 @@ either = "1.5.0"
 field-offset = "0.3.5"
 gsgdt = "0.1.2"
 polonius-engine = "0.13.0"
-rustc-rayon = { version = "0.5.0", optional = true }
 rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
@@ -28,7 +27,6 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
-rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
@@ -42,5 +40,5 @@ tracing = "0.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["rustc-rayon", "rustc-rayon-core"]
+rustc_use_parallel_compiler = ["rustc-rayon-core"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index bf6ab800064..de786c38326 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -62,7 +62,7 @@ macro_rules! arena_types {
             [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
             [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
             [] canonical_goal_evaluation:
-                rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep<
+                rustc_type_ir::solve::inspect::CanonicalGoalEvaluationStep<
                     rustc_middle::ty::TyCtxt<'tcx>
                 >,
             [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 639c98155e7..305ba1ef3bb 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,5 +1,3 @@
-use std::borrow::Cow;
-
 use crate::hir::ModuleItems;
 use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
@@ -256,26 +254,13 @@ impl<'hir> Map<'hir> {
 
     /// Given a `LocalDefId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
-    pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<Cow<'hir, Body<'hir>>> {
-        Some(match self.tcx.def_kind(id) {
-            // Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler.
-            DefKind::InlineConst => {
-                let e = self.expect_expr(self.tcx.local_def_id_to_hir_id(id));
-                Cow::Owned(Body {
-                    params: &[],
-                    value: match e.kind {
-                        ExprKind::ConstBlock(body) => body,
-                        _ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"),
-                    },
-                })
-            }
-            _ => Cow::Borrowed(self.body(self.tcx.hir_node_by_def_id(id).body_id()?)),
-        })
+    pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<&'hir Body<'hir>> {
+        Some(self.body(self.tcx.hir_node_by_def_id(id).body_id()?))
     }
 
     /// Given a body owner's id, returns the `BodyId` associated with it.
     #[track_caller]
-    pub fn body_owned_by(self, id: LocalDefId) -> Cow<'hir, Body<'hir>> {
+    pub fn body_owned_by(self, id: LocalDefId) -> &'hir Body<'hir> {
         self.maybe_body_owned_by(id).unwrap_or_else(|| {
             let hir_id = self.tcx.local_def_id_to_hir_id(id);
             span_bug!(
@@ -305,7 +290,9 @@ impl<'hir> Map<'hir> {
             DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
             DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
             DefKind::Closure => BodyOwnerKind::Closure,
-            DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability),
+            DefKind::Static { safety: _, mutability, nested: false } => {
+                BodyOwnerKind::Static(mutability)
+            }
             dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
         }
     }
@@ -336,7 +323,7 @@ impl<'hir> Map<'hir> {
 
     /// Returns an iterator of the `DefId`s for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
-    /// themselves, you can do `self.hir().krate().owners.iter()`.
+    /// themselves, you can do `self.hir().krate().body_ids.iter()`.
     #[inline]
     pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
         self.tcx.hir_crate_items(()).body_owners.iter().copied()
@@ -523,17 +510,7 @@ impl<'hir> Map<'hir> {
     /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
     /// Used exclusively for diagnostics, to avoid suggestion function calls.
     pub fn is_inside_const_context(self, hir_id: HirId) -> bool {
-        for (_, node) in self.parent_iter(hir_id) {
-            if let Some((def_id, _)) = node.associated_body() {
-                return self.body_const_context(def_id).is_some();
-            }
-            if let Node::Expr(e) = node {
-                if let ExprKind::ConstBlock(_) = e.kind {
-                    return true;
-                }
-            }
-        }
-        false
+        self.body_const_context(self.enclosing_body_owner(hir_id)).is_some()
     }
 
     /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
@@ -886,7 +863,7 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => named_span(variant.span, variant.ident, None),
             Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
             Node::ForeignItem(item) => match item.kind {
-                ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
+                ForeignItemKind::Fn(decl, _, _, _) => until_within(item.span, decl.output.span()),
                 _ => named_span(item.span, item.ident, None),
             },
             Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
@@ -916,6 +893,7 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => variant.span,
             Node::Field(field) => field.span,
             Node::AnonConst(constant) => constant.span,
+            Node::ConstBlock(constant) => self.body(constant.body).value.span,
             Node::Expr(expr) => expr.span,
             Node::ExprField(field) => field.span,
             Node::Stmt(stmt) => stmt.span,
@@ -1040,7 +1018,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     let krate = tcx.hir_crate(());
     let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
 
-    let upstream_crates = upstream_crates_for_hashing(tcx);
+    let upstream_crates = upstream_crates(tcx);
 
     let resolutions = tcx.resolutions(());
 
@@ -1109,9 +1087,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     Svh::new(crate_hash)
 }
 
-fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
+fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
     let mut upstream_crates: Vec<_> = tcx
-        .crates_including_speculative(())
+        .crates(())
         .iter()
         .map(|&cnum| {
             let stable_crate_id = tcx.stable_crate_id(cnum);
@@ -1185,6 +1163,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
             format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
         }
         Node::AnonConst(_) => node_str("const"),
+        Node::ConstBlock(_) => node_str("const"),
         Node::Expr(_) => node_str("expr"),
         Node::ExprField(_) => node_str("expr field"),
         Node::Stmt(_) => node_str("stmt"),
@@ -1334,6 +1313,11 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
         intravisit::walk_anon_const(self, c)
     }
 
+    fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
+        self.body_owners.push(c.def_id);
+        intravisit::walk_inline_const(self, c)
+    }
+
     fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
         if let ExprKind::Closure(closure) = ex.kind {
             self.body_owners.push(closure.def_id);
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index b0c14cdfec9..57c8ba96a20 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -201,7 +201,7 @@ pub fn provide(providers: &mut Providers) {
             ..
         })
         | Node::ForeignItem(&ForeignItem {
-            kind: ForeignItemKind::Fn(_, idents, _),
+            kind: ForeignItemKind::Fn(_, idents, _, _),
             ..
         }) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
         {
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 105be21f272..a5da7e7739e 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -86,21 +86,6 @@ impl<'tcx> UnifyValue for RegionVariableValue<'tcx> {
     }
 }
 
-impl ToType for ty::IntVarValue {
-    fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        match *self {
-            ty::IntType(i) => Ty::new_int(tcx, i),
-            ty::UintType(i) => Ty::new_uint(tcx, i),
-        }
-    }
-}
-
-impl ToType for ty::FloatVarValue {
-    fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        Ty::new_float(tcx, self.0)
-    }
-}
-
 // Generic consts.
 
 #[derive(Copy, Clone, Debug)]
@@ -211,6 +196,7 @@ impl<'tcx> EffectVarValue<'tcx> {
 
 impl<'tcx> UnifyValue for EffectVarValue<'tcx> {
     type Error = NoError;
+
     fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
         match (*value1, *value2) {
             (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown),
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index d47e393c912..b499604df87 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -4,15 +4,16 @@
 //! has their own README with further details).
 //!
 //! - **HIR.** The "high-level (H) intermediate representation (IR)" is
-//!   defined in the `hir` module.
+//!   defined in the [`hir`] module.
 //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
-//!   defined in the `mir` module. This module contains only the
+//!   defined in the [`mir`] module. This module contains only the
 //!   *definition* of the MIR; the passes that transform and operate
 //!   on MIR are found in `rustc_const_eval` crate.
 //! - **Types.** The internal representation of types used in rustc is
-//!   defined in the `ty` module. This includes the **type context**
-//!   (or `tcx`), which is the central context during most of
-//!   compilation, containing the interners and other things.
+//!   defined in the [`ty`] module. This includes the
+//!   [**type context**][ty::TyCtxt] (or `tcx`), which is the central
+//!   context during most of compilation, containing the interners and
+//!   other things.
 //!
 //! For more information about how rustc works, see the [rustc dev guide].
 //!
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index e107c2c12bd..89f5acacf9d 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -84,11 +84,11 @@ impl<'tcx> ConstValue<'tcx> {
     }
 
     pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
-        self.try_to_scalar()?.try_to_int().ok()
+        self.try_to_scalar()?.try_to_scalar_int().ok()
     }
 
     pub fn try_to_bits(&self, size: Size) -> Option<u128> {
-        self.try_to_scalar_int()?.try_to_bits(size).ok()
+        Some(self.try_to_scalar_int()?.to_bits(size))
     }
 
     pub fn try_to_bool(&self) -> Option<bool> {
@@ -96,7 +96,7 @@ impl<'tcx> ConstValue<'tcx> {
     }
 
     pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
-        self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
+        Some(self.try_to_scalar_int()?.to_target_usize(tcx))
     }
 
     pub fn try_to_bits_for_ty(
@@ -204,7 +204,9 @@ pub enum Const<'tcx> {
     /// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`;
     /// this ensures that we consistently produce "clean" values without data in the padding or
     /// anything like that.
-    Ty(ty::Const<'tcx>),
+    ///
+    /// FIXME(BoxyUwU): We should remove this `Ty` and look up the type for params via `ParamEnv`
+    Ty(Ty<'tcx>, ty::Const<'tcx>),
 
     /// An unevaluated mir constant which is not part of the type system.
     ///
@@ -237,7 +239,15 @@ impl<'tcx> Const<'tcx> {
     #[inline(always)]
     pub fn ty(&self) -> Ty<'tcx> {
         match self {
-            Const::Ty(c) => c.ty(),
+            Const::Ty(ty, ct) => {
+                match ct.kind() {
+                    // Dont use the outter ty as on invalid code we can wind up with them not being the same.
+                    // this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir
+                    // was originally `({N: usize} + 1_usize)` under `generic_const_exprs`.
+                    ty::ConstKind::Value(ty, _) => ty,
+                    _ => *ty,
+                }
+            }
             Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
         }
     }
@@ -247,8 +257,8 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     pub fn is_required_const(&self) -> bool {
         match self {
-            Const::Ty(c) => match c.kind() {
-                ty::ConstKind::Value(_) => false, // already a value, cannot error
+            Const::Ty(_, c) => match c.kind() {
+                ty::ConstKind::Value(_, _) => false, // already a value, cannot error
                 _ => true,
             },
             Const::Val(..) => false, // already a value, cannot error
@@ -259,8 +269,8 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar> {
         match self {
-            Const::Ty(c) => match c.kind() {
-                ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
+            Const::Ty(_, c) => match c.kind() {
+                ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
                     // A valtree of a type where leaves directly represent the scalar const value.
                     // Just checking whether it is a leaf is insufficient as e.g. references are leafs
                     // but the leaf value is the value they point to, not the reference itself!
@@ -278,8 +288,8 @@ impl<'tcx> Const<'tcx> {
         // This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
         match self {
             Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
-            Const::Ty(c) => match c.kind() {
-                ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
+            Const::Ty(_, c) => match c.kind() {
+                ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
                     Some(valtree.unwrap_leaf())
                 }
                 _ => None,
@@ -290,7 +300,7 @@ impl<'tcx> Const<'tcx> {
 
     #[inline]
     pub fn try_to_bits(self, size: Size) -> Option<u128> {
-        self.try_to_scalar_int()?.try_to_bits(size).ok()
+        Some(self.try_to_scalar_int()?.to_bits(size))
     }
 
     #[inline]
@@ -306,11 +316,11 @@ impl<'tcx> Const<'tcx> {
         span: Span,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         match self {
-            Const::Ty(c) => {
+            Const::Ty(_, c) => {
                 // We want to consistently have a "clean" value for type system constants (i.e., no
                 // data hidden in the padding), so we always go through a valtree here.
-                let val = c.eval(tcx, param_env, span)?;
-                Ok(tcx.valtree_to_const_val((self.ty(), val)))
+                let (ty, val) = c.eval(tcx, param_env, span)?;
+                Ok(tcx.valtree_to_const_val((ty, val)))
             }
             Const::Unevaluated(uneval, _) => {
                 // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
@@ -326,7 +336,7 @@ impl<'tcx> Const<'tcx> {
         match self.eval(tcx, param_env, DUMMY_SP) {
             Ok(val) => Self::Val(val, self.ty()),
             Err(ErrorHandled::Reported(guar, _span)) => {
-                Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
+                Self::Ty(Ty::new_error(tcx, guar.into()), ty::Const::new_error(tcx, guar.into()))
             }
             Err(ErrorHandled::TooGeneric(_span)) => self,
         }
@@ -338,15 +348,16 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<Scalar> {
-        match self {
-            Const::Ty(c) if c.ty().is_primitive() => {
-                // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
-                // are valtree leaves, and *not* on references. (References should return the
-                // pointer here, which valtrees don't represent.)
-                let val = c.eval(tcx, param_env, DUMMY_SP).ok()?;
-                Some(val.unwrap_leaf().into())
-            }
-            _ => self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar(),
+        if let Const::Ty(_, c) = self
+            && let ty::ConstKind::Value(ty, val) = c.kind()
+            && ty.is_primitive()
+        {
+            // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
+            // are valtree leaves, and *not* on references. (References should return the
+            // pointer here, which valtrees don't represent.)
+            Some(val.unwrap_leaf().into())
+        } else {
+            self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
         }
     }
 
@@ -356,7 +367,7 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<ScalarInt> {
-        self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
+        self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok()
     }
 
     #[inline]
@@ -364,7 +375,7 @@ impl<'tcx> Const<'tcx> {
         let int = self.try_eval_scalar_int(tcx, param_env)?;
         let size =
             tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
-        int.try_to_bits(size).ok()
+        Some(int.to_bits(size))
     }
 
     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
@@ -380,7 +391,7 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<u64> {
-        self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
+        Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx))
     }
 
     #[inline]
@@ -439,14 +450,14 @@ impl<'tcx> Const<'tcx> {
         Self::Val(val, ty)
     }
 
-    pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+    pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
         match c.kind() {
-            ty::ConstKind::Value(valtree) => {
+            ty::ConstKind::Value(ty, valtree) => {
                 // Make sure that if `c` is normalized, then the return value is normalized.
-                let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
-                Self::Val(const_val, c.ty())
+                let const_val = tcx.valtree_to_const_val((ty, valtree));
+                Self::Val(const_val, ty)
             }
-            _ => Self::Ty(c),
+            _ => Self::Ty(ty, c),
         }
     }
 
@@ -458,12 +469,12 @@ impl<'tcx> Const<'tcx> {
         // - valtrees purposefully generate new allocations
         // - ConstValue::Slice also generate new allocations
         match self {
-            Const::Ty(c) => match c.kind() {
+            Const::Ty(_, c) => match c.kind() {
                 ty::ConstKind::Param(..) => true,
                 // A valtree may be a reference. Valtree references correspond to a
                 // different allocation each time they are evaluated. Valtrees for primitive
                 // types are fine though.
-                ty::ConstKind::Value(_) => c.ty().is_primitive(),
+                ty::ConstKind::Value(ty, _) => ty.is_primitive(),
                 ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
                 // This can happen if evaluation of a constant failed. The result does not matter
                 // much since compilation is doomed.
@@ -517,7 +528,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
 impl<'tcx> Display for Const<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         match *self {
-            Const::Ty(c) => pretty_print_const(c, fmt, true),
+            Const::Ty(_, c) => pretty_print_const(c, fmt, true),
             Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
             // FIXME(valtrees): Correctly print mir constants.
             Const::Unevaluated(c, _ty) => {
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index fe743fa4aac..95857e8579d 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,4 +1,6 @@
-use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
+use super::{
+    ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId,
+};
 
 use crate::mir;
 use crate::query::TyCtxtEnsure;
@@ -13,7 +15,7 @@ use tracing::{debug, instrument};
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
-    /// that can't take any generic arguments like statics, const items or enum discriminants. If a
+    /// that can't take any generic arguments like const items or enum discriminants. If a
     /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
     #[instrument(skip(self), level = "debug")]
     pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
@@ -27,6 +29,24 @@ impl<'tcx> TyCtxt<'tcx> {
         let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
         self.const_eval_global_id(param_env, cid, DUMMY_SP)
     }
+
+    /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
+    /// that can't take any generic arguments like const items or enum discriminants. If a
+    /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
+    #[instrument(skip(self), level = "debug")]
+    pub fn const_eval_poly_to_alloc(self, def_id: DefId) -> EvalToAllocationRawResult<'tcx> {
+        // In some situations def_id will have generic parameters within scope, but they aren't allowed
+        // to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
+        // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
+        // encountered.
+        let args = GenericArgs::identity_for_item(self, def_id);
+        let instance = ty::Instance::new(def_id, args);
+        let cid = GlobalId { instance, promoted: None };
+        let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
+        let inputs = self.erase_regions(param_env.and(cid));
+        self.eval_to_allocation_raw(inputs)
+    }
+
     /// Resolves and evaluates a constant.
     ///
     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -177,7 +197,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
 impl<'tcx> TyCtxtEnsure<'tcx> {
     /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
-    /// that can't take any generic arguments like statics, const items or enum discriminants. If a
+    /// that can't take any generic arguments like const items or enum discriminants. If a
     /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
     #[instrument(skip(self), level = "debug")]
     pub fn const_eval_poly(self, def_id: DefId) {
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index c5c87c506b7..70e5ad0635b 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -123,15 +123,11 @@ impl<Prov> Scalar<Prov> {
     }
 
     #[inline]
-    pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
-        ScalarInt::try_from_uint(i, size).map(Scalar::Int)
-    }
-
-    #[inline]
     pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
         let i = i.into();
-        Self::try_from_uint(i, size)
+        ScalarInt::try_from_uint(i, size)
             .unwrap_or_else(|| bug!("Unsigned value {:#x} does not fit in {} bits", i, size.bits()))
+            .into()
     }
 
     #[inline]
@@ -165,15 +161,11 @@ impl<Prov> Scalar<Prov> {
     }
 
     #[inline]
-    pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
-        ScalarInt::try_from_int(i, size).map(Scalar::Int)
-    }
-
-    #[inline]
     pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
         let i = i.into();
-        Self::try_from_int(i, size)
+        ScalarInt::try_from_int(i, size)
             .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
+            .into()
     }
 
     #[inline]
@@ -197,6 +189,11 @@ impl<Prov> Scalar<Prov> {
     }
 
     #[inline]
+    pub fn from_i128(i: i128) -> Self {
+        Self::from_int(i, Size::from_bits(128))
+    }
+
+    #[inline]
     pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
         Self::from_int(i, cx.data_layout().pointer_size)
     }
@@ -222,7 +219,7 @@ impl<Prov> Scalar<Prov> {
     }
 
     /// This is almost certainly not the method you want!  You should dispatch on the type
-    /// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
+    /// and use `to_{u8,u16,...}`/`to_pointer` to perform ptr-to-int / int-to-ptr casts as needed.
     ///
     /// This method only exists for the benefit of low-level operations that truly need to treat the
     /// scalar in whatever form it is.
@@ -284,7 +281,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
     /// The error type is `AllocId`, not `CtfeProvenance`, since `AllocId` is the "minimal"
     /// component all provenance types must have.
     #[inline]
-    pub fn try_to_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
+    pub fn try_to_scalar_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
         match self {
             Scalar::Int(int) => Ok(int),
             Scalar::Ptr(ptr, sz) => {
@@ -302,13 +299,13 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
 
     #[inline(always)]
     pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
-        self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
+        self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
     }
 
     #[inline(always)]
     #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
-    pub fn assert_int(self) -> ScalarInt {
-        self.try_to_int().unwrap()
+    pub fn assert_scalar_int(self) -> ScalarInt {
+        self.try_to_scalar_int().expect("got a pointer where a ScalarInt was expected")
     }
 
     /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
@@ -325,13 +322,6 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
         })
     }
 
-    #[inline(always)]
-    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
-    pub fn assert_bits(self, target_size: Size) -> u128 {
-        self.to_bits(target_size)
-            .unwrap_or_else(|_| panic!("assertion failed: {self:?} fits {target_size:?}"))
-    }
-
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
         let val = self.to_u8()?;
         match val {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index a3d2140eb1b..3d79ec0092f 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -5,9 +5,9 @@ use rustc_data_structures::base_n::BaseNString;
 use rustc_data_structures::base_n::ToBaseN;
 use rustc_data_structures::base_n::CASE_INSENSITIVE;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::unord::UnordMap;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::ItemId;
 use rustc_index::Idx;
@@ -241,7 +241,17 @@ impl<'tcx> fmt::Display for MonoItem<'tcx> {
     }
 }
 
-#[derive(Debug)]
+impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> {
+    type KeyType = Fingerprint;
+
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'_>) -> Self::KeyType {
+        let mut hasher = StableHasher::new();
+        self.hash_stable(&mut hcx.clone(), &mut hasher);
+        hasher.finish()
+    }
+}
+
+#[derive(Debug, HashStable)]
 pub struct CodegenUnit<'tcx> {
     /// A name for this CGU. Incremental compilation requires that
     /// name be unique amongst **all** crates. Therefore, it should
@@ -430,38 +440,19 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let CodegenUnit {
-            ref items,
-            name,
-            // The size estimate is not relevant to the hash
-            size_estimate: _,
-            primary: _,
-            is_code_coverage_dead_code_cgu,
-        } = *self;
-
-        name.hash_stable(hcx, hasher);
-        is_code_coverage_dead_code_cgu.hash_stable(hcx, hasher);
-
-        let mut items: Vec<(Fingerprint, _)> = items
-            .iter()
-            .map(|(mono_item, &attrs)| {
-                let mut hasher = StableHasher::new();
-                mono_item.hash_stable(hcx, &mut hasher);
-                let mono_item_fingerprint = hasher.finish();
-                (mono_item_fingerprint, attrs)
-            })
-            .collect();
-
-        items.sort_unstable_by_key(|i| i.0);
-        items.hash_stable(hcx, hasher);
+impl ToStableHashKey<StableHashingContext<'_>> for CodegenUnit<'_> {
+    type KeyType = String;
+
+    fn to_stable_hash_key(&self, _: &StableHashingContext<'_>) -> Self::KeyType {
+        // Codegen unit names are conceptually required to be stable across
+        // compilation session so that object file names match up.
+        self.name.to_string()
     }
 }
 
 pub struct CodegenUnitNameBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    cache: FxHashMap<CrateNum, String>,
+    cache: UnordMap<CrateNum, String>,
 }
 
 impl<'tcx> CodegenUnitNameBuilder<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f1c79c0b039..b64b7e2b1dc 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -559,10 +559,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
     match (kind, body.source.promoted) {
         (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
         (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
-        (DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => {
+        (DefKind::Static { safety: _, mutability: hir::Mutability::Not, nested: false }, _) => {
             write!(w, "static ")?
         }
-        (DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => {
+        (DefKind::Static { safety: _, mutability: hir::Mutability::Mut, nested: false }, _) => {
             write!(w, "static mut ")?
         }
         (_, _) if is_function => write!(w, "fn ")?,
@@ -1313,12 +1313,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
             };
 
             let val = match const_ {
-                Const::Ty(ct) => match ct.kind() {
+                Const::Ty(_, ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("ty::Param({p})"),
                     ty::ConstKind::Unevaluated(uv) => {
                         format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
                     }
-                    ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)),
+                    ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
                     // No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
                     ty::ConstKind::Error(_) => "Error".to_string(),
                     // These variants shouldn't exist in the MIR.
@@ -1417,7 +1417,7 @@ pub fn write_allocations<'tcx>(
     impl<'tcx> Visitor<'tcx> for CollectAllocIds {
         fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
             match c.const_ {
-                Const::Ty(_) | Const::Unevaluated(..) => {}
+                Const::Ty(_, _) | Const::Unevaluated(..) => {}
                 Const::Val(val, _) => {
                     self.0.extend(alloc_ids_from_const_val(val));
                 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 8901fd42d93..f553b417294 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -895,7 +895,7 @@ macro_rules! make_mir_visitor {
 
                 self.visit_span($(& $mutability)? *span);
                 match const_ {
-                    Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
+                    Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
                     Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
                     Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
                 }
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index f98dbf8a0bd..b29a86d58ed 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -4,7 +4,7 @@ use crate::traits;
 use crate::ty::adjustment::CoerceUnsizedInfo;
 use crate::ty::{self, Ty};
 use std::intrinsics::transmute_unchecked;
-use std::mem::{size_of, MaybeUninit};
+use std::mem::MaybeUninit;
 
 #[derive(Copy, Clone)]
 pub struct Erased<T: Copy> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d72ad09f954..a8bf735fa5a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1309,7 +1309,7 @@ rustc_queries! {
     query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] {
         desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
     }
-    query check_is_object_safe(trait_id: DefId) -> bool {
+    query is_object_safe(trait_id: DefId) -> bool {
         desc { |tcx| "checking if trait `{}` is object safe", tcx.def_path_str(trait_id) }
     }
 
@@ -1494,6 +1494,11 @@ rustc_queries! {
         separate_provide_extern
     }
 
+    query specialization_enabled_in(cnum: CrateNum) -> bool {
+        desc { "checking whether the crate enabled `specialization`/`min_specialization`" }
+        separate_provide_extern
+    }
+
     query specializes(_: (DefId, DefId)) -> bool {
         desc { "computing whether impls specialize one another" }
     }
@@ -1861,22 +1866,13 @@ rustc_queries! {
         eval_always
         desc { "calculating the stability index for the local crate" }
     }
-    /// All loaded crates, including those loaded purely for doc links or diagnostics.
-    /// (Diagnostics include lints, so speculatively loaded crates may occur in successful
-    /// compilation even without doc links.)
-    /// Should be used when encoding crate metadata (and therefore when generating crate hash,
-    /// depinfo and similar things), to avoid dangling crate references in other encoded data,
-    /// like source maps.
-    /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some
-    /// items from it as well.
-    /// But otherwise, `used_crates` should generally be used.
-    query crates_including_speculative(_: ()) -> &'tcx [CrateNum] {
+    query crates(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
-    /// Crates that are loaded non-speculatively (not for diagnostics or doc links).
-    /// Should be used to maintain observable language behavior, for example when collecting lang
-    /// items or impls from all crates, or collecting libraries to link.
+    // Crates that are loaded non-speculatively (not for diagnostics or doc links).
+    // FIXME: This is currently only used for collecting lang items, but should be used instead of
+    // `crates` in most other cases too.
     query used_crates(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching `CrateNum`s for all crates loaded non-speculatively" }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 454897aa672..7c8b0ec671a 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -1033,8 +1033,8 @@ impl<'tcx> PatRangeBoundary<'tcx> {
                 if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
                     let sz = ty.primitive_size(tcx);
                     let cmp = match ty.kind() {
-                        ty::Uint(_) | ty::Char => a.assert_uint(sz).cmp(&b.assert_uint(sz)),
-                        ty::Int(_) => a.assert_int(sz).cmp(&b.assert_int(sz)),
+                        ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
+                        ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
                         _ => unreachable!(),
                     };
                     return Some(cmp);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 62e71c4db11..202d587f0ad 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -32,7 +32,7 @@ use std::hash::{Hash, Hasher};
 
 pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
 // FIXME: Remove this import and import via `solve::`
-pub use rustc_next_trait_solver::solve::BuiltinImplSource;
+pub use rustc_type_ir::solve::BuiltinImplSource;
 
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
@@ -616,6 +616,8 @@ pub enum SelectionError<'tcx> {
     /// We can thus not know whether the hidden type implements an auto trait, so
     /// we should not presume anything about it.
     OpaqueTypeAutoTraitLeakageUnknown(DefId),
+    /// Error for a `ConstArgHasType` goal
+    ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
 }
 
 #[derive(Clone, Debug, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 66e50307733..50b6c77e1b2 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -7,13 +7,12 @@
 
 use crate::error::DropCheckOverflow;
 use crate::infer::canonical::{Canonical, QueryResponse};
-use crate::ty::error::TypeError;
 use crate::ty::GenericArg;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
 use rustc_span::Span;
 // FIXME: Remove this import and import via `traits::solve`.
-pub use rustc_next_trait_solver::solve::NoSolution;
+pub use rustc_type_ir::solve::NoSolution;
 
 pub mod type_op {
     use crate::ty::fold::TypeFoldable;
@@ -91,12 +90,6 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
 
-impl<'tcx> From<TypeError<'tcx>> for NoSolution {
-    fn from(_: TypeError<'tcx>) -> NoSolution {
-        NoSolution
-    }
-}
-
 #[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
 pub struct DropckOutlivesResult<'tcx> {
     pub kinds: Vec<GenericArg<'tcx>>,
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index c8c16ec1e2c..0d9ce402c64 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -1,8 +1,8 @@
 use rustc_ast_ir::try_visit;
 use rustc_data_structures::intern::Interned;
 use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
-use rustc_next_trait_solver as ir;
-pub use rustc_next_trait_solver::solve::*;
+use rustc_type_ir as ir;
+pub use rustc_type_ir::solve::*;
 
 use crate::infer::canonical::QueryRegionConstraints;
 use crate::ty::{
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 7fb5e9aadae..254e1b54481 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
             fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
                 let ct = match c.kind() {
                     ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
-                        Err(e) => ty::Const::new_error(self.tcx, e, c.ty()),
+                        Err(e) => ty::Const::new_error(self.tcx, e),
                         Ok(Some(bac)) => {
                             let args = self.tcx.erase_regions(uv.args);
                             let bac = bac.instantiate(self.tcx, args);
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 5f9b870331c..886dbd317af 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -200,6 +200,12 @@ impl<'tcx> AdtDef<'tcx> {
     }
 }
 
+impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
+    fn def_id(self) -> DefId {
+        self.did()
+    }
+}
+
 #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
 pub enum AdtKind {
     Struct,
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 07652b47929..33f564e9b59 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -350,8 +350,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
     fn decode(decoder: &mut D) -> Self {
-        let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
-        decoder.interner().mk_ct_from_kind(consts.kind, consts.ty)
+        let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
+        decoder.interner().mk_ct_from_kind(kind)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 6416bbbe889..12f0c38b054 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -6,7 +6,7 @@ use rustc_error_messages::MultiSpan;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, instrument};
 
@@ -26,10 +26,9 @@ pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
 #[cfg(target_pointer_width = "64")]
 rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
 
-/// Use this rather than `ConstData`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
-pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
+pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstKind<'tcx>>>);
 
 impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
     type Kind = ConstKind<'tcx>;
@@ -49,26 +48,11 @@ impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> {
     }
 }
 
-/// Typed constant value.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-#[derive(HashStable, TyEncodable, TyDecodable)]
-pub struct ConstData<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub kind: ConstKind<'tcx>,
-}
-
-#[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstData<'_>, 40);
-
 impl<'tcx> Const<'tcx> {
     #[inline]
-    pub fn ty(self) -> Ty<'tcx> {
-        self.0.ty
-    }
-
-    #[inline]
     pub fn kind(self) -> ConstKind<'tcx> {
-        self.0.kind
+        let a: &ConstKind<'tcx> = self.0.0;
+        *a
     }
 
     // FIXME(compiler-errors): Think about removing this.
@@ -84,28 +68,28 @@ impl<'tcx> Const<'tcx> {
     }
 
     #[inline]
-    pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
-        tcx.mk_ct_from_kind(kind, ty)
+    pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
+        tcx.mk_ct_from_kind(kind)
     }
 
     #[inline]
-    pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Param(param), ty)
+    pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Param(param))
     }
 
     #[inline]
-    pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
+    pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
     }
 
     #[inline]
-    pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
+    pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
     }
 
     #[inline]
-    pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Infer(infer), ty)
+    pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Infer(infer))
     }
 
     #[inline]
@@ -113,50 +97,40 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         debruijn: ty::DebruijnIndex,
         var: ty::BoundVar,
-        ty: Ty<'tcx>,
     ) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
+        Const::new(tcx, ty::ConstKind::Bound(debruijn, var))
     }
 
     #[inline]
-    pub fn new_placeholder(
-        tcx: TyCtxt<'tcx>,
-        placeholder: ty::PlaceholderConst,
-        ty: Ty<'tcx>,
-    ) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
+    pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
     }
 
     #[inline]
-    pub fn new_unevaluated(
-        tcx: TyCtxt<'tcx>,
-        uv: ty::UnevaluatedConst<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
+    pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Unevaluated(uv))
     }
 
     #[inline]
     pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Value(val), ty)
+        Const::new(tcx, ty::ConstKind::Value(ty, val))
     }
 
     #[inline]
-    pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Expr(expr), ty)
+    pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Expr(expr))
     }
 
     #[inline]
-    pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
-        Const::new(tcx, ty::ConstKind::Error(e), ty)
+    pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
+        Const::new(tcx, ty::ConstKind::Error(e))
     }
 
     /// Like [Ty::new_error] but for constants.
     #[track_caller]
-    pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+    pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> {
         Const::new_error_with_message(
             tcx,
-            ty,
             DUMMY_SP,
             "ty::ConstKind::Error constructed but no error reported",
         )
@@ -166,52 +140,41 @@ impl<'tcx> Const<'tcx> {
     #[track_caller]
     pub fn new_error_with_message<S: Into<MultiSpan>>(
         tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
         span: S,
         msg: &'static str,
     ) -> Const<'tcx> {
         let reported = tcx.dcx().span_delayed_bug(span, msg);
-        Const::new_error(tcx, reported, ty)
+        Const::new_error(tcx, reported)
     }
 }
 
 impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
-    fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Self {
-        Const::new_infer(tcx, infer, ty)
+    fn try_to_target_usize(self, interner: TyCtxt<'tcx>) -> Option<u64> {
+        self.try_to_target_usize(interner)
     }
 
-    fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self {
-        Const::new_var(tcx, vid, ty)
+    fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
+        Const::new_infer(tcx, infer)
     }
 
-    fn new_bound(
-        interner: TyCtxt<'tcx>,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-        ty: Ty<'tcx>,
-    ) -> Self {
-        Const::new_bound(interner, debruijn, var, ty)
+    fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
+        Const::new_var(tcx, vid)
     }
 
-    fn new_anon_bound(
-        tcx: TyCtxt<'tcx>,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-        ty: Ty<'tcx>,
-    ) -> Self {
-        Const::new_bound(tcx, debruijn, var, ty)
+    fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
+        Const::new_bound(interner, debruijn, var)
     }
 
-    fn new_unevaluated(
-        interner: TyCtxt<'tcx>,
-        uv: ty::UnevaluatedConst<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> Self {
-        Const::new_unevaluated(interner, uv, ty)
+    fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
+        Const::new_bound(tcx, debruijn, var)
     }
 
-    fn ty(self) -> Ty<'tcx> {
-        self.ty()
+    fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
+        Const::new_unevaluated(interner, uv)
+    }
+
+    fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self {
+        Const::new_expr(interner, expr)
     }
 }
 
@@ -241,7 +204,6 @@ impl<'tcx> Const<'tcx> {
                     def: def.to_def_id(),
                     args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
                 },
-                ty,
             ),
         }
     }
@@ -293,9 +255,6 @@ impl<'tcx> Const<'tcx> {
                 _,
                 &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
             )) => {
-                // Use the type from the param's definition, since we can resolve it,
-                // not the expected parameter type from WithOptConstParam.
-                let param_ty = tcx.type_of(def_id).instantiate_identity();
                 match tcx.named_bound_var(expr.hir_id) {
                     Some(rbv::ResolvedArg::EarlyBound(_)) => {
                         // Find the name and index of the const parameter by indexing the generics of
@@ -304,19 +263,12 @@ impl<'tcx> Const<'tcx> {
                         let generics = tcx.generics_of(item_def_id);
                         let index = generics.param_def_id_to_index[&def_id];
                         let name = tcx.item_name(def_id);
-                        Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty))
+                        Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
                     }
                     Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
-                        Some(ty::Const::new_bound(
-                            tcx,
-                            debruijn,
-                            ty::BoundVar::from_u32(index),
-                            param_ty,
-                        ))
-                    }
-                    Some(rbv::ResolvedArg::Error(guar)) => {
-                        Some(ty::Const::new_error(tcx, guar, param_ty))
+                        Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
                     }
+                    Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
                     arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
                 }
             }
@@ -363,7 +315,7 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
         span: Span,
-    ) -> Result<ValTree<'tcx>, ErrorHandled> {
+    ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
         assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
         match self.kind() {
             ConstKind::Unevaluated(unevaluated) => {
@@ -381,9 +333,9 @@ impl<'tcx> Const<'tcx> {
                     );
                     return Err(e.into());
                 };
-                Ok(c)
+                Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
             }
-            ConstKind::Value(val) => Ok(val),
+            ConstKind::Value(ty, val) => Ok((ty, val)),
             ConstKind::Error(g) => Err(g.into()),
             ConstKind::Param(_)
             | ConstKind::Infer(_)
@@ -397,8 +349,8 @@ impl<'tcx> Const<'tcx> {
     #[inline]
     pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
         match self.eval(tcx, param_env, DUMMY_SP) {
-            Ok(val) => Self::new_value(tcx, val, self.ty()),
-            Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()),
+            Ok((ty, val)) => Self::new_value(tcx, val, ty),
+            Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
             Err(ErrorHandled::TooGeneric(_span)) => self,
         }
     }
@@ -408,8 +360,10 @@ impl<'tcx> Const<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> Option<Scalar> {
-        self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
+    ) -> Option<(Ty<'tcx>, Scalar)> {
+        let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
+        let val = val.try_to_scalar()?;
+        Some((ty, val))
     }
 
     #[inline]
@@ -420,8 +374,10 @@ impl<'tcx> Const<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
-    ) -> Option<ScalarInt> {
-        self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
+    ) -> Option<(Ty<'tcx>, ScalarInt)> {
+        let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
+        let val = scalar.try_to_scalar_int().ok()?;
+        Some((ty, val))
     }
 
     #[inline]
@@ -429,18 +385,17 @@ impl<'tcx> Const<'tcx> {
     /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
     /// contains const generic parameters or pointers).
     pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
-        let int = self.try_eval_scalar_int(tcx, param_env)?;
-        let size =
-            tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
+        let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
+        let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
         // if `ty` does not depend on generic parameters, use an empty param_env
-        int.try_to_bits(size).ok()
+        Some(scalar.to_bits(size))
     }
 
     #[inline]
     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 {
         self.try_eval_bits(tcx, param_env)
-            .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
+            .unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self))
     }
 
     #[inline]
@@ -449,12 +404,14 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
     ) -> Option<u64> {
-        self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
+        let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
+        Some(scalar.to_target_usize(tcx))
     }
 
     #[inline]
     pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
-        self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
+        let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
+        scalar.try_into().ok()
     }
 
     #[inline]
@@ -467,7 +424,7 @@ impl<'tcx> Const<'tcx> {
     /// Panics if self.kind != ty::ConstKind::Value
     pub fn to_valtree(self) -> ty::ValTree<'tcx> {
         match self.kind() {
-            ty::ConstKind::Value(valtree) => valtree,
+            ty::ConstKind::Value(_, valtree) => valtree,
             _ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
         }
     }
@@ -475,7 +432,7 @@ impl<'tcx> Const<'tcx> {
     /// Attempts to convert to a `ValTree`
     pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
         match self.kind() {
-            ty::ConstKind::Value(valtree) => Some(valtree),
+            ty::ConstKind::Value(_, valtree) => Some(valtree),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 40ac87873a0..52320dd141b 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -246,6 +246,10 @@ impl ScalarInt {
         Self::try_from_uint(i, tcx.data_layout.pointer_size)
     }
 
+    /// Try to convert this ScalarInt to the raw underlying bits.
+    /// Fails if the size is wrong. Generally a wrong size should lead to a panic,
+    /// but Miri sometimes wants to be resilient to size mismatches,
+    /// so the interpreter will generally use this `try` method.
     #[inline]
     pub fn try_to_bits(self, target_size: Size) -> Result<u128, Size> {
         assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
@@ -258,165 +262,149 @@ impl ScalarInt {
     }
 
     #[inline]
-    pub fn assert_bits(self, target_size: Size) -> u128 {
+    pub fn to_bits(self, target_size: Size) -> u128 {
         self.try_to_bits(target_size).unwrap_or_else(|size| {
             bug!("expected int of size {}, but got size {}", target_size.bytes(), size.bytes())
         })
     }
 
-    /// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
-    /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
-    /// `ScalarInt`s size in that case.
+    /// Extracts the bits from the scalar without checking the size.
     #[inline]
-    pub fn try_to_uint(self, size: Size) -> Result<u128, Size> {
-        self.try_to_bits(size)
+    pub fn to_bits_unchecked(self) -> u128 {
+        self.check_data();
+        self.data
     }
 
+    /// Converts the `ScalarInt` to an unsigned integer of the given size.
+    /// Panics if the size of the `ScalarInt` is not equal to `size`.
     #[inline]
-    pub fn assert_uint(self, size: Size) -> u128 {
-        self.assert_bits(size)
+    pub fn to_uint(self, size: Size) -> u128 {
+        self.to_bits(size)
     }
 
-    // Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
-    // in not equal to 1 byte and returns the `size` value of the `ScalarInt` in
-    // that case.
+    /// Converts the `ScalarInt` to `u8`.
+    /// Panics if the `size` of the `ScalarInt`in not equal to 1 byte.
     #[inline]
-    pub fn try_to_u8(self) -> Result<u8, Size> {
-        self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
+    pub fn to_u8(self) -> u8 {
+        self.to_uint(Size::from_bits(8)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt`
-    /// in not equal to 2 bytes and returns the `size` value of the `ScalarInt` in
-    /// that case.
+    /// Converts the `ScalarInt` to `u16`.
+    /// Panics if the size of the `ScalarInt` in not equal to 2 bytes.
     #[inline]
-    pub fn try_to_u16(self) -> Result<u16, Size> {
-        self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
+    pub fn to_u16(self) -> u16 {
+        self.to_uint(Size::from_bits(16)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt`
-    /// in not equal to 4 bytes and returns the `size` value of the `ScalarInt` in
-    /// that case.
+    /// Converts the `ScalarInt` to `u32`.
+    /// Panics if the `size` of the `ScalarInt` in not equal to 4 bytes.
     #[inline]
-    pub fn try_to_u32(self) -> Result<u32, Size> {
-        self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
+    pub fn to_u32(self) -> u32 {
+        self.to_uint(Size::from_bits(32)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt`
-    /// in not equal to 8 bytes and returns the `size` value of the `ScalarInt` in
-    /// that case.
+    /// Converts the `ScalarInt` to `u64`.
+    /// Panics if the `size` of the `ScalarInt` in not equal to 8 bytes.
     #[inline]
-    pub fn try_to_u64(self) -> Result<u64, Size> {
-        self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
+    pub fn to_u64(self) -> u64 {
+        self.to_uint(Size::from_bits(64)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt`
-    /// in not equal to 16 bytes and returns the `size` value of the `ScalarInt` in
-    /// that case.
+    /// Converts the `ScalarInt` to `u128`.
+    /// Panics if the `size` of the `ScalarInt` in not equal to 16 bytes.
     #[inline]
-    pub fn try_to_u128(self) -> Result<u128, Size> {
-        self.try_to_uint(Size::from_bits(128))
+    pub fn to_u128(self) -> u128 {
+        self.to_uint(Size::from_bits(128))
     }
 
     #[inline]
-    pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
-        self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap())
+    pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 {
+        self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap()
     }
 
-    // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
-    // in not equal to 1 byte or if the value is not 0 or 1 and returns the `size`
-    // value of the `ScalarInt` in that case.
+    /// Converts the `ScalarInt` to `bool`.
+    /// Panics if the `size` of the `ScalarInt` is not equal to 1 byte.
+    /// Errors if it is not a valid `bool`.
     #[inline]
-    pub fn try_to_bool(self) -> Result<bool, Size> {
-        match self.try_to_u8()? {
+    pub fn try_to_bool(self) -> Result<bool, ()> {
+        match self.to_u8() {
             0 => Ok(false),
             1 => Ok(true),
-            _ => Err(self.size()),
+            _ => Err(()),
         }
     }
 
-    /// Tries to convert the `ScalarInt` to a signed integer of the given size.
-    /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
-    /// `ScalarInt`s size in that case.
-    #[inline]
-    pub fn try_to_int(self, size: Size) -> Result<i128, Size> {
-        let b = self.try_to_bits(size)?;
-        Ok(size.sign_extend(b) as i128)
-    }
-
+    /// Converts the `ScalarInt` to a signed integer of the given size.
+    /// Panics if the size of the `ScalarInt` is not equal to `size`.
     #[inline]
-    pub fn assert_int(self, size: Size) -> i128 {
-        let b = self.assert_bits(size);
+    pub fn to_int(self, size: Size) -> i128 {
+        let b = self.to_bits(size);
         size.sign_extend(b) as i128
     }
 
-    /// Tries to convert the `ScalarInt` to i8.
-    /// Fails if the size of the `ScalarInt` is not equal to 1 byte
-    /// and returns the `ScalarInt`s size in that case.
-    pub fn try_to_i8(self) -> Result<i8, Size> {
-        self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
+    /// Converts the `ScalarInt` to i8.
+    /// Panics if the size of the `ScalarInt` is not equal to 1 byte.
+    pub fn to_i8(self) -> i8 {
+        self.to_int(Size::from_bits(8)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to i16.
-    /// Fails if the size of the `ScalarInt` is not equal to 2 bytes
-    /// and returns the `ScalarInt`s size in that case.
-    pub fn try_to_i16(self) -> Result<i16, Size> {
-        self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
+    /// Converts the `ScalarInt` to i16.
+    /// Panics if the size of the `ScalarInt` is not equal to 2 bytes.
+    pub fn to_i16(self) -> i16 {
+        self.to_int(Size::from_bits(16)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to i32.
-    /// Fails if the size of the `ScalarInt` is not equal to 4 bytes
-    /// and returns the `ScalarInt`s size in that case.
-    pub fn try_to_i32(self) -> Result<i32, Size> {
-        self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
+    /// Converts the `ScalarInt` to i32.
+    /// Panics if the size of the `ScalarInt` is not equal to 4 bytes.
+    pub fn to_i32(self) -> i32 {
+        self.to_int(Size::from_bits(32)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to i64.
-    /// Fails if the size of the `ScalarInt` is not equal to 8 bytes
-    /// and returns the `ScalarInt`s size in that case.
-    pub fn try_to_i64(self) -> Result<i64, Size> {
-        self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
+    /// Converts the `ScalarInt` to i64.
+    /// Panics if the size of the `ScalarInt` is not equal to 8 bytes.
+    pub fn to_i64(self) -> i64 {
+        self.to_int(Size::from_bits(64)).try_into().unwrap()
     }
 
-    /// Tries to convert the `ScalarInt` to i128.
-    /// Fails if the size of the `ScalarInt` is not equal to 16 bytes
-    /// and returns the `ScalarInt`s size in that case.
-    pub fn try_to_i128(self) -> Result<i128, Size> {
-        self.try_to_int(Size::from_bits(128))
+    /// Converts the `ScalarInt` to i128.
+    /// Panics if the size of the `ScalarInt` is not equal to 16 bytes.
+    pub fn to_i128(self) -> i128 {
+        self.to_int(Size::from_bits(128))
     }
 
     #[inline]
-    pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result<i64, Size> {
-        self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap())
+    pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 {
+        self.to_int(tcx.data_layout.pointer_size).try_into().unwrap()
     }
 
     #[inline]
-    pub fn try_to_float<F: Float>(self) -> Result<F, Size> {
+    pub fn to_float<F: Float>(self) -> F {
         // Going through `to_uint` to check size and truncation.
-        Ok(F::from_bits(self.try_to_bits(Size::from_bits(F::BITS))?))
+        F::from_bits(self.to_bits(Size::from_bits(F::BITS)))
     }
 
     #[inline]
-    pub fn try_to_f16(self) -> Result<Half, Size> {
-        self.try_to_float()
+    pub fn to_f16(self) -> Half {
+        self.to_float()
     }
 
     #[inline]
-    pub fn try_to_f32(self) -> Result<Single, Size> {
-        self.try_to_float()
+    pub fn to_f32(self) -> Single {
+        self.to_float()
     }
 
     #[inline]
-    pub fn try_to_f64(self) -> Result<Double, Size> {
-        self.try_to_float()
+    pub fn to_f64(self) -> Double {
+        self.to_float()
     }
 
     #[inline]
-    pub fn try_to_f128(self) -> Result<Quad, Size> {
-        self.try_to_float()
+    pub fn to_f128(self) -> Quad {
+        self.to_float()
     }
 }
 
-macro_rules! from {
+macro_rules! from_x_for_scalar_int {
     ($($ty:ty),*) => {
         $(
             impl From<$ty> for ScalarInt {
@@ -432,30 +420,29 @@ macro_rules! from {
     }
 }
 
-macro_rules! try_from {
+macro_rules! from_scalar_int_for_x {
     ($($ty:ty),*) => {
         $(
-            impl TryFrom<ScalarInt> for $ty {
-                type Error = Size;
+            impl From<ScalarInt> for $ty {
                 #[inline]
-                fn try_from(int: ScalarInt) -> Result<Self, Size> {
+                fn from(int: ScalarInt) -> Self {
                     // The `unwrap` cannot fail because to_bits (if it succeeds)
                     // is guaranteed to return a value that fits into the size.
-                    int.try_to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
-                       .map(|u| u.try_into().unwrap())
+                    int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
+                       .try_into().unwrap()
                 }
             }
         )*
     }
 }
 
-from!(u8, u16, u32, u64, u128, bool);
-try_from!(u8, u16, u32, u64, u128);
+from_x_for_scalar_int!(u8, u16, u32, u64, u128, bool);
+from_scalar_int_for_x!(u8, u16, u32, u64, u128);
 
 impl TryFrom<ScalarInt> for bool {
-    type Error = Size;
+    type Error = ();
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
+    fn try_from(int: ScalarInt) -> Result<Self, ()> {
         int.try_to_bool()
     }
 }
@@ -463,7 +450,7 @@ impl TryFrom<ScalarInt> for bool {
 impl From<char> for ScalarInt {
     #[inline]
     fn from(c: char) -> Self {
-        Self { data: c as u128, size: NonZero::new(std::mem::size_of::<char>() as u8).unwrap() }
+        (c as u32).into()
     }
 }
 
@@ -476,10 +463,7 @@ impl TryFrom<ScalarInt> for char {
 
     #[inline]
     fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
-        let Ok(bits) = int.try_to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
-            return Err(CharTryFromScalarInt);
-        };
-        match char::from_u32(bits.try_into().unwrap()) {
+        match char::from_u32(int.to_u32()) {
             Some(c) => Ok(c),
             None => Err(CharTryFromScalarInt),
         }
@@ -494,11 +478,10 @@ impl From<Half> for ScalarInt {
     }
 }
 
-impl TryFrom<ScalarInt> for Half {
-    type Error = Size;
+impl From<ScalarInt> for Half {
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
-        int.try_to_bits(Size::from_bytes(2)).map(Self::from_bits)
+    fn from(int: ScalarInt) -> Self {
+        Self::from_bits(int.to_bits(Size::from_bytes(2)))
     }
 }
 
@@ -510,11 +493,10 @@ impl From<Single> for ScalarInt {
     }
 }
 
-impl TryFrom<ScalarInt> for Single {
-    type Error = Size;
+impl From<ScalarInt> for Single {
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
-        int.try_to_bits(Size::from_bytes(4)).map(Self::from_bits)
+    fn from(int: ScalarInt) -> Self {
+        Self::from_bits(int.to_bits(Size::from_bytes(4)))
     }
 }
 
@@ -526,11 +508,10 @@ impl From<Double> for ScalarInt {
     }
 }
 
-impl TryFrom<ScalarInt> for Double {
-    type Error = Size;
+impl From<ScalarInt> for Double {
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
-        int.try_to_bits(Size::from_bytes(8)).map(Self::from_bits)
+    fn from(int: ScalarInt) -> Self {
+        Self::from_bits(int.to_bits(Size::from_bytes(8)))
     }
 }
 
@@ -542,11 +523,10 @@ impl From<Quad> for ScalarInt {
     }
 }
 
-impl TryFrom<ScalarInt> for Quad {
-    type Error = Size;
+impl From<ScalarInt> for Quad {
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
-        int.try_to_bits(Size::from_bytes(16)).map(Self::from_bits)
+    fn from(int: ScalarInt) -> Self {
+        Self::from_bits(int.to_bits(Size::from_bytes(16)))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index d7ae050ed4d..bf834ef7607 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,7 +1,7 @@
 use super::Const;
 use crate::mir;
 use crate::ty::abstract_const::CastKind;
-use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
+use crate::ty::{self, visit::TypeVisitableExt as _, Ty, TyCtxt};
 use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 
 #[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
@@ -40,14 +40,127 @@ impl<'tcx> ty::UnevaluatedConst<'tcx> {
     }
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
+pub enum ExprKind {
+    Binop(mir::BinOp),
+    UnOp(mir::UnOp),
+    FunctionCall,
+    Cast(CastKind),
+}
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
-pub enum Expr<'tcx> {
-    Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
-    UnOp(mir::UnOp, Const<'tcx>),
-    FunctionCall(Const<'tcx>, &'tcx List<Const<'tcx>>),
-    Cast(CastKind, Const<'tcx>, Ty<'tcx>),
+pub struct Expr<'tcx> {
+    pub kind: ExprKind,
+    args: ty::GenericArgsRef<'tcx>,
+}
+impl<'tcx> Expr<'tcx> {
+    pub fn new_binop(
+        tcx: TyCtxt<'tcx>,
+        binop: mir::BinOp,
+        lhs_ty: Ty<'tcx>,
+        rhs_ty: Ty<'tcx>,
+        lhs_ct: Const<'tcx>,
+        rhs_ct: Const<'tcx>,
+    ) -> Self {
+        let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
+            [lhs_ty.into(), rhs_ty.into(), lhs_ct.into(), rhs_ct.into()].into_iter(),
+        );
+
+        Self { kind: ExprKind::Binop(binop), args }
+    }
+
+    pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) {
+        assert!(matches!(self.kind, ExprKind::Binop(_)));
+
+        match self.args().as_slice() {
+            [lhs_ty, rhs_ty, lhs_ct, rhs_ct] => (
+                lhs_ty.expect_ty(),
+                rhs_ty.expect_ty(),
+                lhs_ct.expect_const(),
+                rhs_ct.expect_const(),
+            ),
+            _ => bug!("Invalid args for `Binop` expr {self:?}"),
+        }
+    }
+
+    pub fn new_unop(tcx: TyCtxt<'tcx>, unop: mir::UnOp, ty: Ty<'tcx>, ct: Const<'tcx>) -> Self {
+        let args =
+            tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>([ty.into(), ct.into()].into_iter());
+
+        Self { kind: ExprKind::UnOp(unop), args }
+    }
+
+    pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) {
+        assert!(matches!(self.kind, ExprKind::UnOp(_)));
+
+        match self.args().as_slice() {
+            [ty, ct] => (ty.expect_ty(), ct.expect_const()),
+            _ => bug!("Invalid args for `UnOp` expr {self:?}"),
+        }
+    }
+
+    pub fn new_call(
+        tcx: TyCtxt<'tcx>,
+        func_ty: Ty<'tcx>,
+        func_expr: Const<'tcx>,
+        arguments: impl IntoIterator<Item = Const<'tcx>>,
+    ) -> Self {
+        let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
+            [func_ty.into(), func_expr.into()]
+                .into_iter()
+                .chain(arguments.into_iter().map(|ct| ct.into())),
+        );
+
+        Self { kind: ExprKind::FunctionCall, args }
+    }
+
+    pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator<Item = Const<'tcx>>) {
+        assert!(matches!(self.kind, ExprKind::FunctionCall));
+
+        match self.args().as_slice() {
+            [func_ty, func, rest @ ..] => (
+                func_ty.expect_ty(),
+                func.expect_const(),
+                rest.iter().map(|arg| arg.expect_const()),
+            ),
+            _ => bug!("Invalid args for `Call` expr {self:?}"),
+        }
+    }
+
+    pub fn new_cast(
+        tcx: TyCtxt<'tcx>,
+        cast: CastKind,
+        value_ty: Ty<'tcx>,
+        value: Const<'tcx>,
+        to_ty: Ty<'tcx>,
+    ) -> Self {
+        let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
+            [value_ty.into(), value.into(), to_ty.into()].into_iter(),
+        );
+
+        Self { kind: ExprKind::Cast(cast), args }
+    }
+
+    pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) {
+        assert!(matches!(self.kind, ExprKind::Cast(_)));
+
+        match self.args().as_slice() {
+            [value_ty, value, to_ty] => {
+                (value_ty.expect_ty(), value.expect_const(), to_ty.expect_ty())
+            }
+            _ => bug!("Invalid args for `Cast` expr {self:?}"),
+        }
+    }
+
+    pub fn new(kind: ExprKind, args: ty::GenericArgsRef<'tcx>) -> Self {
+        Self { kind, args }
+    }
+
+    pub fn args(self) -> ty::GenericArgsRef<'tcx> {
+        self.args
+    }
 }
 
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(Expr<'_>, 24);
+rustc_data_structures::static_assert_size!(Expr<'_>, 16);
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 96bc5515a56..efc91357af8 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -79,7 +79,7 @@ impl<'tcx> ValTree<'tcx> {
     }
 
     pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
-        self.try_to_scalar_int().and_then(|s| s.try_to_target_usize(tcx).ok())
+        self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
     }
 
     /// Get the values inside the ValTree as a slice of bytes. This only works for
@@ -100,8 +100,9 @@ impl<'tcx> ValTree<'tcx> {
             _ => return None,
         }
 
-        Some(tcx.arena.alloc_from_iter(
-            self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().try_to_u8().unwrap()),
-        ))
+        Some(
+            tcx.arena
+                .alloc_from_iter(self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8())),
+        )
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 47f66c64406..65d744239a6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -28,10 +28,10 @@ use crate::traits::solve::{
 };
 use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
-    GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
-    PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
-    Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
+    self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericParamDefKind,
+    ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, PatternKind,
+    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
+    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
 };
 use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_ast::{self as ast, attr};
@@ -69,6 +69,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
+use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
@@ -135,9 +136,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type ParamEnv = ty::ParamEnv<'tcx>;
     type Predicate = Predicate<'tcx>;
     type Clause = Clause<'tcx>;
-
     type Clauses = ty::Clauses<'tcx>;
 
+    fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
+        self.expand_abstract_consts(t)
+    }
+
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
     }
@@ -148,6 +152,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.generics_of(def_id)
     }
 
+    type VariancesOf = &'tcx [ty::Variance];
+
+    fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
+        self.variances_of(def_id)
+    }
+
     fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
         self.type_of(def_id)
     }
@@ -205,7 +215,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.mk_args(args)
     }
 
-    fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs {
+    fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Self::GenericArg, Self::GenericArgs>,
+    {
         self.mk_args_from_iter(args)
     }
 
@@ -224,6 +238,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.arena.alloc(step)
     }
 
+    fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Self::Ty, Self::Tys>,
+    {
+        self.mk_type_list_from_iter(args)
+    }
+
     fn parent(self, def_id: Self::DefId) -> Self::DefId {
         self.parent(def_id)
     }
@@ -231,6 +253,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     fn recursion_limit(self) -> usize {
         self.recursion_limit().0
     }
+
+    type Features = &'tcx rustc_feature::Features;
+
+    fn features(self) -> Self::Features {
+        self.features()
+    }
 }
 
 impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
@@ -249,6 +277,12 @@ impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
     }
 }
 
+impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
+    fn generic_const_exprs(self) -> bool {
+        self.generic_const_exprs
+    }
+}
+
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
@@ -268,7 +302,7 @@ pub struct CtxtInterners<'tcx> {
     clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
-    const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
+    const_: InternedSet<'tcx, WithCachedTypeInfo<ty::ConstKind<'tcx>>>,
     pat: InternedSet<'tcx, PatternKind<'tcx>>,
     const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
@@ -338,18 +372,18 @@ impl<'tcx> CtxtInterners<'tcx> {
     #[inline(never)]
     fn intern_const(
         &self,
-        data: ty::ConstData<'tcx>,
+        kind: ty::ConstKind<'tcx>,
         sess: &Session,
         untracked: &Untracked,
     ) -> Const<'tcx> {
         Const(Interned::new_unchecked(
             self.const_
-                .intern(data, |data: ConstData<'_>| {
-                    let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty);
-                    let stable_hash = self.stable_hash(&flags, sess, untracked, &data);
+                .intern(kind, |kind: ty::ConstKind<'_>| {
+                    let flags = super::flags::FlagComputation::for_const_kind(&kind);
+                    let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
 
                     InternedInSet(self.arena.alloc(WithCachedTypeInfo {
-                        internee: data,
+                        internee: kind,
                         stable_hash,
                         flags: flags.flags,
                         outer_exclusive_binder: flags.outer_exclusive_binder,
@@ -601,18 +635,15 @@ impl<'tcx> CommonConsts<'tcx> {
         };
 
         CommonConsts {
-            unit: mk_const(ty::ConstData {
-                kind: ty::ConstKind::Value(ty::ValTree::zst()),
-                ty: types.unit,
-            }),
-            true_: mk_const(ty::ConstData {
-                kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
-                ty: types.bool,
-            }),
-            false_: mk_const(ty::ConstData {
-                kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
-                ty: types.bool,
-            }),
+            unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())),
+            true_: mk_const(ty::ConstKind::Value(
+                types.bool,
+                ty::ValTree::Leaf(ty::ScalarInt::TRUE),
+            )),
+            false_: mk_const(ty::ConstKind::Value(
+                types.bool,
+                ty::ValTree::Leaf(ty::ScalarInt::FALSE),
+            )),
         }
     }
 }
@@ -743,7 +774,6 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
                 1,
             ),
             bodies,
-            has_inline_consts: false,
         })));
         self.feed_owner_id().hir_attrs(attrs);
     }
@@ -1619,7 +1649,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
-            .chain(self.used_crates(()).iter().copied())
+            .chain(self.crates(()).iter().copied())
             .flat_map(move |cnum| self.traits(cnum).iter().copied())
     }
 
@@ -2225,9 +2255,9 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+    pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
         self.interners.intern_const(
-            ty::ConstData { kind, ty },
+            kind,
             self.sess,
             // This is only used to create a stable hashing context.
             &self.untracked,
@@ -2252,14 +2282,10 @@ impl<'tcx> TyCtxt<'tcx> {
                 ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
             }
             GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
-            GenericParamDefKind::Const { .. } => ty::Const::new_param(
-                self,
-                ParamConst { index: param.index, name: param.name },
-                self.type_of(param.def_id)
-                    .no_bound_vars()
-                    .expect("const parameter types cannot be generic"),
-            )
-            .into(),
+            GenericParamDefKind::Const { .. } => {
+                ty::Const::new_param(self, ParamConst { index: param.index, name: param.name })
+                    .into()
+            }
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 99d703be873..32dc9fa5fc6 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,91 +1,26 @@
 use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
-use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
+
 use rustc_errors::pluralize;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind};
-use rustc_hir::def_id::DefId;
-use rustc_macros::{TypeFoldable, TypeVisitable};
-use rustc_span::symbol::Symbol;
-use rustc_target::spec::abi;
+use rustc_macros::extension;
+pub use rustc_type_ir::error::ExpectedFound;
+
 use std::borrow::Cow;
 use std::hash::{DefaultHasher, Hash, Hasher};
 use std::path::PathBuf;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
-pub struct ExpectedFound<T> {
-    pub expected: T,
-    pub found: T,
-}
-
-impl<T> ExpectedFound<T> {
-    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
-        if a_is_expected {
-            ExpectedFound { expected: a, found: b }
-        } else {
-            ExpectedFound { expected: b, found: a }
-        }
-    }
-}
-
-// Data structures used in type unification
-#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)]
-#[rustc_pass_by_value]
-pub enum TypeError<'tcx> {
-    Mismatch,
-    ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
-    PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
-    SafetyMismatch(ExpectedFound<hir::Safety>),
-    AbiMismatch(ExpectedFound<abi::Abi>),
-    Mutability,
-    ArgumentMutability(usize),
-    TupleSize(ExpectedFound<usize>),
-    FixedArraySize(ExpectedFound<u64>),
-    ArgCount,
-    FieldMisMatch(Symbol, Symbol),
-
-    RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
-    RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
-    RegionsPlaceholderMismatch,
-
-    Sorts(ExpectedFound<Ty<'tcx>>),
-    ArgumentSorts(ExpectedFound<Ty<'tcx>>, usize),
-    IntMismatch(ExpectedFound<ty::IntVarValue>),
-    FloatMismatch(ExpectedFound<ty::FloatTy>),
-    Traits(ExpectedFound<DefId>),
-    VariadicMismatch(ExpectedFound<bool>),
-
-    /// Instantiating a type variable with the given type would have
-    /// created a cycle (because it appears somewhere within that
-    /// type).
-    CyclicTy(Ty<'tcx>),
-    CyclicConst(ty::Const<'tcx>),
-    ProjectionMismatched(ExpectedFound<DefId>),
-    ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>),
-    ConstMismatch(ExpectedFound<ty::Const<'tcx>>),
-
-    IntrinsicCast,
-    /// Safe `#[target_feature]` functions are not assignable to safe function pointers.
-    TargetFeatureCast(DefId),
-}
-
-impl TypeError<'_> {
-    pub fn involves_regions(self) -> bool {
-        match self {
-            TypeError::RegionsDoesNotOutlive(_, _)
-            | TypeError::RegionsInsufficientlyPolymorphic(_, _)
-            | TypeError::RegionsPlaceholderMismatch => true,
-            _ => false,
-        }
-    }
-}
+pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
 
-/// Explains the source of a type err in a short, human readable way. This is meant to be placed
-/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
-/// afterwards to present additional details, particularly when it comes to lifetime-related
-/// errors.
+/// Explains the source of a type err in a short, human readable way.
+/// This is meant to be placed in parentheses after some larger message.
+/// You should also invoke `note_and_explain_type_err()` afterwards
+/// to present additional details, particularly when it comes to lifetime-
+/// related errors.
+#[extension(pub trait TypeErrorToStringExt<'tcx>)]
 impl<'tcx> TypeError<'tcx> {
-    pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
-        use self::TypeError::*;
+    fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
         fn report_maybe_different(expected: &str, found: &str) -> String {
             // A naive approach to making sure that we're not reporting silly errors such as:
             // (expected closure, found closure).
@@ -97,24 +32,26 @@ impl<'tcx> TypeError<'tcx> {
         }
 
         match self {
-            CyclicTy(_) => "cyclic type of infinite size".into(),
-            CyclicConst(_) => "encountered a self-referencing constant".into(),
-            Mismatch => "types differ".into(),
-            ConstnessMismatch(values) => {
+            TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
+            TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
+            TypeError::Mismatch => "types differ".into(),
+            TypeError::ConstnessMismatch(values) => {
                 format!("expected {} bound, found {} bound", values.expected, values.found).into()
             }
-            PolarityMismatch(values) => {
+            TypeError::PolarityMismatch(values) => {
                 format!("expected {} polarity, found {} polarity", values.expected, values.found)
                     .into()
             }
-            SafetyMismatch(values) => {
+            TypeError::SafetyMismatch(values) => {
                 format!("expected {} fn, found {} fn", values.expected, values.found).into()
             }
-            AbiMismatch(values) => {
+            TypeError::AbiMismatch(values) => {
                 format!("expected {} fn, found {} fn", values.expected, values.found).into()
             }
-            ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
-            TupleSize(values) => format!(
+            TypeError::ArgumentMutability(_) | TypeError::Mutability => {
+                "types differ in mutability".into()
+            }
+            TypeError::TupleSize(values) => format!(
                 "expected a tuple with {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
@@ -122,7 +59,7 @@ impl<'tcx> TypeError<'tcx> {
                 pluralize!(values.found)
             )
             .into(),
-            FixedArraySize(values) => format!(
+            TypeError::FixedArraySize(values) => format!(
                 "expected an array with a fixed size of {} element{}, found one with {} element{}",
                 values.expected,
                 pluralize!(values.expected),
@@ -130,20 +67,21 @@ impl<'tcx> TypeError<'tcx> {
                 pluralize!(values.found)
             )
             .into(),
-            ArgCount => "incorrect number of function parameters".into(),
-            FieldMisMatch(adt, field) => format!("field type mismatch: {adt}.{field}").into(),
-            RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
+            TypeError::ArgCount => "incorrect number of function parameters".into(),
+            TypeError::RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
             // Actually naming the region here is a bit confusing because context is lacking
-            RegionsInsufficientlyPolymorphic(..) => {
+            TypeError::RegionsInsufficientlyPolymorphic(..) => {
+                "one type is more general than the other".into()
+            }
+            TypeError::RegionsPlaceholderMismatch => {
                 "one type is more general than the other".into()
             }
-            RegionsPlaceholderMismatch => "one type is more general than the other".into(),
-            ArgumentSorts(values, _) | Sorts(values) => {
+            TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
                 let expected = values.expected.sort_string(tcx);
                 let found = values.found.sort_string(tcx);
                 report_maybe_different(&expected, &found).into()
             }
-            Traits(values) => {
+            TypeError::Traits(values) => {
                 let (mut expected, mut found) = with_forced_trimmed_paths!((
                     tcx.def_path_str(values.expected),
                     tcx.def_path_str(values.found),
@@ -155,77 +93,34 @@ impl<'tcx> TypeError<'tcx> {
                 report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
                     .into()
             }
-            IntMismatch(ref values) => {
-                let expected = match values.expected {
-                    ty::IntVarValue::IntType(ty) => ty.name_str(),
-                    ty::IntVarValue::UintType(ty) => ty.name_str(),
-                };
-                let found = match values.found {
-                    ty::IntVarValue::IntType(ty) => ty.name_str(),
-                    ty::IntVarValue::UintType(ty) => ty.name_str(),
-                };
-                format!("expected `{expected}`, found `{found}`").into()
-            }
-            FloatMismatch(ref values) => format!(
-                "expected `{}`, found `{}`",
-                values.expected.name_str(),
-                values.found.name_str()
-            )
-            .into(),
-            VariadicMismatch(ref values) => format!(
+            TypeError::VariadicMismatch(ref values) => format!(
                 "expected {} fn, found {} function",
                 if values.expected { "variadic" } else { "non-variadic" },
                 if values.found { "variadic" } else { "non-variadic" }
             )
             .into(),
-            ProjectionMismatched(ref values) => format!(
+            TypeError::ProjectionMismatched(ref values) => format!(
                 "expected `{}`, found `{}`",
                 tcx.def_path_str(values.expected),
                 tcx.def_path_str(values.found)
             )
             .into(),
-            ExistentialMismatch(ref values) => report_maybe_different(
+            TypeError::ExistentialMismatch(ref values) => report_maybe_different(
                 &format!("trait `{}`", values.expected),
                 &format!("trait `{}`", values.found),
             )
             .into(),
-            ConstMismatch(ref values) => {
+            TypeError::ConstMismatch(ref values) => {
                 format!("expected `{}`, found `{}`", values.expected, values.found).into()
             }
-            IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
-            TargetFeatureCast(_) => {
+            TypeError::IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
+            TypeError::TargetFeatureCast(_) => {
                 "cannot coerce functions with `#[target_feature]` to safe function pointers".into()
             }
         }
     }
 }
 
-impl<'tcx> TypeError<'tcx> {
-    pub fn must_include_note(self) -> bool {
-        use self::TypeError::*;
-        match self {
-            CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
-            | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
-            | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_)
-            | VariadicMismatch(_) | TargetFeatureCast(_) => false,
-
-            Mutability
-            | ArgumentMutability(_)
-            | TupleSize(_)
-            | ArgCount
-            | FieldMisMatch(..)
-            | RegionsDoesNotOutlive(..)
-            | RegionsInsufficientlyPolymorphic(..)
-            | RegionsPlaceholderMismatch
-            | Traits(_)
-            | ProjectionMismatched(_)
-            | ExistentialMismatch(_)
-            | ConstMismatch(_)
-            | IntrinsicCast => true,
-        }
-    }
-}
-
 impl<'tcx> Ty<'tcx> {
     pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
         match *self.kind() {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 7508f0080cc..923667e609b 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -337,7 +337,7 @@ impl DeepRejectCtxt {
             | ty::ConstKind::Error(_) => {
                 return true;
             }
-            ty::ConstKind::Value(impl_val) => impl_val,
+            ty::ConstKind::Value(_, impl_val) => impl_val,
             ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
                 bug!("unexpected impl arg: {:?}", impl_ct)
             }
@@ -357,7 +357,7 @@ impl DeepRejectCtxt {
             ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
                 true
             }
-            ty::ConstKind::Value(obl_val) => obl_val == impl_val,
+            ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
 
             ty::ConstKind::Infer(_) => true,
 
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 4de7d532c96..21c115c2c96 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -28,10 +28,9 @@ impl FlagComputation {
         result
     }
 
-    pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation {
+    pub fn for_const_kind(kind: &ty::ConstKind<'_>) -> FlagComputation {
         let mut result = FlagComputation::new();
-        result.add_const_kind(c);
-        result.add_ty(t);
+        result.add_const_kind(kind);
         result
     }
 
@@ -373,27 +372,8 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
-            ty::ConstKind::Value(_) => {}
-            ty::ConstKind::Expr(e) => {
-                use ty::Expr;
-                match e {
-                    Expr::Binop(_, l, r) => {
-                        self.add_const(l);
-                        self.add_const(r);
-                    }
-                    Expr::UnOp(_, v) => self.add_const(v),
-                    Expr::FunctionCall(f, args) => {
-                        self.add_const(f);
-                        for arg in args {
-                            self.add_const(arg);
-                        }
-                    }
-                    Expr::Cast(_, c, t) => {
-                        self.add_ty(t);
-                        self.add_const(c);
-                    }
-                }
-            }
+            ty::ConstKind::Value(ty, _) => self.add_ty(ty),
+            ty::ConstKind::Expr(e) => self.add_args(e.args()),
             ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
         }
     }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index b5b36cbd1ba..9b5b1430c27 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -134,13 +134,13 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
 pub trait BoundVarReplacerDelegate<'tcx> {
     fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
     fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>;
-    fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx>;
+    fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx>;
 }
 
 pub struct FnMutDelegate<'a, 'tcx> {
     pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
     pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
-    pub consts: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a),
+    pub consts: &'a mut (dyn FnMut(ty::BoundVar) -> ty::Const<'tcx> + 'a),
 }
 
 impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
@@ -150,8 +150,8 @@ impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
     fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
         (self.types)(bt)
     }
-    fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        (self.consts)(bv, ty)
+    fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
+        (self.consts)(bv)
     }
 }
 
@@ -224,7 +224,7 @@ where
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         match ct.kind() {
             ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
-                let ct = self.delegate.replace_const(bound_const, ct.ty());
+                let ct = self.delegate.replace_const(bound_const);
                 debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
                 ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
             }
@@ -282,7 +282,7 @@ impl<'tcx> TyCtxt<'tcx> {
             let delegate = FnMutDelegate {
                 regions: &mut replace_regions,
                 types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
-                consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
+                consts: &mut |b| bug!("unexpected bound ct in binder: {b:?}"),
             };
             let mut replacer = BoundVarReplacer::new(self, delegate);
             value.fold_with(&mut replacer)
@@ -353,9 +353,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
                     )
                 },
-                consts: &mut |c, ty: Ty<'tcx>| {
-                    ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty)
-                },
+                consts: &mut |c| ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c)),
             },
         )
     }
@@ -398,12 +396,12 @@ impl<'tcx> TyCtxt<'tcx> {
                     .expect_ty();
                 Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind })
             }
-            fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+            fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
                 let entry = self.map.entry(bv);
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
-                ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty)
+                ty::Const::new_bound(self.tcx, ty::INNERMOST, var)
             }
         }
 
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index c3ab755175d..7fff3d01324 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -228,7 +228,7 @@ impl<'tcx> GenericArg<'tcx> {
                     ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
                 ))),
                 CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
-                    ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
+                    ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
                 ))),
                 _ => intrinsics::unreachable(),
             }
@@ -454,11 +454,11 @@ impl<'tcx> GenericArgs<'tcx> {
         def_id: DefId,
         original_args: &[GenericArg<'tcx>],
     ) -> GenericArgsRef<'tcx> {
-        ty::GenericArgs::for_item(tcx, def_id, |def, args| {
+        ty::GenericArgs::for_item(tcx, def_id, |def, _| {
             if let Some(arg) = original_args.get(def.index as usize) {
                 *arg
             } else {
-                def.to_error(tcx, args)
+                def.to_error(tcx)
             }
         })
     }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 89ba8cd2ad4..185dbe44735 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -100,19 +100,11 @@ impl GenericParamDef {
         }
     }
 
-    pub fn to_error<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        preceding_args: &[ty::GenericArg<'tcx>],
-    ) -> ty::GenericArg<'tcx> {
+    pub fn to_error<'tcx>(&self, tcx: TyCtxt<'tcx>) -> ty::GenericArg<'tcx> {
         match &self.kind {
             ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
             ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
-            ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
-                tcx,
-                tcx.type_of(self.def_id).instantiate(tcx, preceding_args),
-            )
-            .into(),
+            ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(tcx).into(),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index a2df90b2c0f..56945bf6be4 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -385,9 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     ),
                 }
             }
-            ty::Array(inner, len)
-                if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
-            {
+            ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
                 let len_eval = len.try_eval_target_usize(tcx, param_env);
                 if len_eval == Some(0) {
                     return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
@@ -1353,3 +1351,37 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
 }
 
 impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
+
+impl<'tcx> TyCtxt<'tcx> {
+    pub fn offset_of_subfield<I>(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        mut layout: TyAndLayout<'tcx>,
+        indices: I,
+    ) -> Size
+    where
+        I: Iterator<Item = (VariantIdx, FieldIdx)>,
+    {
+        let cx = LayoutCx { tcx: self, param_env };
+        let mut offset = Size::ZERO;
+
+        for (variant, field) in indices {
+            layout = layout.for_variant(&cx, variant);
+            let index = field.index();
+            offset += layout.fields.offset(index);
+            layout = layout.field(&cx, index);
+            if !layout.is_sized() {
+                // If it is not sized, then the tail must still have at least a known static alignment.
+                let tail = self.struct_tail_erasing_lifetimes(layout.ty, param_env);
+                if !matches!(tail.kind(), ty::Slice(..)) {
+                    bug!(
+                        "offset of not-statically-aligned field (type {:?}) cannot be computed statically",
+                        layout.ty
+                    );
+                }
+            }
+        }
+
+        offset
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 2643ce976de..7ff1b799822 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -60,6 +60,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
+pub use rustc_type_ir::relate::VarianceDiagInfo;
 pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
 use tracing::{debug, instrument};
 pub use vtable::*;
@@ -87,7 +88,7 @@ pub use self::closure::{
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
-    Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
+    Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
@@ -114,7 +115,7 @@ pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
     CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
-    ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
+    ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -122,7 +123,6 @@ pub use self::typeck_results::{
     TypeckResults, UserType, UserTypeAnnotationIndex,
 };
 
-pub mod _match;
 pub mod abstract_const;
 pub mod adjustment;
 pub mod cast;
@@ -313,38 +313,6 @@ impl Visibility {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
-pub enum BoundConstness {
-    /// `Type: Trait`
-    NotConst,
-    /// `Type: const Trait`
-    Const,
-    /// `Type: ~const Trait`
-    ///
-    /// Requires resolving to const only when we are in a const context.
-    ConstIfConst,
-}
-
-impl BoundConstness {
-    pub fn as_str(self) -> &'static str {
-        match self {
-            Self::NotConst => "",
-            Self::Const => "const",
-            Self::ConstIfConst => "~const",
-        }
-    }
-}
-
-impl fmt::Display for BoundConstness {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::NotConst => f.write_str("normal"),
-            Self::Const => f.write_str("const"),
-            Self::ConstIfConst => f.write_str("~const"),
-        }
-    }
-}
-
 #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct ClosureSizeProfileData<'tcx> {
@@ -617,21 +585,29 @@ impl<'tcx> Term<'tcx> {
                     ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
                 ))),
                 CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
-                    ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
+                    ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
                 ))),
                 _ => core::intrinsics::unreachable(),
             }
         }
     }
 
-    pub fn ty(&self) -> Option<Ty<'tcx>> {
+    pub fn as_type(&self) -> Option<Ty<'tcx>> {
         if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None }
     }
 
-    pub fn ct(&self) -> Option<Const<'tcx>> {
+    pub fn expect_type(&self) -> Ty<'tcx> {
+        self.as_type().expect("expected a type, but found a const")
+    }
+
+    pub fn as_const(&self) -> Option<Const<'tcx>> {
         if let TermKind::Const(c) = self.unpack() { Some(c) } else { None }
     }
 
+    pub fn expect_const(&self) -> Const<'tcx> {
+        self.as_const().expect("expected a const, but found a type")
+    }
+
     pub fn into_arg(self) -> GenericArg<'tcx> {
         match self.unpack() {
             TermKind::Ty(ty) => ty.into(),
@@ -926,6 +902,30 @@ pub struct Placeholder<T> {
     pub universe: UniverseIndex,
     pub bound: T,
 }
+impl Placeholder<BoundVar> {
+    pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
+        let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
+            // `ConstArgHasType` are never desugared to be higher ranked.
+            match clause.kind().skip_binder() {
+                ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
+                    assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
+
+                    match placeholder_ct.kind() {
+                        ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
+                            Some(ty)
+                        }
+                        _ => None,
+                    }
+                }
+                _ => None,
+            }
+        });
+
+        let ty = candidates.next().unwrap();
+        assert!(candidates.next().is_none());
+        ty
+    }
+}
 
 pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index bbcbcdce1b2..52902aadd7c 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                             })
                             .emit_unless(self.ignore_errors);
 
-                        ty::Const::new_error(self.tcx, guar, ct.ty())
+                        ty::Const::new_error(self.tcx, guar)
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8fb4367d3b5..662eafd0ccb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1077,7 +1077,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         }
 
                         p!(")");
-                        if let Some(ty) = return_ty.skip_binder().ty() {
+                        if let Some(ty) = return_ty.skip_binder().as_type() {
                             if !ty.is_unit() {
                                 p!(" -> ", print(return_ty));
                             }
@@ -1144,7 +1144,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     for (assoc_item_def_id, term) in assoc_items {
                         // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
                         // unless we can find out what coroutine return type it comes from.
-                        let term = if let Some(ty) = term.skip_binder().ty()
+                        let term = if let Some(ty) = term.skip_binder().as_type()
                             && let ty::Alias(ty::Projection, proj) = ty.kind()
                             && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
                             && assoc.trait_container(tcx) == tcx.lang_items().coroutine_trait()
@@ -1322,7 +1322,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                             p!(pretty_fn_sig(
                                 tys,
                                 false,
-                                proj.skip_binder().term.ty().expect("Return type was a const")
+                                proj.skip_binder().term.as_type().expect("Return type was a const")
                             ));
                             resugared = true;
                         }
@@ -1459,23 +1459,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             return Ok(());
         }
 
-        macro_rules! print_underscore {
-            () => {{
-                if print_ty {
-                    self.typed_value(
-                        |this| {
-                            write!(this, "_")?;
-                            Ok(())
-                        },
-                        |this| this.print_type(ct.ty()),
-                        ": ",
-                    )?;
-                } else {
-                    write!(self, "_")?;
-                }
-            }};
-        }
-
         match ct.kind() {
             ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
                 match self.tcx().def_kind(def) {
@@ -1508,11 +1491,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 ty::InferConst::Var(ct_vid) if let Some(name) = self.const_infer_name(ct_vid) => {
                     p!(write("{}", name))
                 }
-                _ => print_underscore!(),
+                _ => write!(self, "_")?,
             },
             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
-            ty::ConstKind::Value(value) => {
-                return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
+            ty::ConstKind::Value(ty, value) => {
+                return self.pretty_print_const_valtree(value, ty, print_ty);
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
@@ -1533,8 +1516,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         print_ty: bool,
     ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
-        match expr {
-            Expr::Binop(op, c1, c2) => {
+        match expr.kind {
+            ty::ExprKind::Binop(op) => {
+                let (_, _, c1, c2) = expr.binop_args();
+
                 let precedence = |binop: rustc_middle::mir::BinOp| {
                     use rustc_ast::util::parser::AssocOp;
                     AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
@@ -1543,22 +1528,26 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 let formatted_op = op.to_hir_binop().as_str();
                 let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
                     (
-                        ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)),
-                        ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)),
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
                     ) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
-                    (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), ty::ConstKind::Expr(_)) => {
-                        (precedence(lhs_op) < op_precedence, true)
-                    }
-                    (ty::ConstKind::Expr(_), ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
-                        (true, precedence(rhs_op) < op_precedence)
-                    }
+                    (
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
+                        ty::ConstKind::Expr(_),
+                    ) => (precedence(lhs_op) < op_precedence, true),
+                    (
+                        ty::ConstKind::Expr(_),
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
+                    ) => (true, precedence(rhs_op) < op_precedence),
                     (ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
-                    (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), _) => {
-                        (precedence(lhs_op) < op_precedence, false)
-                    }
-                    (_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
-                        (false, precedence(rhs_op) < op_precedence)
-                    }
+                    (
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
+                        _,
+                    ) => (precedence(lhs_op) < op_precedence, false),
+                    (
+                        _,
+                        ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
+                    ) => (false, precedence(rhs_op) < op_precedence),
                     (ty::ConstKind::Expr(_), _) => (true, false),
                     (_, ty::ConstKind::Expr(_)) => (false, true),
                     _ => (false, false),
@@ -1574,7 +1563,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     rhs_parenthesized,
                 )?;
             }
-            Expr::UnOp(op, ct) => {
+            ty::ExprKind::UnOp(op) => {
+                let (_, ct) = expr.unop_args();
+
                 use rustc_middle::mir::UnOp;
                 let formatted_op = match op {
                     UnOp::Not => "!",
@@ -1583,7 +1574,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 };
                 let parenthesized = match ct.kind() {
                     _ if op == UnOp::PtrMetadata => true,
-                    ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
+                    ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::UnOp(c_op), .. }) => {
+                        c_op != op
+                    }
                     ty::ConstKind::Expr(_) => true,
                     _ => false,
                 };
@@ -1593,61 +1586,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     parenthesized,
                 )?
             }
-            Expr::FunctionCall(fn_def, fn_args) => {
-                use ty::TyKind;
-                match fn_def.ty().kind() {
-                    TyKind::FnDef(def_id, gen_args) => {
-                        p!(print_value_path(*def_id, gen_args), "(");
-                        if print_ty {
-                            let tcx = self.tcx();
-                            let sig = tcx.fn_sig(def_id).instantiate(tcx, gen_args).skip_binder();
-
-                            let mut args_with_ty = fn_args.iter().map(|ct| (ct, ct.ty()));
-                            let output_ty = sig.output();
-
-                            if let Some((ct, ty)) = args_with_ty.next() {
-                                self.typed_value(
-                                    |this| this.pretty_print_const(ct, print_ty),
-                                    |this| this.pretty_print_type(ty),
-                                    ": ",
-                                )?;
-                                for (ct, ty) in args_with_ty {
-                                    p!(", ");
-                                    self.typed_value(
-                                        |this| this.pretty_print_const(ct, print_ty),
-                                        |this| this.pretty_print_type(ty),
-                                        ": ",
-                                    )?;
-                                }
-                            }
-                            p!(write(") -> {output_ty}"));
-                        } else {
-                            p!(comma_sep(fn_args.iter()), ")");
-                        }
-                    }
-                    _ => bug!("unexpected type of fn def"),
-                }
+            ty::ExprKind::FunctionCall => {
+                let (_, fn_def, fn_args) = expr.call_args();
+
+                write!(self, "(")?;
+                self.pretty_print_const(fn_def, print_ty)?;
+                p!(")(", comma_sep(fn_args), ")");
             }
-            Expr::Cast(kind, ct, ty) => {
+            ty::ExprKind::Cast(kind) => {
+                let (_, value, to_ty) = expr.cast_args();
+
                 use ty::abstract_const::CastKind;
                 if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
-                    let parenthesized = match ct.kind() {
-                        ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false,
+                    let parenthesized = match value.kind() {
+                        ty::ConstKind::Expr(ty::Expr {
+                            kind: ty::ExprKind::Cast { .. }, ..
+                        }) => false,
                         ty::ConstKind::Expr(_) => true,
                         _ => false,
                     };
                     self.maybe_parenthesized(
                         |this| {
                             this.typed_value(
-                                |this| this.pretty_print_const(ct, print_ty),
-                                |this| this.pretty_print_type(ty),
+                                |this| this.pretty_print_const(value, print_ty),
+                                |this| this.pretty_print_type(to_ty),
                                 " as ",
                             )
                         },
                         parenthesized,
                     )?;
                 } else {
-                    self.pretty_print_const(ct, print_ty)?
+                    self.pretty_print_const(value, print_ty)?
                 }
             }
         }
@@ -1680,10 +1649,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::Ref(_, inner, _) => {
                 if let ty::Array(elem, len) = inner.kind() {
                     if let ty::Uint(ty::UintTy::U8) = elem.kind() {
-                        if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
+                        if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() {
                             match self.tcx().try_get_global_alloc(prov.alloc_id()) {
                                 Some(GlobalAlloc::Memory(alloc)) => {
-                                    let len = int.assert_bits(self.tcx().data_layout.pointer_size);
+                                    let len = int.to_bits(self.tcx().data_layout.pointer_size);
                                     let range =
                                         AllocRange { start: offset, size: Size::from_bytes(len) };
                                     if let Ok(byte_str) =
@@ -1761,7 +1730,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             // Pointer types
             ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(_) => {
-                let data = int.assert_bits(self.tcx().data_layout.pointer_size);
+                let data = int.to_bits(self.tcx().data_layout.pointer_size);
                 self.typed_value(
                     |this| {
                         write!(this, "0x{data:x}")?;
@@ -3263,7 +3232,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     let queue = &mut Vec::new();
     let mut seen_defs: DefIdSet = Default::default();
 
-    for &cnum in tcx.crates_including_speculative(()).iter() {
+    for &cnum in tcx.crates(()).iter() {
         let def_id = cnum.as_def_id();
 
         // Ignore crates that are not direct dependencies.
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index b4179858890..b169d672a84 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -1,383 +1,54 @@
-//! Generalized type relating mechanism.
-//!
-//! A type relation `R` relates a pair of values `(A, B)`. `A and B` are usually
-//! types or regions but can be other things. Examples of type relations are
-//! subtyping, type equality, etc.
+use std::iter;
 
-use crate::ty::error::{ExpectedFound, TypeError};
-use crate::ty::{
-    self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg,
-    GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
-};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_macros::TypeVisitable;
 use rustc_target::spec::abi;
-use std::iter;
-use tracing::{debug, instrument};
-
-use super::Pattern;
-
-pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;
-
-pub trait TypeRelation<'tcx>: Sized {
-    fn tcx(&self) -> TyCtxt<'tcx>;
-
-    /// Returns a static string we can use for printouts.
-    fn tag(&self) -> &'static str;
-
-    /// Generic relation routine suitable for most anything.
-    fn relate<T: Relate<'tcx>>(&mut self, a: T, b: T) -> RelateResult<'tcx, T> {
-        Relate::relate(self, a, b)
-    }
-
-    /// Relate the two args for the given item. The default
-    /// is to look up the variance for the item and proceed
-    /// accordingly.
-    fn relate_item_args(
-        &mut self,
-        item_def_id: DefId,
-        a_arg: GenericArgsRef<'tcx>,
-        b_arg: GenericArgsRef<'tcx>,
-    ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
-        debug!(
-            "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
-            item_def_id, a_arg, b_arg
-        );
-
-        let tcx = self.tcx();
-        let opt_variances = tcx.variances_of(item_def_id);
-        relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
-    }
-
-    /// Switch variance for the purpose of relating `a` and `b`.
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        variance: ty::Variance,
-        info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T>;
-
-    // Overridable relations. You shouldn't typically call these
-    // directly, instead call `relate()`, which in turn calls
-    // these. This is both more uniform but also allows us to add
-    // additional hooks for other types in the future if needed
-    // without making older code, which called `relate`, obsolete.
-
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>;
-
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        b: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>>;
-
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        b: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>>;
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>;
-}
-
-pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: Self,
-        b: Self,
-    ) -> RelateResult<'tcx, Self>;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Relate impls
-
-#[inline]
-pub fn relate_args_invariantly<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    a_arg: GenericArgsRef<'tcx>,
-    b_arg: GenericArgsRef<'tcx>,
-) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
-    relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
-        relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
-    }))
-}
-
-pub fn relate_args_with_variances<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    ty_def_id: DefId,
-    variances: &[ty::Variance],
-    a_arg: GenericArgsRef<'tcx>,
-    b_arg: GenericArgsRef<'tcx>,
-    fetch_ty_for_diag: bool,
-) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
-    let tcx = relation.tcx();
-
-    let mut cached_ty = None;
-    let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
-        let variance = variances[i];
-        let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
-            let ty =
-                *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg));
-            ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
-        } else {
-            ty::VarianceDiagInfo::default()
-        };
-        relation.relate_with_variance(variance, variance_info, a, b)
-    });
-
-    tcx.mk_args_from_iter(params)
-}
-
-impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::FnSig<'tcx>,
-        b: ty::FnSig<'tcx>,
-    ) -> RelateResult<'tcx, ty::FnSig<'tcx>> {
-        let tcx = relation.tcx();
-
-        if a.c_variadic != b.c_variadic {
-            return Err(TypeError::VariadicMismatch(expected_found(a.c_variadic, b.c_variadic)));
-        }
-        let safety = relation.relate(a.safety, b.safety)?;
-        let abi = relation.relate(a.abi, b.abi)?;
-
-        if a.inputs().len() != b.inputs().len() {
-            return Err(TypeError::ArgCount);
-        }
-
-        let inputs_and_output = iter::zip(a.inputs(), b.inputs())
-            .map(|(&a, &b)| ((a, b), false))
-            .chain(iter::once(((a.output(), b.output()), true)))
-            .map(|((a, b), is_output)| {
-                if is_output {
-                    relation.relate(a, b)
-                } else {
-                    relation.relate_with_variance(
-                        ty::Contravariant,
-                        ty::VarianceDiagInfo::default(),
-                        a,
-                        b,
-                    )
-                }
-            })
-            .enumerate()
-            .map(|(i, r)| match r {
-                Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
-                    Err(TypeError::ArgumentSorts(exp_found, i))
-                }
-                Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
-                    Err(TypeError::ArgumentMutability(i))
-                }
-                r => r,
-            });
-        Ok(ty::FnSig {
-            inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
-            c_variadic: a.c_variadic,
-            safety,
-            abi,
-        })
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::BoundConstness {
-    fn relate<R: TypeRelation<'tcx>>(
-        _relation: &mut R,
-        a: ty::BoundConstness,
-        b: ty::BoundConstness,
-    ) -> RelateResult<'tcx, ty::BoundConstness> {
-        if a != b { Err(TypeError::ConstnessMismatch(expected_found(a, b))) } else { Ok(a) }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for hir::Safety {
-    fn relate<R: TypeRelation<'tcx>>(
-        _relation: &mut R,
-        a: hir::Safety,
-        b: hir::Safety,
-    ) -> RelateResult<'tcx, hir::Safety> {
-        if a != b { Err(TypeError::SafetyMismatch(expected_found(a, b))) } else { Ok(a) }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for abi::Abi {
-    fn relate<R: TypeRelation<'tcx>>(
-        _relation: &mut R,
-        a: abi::Abi,
-        b: abi::Abi,
-    ) -> RelateResult<'tcx, abi::Abi> {
-        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(a, b))) }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::AliasTy<'tcx>,
-        b: ty::AliasTy<'tcx>,
-    ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
-        if a.def_id != b.def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
-        } else {
-            let args = match a.kind(relation.tcx()) {
-                ty::Opaque => relate_args_with_variances(
-                    relation,
-                    a.def_id,
-                    relation.tcx().variances_of(a.def_id),
-                    a.args,
-                    b.args,
-                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
-                )?,
-                ty::Projection | ty::Weak | ty::Inherent => {
-                    relate_args_invariantly(relation, a.args, b.args)?
-                }
-            };
-            Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
-        }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::AliasTerm<'tcx>,
-        b: ty::AliasTerm<'tcx>,
-    ) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> {
-        if a.def_id != b.def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
-        } else {
-            let args = match a.kind(relation.tcx()) {
-                ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
-                    relation,
-                    a.def_id,
-                    relation.tcx().variances_of(a.def_id),
-                    a.args,
-                    b.args,
-                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
-                )?,
-                ty::AliasTermKind::ProjectionTy
-                | ty::AliasTermKind::WeakTy
-                | ty::AliasTermKind::InherentTy
-                | ty::AliasTermKind::UnevaluatedConst
-                | ty::AliasTermKind::ProjectionConst => {
-                    relate_args_invariantly(relation, a.args, b.args)?
-                }
-            };
-            Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
-        }
-    }
-}
+pub use rustc_type_ir::relate::*;
 
-impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::ExistentialProjection<'tcx>,
-        b: ty::ExistentialProjection<'tcx>,
-    ) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
-        if a.def_id != b.def_id {
-            Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id)))
-        } else {
-            let term = relation.relate_with_variance(
-                ty::Invariant,
-                ty::VarianceDiagInfo::default(),
-                a.term,
-                b.term,
-            )?;
-            let args = relation.relate_with_variance(
-                ty::Invariant,
-                ty::VarianceDiagInfo::default(),
-                a.args,
-                b.args,
-            )?;
-            Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
-        }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::TraitRef<'tcx>,
-        b: ty::TraitRef<'tcx>,
-    ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
-        // Different traits cannot be related.
-        if a.def_id != b.def_id {
-            Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
-        } else {
-            let args = relate_args_invariantly(relation, a.args, b.args)?;
-            Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
-        }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::ExistentialTraitRef<'tcx>,
-        b: ty::ExistentialTraitRef<'tcx>,
-    ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
-        // Different traits cannot be related.
-        if a.def_id != b.def_id {
-            Err(TypeError::Traits(expected_found(a.def_id, b.def_id)))
-        } else {
-            let args = relate_args_invariantly(relation, a.args, b.args)?;
-            Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
-        }
-    }
-}
+use crate::ty::error::{ExpectedFound, TypeError};
+use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
+use crate::ty::{self as ty, Ty, TyCtxt};
 
-#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
-struct CoroutineWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
+pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult<TyCtxt<'tcx>, T>;
 
-impl<'tcx> Relate<'tcx> for CoroutineWitness<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: CoroutineWitness<'tcx>,
-        b: CoroutineWitness<'tcx>,
-    ) -> RelateResult<'tcx, CoroutineWitness<'tcx>> {
-        assert_eq!(a.0.len(), b.0.len());
-        let tcx = relation.tcx();
-        let types =
-            tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
-        Ok(CoroutineWitness(types))
-    }
+/// Whether aliases should be related structurally or not. Used
+/// to adjust the behavior of generalization and combine.
+///
+/// This should always be `No` unless in a few special-cases when
+/// instantiating canonical responses and in the new solver. Each
+/// such case should have a comment explaining why it is used.
+#[derive(Debug, Copy, Clone)]
+pub enum StructurallyRelateAliases {
+    Yes,
+    No,
 }
 
-impl<'tcx> Relate<'tcx> for ImplSubject<'tcx> {
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::ImplSubject<'tcx> {
     #[inline]
-    fn relate<R: TypeRelation<'tcx>>(
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
-        a: ImplSubject<'tcx>,
-        b: ImplSubject<'tcx>,
-    ) -> RelateResult<'tcx, ImplSubject<'tcx>> {
+        a: ty::ImplSubject<'tcx>,
+        b: ty::ImplSubject<'tcx>,
+    ) -> RelateResult<'tcx, ty::ImplSubject<'tcx>> {
         match (a, b) {
-            (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => {
+            (ty::ImplSubject::Trait(trait_ref_a), ty::ImplSubject::Trait(trait_ref_b)) => {
                 let trait_ref = ty::TraitRef::relate(relation, trait_ref_a, trait_ref_b)?;
-                Ok(ImplSubject::Trait(trait_ref))
+                Ok(ty::ImplSubject::Trait(trait_ref))
             }
-            (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => {
+            (ty::ImplSubject::Inherent(ty_a), ty::ImplSubject::Inherent(ty_b)) => {
                 let ty = Ty::relate(relation, ty_a, ty_b)?;
-                Ok(ImplSubject::Inherent(ty))
+                Ok(ty::ImplSubject::Inherent(ty))
             }
-            (ImplSubject::Trait(_), ImplSubject::Inherent(_))
-            | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => {
+            (ty::ImplSubject::Trait(_), ty::ImplSubject::Inherent(_))
+            | (ty::ImplSubject::Inherent(_), ty::ImplSubject::Trait(_)) => {
                 bug!("can not relate TraitRef and Ty");
             }
         }
     }
 }
 
-impl<'tcx> Relate<'tcx> for Ty<'tcx> {
+impl<'tcx> Relate<TyCtxt<'tcx>> for Ty<'tcx> {
     #[inline]
-    fn relate<R: TypeRelation<'tcx>>(
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: Ty<'tcx>,
         b: Ty<'tcx>,
@@ -386,9 +57,9 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
     }
 }
 
-impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
     #[inline]
-    fn relate<R: TypeRelation<'tcx>>(
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: Self,
         b: Self,
@@ -416,303 +87,8 @@ impl<'tcx> Relate<'tcx> for Pattern<'tcx> {
     }
 }
 
-/// Relates `a` and `b` structurally, calling the relation for all nested values.
-/// Any semantic equality, e.g. of projections, and inference variables have to be
-/// handled by the caller.
-#[instrument(level = "trace", skip(relation), ret)]
-pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    a: Ty<'tcx>,
-    b: Ty<'tcx>,
-) -> RelateResult<'tcx, Ty<'tcx>> {
-    let tcx = relation.tcx();
-    match (a.kind(), b.kind()) {
-        (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
-            // The caller should handle these cases!
-            bug!("var types encountered in structurally_relate_tys")
-        }
-
-        (ty::Bound(..), _) | (_, ty::Bound(..)) => {
-            bug!("bound types encountered in structurally_relate_tys")
-        }
-
-        (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
-
-        (&ty::Never, _)
-        | (&ty::Char, _)
-        | (&ty::Bool, _)
-        | (&ty::Int(_), _)
-        | (&ty::Uint(_), _)
-        | (&ty::Float(_), _)
-        | (&ty::Str, _)
-            if a == b =>
-        {
-            Ok(a)
-        }
-
-        (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => {
-            debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
-            Ok(a)
-        }
-
-        (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
-
-        (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def => {
-            let args = relation.relate_item_args(a_def.did(), a_args, b_args)?;
-            Ok(Ty::new_adt(tcx, a_def, args))
-        }
-
-        (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
-
-        (&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
-            if a_repr == b_repr =>
-        {
-            Ok(Ty::new_dynamic(
-                tcx,
-                relation.relate(a_obj, b_obj)?,
-                relation.relate(a_region, b_region)?,
-                a_repr,
-            ))
-        }
-
-        (&ty::Coroutine(a_id, a_args), &ty::Coroutine(b_id, b_args)) if a_id == b_id => {
-            // All Coroutine types with the same id represent
-            // the (anonymous) type of the same coroutine expression. So
-            // all of their regions should be equated.
-            let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine(tcx, a_id, args))
-        }
-
-        (&ty::CoroutineWitness(a_id, a_args), &ty::CoroutineWitness(b_id, b_args))
-            if a_id == b_id =>
-        {
-            // All CoroutineWitness types with the same id represent
-            // the (anonymous) type of the same coroutine expression. So
-            // all of their regions should be equated.
-            let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine_witness(tcx, a_id, args))
-        }
-
-        (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => {
-            // All Closure types with the same id represent
-            // the (anonymous) type of the same closure expression. So
-            // all of their regions should be equated.
-            let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_closure(tcx, a_id, args))
-        }
-
-        (&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args))
-            if a_id == b_id =>
-        {
-            let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine_closure(tcx, a_id, args))
-        }
-
-        (&ty::RawPtr(a_ty, a_mutbl), &ty::RawPtr(b_ty, b_mutbl)) => {
-            if a_mutbl != b_mutbl {
-                return Err(TypeError::Mutability);
-            }
-
-            let (variance, info) = match a_mutbl {
-                hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
-                hir::Mutability::Mut => {
-                    (ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
-                }
-            };
-
-            let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
-
-            Ok(Ty::new_ptr(tcx, ty, a_mutbl))
-        }
-
-        (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
-            if a_mutbl != b_mutbl {
-                return Err(TypeError::Mutability);
-            }
-
-            let (variance, info) = match a_mutbl {
-                hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
-                hir::Mutability::Mut => {
-                    (ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
-                }
-            };
-
-            let r = relation.relate(a_r, b_r)?;
-            let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
-
-            Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
-        }
-
-        (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
-            let t = relation.relate(a_t, b_t)?;
-            match relation.relate(sz_a, sz_b) {
-                Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
-                Err(err) => {
-                    // Check whether the lengths are both concrete/known values,
-                    // but are unequal, for better diagnostics.
-                    let sz_a = sz_a.try_to_target_usize(tcx);
-                    let sz_b = sz_b.try_to_target_usize(tcx);
-
-                    match (sz_a, sz_b) {
-                        (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
-                            Err(TypeError::FixedArraySize(expected_found(sz_a_val, sz_b_val)))
-                        }
-                        _ => Err(err),
-                    }
-                }
-            }
-        }
-
-        (&ty::Slice(a_t), &ty::Slice(b_t)) => {
-            let t = relation.relate(a_t, b_t)?;
-            Ok(Ty::new_slice(tcx, t))
-        }
-
-        (&ty::Tuple(as_), &ty::Tuple(bs)) => {
-            if as_.len() == bs.len() {
-                Ok(Ty::new_tup_from_iter(
-                    tcx,
-                    iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
-                )?)
-            } else if !(as_.is_empty() || bs.is_empty()) {
-                Err(TypeError::TupleSize(expected_found(as_.len(), bs.len())))
-            } else {
-                Err(TypeError::Sorts(expected_found(a, b)))
-            }
-        }
-
-        (&ty::FnDef(a_def_id, a_args), &ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
-            let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
-            Ok(Ty::new_fn_def(tcx, a_def_id, args))
-        }
-
-        (&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
-            let fty = relation.relate(a_fty, b_fty)?;
-            Ok(Ty::new_fn_ptr(tcx, fty))
-        }
-
-        // Alias tend to mostly already be handled downstream due to normalization.
-        (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
-            let alias_ty = relation.relate(a_data, b_data)?;
-            assert_eq!(a_kind, b_kind);
-            Ok(Ty::new_alias(tcx, a_kind, alias_ty))
-        }
-
-        (&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => {
-            let ty = relation.relate(a_ty, b_ty)?;
-            let pat = relation.relate(a_pat, b_pat)?;
-            Ok(Ty::new_pat(tcx, ty, pat))
-        }
-
-        _ => Err(TypeError::Sorts(expected_found(a, b))),
-    }
-}
-
-/// Relates `a` and `b` structurally, calling the relation for all nested values.
-/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
-/// to be handled by the caller.
-///
-/// FIXME: This is not totally structual, which probably should be fixed.
-/// See the HACKs below.
-pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    mut a: ty::Const<'tcx>,
-    mut b: ty::Const<'tcx>,
-) -> RelateResult<'tcx, ty::Const<'tcx>> {
-    debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
-    let tcx = relation.tcx();
-
-    if tcx.features().generic_const_exprs {
-        a = tcx.expand_abstract_consts(a);
-        b = tcx.expand_abstract_consts(b);
-    }
-
-    debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
-
-    // Currently, the values that can be unified are primitive types,
-    // and those that derive both `PartialEq` and `Eq`, corresponding
-    // to structural-match types.
-    let is_match = match (a.kind(), b.kind()) {
-        (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
-            // The caller should handle these cases!
-            bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
-        }
-
-        (ty::ConstKind::Error(_), _) => return Ok(a),
-        (_, ty::ConstKind::Error(_)) => return Ok(b),
-
-        (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
-            debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
-            true
-        }
-        (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
-        (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
-
-        // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
-        // and is the better alternative to waiting until `generic_const_exprs` can
-        // be stabilized.
-        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
-            assert_eq!(a.ty(), b.ty());
-            let args = relation.relate_with_variance(
-                ty::Variance::Invariant,
-                ty::VarianceDiagInfo::default(),
-                au.args,
-                bu.args,
-            )?;
-            return Ok(ty::Const::new_unevaluated(
-                tcx,
-                ty::UnevaluatedConst { def: au.def, args },
-                a.ty(),
-            ));
-        }
-        // Before calling relate on exprs, it is necessary to ensure that the nested consts
-        // have identical types.
-        (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
-            let r = relation;
-
-            // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
-            // exprs? Should we care about that?
-            // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
-            // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
-            // of as being generic over the argument types, however this is implicit so these types don't get
-            // related when we relate the args of the item this const arg is for.
-            let expr = match (ae, be) {
-                (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
-                    r.relate(al.ty(), bl.ty())?;
-                    r.relate(ar.ty(), br.ty())?;
-                    Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
-                }
-                (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
-                    r.relate(av.ty(), bv.ty())?;
-                    Expr::UnOp(a_op, r.consts(av, bv)?)
-                }
-                (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
-                    r.relate(av.ty(), bv.ty())?;
-                    Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
-                }
-                (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
-                    if aa.len() == ba.len() =>
-                {
-                    r.relate(af.ty(), bf.ty())?;
-                    let func = r.consts(af, bf)?;
-                    let mut related_args = Vec::with_capacity(aa.len());
-                    for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
-                        related_args.push(r.consts(a_arg, b_arg)?);
-                    }
-                    let related_args = tcx.mk_const_list(&related_args);
-                    Expr::FunctionCall(func, related_args)
-                }
-                _ => return Err(TypeError::ConstMismatch(expected_found(a, b))),
-            };
-            return Ok(ty::Const::new_expr(tcx, expr, a.ty()));
-        }
-        _ => false,
-    };
-    if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(a, b))) }
-}
-
-impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: Self,
         b: Self,
@@ -730,44 +106,65 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
         b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
         b_v.dedup();
         if a_v.len() != b_v.len() {
-            return Err(TypeError::ExistentialMismatch(expected_found(a, b)));
+            return Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b)));
         }
 
         let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
             match (ep_a.skip_binder(), ep_b.skip_binder()) {
-                (ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a
-                    .rebind(ExistentialPredicate::Trait(
-                        relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
-                    ))),
-                (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
-                    Ok(ep_a.rebind(ExistentialPredicate::Projection(
+                (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
+                    Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
                         relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
                     )))
                 }
-                (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b))
-                    if a == b =>
-                {
-                    Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a)))
-                }
-                _ => Err(TypeError::ExistentialMismatch(expected_found(a, b))),
+                (
+                    ty::ExistentialPredicate::Projection(a),
+                    ty::ExistentialPredicate::Projection(b),
+                ) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
+                    relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
+                ))),
+                (
+                    ty::ExistentialPredicate::AutoTrait(a),
+                    ty::ExistentialPredicate::AutoTrait(b),
+                ) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
+                _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))),
             }
         });
         tcx.mk_poly_existential_predicates_from_iter(v)
     }
 }
 
-impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for hir::Safety {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
+        _relation: &mut R,
+        a: hir::Safety,
+        b: hir::Safety,
+    ) -> RelateResult<'tcx, hir::Safety> {
+        if a != b { Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a, b))) } else { Ok(a) }
+    }
+}
+
+impl<'tcx> Relate<TyCtxt<'tcx>> for abi::Abi {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
+        _relation: &mut R,
+        a: abi::Abi,
+        b: abi::Abi,
+    ) -> RelateResult<'tcx, abi::Abi> {
+        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(ExpectedFound::new(true, a, b))) }
+    }
+}
+
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
-        a: GenericArgsRef<'tcx>,
-        b: GenericArgsRef<'tcx>,
-    ) -> RelateResult<'tcx, GenericArgsRef<'tcx>> {
+        a: ty::GenericArgsRef<'tcx>,
+        b: ty::GenericArgsRef<'tcx>,
+    ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
         relate_args_invariantly(relation, a, b)
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Region<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
@@ -776,8 +173,8 @@ impl<'tcx> Relate<'tcx> for ty::Region<'tcx> {
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::Const<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Const<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
@@ -786,85 +183,70 @@ impl<'tcx> Relate<'tcx> for ty::Const<'tcx> {
     }
 }
 
-impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
-        relation.binders(a, b)
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Expr<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
+        relation: &mut R,
+        ae: ty::Expr<'tcx>,
+        be: ty::Expr<'tcx>,
+    ) -> RelateResult<'tcx, ty::Expr<'tcx>> {
+        // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
+        // exprs? Should we care about that?
+        // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+        // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+        // of as being generic over the argument types, however this is implicit so these types don't get
+        // related when we relate the args of the item this const arg is for.
+        match (ae.kind, be.kind) {
+            (ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) if a_binop == b_binop => {}
+            (ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
+            (ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
+            (ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
+            _ => return Err(TypeError::Mismatch),
+        }
+
+        let args = relation.relate(ae.args(), be.args())?;
+        Ok(ty::Expr::new(ae.kind, args))
     }
 }
 
-impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArg<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
-        a: GenericArg<'tcx>,
-        b: GenericArg<'tcx>,
-    ) -> RelateResult<'tcx, GenericArg<'tcx>> {
+        a: ty::GenericArg<'tcx>,
+        b: ty::GenericArg<'tcx>,
+    ) -> RelateResult<'tcx, ty::GenericArg<'tcx>> {
         match (a.unpack(), b.unpack()) {
-            (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
+            (ty::GenericArgKind::Lifetime(a_lt), ty::GenericArgKind::Lifetime(b_lt)) => {
                 Ok(relation.relate(a_lt, b_lt)?.into())
             }
-            (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
+            (ty::GenericArgKind::Type(a_ty), ty::GenericArgKind::Type(b_ty)) => {
                 Ok(relation.relate(a_ty, b_ty)?.into())
             }
-            (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
+            (ty::GenericArgKind::Const(a_ct), ty::GenericArgKind::Const(b_ct)) => {
                 Ok(relation.relate(a_ct, b_ct)?.into())
             }
-            (GenericArgKind::Lifetime(unpacked), x) => {
+            (ty::GenericArgKind::Lifetime(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
-            (GenericArgKind::Type(unpacked), x) => {
+            (ty::GenericArgKind::Type(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
-            (GenericArgKind::Const(unpacked), x) => {
+            (ty::GenericArgKind::Const(unpacked), x) => {
                 bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
             }
         }
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::PredicatePolarity {
-    fn relate<R: TypeRelation<'tcx>>(
-        _relation: &mut R,
-        a: ty::PredicatePolarity,
-        b: ty::PredicatePolarity,
-    ) -> RelateResult<'tcx, ty::PredicatePolarity> {
-        if a != b { Err(TypeError::PolarityMismatch(expected_found(a, b))) } else { Ok(a) }
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::TraitPredicate<'tcx>,
-        b: ty::TraitPredicate<'tcx>,
-    ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
-        Ok(ty::TraitPredicate {
-            trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
-            polarity: relation.relate(a.polarity, b.polarity)?,
-        })
-    }
-}
-
-impl<'tcx> Relate<'tcx> for Term<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
+impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Term<'tcx> {
+    fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
         relation: &mut R,
         a: Self,
         b: Self,
     ) -> RelateResult<'tcx, Self> {
         Ok(match (a.unpack(), b.unpack()) {
-            (TermKind::Ty(a), TermKind::Ty(b)) => relation.relate(a, b)?.into(),
-            (TermKind::Const(a), TermKind::Const(b)) => relation.relate(a, b)?.into(),
+            (ty::TermKind::Ty(a), ty::TermKind::Ty(b)) => relation.relate(a, b)?.into(),
+            (ty::TermKind::Const(a), ty::TermKind::Const(b)) => relation.relate(a, b)?.into(),
             _ => return Err(TypeError::Mismatch),
         })
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Error handling
-
-pub fn expected_found<T>(a: T, b: T) -> ExpectedFound<T> {
-    ExpectedFound::new(true, a, b)
-}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 90791bdd20d..cc6b1d57f87 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -147,14 +147,27 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
         this: WithInfcx<'_, Infcx, &Self>,
         f: &mut core::fmt::Formatter<'_>,
     ) -> core::fmt::Result {
-        match this.data {
-            ty::Expr::Binop(op, lhs, rhs) => {
-                write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
+        match this.data.kind {
+            ty::ExprKind::Binop(op) => {
+                let (lhs_ty, rhs_ty, lhs, rhs) = this.data.binop_args();
+                write!(
+                    f,
+                    "({op:?}: ({:?}: {:?}), ({:?}: {:?}))",
+                    &this.wrap(lhs),
+                    &this.wrap(lhs_ty),
+                    &this.wrap(rhs),
+                    &this.wrap(rhs_ty),
+                )
             }
-            ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)),
-            ty::Expr::FunctionCall(func, args) => {
-                write!(f, "{:?}(", &this.wrap(func))?;
-                for arg in args.as_slice().iter().rev().skip(1).rev() {
+            ty::ExprKind::UnOp(op) => {
+                let (rhs_ty, rhs) = this.data.unop_args();
+                write!(f, "({op:?}: ({:?}: {:?}))", &this.wrap(rhs), &this.wrap(rhs_ty))
+            }
+            ty::ExprKind::FunctionCall => {
+                let (func_ty, func, args) = this.data.call_args();
+                let args = args.collect::<Vec<_>>();
+                write!(f, "({:?}: {:?})(", &this.wrap(func), &this.wrap(func_ty))?;
+                for arg in args.iter().rev().skip(1).rev() {
                     write!(f, "{:?}, ", &this.wrap(arg))?;
                 }
                 if let Some(arg) = args.last() {
@@ -163,8 +176,15 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
 
                 write!(f, ")")
             }
-            ty::Expr::Cast(cast_kind, lhs, rhs) => {
-                write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
+            ty::ExprKind::Cast(kind) => {
+                let (value_ty, value, to_ty) = this.data.cast_args();
+                write!(
+                    f,
+                    "({kind:?}: ({:?}: {:?}), {:?})",
+                    &this.wrap(value),
+                    &this.wrap(value_ty),
+                    &this.wrap(to_ty)
+                )
             }
         }
     }
@@ -181,26 +201,21 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
         f: &mut core::fmt::Formatter<'_>,
     ) -> core::fmt::Result {
         // If this is a value, we spend some effort to make it look nice.
-        if let ConstKind::Value(_) = this.data.kind() {
+        if let ConstKind::Value(_, _) = this.data.kind() {
             return ty::tls::with(move |tcx| {
                 // Somehow trying to lift the valtree results in lifetime errors, so we lift the
                 // entire constant.
                 let lifted = tcx.lift(*this.data).unwrap();
-                let ConstKind::Value(valtree) = lifted.kind() else {
+                let ConstKind::Value(ty, valtree) = lifted.kind() else {
                     bug!("we checked that this is a valtree")
                 };
                 let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-                cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?;
+                cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?;
                 f.write_str(&cx.into_buffer())
             });
         }
         // Fall back to something verbose.
-        write!(
-            f,
-            "{kind:?}: {ty:?}",
-            ty = &this.map(|data| data.ty()),
-            kind = &this.map(|data| data.kind())
-        )
+        write!(f, "{kind:?}", kind = &this.map(|data| data.kind()))
     }
 }
 
@@ -281,7 +296,6 @@ TrivialTypeTraversalImpls! {
     ::rustc_target::abi::FieldIdx,
     ::rustc_target::abi::VariantIdx,
     crate::middle::region::Scope,
-    crate::ty::FloatTy,
     ::rustc_ast::InlineAsmOptions,
     ::rustc_ast::InlineAsmTemplatePiece,
     ::rustc_ast::NodeId,
@@ -301,7 +315,7 @@ TrivialTypeTraversalImpls! {
     crate::traits::Reveal,
     crate::ty::adjustment::AutoBorrowMutability,
     crate::ty::AdtKind,
-    crate::ty::BoundConstness,
+    crate::ty::BoundRegion,
     // Including `BoundRegionKind` is a *bit* dubious, but direct
     // references to bound region appear in `ty::Error`, and aren't
     // really meant to be folded. In general, we can only fold a fully
@@ -309,16 +323,11 @@ TrivialTypeTraversalImpls! {
     crate::ty::BoundRegionKind,
     crate::ty::AssocItem,
     crate::ty::AssocKind,
-    crate::ty::AliasTyKind,
     crate::ty::Placeholder<crate::ty::BoundRegion>,
     crate::ty::Placeholder<crate::ty::BoundTy>,
     crate::ty::Placeholder<ty::BoundVar>,
     crate::ty::LateParamRegion,
-    crate::ty::InferTy,
-    crate::ty::IntVarValue,
     crate::ty::adjustment::PointerCoercion,
-    crate::ty::RegionVid,
-    crate::ty::Variance,
     ::rustc_span::Span,
     ::rustc_span::symbol::Ident,
     ::rustc_errors::ErrorGuaranteed,
@@ -627,7 +636,6 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        let ty = self.ty().try_fold_with(folder)?;
         let kind = match self.kind() {
             ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
             ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?),
@@ -636,21 +644,18 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
             }
             ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
             ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
-            ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
+            ConstKind::Value(t, v) => {
+                ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?)
+            }
             ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
             ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
         };
-        if ty != self.ty() || kind != self.kind() {
-            Ok(folder.interner().mk_ct_from_kind(kind, ty))
-        } else {
-            Ok(self)
-        }
+        if kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind)) } else { Ok(self) }
     }
 }
 
 impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
     fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        try_visit!(self.ty().visit_with(visitor));
         match self.kind() {
             ConstKind::Param(p) => p.visit_with(visitor),
             ConstKind::Infer(i) => i.visit_with(visitor),
@@ -660,7 +665,10 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
             }
             ConstKind::Placeholder(p) => p.visit_with(visitor),
             ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
-            ConstKind::Value(v) => v.visit_with(visitor),
+            ConstKind::Value(t, v) => {
+                try_visit!(t.visit_with(visitor));
+                v.visit_with(visitor)
+            }
             ConstKind::Error(e) => e.visit_with(visitor),
             ConstKind::Expr(e) => e.visit_with(visitor),
         }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 879396b0678..ba9ed0d5b70 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_target::spec::abi;
+use rustc_type_ir::visit::TypeVisitableExt;
 use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
@@ -339,6 +340,27 @@ impl ParamConst {
     pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
         ParamConst::new(def.index, def.name)
     }
+
+    pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
+        let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
+            // `ConstArgHasType` are never desugared to be higher ranked.
+            match clause.kind().skip_binder() {
+                ty::ClauseKind::ConstArgHasType(param_ct, ty) => {
+                    assert!(!(param_ct, ty).has_escaping_bound_vars());
+
+                    match param_ct.kind() {
+                        ty::ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
+                        _ => None,
+                    }
+                }
+                _ => None,
+            }
+        });
+
+        let ty = candidates.next().unwrap();
+        assert!(candidates.next().is_none());
+        ty
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -788,6 +810,31 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
         Ty::new_alias(interner, kind, alias_ty)
     }
 
+    fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
+        Ty::new_error(interner, guar)
+    }
+
+    fn new_adt(
+        interner: TyCtxt<'tcx>,
+        adt_def: ty::AdtDef<'tcx>,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> Self {
+        Ty::new_adt(interner, adt_def, args)
+    }
+
+    fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
+        Ty::new_foreign(interner, def_id)
+    }
+
+    fn new_dynamic(
+        interner: TyCtxt<'tcx>,
+        preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
+        region: ty::Region<'tcx>,
+        kind: ty::DynKind,
+    ) -> Self {
+        Ty::new_dynamic(interner, preds, region, kind)
+    }
+
     fn new_coroutine(
         interner: TyCtxt<'tcx>,
         def_id: DefId,
@@ -796,6 +843,51 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
         Ty::new_coroutine(interner, def_id, args)
     }
 
+    fn new_coroutine_closure(
+        interner: TyCtxt<'tcx>,
+        def_id: DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> Self {
+        Ty::new_coroutine_closure(interner, def_id, args)
+    }
+
+    fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
+        Ty::new_closure(interner, def_id, args)
+    }
+
+    fn new_coroutine_witness(
+        interner: TyCtxt<'tcx>,
+        def_id: DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> Self {
+        Ty::new_coroutine_witness(interner, def_id, args)
+    }
+
+    fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
+        Ty::new_ptr(interner, ty, mutbl)
+    }
+
+    fn new_ref(
+        interner: TyCtxt<'tcx>,
+        region: ty::Region<'tcx>,
+        ty: Self,
+        mutbl: hir::Mutability,
+    ) -> Self {
+        Ty::new_ref(interner, region, ty, mutbl)
+    }
+
+    fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
+        Ty::new_array_with_const_len(interner, ty, len)
+    }
+
+    fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
+        Ty::new_slice(interner, ty)
+    }
+
+    fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
+        Ty::new_tup(interner, tys)
+    }
+
     fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
     where
         It: Iterator<Item = T>,
@@ -822,6 +914,18 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     ) -> Self {
         Ty::from_coroutine_closure_kind(interner, kind)
     }
+
+    fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
+        Ty::new_fn_def(interner, def_id, args)
+    }
+
+    fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
+        Ty::new_fn_ptr(interner, sig)
+    }
+
+    fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
+        Ty::new_pat(interner, ty, pat)
+    }
 }
 
 /// Type utilities
@@ -1790,43 +1894,6 @@ impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx
     }
 }
 
-/// Extra information about why we ended up with a particular variance.
-/// This is only used to add more information to error messages, and
-/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
-/// may lead to confusing notes in error messages, it will never cause
-/// a miscompilation or unsoundness.
-///
-/// When in doubt, use `VarianceDiagInfo::default()`
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
-pub enum VarianceDiagInfo<'tcx> {
-    /// No additional information - this is the default.
-    /// We will not add any additional information to error messages.
-    #[default]
-    None,
-    /// We switched our variance because a generic argument occurs inside
-    /// the invariant generic argument of another type.
-    Invariant {
-        /// The generic type containing the generic parameter
-        /// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
-        ty: Ty<'tcx>,
-        /// The index of the generic parameter being used
-        /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
-        param_index: u32,
-    },
-}
-
-impl<'tcx> VarianceDiagInfo<'tcx> {
-    /// Mirrors `Variance::xform` - used to 'combine' the existing
-    /// and new `VarianceDiagInfo`s when our variance changes.
-    pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
-        // For now, just use the first `VarianceDiagInfo::Invariant` that we see
-        match self {
-            VarianceDiagInfo::None => other,
-            VarianceDiagInfo::Invariant { .. } => self,
-        }
-    }
-}
-
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
 mod size_asserts {
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 37a34f28338..4dba97c3b5b 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -206,7 +206,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
     // Traits defined in the current crate can't have impls in upstream
     // crates, so we don't bother querying the cstore.
     if !trait_id.is_local() {
-        for &cnum in tcx.used_crates(()).iter() {
+        for &cnum in tcx.crates(()).iter() {
             for &(impl_def_id, simplified_self_ty) in
                 tcx.implementations_of_trait((cnum, trait_id)).iter()
             {
@@ -248,7 +248,7 @@ pub(super) fn incoherent_impls_provider(
     let mut impls = Vec::new();
 
     let mut res = Ok(());
-    for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) {
+    for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
         let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
             Ok(impls) => impls,
             Err(e) => {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 69ea9c9843a..24e3e623ff2 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -217,10 +217,6 @@ pub struct TypeckResults<'tcx> {
 
     /// Container types and field indices of `offset_of!` expressions
     offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
-
-    /// Maps from `HirId`s of const blocks (the `ExprKind::ConstBlock`, not the inner expression's)
-    /// to the `DefId` of the corresponding inline const.
-    pub inline_consts: FxIndexMap<ItemLocalId, LocalDefId>,
 }
 
 impl<'tcx> TypeckResults<'tcx> {
@@ -253,7 +249,6 @@ impl<'tcx> TypeckResults<'tcx> {
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
-            inline_consts: Default::default(),
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a9421aacff8..e0f204a687f 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -212,38 +212,19 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
             }
         },
         GenericArgKind::Lifetime(_) => {}
-        GenericArgKind::Const(parent_ct) => {
-            stack.push(parent_ct.ty().into());
-            match parent_ct.kind() {
-                ty::ConstKind::Infer(_)
-                | ty::ConstKind::Param(_)
-                | ty::ConstKind::Placeholder(_)
-                | ty::ConstKind::Bound(..)
-                | ty::ConstKind::Value(_)
-                | ty::ConstKind::Error(_) => {}
-
-                ty::ConstKind::Expr(expr) => match expr {
-                    ty::Expr::UnOp(_, v) => push_inner(stack, v.into()),
-                    ty::Expr::Binop(_, l, r) => {
-                        push_inner(stack, r.into());
-                        push_inner(stack, l.into())
-                    }
-                    ty::Expr::FunctionCall(func, args) => {
-                        for a in args.iter().rev() {
-                            push_inner(stack, a.into());
-                        }
-                        push_inner(stack, func.into());
-                    }
-                    ty::Expr::Cast(_, c, t) => {
-                        push_inner(stack, t.into());
-                        push_inner(stack, c.into());
-                    }
-                },
-
-                ty::ConstKind::Unevaluated(ct) => {
-                    stack.extend(ct.args.iter().rev());
-                }
+        GenericArgKind::Const(parent_ct) => match parent_ct.kind() {
+            ty::ConstKind::Infer(_)
+            | ty::ConstKind::Param(_)
+            | ty::ConstKind::Placeholder(_)
+            | ty::ConstKind::Bound(..)
+            | ty::ConstKind::Error(_) => {}
+
+            ty::ConstKind::Value(ty, _) => stack.push(ty.into()),
+
+            ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
+            ty::ConstKind::Unevaluated(ct) => {
+                stack.extend(ct.args.iter().rev());
             }
-        }
+        },
     }
 }
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 77f27236437..5d828d0093f 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -5,7 +5,6 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-either = "1"
 itertools = "0.12"
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
@@ -24,6 +23,5 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
index 7d7b7caf9ef..f97e9ef60a2 100644
--- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
+++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs
@@ -179,18 +179,18 @@ impl MCDCState {
     }
 }
 
-pub struct MCDCInfoBuilder {
+pub(crate) struct MCDCInfoBuilder {
     branch_spans: Vec<MCDCBranchSpan>,
     decision_spans: Vec<MCDCDecisionSpan>,
     state: MCDCState,
 }
 
 impl MCDCInfoBuilder {
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Self { branch_spans: vec![], decision_spans: vec![], state: MCDCState::new() }
     }
 
-    pub fn visit_evaluated_condition(
+    pub(crate) fn visit_evaluated_condition(
         &mut self,
         tcx: TyCtxt<'_>,
         source_info: SourceInfo,
@@ -243,7 +243,7 @@ impl MCDCInfoBuilder {
         });
     }
 
-    pub fn into_done(self) -> (Vec<MCDCDecisionSpan>, Vec<MCDCBranchSpan>) {
+    pub(crate) fn into_done(self) -> (Vec<MCDCDecisionSpan>, Vec<MCDCBranchSpan>) {
         (self.decision_spans, self.branch_spans)
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index 8bcd429b67e..9607022c6df 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -91,7 +91,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
         }
     }
 
-    pub fn parse_args(&mut self, params: &IndexSlice<ParamId, Param<'tcx>>) -> PResult<()> {
+    pub(crate) fn parse_args(&mut self, params: &IndexSlice<ParamId, Param<'tcx>>) -> PResult<()> {
         for param in params.iter() {
             let (var, span) = {
                 let pat = param.pat.as_ref().unwrap();
@@ -149,7 +149,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
     ///
     /// This allows us to easily parse the basic blocks declarations, local declarations, and
     /// basic block definitions in order.
-    pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
+    pub(crate) fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
         let body = parse_by_kind!(self, expr_id, _, "whole body",
             ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
         );
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index de748b9c85d..b1a305efa4c 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -12,7 +12,7 @@ use crate::build::expr::as_constant::as_constant_inner;
 use super::{parse_by_kind, PResult, ParseCtxt};
 
 impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
-    pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
+    pub(crate) fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
         parse_by_kind!(self, expr_id, _, "statement",
             @call(mir_storage_live, args) => {
                 Ok(StatementKind::StorageLive(self.parse_local(args[0])?))
@@ -46,7 +46,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
         )
     }
 
-    pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
+    pub(crate) fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
         parse_by_kind!(self, expr_id, expr, "terminator",
             @call(mir_return, _args) => {
                 Ok(TerminatorKind::Return)
@@ -261,7 +261,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
         )
     }
 
-    pub fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
+    pub(crate) fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
         parse_by_kind!(self, expr_id, expr, "operand",
             @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move),
             @call(mir_static, args) => self.parse_static(args[0]),
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index b4dd423f344..b783eba8c4e 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -7,7 +7,7 @@ use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput,
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{
-    self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
+    self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Size;
@@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
-pub fn as_constant_inner<'tcx>(
+pub(crate) fn as_constant_inner<'tcx>(
     expr: &Expr<'tcx>,
     push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
     tcx: TyCtxt<'tcx>,
@@ -51,7 +51,7 @@ pub fn as_constant_inner<'tcx>(
             {
                 Ok(c) => c,
                 Err(LitToConstError::Reported(guar)) => {
-                    Const::Ty(ty::Const::new_error(tcx, guar, ty))
+                    Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar))
                 }
                 Err(LitToConstError::TypeError) => {
                     bug!("encountered type error in `lit_to_mir_constant`")
@@ -83,8 +83,8 @@ pub fn as_constant_inner<'tcx>(
             ConstOperand { user_ty, span, const_ }
         }
         ExprKind::ConstParam { param, def_id: _ } => {
-            let const_param = ty::Const::new_param(tcx, param, expr.ty);
-            let const_ = Const::Ty(const_param);
+            let const_param = ty::Const::new_param(tcx, param);
+            let const_ = Const::Ty(expr.ty, const_param);
 
             ConstOperand { user_ty: None, span, const_ }
         }
diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs
index dfe85b858cd..3de43a3370f 100644
--- a/compiler/rustc_mir_build/src/build/expr/mod.rs
+++ b/compiler/rustc_mir_build/src/build/expr/mod.rs
@@ -62,9 +62,9 @@
 
 pub(crate) mod as_constant;
 mod as_operand;
-pub mod as_place;
+pub(crate) mod as_place;
 mod as_rvalue;
 mod as_temp;
-pub mod category;
+pub(crate) mod category;
 mod into;
 mod stmt;
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 770f689724a..50f4ca2d819 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -456,7 +456,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
 }
 
 #[must_use]
-pub fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
+pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
     match ref_mutability {
         Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default },
         Mutability::Not => BorrowKind::Shared,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 14d1b502474..601e5d4d3dc 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -15,11 +15,10 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -568,8 +567,11 @@ fn construct_const<'a, 'tcx>(
             ..
         }) => (*span, ty.span),
         Node::AnonConst(ct) => (ct.span, ct.span),
-        Node::Expr(&hir::Expr { span, kind: hir::ExprKind::ConstBlock(_), .. }) => (span, span),
-        node => span_bug!(tcx.def_span(def), "can't build MIR for {def:?}: {node:#?}"),
+        Node::ConstBlock(_) => {
+            let span = tcx.def_span(def);
+            (span, span)
+        }
+        _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
     };
 
     let infcx = tcx.infer_ctxt().build();
@@ -1011,14 +1013,14 @@ fn parse_float_into_constval<'tcx>(
     float_ty: ty::FloatTy,
     neg: bool,
 ) -> Option<ConstValue<'tcx>> {
-    parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
+    parse_float_into_scalar(num, float_ty, neg).map(|s| ConstValue::Scalar(s.into()))
 }
 
 pub(crate) fn parse_float_into_scalar(
     num: Symbol,
     float_ty: ty::FloatTy,
     neg: bool,
-) -> Option<Scalar> {
+) -> Option<ScalarInt> {
     let num = num.as_str();
     match float_ty {
         // FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
@@ -1027,7 +1029,7 @@ pub(crate) fn parse_float_into_scalar(
             if neg {
                 f = -f;
             }
-            Some(Scalar::from_f16(f))
+            Some(ScalarInt::from(f))
         }
         ty::FloatTy::F32 => {
             let Ok(rust_f) = num.parse::<f32>() else { return None };
@@ -1050,7 +1052,7 @@ pub(crate) fn parse_float_into_scalar(
                 f = -f;
             }
 
-            Some(Scalar::from_f32(f))
+            Some(ScalarInt::from(f))
         }
         ty::FloatTy::F64 => {
             let Ok(rust_f) = num.parse::<f64>() else { return None };
@@ -1073,7 +1075,7 @@ pub(crate) fn parse_float_into_scalar(
                 f = -f;
             }
 
-            Some(Scalar::from_f64(f))
+            Some(ScalarInt::from(f))
         }
         // FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
         ty::FloatTy::F128 => {
@@ -1081,7 +1083,7 @@ pub(crate) fn parse_float_into_scalar(
             if neg {
                 f = -f;
             }
-            Some(Scalar::from_f128(f))
+            Some(ScalarInt::from(f))
         }
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index c7850c7aea8..5b6de39bb2e 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -97,7 +97,7 @@ use rustc_span::{Span, DUMMY_SP};
 use tracing::{debug, instrument};
 
 #[derive(Debug)]
-pub struct Scopes<'tcx> {
+pub(crate) struct Scopes<'tcx> {
     scopes: Vec<Scope>,
 
     /// The current set of breakable scopes. See module comment for more details.
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 24098282d93..d781fb1c297 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -2,6 +2,7 @@ use crate::build::ExprCategory;
 use crate::errors::*;
 
 use rustc_errors::DiagArgValue;
+use rustc_hir::def::DefKind;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::span_bug;
@@ -88,6 +89,33 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
         }
     }
 
+    fn emit_deprecated_safe_fn_call(&self, span: Span, kind: &UnsafeOpKind) -> bool {
+        match kind {
+            // Allow calls to deprecated-safe unsafe functions if the caller is
+            // from an edition before 2024.
+            &UnsafeOpKind::CallToUnsafeFunction(Some(id))
+                if !span.at_least_rust_2024()
+                    && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) =>
+            {
+                self.tcx.emit_node_span_lint(
+                    DEPRECATED_SAFE,
+                    self.hir_context,
+                    span,
+                    CallToDeprecatedSafeFnRequiresUnsafe {
+                        span,
+                        function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
+                        sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
+                            left: span.shrink_to_lo(),
+                            right: span.shrink_to_hi(),
+                        },
+                    },
+                );
+                true
+            }
+            _ => false,
+        }
+    }
+
     fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
         let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
         match self.safety_context {
@@ -101,43 +129,29 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
             }
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
-                // unsafe_op_in_unsafe_fn is disallowed
-                kind.emit_unsafe_op_in_unsafe_fn_lint(
-                    self.tcx,
-                    self.hir_context,
-                    span,
-                    self.suggest_unsafe_block,
-                );
-                self.suggest_unsafe_block = false;
-            }
-            SafetyContext::Safe => match kind {
-                // Allow calls to deprecated-safe unsafe functions if the
-                // caller is from an edition before 2024.
-                UnsafeOpKind::CallToUnsafeFunction(Some(id))
-                    if !span.at_least_rust_2024()
-                        && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) =>
-                {
-                    self.tcx.emit_node_span_lint(
-                        DEPRECATED_SAFE,
+                let deprecated_safe_fn = self.emit_deprecated_safe_fn_call(span, &kind);
+                if !deprecated_safe_fn {
+                    // unsafe_op_in_unsafe_fn is disallowed
+                    kind.emit_unsafe_op_in_unsafe_fn_lint(
+                        self.tcx,
                         self.hir_context,
                         span,
-                        CallToDeprecatedSafeFnRequiresUnsafe {
-                            span,
-                            function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
-                            sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
-                                left: span.shrink_to_lo(),
-                                right: span.shrink_to_hi(),
-                            },
-                        },
-                    )
+                        self.suggest_unsafe_block,
+                    );
+                    self.suggest_unsafe_block = false;
                 }
-                _ => kind.emit_requires_unsafe_err(
-                    self.tcx,
-                    span,
-                    self.hir_context,
-                    unsafe_op_in_unsafe_fn_allowed,
-                ),
-            },
+            }
+            SafetyContext::Safe => {
+                let deprecated_safe_fn = self.emit_deprecated_safe_fn_call(span, &kind);
+                if !deprecated_safe_fn {
+                    kind.emit_requires_unsafe_err(
+                        self.tcx,
+                        span,
+                        self.hir_context,
+                        unsafe_op_in_unsafe_fn_allowed,
+                    );
+                }
+            }
         }
     }
 
@@ -456,7 +470,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     if self.tcx.is_mutable_static(def_id) {
                         self.requires_unsafe(expr.span, UseOfMutableStatic);
                     } else if self.tcx.is_foreign_item(def_id) {
-                        self.requires_unsafe(expr.span, UseOfExternStatic);
+                        match self.tcx.def_kind(def_id) {
+                            DefKind::Static { safety: hir::Safety::Safe, .. } => {}
+                            _ => self.requires_unsafe(expr.span, UseOfExternStatic),
+                        }
                     }
                 } else if self.thir[arg].ty.is_unsafe_ptr() {
                     self.requires_unsafe(expr.span, DerefOfRawPointer);
@@ -597,7 +614,7 @@ enum UnsafeOpKind {
 use UnsafeOpKind::*;
 
 impl UnsafeOpKind {
-    pub fn emit_unsafe_op_in_unsafe_fn_lint(
+    fn emit_unsafe_op_in_unsafe_fn_lint(
         &self,
         tcx: TyCtxt<'_>,
         hir_id: HirId,
@@ -737,7 +754,7 @@ impl UnsafeOpKind {
         }
     }
 
-    pub fn emit_requires_unsafe_err(
+    fn emit_requires_unsafe_err(
         &self,
         tcx: TyCtxt<'_>,
         span: Span,
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index d7ed4f57e59..cf324c03dc9 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -13,111 +13,111 @@ use rustc_span::Span;
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unconditional_recursion)]
 #[help]
-pub struct UnconditionalRecursion {
+pub(crate) struct UnconditionalRecursion {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[label(mir_build_unconditional_recursion_call_site_label)]
-    pub call_sites: Vec<Span>,
+    pub(crate) call_sites: Vec<Span>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)]
-pub struct CallToDeprecatedSafeFnRequiresUnsafe {
+pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
     #[label]
-    pub span: Span,
-    pub function: String,
+    pub(crate) span: Span,
+    pub(crate) function: String,
     #[subdiagnostic]
-    pub sub: CallToDeprecatedSafeFnRequiresUnsafeSub,
+    pub(crate) sub: CallToDeprecatedSafeFnRequiresUnsafeSub,
 }
 
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")]
-pub struct CallToDeprecatedSafeFnRequiresUnsafeSub {
+pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub {
     #[suggestion_part(code = "unsafe {{ ")]
-    pub left: Span,
+    pub(crate) left: Span,
     #[suggestion_part(code = " }}")]
-    pub right: Span,
+    pub(crate) right: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
     #[label]
-    pub span: Span,
-    pub function: String,
+    pub(crate) span: Span,
+    pub(crate) function: String,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
+pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)]
 #[note]
-pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -126,11 +126,11 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
     code = E0133
 )]
 #[note]
-pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -138,63 +138,63 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
     mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe,
     code = E0133,
 )]
-pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)]
 #[help]
-pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
+pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
     #[label]
-    pub span: Span,
-    pub function: String,
-    pub missing_target_features: DiagArgValue,
-    pub missing_target_features_count: usize,
+    pub(crate) span: Span,
+    pub(crate) function: String,
+    pub(crate) missing_target_features: DiagArgValue,
+    pub(crate) missing_target_features_count: usize,
     #[note]
-    pub note: Option<()>,
-    pub build_target_features: DiagArgValue,
-    pub build_target_features_count: usize,
+    pub(crate) note: Option<()>,
+    pub(crate) build_target_features: DiagArgValue,
+    pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)]
 #[note]
-pub struct CallToUnsafeFunctionRequiresUnsafe {
+pub(crate) struct CallToUnsafeFunctionRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub function: String,
+    pub(crate) span: Span,
+    pub(crate) function: String,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)]
 #[note]
-pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
+pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNameless {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub function: String,
+    pub(crate) span: Span,
+    pub(crate) function: String,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
@@ -203,45 +203,45 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     code = E0133
 )]
 #[note]
-pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)]
 #[note]
-pub struct UseOfInlineAssemblyRequiresUnsafe {
+pub(crate) struct UseOfInlineAssemblyRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)]
 #[note]
-pub struct InitializingTypeWithRequiresUnsafe {
+pub(crate) struct InitializingTypeWithRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
@@ -250,111 +250,111 @@ pub struct InitializingTypeWithRequiresUnsafe {
     code = E0133
 )]
 #[note]
-pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
 #[note]
-pub struct UseOfMutableStaticRequiresUnsafe {
+pub(crate) struct UseOfMutableStaticRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_extern_static_requires_unsafe, code = E0133)]
 #[note]
-pub struct UseOfExternStaticRequiresUnsafe {
+pub(crate) struct UseOfExternStaticRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)]
 #[note]
-pub struct DerefOfRawPointerRequiresUnsafe {
+pub(crate) struct DerefOfRawPointerRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_union_field_requires_unsafe, code = E0133)]
 #[note]
-pub struct AccessToUnionFieldRequiresUnsafe {
+pub(crate) struct AccessToUnionFieldRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
-pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
-pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
+pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
@@ -363,23 +363,23 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
     code = E0133
 )]
 #[note]
-pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
-pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
+pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
@@ -388,60 +388,60 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
     code = E0133
 )]
 #[note]
-pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)]
 #[help]
-pub struct CallToFunctionWithRequiresUnsafe {
+pub(crate) struct CallToFunctionWithRequiresUnsafe {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub function: String,
-    pub missing_target_features: DiagArgValue,
-    pub missing_target_features_count: usize,
+    pub(crate) span: Span,
+    pub(crate) function: String,
+    pub(crate) missing_target_features: DiagArgValue,
+    pub(crate) missing_target_features_count: usize,
     #[note]
-    pub note: Option<()>,
-    pub build_target_features: DiagArgValue,
-    pub build_target_features_count: usize,
+    pub(crate) note: Option<()>,
+    pub(crate) build_target_features: DiagArgValue,
+    pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[help]
-pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub function: String,
-    pub missing_target_features: DiagArgValue,
-    pub missing_target_features_count: usize,
+    pub(crate) span: Span,
+    pub(crate) function: String,
+    pub(crate) missing_target_features: DiagArgValue,
+    pub(crate) missing_target_features_count: usize,
     #[note]
-    pub note: Option<()>,
-    pub build_target_features: DiagArgValue,
-    pub build_target_features_count: usize,
+    pub(crate) note: Option<()>,
+    pub(crate) build_target_features: DiagArgValue,
+    pub(crate) build_target_features_count: usize,
     #[subdiagnostic]
-    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
+    pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
 }
 
 #[derive(Subdiagnostic)]
 #[label(mir_build_unsafe_not_inherited)]
-pub struct UnsafeNotInheritedNote {
+pub(crate) struct UnsafeNotInheritedNote {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
-pub struct UnsafeNotInheritedLintNote {
-    pub signature_span: Span,
-    pub body_span: Span,
+pub(crate) struct UnsafeNotInheritedLintNote {
+    pub(crate) signature_span: Span,
+    pub(crate) body_span: Span,
 }
 
 impl Subdiagnostic for UnsafeNotInheritedLintNote {
@@ -463,15 +463,15 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote {
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unused_unsafe)]
-pub struct UnusedUnsafe {
+pub(crate) struct UnusedUnsafe {
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub enclosing: Option<UnusedUnsafeEnclosing>,
+    pub(crate) enclosing: Option<UnusedUnsafeEnclosing>,
 }
 
 #[derive(Subdiagnostic)]
-pub enum UnusedUnsafeEnclosing {
+pub(crate) enum UnusedUnsafeEnclosing {
     #[label(mir_build_unused_unsafe_enclosing_block_label)]
     Block {
         #[primary_span]
@@ -480,10 +480,10 @@ pub enum UnusedUnsafeEnclosing {
 }
 
 pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
-    pub cx: &'m RustcPatCtxt<'p, 'tcx>,
-    pub scrut_span: Span,
-    pub braces_span: Option<Span>,
-    pub ty: Ty<'tcx>,
+    pub(crate) cx: &'m RustcPatCtxt<'p, 'tcx>,
+    pub(crate) scrut_span: Span,
+    pub(crate) braces_span: Option<Span>,
+    pub(crate) ty: Ty<'tcx>,
 }
 
 impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
@@ -552,197 +552,197 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo
 
 #[derive(Subdiagnostic)]
 #[note(mir_build_non_exhaustive_match_all_arms_guarded)]
-pub struct NonExhaustiveMatchAllArmsGuarded;
+pub(crate) struct NonExhaustiveMatchAllArmsGuarded;
 
 #[derive(Diagnostic)]
 #[diag(mir_build_static_in_pattern, code = E0158)]
-pub struct StaticInPattern {
+pub(crate) struct StaticInPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_assoc_const_in_pattern, code = E0158)]
-pub struct AssocConstInPattern {
+pub(crate) struct AssocConstInPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_const_param_in_pattern, code = E0158)]
-pub struct ConstParamInPattern {
+pub(crate) struct ConstParamInPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_non_const_path, code = E0080)]
-pub struct NonConstPath {
+pub(crate) struct NonConstPath {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unreachable_pattern)]
-pub struct UnreachablePattern {
+pub(crate) struct UnreachablePattern {
     #[label]
-    pub span: Option<Span>,
+    pub(crate) span: Option<Span>,
     #[label(mir_build_catchall_label)]
-    pub catchall: Option<Span>,
+    pub(crate) catchall: Option<Span>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_const_pattern_depends_on_generic_parameter)]
-pub struct ConstPatternDependsOnGenericParameter {
+pub(crate) struct ConstPatternDependsOnGenericParameter {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_could_not_eval_const_pattern)]
-pub struct CouldNotEvalConstPattern {
+pub(crate) struct CouldNotEvalConstPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)]
-pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
+pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub(crate) span: Span,
     #[note(mir_build_teach_note)]
-    pub teach: Option<()>,
+    pub(crate) teach: Option<()>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_literal_in_range_out_of_bounds)]
-pub struct LiteralOutOfRange<'tcx> {
+pub(crate) struct LiteralOutOfRange<'tcx> {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub ty: Ty<'tcx>,
-    pub min: i128,
-    pub max: u128,
+    pub(crate) span: Span,
+    pub(crate) ty: Ty<'tcx>,
+    pub(crate) min: i128,
+    pub(crate) max: u128,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)]
-pub struct LowerRangeBoundMustBeLessThanUpper {
+pub(crate) struct LowerRangeBoundMustBeLessThanUpper {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_leading_irrefutable_let_patterns)]
 #[note]
 #[help]
-pub struct LeadingIrrefutableLetPatterns {
-    pub count: usize,
+pub(crate) struct LeadingIrrefutableLetPatterns {
+    pub(crate) count: usize,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_trailing_irrefutable_let_patterns)]
 #[note]
 #[help]
-pub struct TrailingIrrefutableLetPatterns {
-    pub count: usize,
+pub(crate) struct TrailingIrrefutableLetPatterns {
+    pub(crate) count: usize,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_bindings_with_variant_name, code = E0170)]
-pub struct BindingsWithVariantName {
+pub(crate) struct BindingsWithVariantName {
     #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")]
-    pub suggestion: Option<Span>,
-    pub ty_path: String,
-    pub name: Symbol,
+    pub(crate) suggestion: Option<Span>,
+    pub(crate) ty_path: String,
+    pub(crate) name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_irrefutable_let_patterns_if_let)]
 #[note]
 #[help]
-pub struct IrrefutableLetPatternsIfLet {
-    pub count: usize,
+pub(crate) struct IrrefutableLetPatternsIfLet {
+    pub(crate) count: usize,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_irrefutable_let_patterns_if_let_guard)]
 #[note]
 #[help]
-pub struct IrrefutableLetPatternsIfLetGuard {
-    pub count: usize,
+pub(crate) struct IrrefutableLetPatternsIfLetGuard {
+    pub(crate) count: usize,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_irrefutable_let_patterns_let_else)]
 #[note]
 #[help]
-pub struct IrrefutableLetPatternsLetElse {
-    pub count: usize,
+pub(crate) struct IrrefutableLetPatternsLetElse {
+    pub(crate) count: usize,
 }
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_irrefutable_let_patterns_while_let)]
 #[note]
 #[help]
-pub struct IrrefutableLetPatternsWhileLet {
-    pub count: usize,
+pub(crate) struct IrrefutableLetPatternsWhileLet {
+    pub(crate) count: usize,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_borrow_of_moved_value)]
-pub struct BorrowOfMovedValue<'tcx> {
+pub(crate) struct BorrowOfMovedValue<'tcx> {
     #[primary_span]
     #[label]
     #[label(mir_build_occurs_because_label)]
-    pub binding_span: Span,
+    pub(crate) binding_span: Span,
     #[label(mir_build_value_borrowed_label)]
-    pub conflicts_ref: Vec<Span>,
-    pub name: Symbol,
-    pub ty: Ty<'tcx>,
+    pub(crate) conflicts_ref: Vec<Span>,
+    pub(crate) name: Symbol,
+    pub(crate) ty: Ty<'tcx>,
     #[suggestion(code = "ref ", applicability = "machine-applicable")]
-    pub suggest_borrowing: Option<Span>,
+    pub(crate) suggest_borrowing: Option<Span>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_multiple_mut_borrows)]
-pub struct MultipleMutBorrows {
+pub(crate) struct MultipleMutBorrows {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub occurrences: Vec<Conflict>,
+    pub(crate) occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_already_borrowed)]
-pub struct AlreadyBorrowed {
+pub(crate) struct AlreadyBorrowed {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub occurrences: Vec<Conflict>,
+    pub(crate) occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_already_mut_borrowed)]
-pub struct AlreadyMutBorrowed {
+pub(crate) struct AlreadyMutBorrowed {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub occurrences: Vec<Conflict>,
+    pub(crate) occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_moved_while_borrowed)]
-pub struct MovedWhileBorrowed {
+pub(crate) struct MovedWhileBorrowed {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub occurrences: Vec<Conflict>,
+    pub(crate) occurrences: Vec<Conflict>,
 }
 
 #[derive(Subdiagnostic)]
-pub enum Conflict {
+pub(crate) enum Conflict {
     #[label(mir_build_mutable_borrow)]
     Mut {
         #[primary_span]
@@ -765,118 +765,118 @@ pub enum Conflict {
 
 #[derive(Diagnostic)]
 #[diag(mir_build_union_pattern)]
-pub struct UnionPattern {
+pub(crate) struct UnionPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_type_not_structural)]
 #[note(mir_build_type_not_structural_tip)]
 #[note(mir_build_type_not_structural_more_info)]
-pub struct TypeNotStructural<'tcx> {
+pub(crate) struct TypeNotStructural<'tcx> {
     #[primary_span]
-    pub span: Span,
-    pub non_sm_ty: Ty<'tcx>,
+    pub(crate) span: Span,
+    pub(crate) non_sm_ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_non_partial_eq_match)]
-pub struct TypeNotPartialEq<'tcx> {
+pub(crate) struct TypeNotPartialEq<'tcx> {
     #[primary_span]
-    pub span: Span,
-    pub non_peq_ty: Ty<'tcx>,
+    pub(crate) span: Span,
+    pub(crate) non_peq_ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_invalid_pattern)]
-pub struct InvalidPattern<'tcx> {
+pub(crate) struct InvalidPattern<'tcx> {
     #[primary_span]
-    pub span: Span,
-    pub non_sm_ty: Ty<'tcx>,
+    pub(crate) span: Span,
+    pub(crate) non_sm_ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_unsized_pattern)]
-pub struct UnsizedPattern<'tcx> {
+pub(crate) struct UnsizedPattern<'tcx> {
     #[primary_span]
-    pub span: Span,
-    pub non_sm_ty: Ty<'tcx>,
+    pub(crate) span: Span,
+    pub(crate) non_sm_ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_nan_pattern)]
 #[note]
 #[help]
-pub struct NaNPattern {
+pub(crate) struct NaNPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_pointer_pattern)]
-pub struct PointerPattern {
+pub(crate) struct PointerPattern {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_non_empty_never_pattern)]
 #[note]
-pub struct NonEmptyNeverPattern<'tcx> {
+pub(crate) struct NonEmptyNeverPattern<'tcx> {
     #[primary_span]
     #[label]
-    pub span: Span,
-    pub ty: Ty<'tcx>,
+    pub(crate) span: Span,
+    pub(crate) ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_exceeds_mcdc_condition_limit)]
 pub(crate) struct MCDCExceedsConditionLimit {
     #[primary_span]
-    pub span: Span,
-    pub num_conditions: usize,
-    pub max_conditions: usize,
+    pub(crate) span: Span,
+    pub(crate) num_conditions: usize,
+    pub(crate) max_conditions: usize,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_pattern_not_covered, code = E0005)]
 pub(crate) struct PatternNotCovered<'s, 'tcx> {
     #[primary_span]
-    pub span: Span,
-    pub origin: &'s str,
+    pub(crate) span: Span,
+    pub(crate) origin: &'s str,
     #[subdiagnostic]
-    pub uncovered: Uncovered<'tcx>,
+    pub(crate) uncovered: Uncovered<'tcx>,
     #[subdiagnostic]
-    pub inform: Option<Inform>,
+    pub(crate) inform: Option<Inform>,
     #[subdiagnostic]
-    pub interpreted_as_const: Option<InterpretedAsConst>,
+    pub(crate) interpreted_as_const: Option<InterpretedAsConst>,
     #[subdiagnostic]
-    pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
+    pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
     #[note(mir_build_privately_uninhabited)]
-    pub witness_1_is_privately_uninhabited: Option<()>,
+    pub(crate) witness_1_is_privately_uninhabited: Option<()>,
     #[note(mir_build_pattern_ty)]
-    pub _p: (),
-    pub pattern_ty: Ty<'tcx>,
+    pub(crate) _p: (),
+    pub(crate) pattern_ty: Ty<'tcx>,
     #[subdiagnostic]
-    pub let_suggestion: Option<SuggestLet>,
+    pub(crate) let_suggestion: Option<SuggestLet>,
     #[subdiagnostic]
-    pub misc_suggestion: Option<MiscPatternSuggestion>,
+    pub(crate) misc_suggestion: Option<MiscPatternSuggestion>,
 }
 
 #[derive(Subdiagnostic)]
 #[note(mir_build_inform_irrefutable)]
 #[note(mir_build_more_information)]
-pub struct Inform;
+pub(crate) struct Inform;
 
-pub struct AdtDefinedHere<'tcx> {
-    pub adt_def_span: Span,
-    pub ty: Ty<'tcx>,
-    pub variants: Vec<Variant>,
+pub(crate) struct AdtDefinedHere<'tcx> {
+    pub(crate) adt_def_span: Span,
+    pub(crate) ty: Ty<'tcx>,
+    pub(crate) variants: Vec<Variant>,
 }
 
-pub struct Variant {
-    pub span: Span,
+pub(crate) struct Variant {
+    pub(crate) span: Span,
 }
 
 impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
@@ -903,14 +903,14 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
     applicability = "maybe-incorrect"
 )]
 #[label(mir_build_confused)]
-pub struct InterpretedAsConst {
+pub(crate) struct InterpretedAsConst {
     #[primary_span]
-    pub span: Span,
-    pub variable: String,
+    pub(crate) span: Span,
+    pub(crate) variable: String,
 }
 
 #[derive(Subdiagnostic)]
-pub enum SuggestLet {
+pub(crate) enum SuggestLet {
     #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
     If {
         #[suggestion_part(code = "if ")]
@@ -932,7 +932,7 @@ pub enum SuggestLet {
 }
 
 #[derive(Subdiagnostic)]
-pub enum MiscPatternSuggestion {
+pub(crate) enum MiscPatternSuggestion {
     #[suggestion(
         mir_build_suggest_attempted_int_lit,
         code = "_",
@@ -946,15 +946,15 @@ pub enum MiscPatternSuggestion {
 
 #[derive(Diagnostic)]
 #[diag(mir_build_rustc_box_attribute_error)]
-pub struct RustcBoxAttributeError {
+pub(crate) struct RustcBoxAttributeError {
     #[primary_span]
-    pub span: Span,
+    pub(crate) span: Span,
     #[subdiagnostic]
-    pub reason: RustcBoxAttrReason,
+    pub(crate) reason: RustcBoxAttrReason,
 }
 
 #[derive(Subdiagnostic)]
-pub enum RustcBoxAttrReason {
+pub(crate) enum RustcBoxAttrReason {
     #[note(mir_build_attributes)]
     Attributes,
     #[note(mir_build_not_box)]
@@ -965,13 +965,13 @@ pub enum RustcBoxAttrReason {
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_rust_2024_incompatible_pat)]
-pub struct Rust2024IncompatiblePat {
+pub(crate) struct Rust2024IncompatiblePat {
     #[subdiagnostic]
-    pub sugg: Rust2024IncompatiblePatSugg,
+    pub(crate) sugg: Rust2024IncompatiblePatSugg,
 }
 
-pub struct Rust2024IncompatiblePatSugg {
-    pub suggestion: Vec<(Span, String)>,
+pub(crate) struct Rust2024IncompatiblePatSugg {
+    pub(crate) suggestion: Vec<(Span, String)>,
 }
 
 impl Subdiagnostic for Rust2024IncompatiblePatSugg {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 74600c6b12e..a1b8b578349 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -1,6 +1,4 @@
 //! Construction of MIR from HIR.
-//!
-//! This crate also contains the match exhaustiveness and usefulness checking.
 
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 31bc72184ca..a98e046d4dc 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -58,11 +58,9 @@ pub(crate) fn lit_to_const<'tcx>(
         }
         (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
         (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            let bits = parse_float_into_scalar(*n, *fty, neg)
-                .ok_or_else(|| {
-                    tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
-                })?
-                .assert_int();
+            let bits = parse_float_into_scalar(*n, *fty, neg).ok_or_else(|| {
+                tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
+            })?;
             ty::ValTree::from_scalar_int(bits)
         }
         (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index bd66257e6b6..28f9300b97a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -671,9 +671,9 @@ impl<'tcx> Cx<'tcx> {
                 ExprKind::OffsetOf { container, fields }
             }
 
-            hir::ExprKind::ConstBlock(body) => {
-                let ty = self.typeck_results().node_type(body.hir_id);
-                let did = self.typeck_results().inline_consts[&expr.hir_id.local_id].into();
+            hir::ExprKind::ConstBlock(ref anon_const) => {
+                let ty = self.typeck_results().node_type(anon_const.hir_id);
+                let did = anon_const.def_id.to_def_id();
                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
                 let parent_args =
                     tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id));
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index bd9e34ae80f..244ac409fd3 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -165,7 +165,7 @@ impl<'tcx> Cx<'tcx> {
         &'a mut self,
         owner_id: HirId,
         fn_decl: &'tcx hir::FnDecl<'tcx>,
-        body: &hir::Body<'tcx>,
+        body: &'tcx hir::Body<'tcx>,
     ) -> impl Iterator<Item = Param<'tcx>> + 'a {
         let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 8d881713eeb..192d706bce2 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -101,9 +101,9 @@ impl<'tcx> ConstToPat<'tcx> {
         // level of indirection can be eliminated
 
         let have_valtree =
-            matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_)));
+            matches!(cv, mir::Const::Ty(_, c) if matches!(c.kind(), ty::ConstKind::Value(_, _)));
         let inlined_const_as_pat = match cv {
-            mir::Const::Ty(c) => match c.kind() {
+            mir::Const::Ty(_, c) => match c.kind() {
                 ty::ConstKind::Param(_)
                 | ty::ConstKind::Infer(_)
                 | ty::ConstKind::Bound(_, _)
@@ -113,8 +113,8 @@ impl<'tcx> ConstToPat<'tcx> {
                 | ty::ConstKind::Expr(_) => {
                     span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
                 }
-                ty::ConstKind::Value(valtree) => {
-                    self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| {
+                ty::ConstKind::Value(ty, valtree) => {
+                    self.recur(valtree, ty).unwrap_or_else(|_: FallbackToOpaqueConst| {
                         Box::new(Pat {
                             span: self.span,
                             ty: cv.ty(),
@@ -282,8 +282,7 @@ impl<'tcx> ConstToPat<'tcx> {
             }
             ty::Adt(adt_def, args) if adt_def.is_enum() => {
                 let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
-                let variant_index =
-                    VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
+                let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().to_u32());
                 PatKind::Variant {
                     adt_def: *adt_def,
                     args,
@@ -336,9 +335,9 @@ impl<'tcx> ConstToPat<'tcx> {
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.
-                ty::Str => {
-                    PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
-                }
+                ty::Str => PatKind::Constant {
+                    value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
+                },
                 // All other references are converted into deref patterns and then recursively
                 // convert the dereferenced constant to a pattern that is the sub-pattern of the
                 // deref pattern.
@@ -371,8 +370,8 @@ impl<'tcx> ConstToPat<'tcx> {
                 let v = cv.unwrap_leaf();
                 let is_nan = match flt {
                     ty::FloatTy::F16 => unimplemented!("f16_f128"),
-                    ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(),
-                    ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(),
+                    ty::FloatTy::F32 => v.to_f32().is_nan(),
+                    ty::FloatTy::F64 => v.to_f64().is_nan(),
                     ty::FloatTy::F128 => unimplemented!("f16_f128"),
                 };
                 if is_nan {
@@ -382,13 +381,15 @@ impl<'tcx> ConstToPat<'tcx> {
                     self.saw_const_match_error.set(Some(e));
                     return Err(FallbackToOpaqueConst);
                 } else {
-                    PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
+                    PatKind::Constant {
+                        value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
+                    }
                 }
             }
             ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
                 // The raw pointers we see here have been "vetted" by valtree construction to be
                 // just integers, so we simply allow them.
-                PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
+                PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) }
             }
             ty::FnPtr(..) => {
                 unreachable!(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 33401cad631..158ca91fcf1 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -580,7 +580,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             .tcx
             .const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
             .map(|val| match val {
-                Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
+                Some(valtree) => mir::Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
                 None => mir::Const::Val(
                     self.tcx
                         .const_eval_global_id(param_env_reveal_all, cid, span)
@@ -637,13 +637,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// Converts inline const patterns.
     fn lower_inline_const(
         &mut self,
-        expr: &'tcx hir::Expr<'tcx>,
+        block: &'tcx hir::ConstBlock,
         id: hir::HirId,
         span: Span,
     ) -> PatKind<'tcx> {
         let tcx = self.tcx;
-        let def_id = self.typeck_results.inline_consts[&id.local_id];
-        let ty = tcx.typeck(def_id).node_type(expr.hir_id);
+        let def_id = block.def_id;
+        let body_id = block.body;
+        let expr = &tcx.hir().body(body_id).value;
+        let ty = tcx.typeck(def_id).node_type(block.hir_id);
 
         // Special case inline consts that are just literals. This is solely
         // a performance optimization, as we could also just go through the regular
@@ -659,7 +661,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         };
         if let Some(lit_input) = lit_input {
             match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind,
+                Ok(c) => return self.const_to_pat(Const::Ty(ty, c), id, span).kind,
                 // If an error occurred, ignore that it's a literal
                 // and leave reporting the error up to const eval of
                 // the unevaluated constant below.
@@ -681,8 +683,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // but something more principled, like a trait query checking whether this can be turned into a valtree.
         if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
         {
-            let subpattern =
-                self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
+            let subpattern = self.const_to_pat(
+                Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
+                id,
+                span,
+            );
             PatKind::InlineConstant { subpattern, def: def_id }
         } else {
             // If that fails, convert it to an opaque constant pattern.
@@ -720,10 +725,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             _ => span_bug!(expr.span, "not a literal: {:?}", expr),
         };
 
-        let lit_input =
-            LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
+        let ct_ty = self.typeck_results.expr_ty(expr);
+        let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
         match self.tcx.at(expr.span).lit_to_const(lit_input) {
-            Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind,
+            Ok(constant) => {
+                self.const_to_pat(Const::Ty(ct_ty, constant), expr.hir_id, lit.span).kind
+            }
             Err(LitToConstError::Reported(e)) => PatKind::Error(e),
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
deleted file mode 100644
index e4e4270c499..00000000000
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! Finds locals which are assigned once to a const and unused except for debuginfo and converts
-//! their debuginfo to use the const directly, allowing the local to be removed.
-
-use rustc_middle::{
-    mir::{
-        visit::{PlaceContext, Visitor},
-        Body, ConstOperand, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents,
-    },
-    ty::TyCtxt,
-};
-
-use crate::MirPass;
-use rustc_index::{bit_set::BitSet, IndexVec};
-
-pub struct ConstDebugInfo;
-
-impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
-    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() > 0
-    }
-
-    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        trace!("running ConstDebugInfo on {:?}", body.source);
-
-        for (local, constant) in find_optimization_opportunities(body) {
-            for debuginfo in &mut body.var_debug_info {
-                if let VarDebugInfoContents::Place(p) = debuginfo.value {
-                    if p.local == local && p.projection.is_empty() {
-                        trace!(
-                            "changing debug info for {:?} from place {:?} to constant {:?}",
-                            debuginfo.name,
-                            p,
-                            constant
-                        );
-                        debuginfo.value = VarDebugInfoContents::Const(constant);
-                    }
-                }
-            }
-        }
-    }
-}
-
-struct LocalUseVisitor {
-    local_mutating_uses: IndexVec<Local, u8>,
-    local_assignment_locations: IndexVec<Local, Option<Location>>,
-}
-
-fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, ConstOperand<'tcx>)> {
-    let mut visitor = LocalUseVisitor {
-        local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
-        local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),
-    };
-
-    visitor.visit_body(body);
-
-    let mut locals_to_debuginfo = BitSet::new_empty(body.local_decls.len());
-    for debuginfo in &body.var_debug_info {
-        if let VarDebugInfoContents::Place(p) = debuginfo.value
-            && let Some(l) = p.as_local()
-        {
-            locals_to_debuginfo.insert(l);
-        }
-    }
-
-    let mut eligible_locals = Vec::new();
-    for (local, mutating_uses) in visitor.local_mutating_uses.drain_enumerated(..) {
-        if mutating_uses != 1 || !locals_to_debuginfo.contains(local) {
-            continue;
-        }
-
-        if let Some(location) = visitor.local_assignment_locations[local] {
-            let bb = &body[location.block];
-
-            // The value is assigned as the result of a call, not a constant
-            if bb.statements.len() == location.statement_index {
-                continue;
-            }
-
-            if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(box c)))) =
-                &bb.statements[location.statement_index].kind
-            {
-                if let Some(local) = p.as_local() {
-                    eligible_locals.push((local, *c));
-                }
-            }
-        }
-    }
-
-    eligible_locals
-}
-
-impl Visitor<'_> for LocalUseVisitor {
-    fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
-        if context.is_mutating_use() {
-            self.local_mutating_uses[local] = self.local_mutating_uses[local].saturating_add(1);
-
-            if context.is_place_assignment() {
-                self.local_assignment_locations[local] = Some(location);
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index ade2ac0080e..84512e81637 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -1608,7 +1608,7 @@ fn check_field_tys_sized<'tcx>(
     let infcx = tcx.infer_ctxt().ignoring_regions().build();
     let param_env = tcx.param_env(def_id);
 
-    let ocx = ObligationCtxt::new(&infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     for field_ty in &coroutine_layout.field_tys {
         ocx.register_bound(
             ObligationCause::new(
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index f2f76ac70c2..743f1cc24be 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -20,37 +20,31 @@ pub(super) fn extract_refined_covspans(
     basic_coverage_blocks: &CoverageGraph,
     code_mappings: &mut impl Extend<mappings::CodeMapping>,
 ) {
-    let sorted_spans =
+    let sorted_span_buckets =
         from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks);
-    let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans);
-    code_mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| {
-        // Each span produced by the generator represents an ordinary code region.
-        mappings::CodeMapping { span, bcb }
-    }));
+    for bucket in sorted_span_buckets {
+        let refined_spans = SpansRefiner::refine_sorted_spans(bucket);
+        code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| {
+            // Each span produced by the refiner represents an ordinary code region.
+            mappings::CodeMapping { span, bcb }
+        }));
+    }
 }
 
 #[derive(Debug)]
 struct CurrCovspan {
     span: Span,
     bcb: BasicCoverageBlock,
-    is_hole: bool,
 }
 
 impl CurrCovspan {
-    fn new(span: Span, bcb: BasicCoverageBlock, is_hole: bool) -> Self {
-        Self { span, bcb, is_hole }
+    fn new(span: Span, bcb: BasicCoverageBlock) -> Self {
+        Self { span, bcb }
     }
 
     fn into_prev(self) -> PrevCovspan {
-        let Self { span, bcb, is_hole } = self;
-        PrevCovspan { span, bcb, merged_spans: vec![span], is_hole }
-    }
-
-    fn into_refined(self) -> RefinedCovspan {
-        // This is only called in cases where `curr` is a hole span that has
-        // been carved out of `prev`.
-        debug_assert!(self.is_hole);
-        self.into_prev().into_refined()
+        let Self { span, bcb } = self;
+        PrevCovspan { span, bcb, merged_spans: vec![span] }
     }
 }
 
@@ -61,12 +55,11 @@ struct PrevCovspan {
     /// List of all the original spans from MIR that have been merged into this
     /// span. Mainly used to precisely skip over gaps when truncating a span.
     merged_spans: Vec<Span>,
-    is_hole: bool,
 }
 
 impl PrevCovspan {
     fn is_mergeable(&self, other: &CurrCovspan) -> bool {
-        self.bcb == other.bcb && !self.is_hole && !other.is_hole
+        self.bcb == other.bcb
     }
 
     fn merge_from(&mut self, other: &CurrCovspan) {
@@ -84,14 +77,9 @@ impl PrevCovspan {
         if self.merged_spans.is_empty() { None } else { Some(self.into_refined()) }
     }
 
-    fn refined_copy(&self) -> RefinedCovspan {
-        let &Self { span, bcb, merged_spans: _, is_hole } = self;
-        RefinedCovspan { span, bcb, is_hole }
-    }
-
     fn into_refined(self) -> RefinedCovspan {
-        // Even though we consume self, we can just reuse the copying impl.
-        self.refined_copy()
+        let Self { span, bcb, merged_spans: _ } = self;
+        RefinedCovspan { span, bcb }
     }
 }
 
@@ -99,12 +87,11 @@ impl PrevCovspan {
 struct RefinedCovspan {
     span: Span,
     bcb: BasicCoverageBlock,
-    is_hole: bool,
 }
 
 impl RefinedCovspan {
     fn is_mergeable(&self, other: &Self) -> bool {
-        self.bcb == other.bcb && !self.is_hole && !other.is_hole
+        self.bcb == other.bcb
     }
 
     fn merge_from(&mut self, other: &Self) {
@@ -119,8 +106,6 @@ impl RefinedCovspan {
 ///  * Remove duplicate source code coverage regions
 ///  * Merge spans that represent continuous (both in source code and control flow), non-branching
 ///    execution
-///  * Carve out (leave uncovered) any "hole" spans that need to be left blank
-///    (e.g. closures that will be counted by their own MIR body)
 struct SpansRefiner {
     /// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative
     /// dominance between the `BasicCoverageBlock`s of equal `Span`s.
@@ -181,13 +166,6 @@ impl SpansRefiner {
                 );
                 let prev = self.take_prev().into_refined();
                 self.refined_spans.push(prev);
-            } else if prev.is_hole {
-                // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
-                // next iter
-                debug!(?prev, "prev (a hole) overlaps curr, so discarding curr");
-                self.take_curr(); // Discards curr.
-            } else if curr.is_hole {
-                self.carve_out_span_for_hole();
             } else {
                 self.cutoff_prev_at_overlapping_curr();
             }
@@ -211,9 +189,6 @@ impl SpansRefiner {
             }
         });
 
-        // Discard hole spans, since their purpose was to carve out chunks from
-        // other spans, but we don't want the holes themselves in the final mappings.
-        self.refined_spans.retain(|covspan| !covspan.is_hole);
         self.refined_spans
     }
 
@@ -249,50 +224,17 @@ impl SpansRefiner {
         if let Some(curr) = self.some_curr.take() {
             self.some_prev = Some(curr.into_prev());
         }
-        while let Some(curr) = self.sorted_spans_iter.next() {
-            debug!("FOR curr={:?}", curr);
-            if let Some(prev) = &self.some_prev
-                && prev.span.lo() > curr.span.lo()
-            {
-                // Skip curr because prev has already advanced beyond the end of curr.
-                // This can only happen if a prior iteration updated `prev` to skip past
-                // a region of code, such as skipping past a hole.
-                debug!(?prev, "prev.span starts after curr.span, so curr will be dropped");
-            } else {
-                self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, curr.is_hole));
-                return true;
+        if let Some(SpanFromMir { span, bcb, .. }) = self.sorted_spans_iter.next() {
+            // This code only sees sorted spans after hole-carving, so there should
+            // be no way for `curr` to start before `prev`.
+            if let Some(prev) = &self.some_prev {
+                debug_assert!(prev.span.lo() <= span.lo());
             }
-        }
-        false
-    }
-
-    /// If `prev`s span extends left of the hole (`curr`), carve out the hole's span from
-    /// `prev`'s span. Add the portion of the span to the left of the hole; and if the span
-    /// extends to the right of the hole, update `prev` to that portion of the span.
-    fn carve_out_span_for_hole(&mut self) {
-        let prev = self.prev();
-        let curr = self.curr();
-
-        let left_cutoff = curr.span.lo();
-        let right_cutoff = curr.span.hi();
-        let has_pre_hole_span = prev.span.lo() < right_cutoff;
-        let has_post_hole_span = prev.span.hi() > right_cutoff;
-
-        if has_pre_hole_span {
-            let mut pre_hole = prev.refined_copy();
-            pre_hole.span = pre_hole.span.with_hi(left_cutoff);
-            debug!(?pre_hole, "prev overlaps a hole; adding pre-hole span");
-            self.refined_spans.push(pre_hole);
-        }
-
-        if has_post_hole_span {
-            // Mutate `prev.span` to start after the hole (and discard curr).
-            self.prev_mut().span = self.prev().span.with_lo(right_cutoff);
-            debug!(prev=?self.prev(), "mutated prev to start after the hole");
-
-            // Prevent this curr from becoming prev.
-            let hole_covspan = self.take_curr().into_refined();
-            self.refined_spans.push(hole_covspan); // since self.prev() was already updated
+            self.some_curr = Some(CurrCovspan::new(span, bcb));
+            debug!(?self.some_prev, ?self.some_curr, "next_coverage_span");
+            true
+        } else {
+            false
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index d1727a94a35..b1f71035dde 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -1,3 +1,5 @@
+use std::collections::VecDeque;
+
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
@@ -17,23 +19,34 @@ use crate::coverage::ExtractedHirInfo;
 /// spans, each associated with a node in the coverage graph (BCB) and possibly
 /// other metadata.
 ///
-/// The returned spans are sorted in a specific order that is expected by the
-/// subsequent span-refinement step.
+/// The returned spans are divided into one or more buckets, such that:
+/// - The spans in each bucket are strictly after all spans in previous buckets,
+///   and strictly before all spans in subsequent buckets.
+/// - The contents of each bucket are also sorted, in a specific order that is
+///   expected by the subsequent span-refinement step.
 pub(super) fn mir_to_initial_sorted_coverage_spans(
     mir_body: &mir::Body<'_>,
     hir_info: &ExtractedHirInfo,
     basic_coverage_blocks: &CoverageGraph,
-) -> Vec<SpanFromMir> {
+) -> Vec<Vec<SpanFromMir>> {
     let &ExtractedHirInfo { body_span, .. } = hir_info;
 
     let mut initial_spans = vec![];
+    let mut holes = vec![];
 
     for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() {
-        initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data));
+        bcb_to_initial_coverage_spans(
+            mir_body,
+            body_span,
+            bcb,
+            bcb_data,
+            &mut initial_spans,
+            &mut holes,
+        );
     }
 
     // Only add the signature span if we found at least one span in the body.
-    if !initial_spans.is_empty() {
+    if !initial_spans.is_empty() || !holes.is_empty() {
         // If there is no usable signature span, add a fake one (before refinement)
         // to avoid an ugly gap between the body start and the first real span.
         // FIXME: Find a more principled way to solve this problem.
@@ -45,29 +58,82 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
     remove_unwanted_macro_spans(&mut initial_spans);
     split_visible_macro_spans(&mut initial_spans);
 
-    initial_spans.sort_by(|a, b| {
-        // First sort by span start.
-        Ord::cmp(&a.span.lo(), &b.span.lo())
-            // If span starts are the same, sort by span end in reverse order.
-            // This ensures that if spans A and B are adjacent in the list,
-            // and they overlap but are not equal, then either:
-            // - Span A extends further left, or
-            // - Both have the same start and span A extends further right
-            .then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
-            // If two spans have the same lo & hi, put hole spans first,
-            // as they take precedence over non-hole spans.
-            .then_with(|| Ord::cmp(&a.is_hole, &b.is_hole).reverse())
+    let compare_covspans = |a: &SpanFromMir, b: &SpanFromMir| {
+        compare_spans(a.span, b.span)
             // After deduplication, we want to keep only the most-dominated BCB.
             .then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
-    });
+    };
+    initial_spans.sort_by(compare_covspans);
 
-    // Among covspans with the same span, keep only one. Hole spans take
-    // precedence, otherwise keep the one with the most-dominated BCB.
+    // Among covspans with the same span, keep only one,
+    // preferring the one with the most-dominated BCB.
     // (Ideally we should try to preserve _all_ non-dominating BCBs, but that
     // requires a lot more complexity in the span refiner, for little benefit.)
     initial_spans.dedup_by(|b, a| a.span.source_equal(b.span));
 
-    initial_spans
+    // Sort the holes, and merge overlapping/adjacent holes.
+    holes.sort_by(|a, b| compare_spans(a.span, b.span));
+    holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
+
+    // Now we're ready to start carving holes out of the initial coverage spans,
+    // and grouping them in buckets separated by the holes.
+
+    let mut initial_spans = VecDeque::from(initial_spans);
+    let mut fragments: Vec<SpanFromMir> = vec![];
+
+    // For each hole:
+    // - Identify the spans that are entirely or partly before the hole.
+    // - Put those spans in a corresponding bucket, truncated to the start of the hole.
+    // - If one of those spans also extends after the hole, put the rest of it
+    //   in a "fragments" vector that is processed by the next hole.
+    let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
+    for (hole, bucket) in holes.iter().zip(&mut buckets) {
+        let fragments_from_prev = std::mem::take(&mut fragments);
+
+        // Only inspect spans that precede or overlap this hole,
+        // leaving the rest to be inspected by later holes.
+        // (This relies on the spans and holes both being sorted.)
+        let relevant_initial_spans =
+            drain_front_while(&mut initial_spans, |c| c.span.lo() < hole.span.hi());
+
+        for covspan in fragments_from_prev.into_iter().chain(relevant_initial_spans) {
+            let (before, after) = covspan.split_around_hole_span(hole.span);
+            bucket.extend(before);
+            fragments.extend(after);
+        }
+    }
+
+    // After finding the spans before each hole, any remaining fragments/spans
+    // form their own final bucket, after the final hole.
+    // (If there were no holes, this will just be all of the initial spans.)
+    fragments.extend(initial_spans);
+    buckets.push(fragments);
+
+    // Make sure each individual bucket is still internally sorted.
+    for bucket in &mut buckets {
+        bucket.sort_by(compare_covspans);
+    }
+    buckets
+}
+
+fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
+    // First sort by span start.
+    Ord::cmp(&a.lo(), &b.lo())
+        // If span starts are the same, sort by span end in reverse order.
+        // This ensures that if spans A and B are adjacent in the list,
+        // and they overlap but are not equal, then either:
+        // - Span A extends further left, or
+        // - Both have the same start and span A extends further right
+        .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
+}
+
+/// Similar to `.drain(..)`, but stops just before it would remove an item not
+/// satisfying the predicate.
+fn drain_front_while<'a, T>(
+    queue: &'a mut VecDeque<T>,
+    mut pred_fn: impl FnMut(&T) -> bool,
+) -> impl Iterator<Item = T> + Captures<'a> {
+    std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
 }
 
 /// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate
@@ -80,8 +146,8 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
 fn remove_unwanted_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
     let mut seen_macro_spans = FxHashSet::default();
     initial_spans.retain(|covspan| {
-        // Ignore (retain) hole spans and non-macro-expansion spans.
-        if covspan.is_hole || covspan.visible_macro.is_none() {
+        // Ignore (retain) non-macro-expansion spans.
+        if covspan.visible_macro.is_none() {
             return true;
         }
 
@@ -98,10 +164,6 @@ fn split_visible_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
     let mut extra_spans = vec![];
 
     initial_spans.retain(|covspan| {
-        if covspan.is_hole {
-            return true;
-        }
-
         let Some(visible_macro) = covspan.visible_macro else { return true };
 
         let split_len = visible_macro.as_str().len() as u32 + 1;
@@ -114,9 +176,8 @@ fn split_visible_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
             return true;
         }
 
-        assert!(!covspan.is_hole);
-        extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb, false));
-        extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb, false));
+        extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
+        extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
         false // Discard the original covspan that we just split.
     });
 
@@ -135,8 +196,10 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
     body_span: Span,
     bcb: BasicCoverageBlock,
     bcb_data: &'a BasicCoverageBlockData,
-) -> impl Iterator<Item = SpanFromMir> + Captures<'a> + Captures<'tcx> {
-    bcb_data.basic_blocks.iter().flat_map(move |&bb| {
+    initial_covspans: &mut Vec<SpanFromMir>,
+    holes: &mut Vec<Hole>,
+) {
+    for &bb in &bcb_data.basic_blocks {
         let data = &mir_body[bb];
 
         let unexpand = move |expn_span| {
@@ -146,24 +209,32 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
                 .filter(|(span, _)| !span.source_equal(body_span))
         };
 
-        let statement_spans = data.statements.iter().filter_map(move |statement| {
+        let mut extract_statement_span = |statement| {
             let expn_span = filtered_statement_span(statement)?;
             let (span, visible_macro) = unexpand(expn_span)?;
 
             // A statement that looks like the assignment of a closure expression
             // is treated as a "hole" span, to be carved out of other spans.
-            Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)))
-        });
+            if is_closure_like(statement) {
+                holes.push(Hole { span });
+            } else {
+                initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+            }
+            Some(())
+        };
+        for statement in data.statements.iter() {
+            extract_statement_span(statement);
+        }
 
-        let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
+        let mut extract_terminator_span = |terminator| {
             let expn_span = filtered_terminator_span(terminator)?;
             let (span, visible_macro) = unexpand(expn_span)?;
 
-            Some(SpanFromMir::new(span, visible_macro, bcb, false))
-        });
-
-        statement_spans.chain(terminator_span)
-    })
+            initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+            Some(())
+        };
+        extract_terminator_span(data.terminator());
+    }
 }
 
 fn is_closure_like(statement: &Statement<'_>) -> bool {
@@ -331,6 +402,22 @@ fn unexpand_into_body_span_with_prev(
 }
 
 #[derive(Debug)]
+struct Hole {
+    span: Span,
+}
+
+impl Hole {
+    fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
+        if !self.span.overlaps_or_adjacent(other.span) {
+            return false;
+        }
+
+        self.span = self.span.to(other.span);
+        true
+    }
+}
+
+#[derive(Debug)]
 pub(super) struct SpanFromMir {
     /// A span that has been extracted from MIR and then "un-expanded" back to
     /// within the current function's `body_span`. After various intermediate
@@ -342,23 +429,30 @@ pub(super) struct SpanFromMir {
     pub(super) span: Span,
     visible_macro: Option<Symbol>,
     pub(super) bcb: BasicCoverageBlock,
-    /// If true, this covspan represents a "hole" that should be carved out
-    /// from other spans, e.g. because it represents a closure expression that
-    /// will be instrumented separately as its own function.
-    pub(super) is_hole: bool,
 }
 
 impl SpanFromMir {
     fn for_fn_sig(fn_sig_span: Span) -> Self {
-        Self::new(fn_sig_span, None, START_BCB, false)
+        Self::new(fn_sig_span, None, START_BCB)
+    }
+
+    fn new(span: Span, visible_macro: Option<Symbol>, bcb: BasicCoverageBlock) -> Self {
+        Self { span, visible_macro, bcb }
     }
 
-    fn new(
-        span: Span,
-        visible_macro: Option<Symbol>,
-        bcb: BasicCoverageBlock,
-        is_hole: bool,
-    ) -> Self {
-        Self { span, visible_macro, bcb, is_hole }
+    /// Splits this span into 0-2 parts:
+    /// - The part that is strictly before the hole span, if any.
+    /// - The part that is strictly after the hole span, if any.
+    fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
+        let before = try {
+            let span = self.span.trim_end(hole_span)?;
+            Self { span, ..*self }
+        };
+        let after = try {
+            let span = self.span.trim_start(hole_span)?;
+            Self { span, ..*self }
+        };
+
+        (before, after)
     }
 }
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index e88b727a21e..0fd85eb345d 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -10,7 +10,7 @@ use rustc_middle::bug;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{
     Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
@@ -203,7 +203,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                     && let operand_ty = operand.ty(self.local_decls, self.tcx)
                     && let Some(operand_ty) = operand_ty.builtin_deref(true)
                     && let ty::Array(_, len) = operand_ty.kind()
-                    && let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
+                    && let Some(len) = Const::Ty(self.tcx.types.usize, *len)
+                        .try_eval_scalar_int(self.tcx, self.param_env)
                 {
                     state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
                 }
@@ -221,7 +222,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             Rvalue::Len(place) => {
                 let place_ty = place.ty(self.local_decls, self.tcx);
                 if let ty::Array(_, len) = place_ty.ty.kind() {
-                    Const::Ty(*len)
+                    Const::Ty(self.tcx.types.usize, *len)
                         .try_eval_scalar(self.tcx, self.param_env)
                         .map_or(FlatSet::Top, FlatSet::Elem)
                 } else if let [ProjectionElem::Deref] = place.projection[..] {
@@ -284,9 +285,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 let val = match null_op {
                     NullOp::SizeOf if layout.is_sized() => layout.size.bytes(),
                     NullOp::AlignOf if layout.is_sized() => layout.align.abi.bytes(),
-                    NullOp::OffsetOf(fields) => {
-                        layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
-                    }
+                    NullOp::OffsetOf(fields) => self
+                        .ecx
+                        .tcx
+                        .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+                        .bytes(),
                     _ => return ValueOrPlace::Value(FlatSet::Top),
                 };
                 FlatSet::Elem(Scalar::from_target_usize(val, &self.tcx))
@@ -323,7 +326,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             // This allows the set of visited edges to grow monotonically with the lattice.
             FlatSet::Bottom => TerminatorEdges::None,
             FlatSet::Elem(scalar) => {
-                let choice = scalar.assert_bits(scalar.size());
+                let choice = scalar.assert_scalar_int().to_bits_unchecked();
                 TerminatorEdges::Single(targets.target_for_value(choice))
             }
             FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets },
@@ -606,7 +609,7 @@ fn propagatable_scalar(
     map: &Map,
 ) -> Option<Scalar> {
     if let FlatSet::Elem(value) = state.get_idx(place, map)
-        && value.try_to_int().is_ok()
+        && value.try_to_scalar_int().is_ok()
     {
         // Do not attempt to propagate pointers, as we may fail to preserve their identity.
         Some(value)
@@ -667,7 +670,7 @@ fn try_write_constant<'tcx>(
                 let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else {
                     throw_machine_stop_str!("discriminant with provenance")
                 };
-                let discr_bits = discr.assert_bits(discr.size());
+                let discr_bits = discr.to_bits(discr.size());
                 let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else {
                     throw_machine_stop_str!("illegal discriminant for enum")
                 };
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 13841be494c..3b71cf02c1a 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -28,6 +28,9 @@ pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
         OutFileName::Real(path) => {
             let mut f = io::BufWriter::new(File::create(&path)?);
             write_mir_pretty(tcx, None, &mut f)?;
+            if tcx.sess.opts.json_artifact_notifications {
+                tcx.dcx().emit_artifact_notification(&path, "mir");
+            }
         }
     }
     Ok(())
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 03d952abad1..665b2260294 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -34,14 +34,14 @@ use std::fmt;
 ///
 /// ```text
 // fn drop_term<T>(t: &mut T) {
-//     mir!(
+//     mir! {
 //         {
 //             Drop(*t, exit)
 //         }
 //         exit = {
 //             Return()
 //         }
-//     )
+//     }
 // }
 /// ```
 pub struct ElaborateDrops;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index fadb5edefdf..121a3b99a39 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -83,8 +83,8 @@
 //! that contain `AllocId`s.
 
 use rustc_const_eval::const_eval::DummyMachine;
-use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind};
-use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar};
+use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemPlaceMeta, MemoryKind};
+use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable, Scalar};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_hir::def::DefKind;
@@ -95,11 +95,11 @@ use rustc_middle::bug;
 use rustc_middle::mir::interpret::GlobalAlloc;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
-use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::DUMMY_SP;
-use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{self, Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
 use smallvec::SmallVec;
 use std::borrow::Cow;
 
@@ -177,6 +177,12 @@ enum AggregateTy<'tcx> {
     Array,
     Tuple,
     Def(DefId, ty::GenericArgsRef<'tcx>),
+    RawPtr {
+        /// Needed for cast propagation.
+        data_pointer_ty: Ty<'tcx>,
+        /// The data pointer can be anything thin, so doesn't determine the output.
+        output_pointer_ty: Ty<'tcx>,
+    },
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -223,7 +229,6 @@ enum Value<'tcx> {
     NullaryOp(NullOp<'tcx>, Ty<'tcx>),
     UnaryOp(UnOp, VnIndex),
     BinaryOp(BinOp, VnIndex, VnIndex),
-    CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead
     Cast {
         kind: CastKind,
         value: VnIndex,
@@ -386,11 +391,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     AggregateTy::Def(def_id, args) => {
                         self.tcx.type_of(def_id).instantiate(self.tcx, args)
                     }
+                    AggregateTy::RawPtr { output_pointer_ty, .. } => output_pointer_ty,
                 };
                 let variant = if ty.is_enum() { Some(variant) } else { None };
                 let ty = self.ecx.layout_of(ty).ok()?;
                 if ty.is_zst() {
                     ImmTy::uninit(ty).into()
+                } else if matches!(kind, AggregateTy::RawPtr { .. }) {
+                    // Pointers don't have fields, so don't `project_field` them.
+                    let data = self.ecx.read_pointer(fields[0]).ok()?;
+                    let meta = if fields[1].layout.is_zst() {
+                        MemPlaceMeta::None
+                    } else {
+                        MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).ok()?)
+                    };
+                    let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx);
+                    ImmTy::from_immediate(ptr_imm, ty).into()
                 } else if matches!(ty.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
                     let dest = self.ecx.allocate(ty, MemoryKind::Stack).ok()?;
                     let variant_dest = if let Some(variant) = variant {
@@ -472,7 +488,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let slice = self.evaluated[slice].as_ref()?;
                 let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
                 let len = slice.len(&self.ecx).ok()?;
-                let imm = ImmTy::try_from_uint(len, usize_layout)?;
+                let imm = ImmTy::from_uint(len, usize_layout);
                 imm.into()
             }
             NullaryOp(null_op, ty) => {
@@ -485,13 +501,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let val = match null_op {
                     NullOp::SizeOf => layout.size.bytes(),
                     NullOp::AlignOf => layout.align.abi.bytes(),
-                    NullOp::OffsetOf(fields) => {
-                        layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
-                    }
+                    NullOp::OffsetOf(fields) => self
+                        .ecx
+                        .tcx
+                        .offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
+                        .bytes(),
                     NullOp::UbChecks => return None,
                 };
                 let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
-                let imm = ImmTy::try_from_uint(val, usize_layout)?;
+                let imm = ImmTy::from_uint(val, usize_layout);
                 imm.into()
             }
             UnaryOp(un_op, operand) => {
@@ -508,17 +526,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
                 val.into()
             }
-            CheckedBinaryOp(bin_op, lhs, rhs) => {
-                let lhs = self.evaluated[lhs].as_ref()?;
-                let lhs = self.ecx.read_immediate(lhs).ok()?;
-                let rhs = self.evaluated[rhs].as_ref()?;
-                let rhs = self.ecx.read_immediate(rhs).ok()?;
-                let val = self
-                    .ecx
-                    .binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs)
-                    .ok()?;
-                val.into()
-            }
             Cast { kind, value, from: _, to } => match kind {
                 CastKind::IntToInt | CastKind::IntToFloat => {
                     let value = self.evaluated[value].as_ref()?;
@@ -829,17 +836,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let lhs = lhs?;
                 let rhs = rhs?;
 
-                if let Some(op) = op.overflowing_to_wrapping() {
-                    if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
-                        return Some(value);
-                    }
-                    Value::CheckedBinaryOp(op, lhs, rhs)
-                } else {
-                    if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
-                        return Some(value);
-                    }
-                    Value::BinaryOp(op, lhs, rhs)
+                if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) {
+                    return Some(value);
                 }
+                Value::BinaryOp(op, lhs, rhs)
             }
             Rvalue::UnaryOp(op, ref mut arg) => {
                 let arg = self.simplify_operand(arg, location)?;
@@ -881,10 +881,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         rvalue: &mut Rvalue<'tcx>,
         location: Location,
     ) -> Option<VnIndex> {
-        let Rvalue::Aggregate(box ref kind, ref mut fields) = *rvalue else { bug!() };
+        let Rvalue::Aggregate(box ref kind, ref mut field_ops) = *rvalue else { bug!() };
 
         let tcx = self.tcx;
-        if fields.is_empty() {
+        if field_ops.is_empty() {
             let is_zst = match *kind {
                 AggregateKind::Array(..)
                 | AggregateKind::Tuple
@@ -903,13 +903,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
         }
 
-        let (ty, variant_index) = match *kind {
+        let (mut ty, variant_index) = match *kind {
             AggregateKind::Array(..) => {
-                assert!(!fields.is_empty());
+                assert!(!field_ops.is_empty());
                 (AggregateTy::Array, FIRST_VARIANT)
             }
             AggregateKind::Tuple => {
-                assert!(!fields.is_empty());
+                assert!(!field_ops.is_empty());
                 (AggregateTy::Tuple, FIRST_VARIANT)
             }
             AggregateKind::Closure(did, args)
@@ -920,15 +920,49 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
             // Do not track unions.
             AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
-            // FIXME: Do the extra work to GVN `from_raw_parts`
-            AggregateKind::RawPtr(..) => return None,
+            AggregateKind::RawPtr(pointee_ty, mtbl) => {
+                assert_eq!(field_ops.len(), 2);
+                let data_pointer_ty = field_ops[FieldIdx::ZERO].ty(self.local_decls, self.tcx);
+                let output_pointer_ty = Ty::new_ptr(self.tcx, pointee_ty, mtbl);
+                (AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty }, FIRST_VARIANT)
+            }
         };
 
-        let fields: Option<Vec<_>> = fields
+        let fields: Option<Vec<_>> = field_ops
             .iter_mut()
             .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
             .collect();
-        let fields = fields?;
+        let mut fields = fields?;
+
+        if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty {
+            let mut was_updated = false;
+
+            // Any thin pointer of matching mutability is fine as the data pointer.
+            while let Value::Cast {
+                kind: CastKind::PtrToPtr,
+                value: cast_value,
+                from: cast_from,
+                to: _,
+            } = self.get(fields[0])
+                && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind()
+                && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind()
+                && from_mtbl == output_mtbl
+                && from_pointee_ty.is_sized(self.tcx, self.param_env)
+            {
+                fields[0] = *cast_value;
+                *data_pointer_ty = *cast_from;
+                was_updated = true;
+            }
+
+            if was_updated {
+                if let Some(const_) = self.try_as_constant(fields[0]) {
+                    field_ops[FieldIdx::ZERO] = Operand::Constant(Box::new(const_));
+                } else if let Some(local) = self.try_as_local(fields[0], location) {
+                    field_ops[FieldIdx::ZERO] = Operand::Copy(Place::from(local));
+                    self.reused_locals.insert(local);
+                }
+            }
+        }
 
         if let AggregateTy::Array = ty
             && fields.len() > 4
@@ -960,6 +994,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
                 Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
             }
+            (UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
+                return Some(fields[1]);
+            }
             _ => return None,
         };
 
@@ -970,7 +1007,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
     fn simplify_binary(
         &mut self,
         op: BinOp,
-        checked: bool,
         lhs_ty: Ty<'tcx>,
         lhs: VnIndex,
         rhs: VnIndex,
@@ -999,22 +1035,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         use Either::{Left, Right};
         let a = as_bits(lhs).map_or(Right(lhs), Left);
         let b = as_bits(rhs).map_or(Right(rhs), Left);
+
         let result = match (op, a, b) {
             // Neutral elements.
-            (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p))
+            (
+                BinOp::Add
+                | BinOp::AddWithOverflow
+                | BinOp::AddUnchecked
+                | BinOp::BitOr
+                | BinOp::BitXor,
+                Left(0),
+                Right(p),
+            )
             | (
                 BinOp::Add
+                | BinOp::AddWithOverflow
+                | BinOp::AddUnchecked
                 | BinOp::BitOr
                 | BinOp::BitXor
                 | BinOp::Sub
+                | BinOp::SubWithOverflow
+                | BinOp::SubUnchecked
                 | BinOp::Offset
                 | BinOp::Shl
                 | BinOp::Shr,
                 Right(p),
                 Left(0),
             )
-            | (BinOp::Mul, Left(1), Right(p))
-            | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p,
+            | (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p))
+            | (
+                BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::Div,
+                Right(p),
+                Left(1),
+            ) => p,
             // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size.
             (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p))
                 if ones == layout.size.truncate(u128::MAX)
@@ -1023,10 +1076,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 p
             }
             // Absorbing elements.
-            (BinOp::Mul | BinOp::BitAnd, _, Left(0))
+            (
+                BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd,
+                _,
+                Left(0),
+            )
             | (BinOp::Rem, _, Left(1))
             | (
-                BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr,
+                BinOp::Mul
+                | BinOp::MulWithOverflow
+                | BinOp::MulUnchecked
+                | BinOp::Div
+                | BinOp::Rem
+                | BinOp::BitAnd
+                | BinOp::Shl
+                | BinOp::Shr,
                 Left(0),
                 _,
             ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty),
@@ -1038,7 +1102,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty)
             }
             // Sub/Xor with itself.
-            (BinOp::Sub | BinOp::BitXor, a, b) if a == b => {
+            (BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b)
+                if a == b =>
+            {
                 self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty)
             }
             // Comparison:
@@ -1052,7 +1118,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             _ => return None,
         };
 
-        if checked {
+        if op.is_overflowing() {
             let false_val = self.insert_bool(false);
             Some(self.insert_tuple(vec![result, false_val]))
         } else {
@@ -1082,6 +1148,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             return self.new_opaque();
         }
 
+        let mut was_updated = false;
+
+        // If that cast just casts away the metadata again,
+        if let PtrToPtr = kind
+            && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
+                self.get(value)
+            && let ty::RawPtr(to_pointee, _) = to.kind()
+            && to_pointee.is_sized(self.tcx, self.param_env)
+        {
+            from = *data_pointer_ty;
+            value = fields[0];
+            was_updated = true;
+            if *data_pointer_ty == to {
+                return Some(fields[0]);
+            }
+        }
+
         if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
             && let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
                 *self.get(value)
@@ -1090,9 +1173,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             from = inner_from;
             value = inner_value;
             *kind = PtrToPtr;
+            was_updated = true;
             if inner_from == to {
                 return Some(inner_value);
             }
+        }
+
+        if was_updated {
             if let Some(const_) = self.try_as_constant(value) {
                 *operand = Operand::Constant(Box::new(const_));
             } else if let Some(local) = self.try_as_local(value, location) {
@@ -1108,7 +1195,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         // Trivial case: we are fetching a statically known length.
         let place_ty = place.ty(self.local_decls, self.tcx).ty;
         if let ty::Array(_, len) = place_ty.kind() {
-            return self.insert_constant(Const::from_ty_const(*len, self.tcx));
+            return self.insert_constant(Const::from_ty_const(
+                *len,
+                self.tcx.types.usize,
+                self.tcx,
+            ));
         }
 
         let mut inner = self.simplify_place_value(place, location)?;
@@ -1130,7 +1221,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             && let Some(to) = to.builtin_deref(true)
             && let ty::Slice(..) = to.kind()
         {
-            return self.insert_constant(Const::from_ty_const(*len, self.tcx));
+            return self.insert_constant(Const::from_ty_const(
+                *len,
+                self.tcx.types.usize,
+                self.tcx,
+            ));
         }
 
         // Fallback: a symbolic `Len`.
@@ -1160,7 +1255,7 @@ fn op_to_prop_const<'tcx>(
     // If this constant has scalar ABI, return it as a `ConstValue::Scalar`.
     if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi
         && let Ok(scalar) = ecx.read_scalar(op)
-        && scalar.try_to_int().is_ok()
+        && scalar.try_to_scalar_int().is_ok()
     {
         return Some(ConstValue::Scalar(scalar));
     }
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 40db3e38fd3..6806c517c17 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -150,7 +150,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
                     return;
                 }
 
-                let const_ = Const::from_ty_const(len, self.tcx);
+                let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx);
                 let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
                 *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
             }
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 8b46658b322..6a20b46e7f9 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -356,15 +356,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 debug!("check_binary_op: reporting assert for {:?}", location);
                 let panic = AssertKind::Overflow(
                     op,
-                    match l {
-                        Some(l) => l.to_const_int(),
-                        // Invent a dummy value, the diagnostic ignores it anyway
-                        None => ConstInt::new(
-                            ScalarInt::try_from_uint(1_u8, left_size).unwrap(),
-                            left_ty.is_signed(),
-                            left_ty.is_ptr_sized_integral(),
-                        ),
-                    },
+                    // Invent a dummy value, the diagnostic ignores it anyway
+                    ConstInt::new(
+                        ScalarInt::try_from_uint(1_u8, left_size).unwrap(),
+                        left_ty.is_signed(),
+                        left_ty.is_ptr_sized_integral(),
+                    ),
                     r.to_const_int(),
                 );
                 self.report_assert_as_lint(location, AssertLintKind::ArithmeticOverflow, panic);
@@ -625,9 +622,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 let val = match null_op {
                     NullOp::SizeOf => op_layout.size.bytes(),
                     NullOp::AlignOf => op_layout.align.abi.bytes(),
-                    NullOp::OffsetOf(fields) => {
-                        op_layout.offset_of_subfield(self, fields.iter()).bytes()
-                    }
+                    NullOp::OffsetOf(fields) => self
+                        .tcx
+                        .offset_of_subfield(self.param_env, op_layout, fields.iter())
+                        .bytes(),
                     NullOp::UbChecks => return None,
                 };
                 ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into()
@@ -786,8 +784,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             TerminatorKind::SwitchInt { ref discr, ref targets } => {
                 if let Some(ref value) = self.eval_operand(discr)
                     && let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value))
-                    && let Ok(constant) = value_const.try_to_int()
-                    && let Ok(constant) = constant.try_to_bits(constant.size())
+                    && let Ok(constant) = value_const.to_bits(value_const.size())
                 {
                     // We managed to evaluate the discriminant, so we know we only need to visit
                     // one target.
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index a8741254ffb..551760f4703 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -55,7 +55,6 @@ mod remove_place_mention;
 // This pass is public to allow external drivers to perform MIR cleanup
 mod add_subtyping_projections;
 pub mod cleanup_post_borrowck;
-mod const_debuginfo;
 mod copy_prop;
 mod coroutine;
 mod cost_checker;
@@ -106,6 +105,7 @@ mod check_alignment;
 pub mod simplify;
 mod simplify_branches;
 mod simplify_comparison_integral;
+mod single_use_consts;
 mod sroa;
 mod unreachable_enum_branching;
 mod unreachable_prop;
@@ -211,7 +211,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
 }
 
 fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    tcx.hir().maybe_body_owned_by(def_id).is_some()
+    tcx.mir_keys(()).contains(&def_id)
 }
 
 /// Finds the full set of `DefId`s within the current crate that have
@@ -222,16 +222,6 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
     // All body-owners have MIR associated with them.
     set.extend(tcx.hir().body_owners());
 
-    // Inline consts' bodies are created in
-    // typeck instead of during ast lowering, like all other bodies so far.
-    for def_id in tcx.hir().body_owners() {
-        // Incremental performance optimization: only load typeck results for things that actually have inline consts
-        if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).id().hir_id.owner).has_inline_consts
-        {
-            set.extend(tcx.typeck(def_id).inline_consts.values())
-        }
-    }
-
     // Additionally, tuple struct/variant constructors have MIR, but
     // they don't have a BodyId, so we need to build them separately.
     struct GatherCtors<'a> {
@@ -603,7 +593,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &gvn::GVN,
             &simplify::SimplifyLocals::AfterGVN,
             &dataflow_const_prop::DataflowConstProp,
-            &const_debuginfo::ConstDebugInfo,
+            &single_use_consts::SingleUseConsts,
             &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
             &jump_threading::JumpThreading,
             &early_otherwise_branch::EarlyOtherwiseBranch,
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 1411d9be223..6ab4ec6fe7e 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -372,7 +372,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
         }
 
         fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
-            l.assert_int(l.size()) == ScalarInt::try_from_uint(r, size).unwrap().assert_int(size)
+            l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked()
         }
 
         // We first compare the two branches, and then the other branches need to fulfill the same conditions.
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index 2070895c900..d5e72706661 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -95,7 +95,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
             *rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
                 span: rustc_span::DUMMY_SP,
                 user_ty: None,
-                const_: Const::from_ty_const(len, self.tcx),
+                const_: Const::from_ty_const(len, self.tcx.types.usize, self.tcx),
             })));
         }
         self.super_rvalue(rvalue, loc);
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 7ec59cc983f..ecd1179ca99 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -500,14 +500,14 @@ impl<'tcx> Validator<'_, 'tcx> {
                                 }
                                 _ => None,
                             };
-                            match rhs_val.map(|x| x.assert_uint(sz)) {
+                            match rhs_val.map(|x| x.to_uint(sz)) {
                                 // for the zero test, int vs uint does not matter
                                 Some(x) if x != 0 => {}        // okay
                                 _ => return Err(Unpromotable), // value not known or 0 -- not okay
                             }
                             // Furthermore, for signed divison, we also have to exclude `int::MIN / -1`.
                             if lhs_ty.is_signed() {
-                                match rhs_val.map(|x| x.assert_int(sz)) {
+                                match rhs_val.map(|x| x.to_int(sz)) {
                                     Some(-1) | None => {
                                         // The RHS is -1 or unknown, so we have to be careful.
                                         // But is the LHS int::MIN?
@@ -518,7 +518,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                                             _ => None,
                                         };
                                         let lhs_min = sz.signed_int_min();
-                                        match lhs_val.map(|x| x.assert_int(sz)) {
+                                        match lhs_val.map(|x| x.to_int(sz)) {
                                             Some(x) if x != lhs_min => {}  // okay
                                             _ => return Err(Unpromotable), // value not known or int::MIN -- not okay
                                         }
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 03907babf2b..e174cccdad6 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -49,7 +49,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
                     let layout = tcx
                         .layout_of(param_env.and(opt.branch_value_ty))
                         .expect("if we have an evaluated constant we must know the layout");
-                    int.assert_bits(layout.size)
+                    int.to_bits(layout.size)
                 }
                 Scalar::Ptr(..) => continue,
             };
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
new file mode 100644
index 00000000000..93736e55996
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -0,0 +1,199 @@
+use rustc_index::{bit_set::BitSet, IndexVec};
+use rustc_middle::bug;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+/// Various parts of MIR building introduce temporaries that are commonly not needed.
+///
+/// Notably, `if CONST` and `match CONST` end up being used-once temporaries, which
+/// obfuscates the structure for other passes and codegen, which would like to always
+/// be able to just see the constant directly.
+///
+/// At higher optimization levels fancier passes like GVN will take care of this
+/// in a more general fashion, but this handles the easy cases so can run in debug.
+///
+/// This only removes constants with a single-use because re-evaluating constants
+/// isn't always an improvement, especially for large ones.
+///
+/// It also removes *never*-used constants, since it had all the information
+/// needed to do that too, including updating the debug info.
+pub struct SingleUseConsts;
+
+impl<'tcx> MirPass<'tcx> for SingleUseConsts {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() > 0
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        let mut finder = SingleUseConstsFinder {
+            ineligible_locals: BitSet::new_empty(body.local_decls.len()),
+            locations: IndexVec::from_elem(LocationPair::new(), &body.local_decls),
+            locals_in_debug_info: BitSet::new_empty(body.local_decls.len()),
+        };
+
+        finder.ineligible_locals.insert_range(..=Local::from_usize(body.arg_count));
+
+        finder.visit_body(body);
+
+        for (local, locations) in finder.locations.iter_enumerated() {
+            if finder.ineligible_locals.contains(local) {
+                continue;
+            }
+
+            let Some(init_loc) = locations.init_loc else {
+                continue;
+            };
+
+            // We're only changing an operand, not the terminator kinds or successors
+            let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
+            let init_statement =
+                basic_blocks[init_loc.block].statements[init_loc.statement_index].replace_nop();
+            let StatementKind::Assign(place_and_rvalue) = init_statement.kind else {
+                bug!("No longer an assign?");
+            };
+            let (place, rvalue) = *place_and_rvalue;
+            assert_eq!(place.as_local(), Some(local));
+            let Rvalue::Use(operand) = rvalue else { bug!("No longer a use?") };
+
+            let mut replacer = LocalReplacer { tcx, local, operand: Some(operand) };
+
+            if finder.locals_in_debug_info.contains(local) {
+                for var_debug_info in &mut body.var_debug_info {
+                    replacer.visit_var_debug_info(var_debug_info);
+                }
+            }
+
+            let Some(use_loc) = locations.use_loc else { continue };
+
+            let use_block = &mut basic_blocks[use_loc.block];
+            if let Some(use_statement) = use_block.statements.get_mut(use_loc.statement_index) {
+                replacer.visit_statement(use_statement, use_loc);
+            } else {
+                replacer.visit_terminator(use_block.terminator_mut(), use_loc);
+            }
+
+            if replacer.operand.is_some() {
+                bug!(
+                    "operand wasn't used replacing local {local:?} with locations {locations:?} in body {body:#?}"
+                );
+            }
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+struct LocationPair {
+    init_loc: Option<Location>,
+    use_loc: Option<Location>,
+}
+
+impl LocationPair {
+    fn new() -> Self {
+        Self { init_loc: None, use_loc: None }
+    }
+}
+
+struct SingleUseConstsFinder {
+    ineligible_locals: BitSet<Local>,
+    locations: IndexVec<Local, LocationPair>,
+    locals_in_debug_info: BitSet<Local>,
+}
+
+impl<'tcx> Visitor<'tcx> for SingleUseConstsFinder {
+    fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+        if let Some(local) = place.as_local()
+            && let Rvalue::Use(operand) = rvalue
+            && let Operand::Constant(_) = operand
+        {
+            let locations = &mut self.locations[local];
+            if locations.init_loc.is_some() {
+                self.ineligible_locals.insert(local);
+            } else {
+                locations.init_loc = Some(location);
+            }
+        } else {
+            self.super_assign(place, rvalue, location);
+        }
+    }
+
+    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
+        if let Some(place) = operand.place()
+            && let Some(local) = place.as_local()
+        {
+            let locations = &mut self.locations[local];
+            if locations.use_loc.is_some() {
+                self.ineligible_locals.insert(local);
+            } else {
+                locations.use_loc = Some(location);
+            }
+        } else {
+            self.super_operand(operand, location);
+        }
+    }
+
+    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
+        match &statement.kind {
+            // Storage markers are irrelevant to this.
+            StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {}
+            _ => self.super_statement(statement, location),
+        }
+    }
+
+    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
+        if let VarDebugInfoContents::Place(place) = &var_debug_info.value
+            && let Some(local) = place.as_local()
+        {
+            self.locals_in_debug_info.insert(local);
+        } else {
+            self.super_var_debug_info(var_debug_info);
+        }
+    }
+
+    fn visit_local(&mut self, local: Local, _context: PlaceContext, _location: Location) {
+        // If there's any path that gets here, rather than being understood elsewhere,
+        // then we'd better not do anything with this local.
+        self.ineligible_locals.insert(local);
+    }
+}
+
+struct LocalReplacer<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    local: Local,
+    operand: Option<Operand<'tcx>>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for LocalReplacer<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _location: Location) {
+        if let Operand::Copy(place) | Operand::Move(place) = operand
+            && let Some(local) = place.as_local()
+            && local == self.local
+        {
+            *operand = self.operand.take().unwrap_or_else(|| {
+                bug!("there was a second use of the operand");
+            });
+        }
+    }
+
+    fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
+        if let VarDebugInfoContents::Place(place) = &var_debug_info.value
+            && let Some(local) = place.as_local()
+            && local == self.local
+        {
+            let const_op = self
+                .operand
+                .as_ref()
+                .unwrap_or_else(|| {
+                    bug!("the operand was already stolen");
+                })
+                .constant()
+                .unwrap()
+                .clone();
+            var_debug_info.value = VarDebugInfoContents::Const(const_op);
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 3b4d4c93877..586c1254995 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -5,12 +5,12 @@ use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_infer::traits::Reveal;
 use rustc_middle::mir::coverage::CoverageKind;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{
-    self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance,
+    self, CoroutineArgsExt, InstanceDef, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
+    Variance,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{Size, FIRST_VARIANT};
@@ -1478,7 +1478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 });
 
                 for (value, _) in targets.iter() {
-                    if Scalar::<()>::try_from_uint(value, size).is_none() {
+                    if ScalarInt::try_from_uint(value, size).is_none() {
                         self.fail(
                             location,
                             format!("the value {value:#x} is not a proper {switch_ty:?}"),
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 9487692662b..61680dbfaf5 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -207,8 +207,8 @@
 
 mod move_check;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_for_each_in, LRef, MTLock};
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@@ -251,10 +251,10 @@ pub enum MonoItemCollectionStrategy {
 
 pub struct UsageMap<'tcx> {
     // Maps every mono item to the mono items used by it.
-    used_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
+    used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
 
     // Maps every mono item to the mono items that use it.
-    user_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
+    user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
 }
 
 type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
@@ -262,10 +262,10 @@ type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
 /// The state that is shared across the concurrent threads that are doing collection.
 struct SharedState<'tcx> {
     /// Items that have been or are currently being recursively collected.
-    visited: MTLock<FxHashSet<MonoItem<'tcx>>>,
+    visited: MTLock<UnordSet<MonoItem<'tcx>>>,
     /// Items that have been or are currently being recursively treated as "mentioned", i.e., their
     /// consts are evaluated but nothing is added to the collection.
-    mentioned: MTLock<FxHashSet<MonoItem<'tcx>>>,
+    mentioned: MTLock<UnordSet<MonoItem<'tcx>>>,
     /// Which items are being used where, for better errors.
     usage_map: MTLock<UsageMap<'tcx>>,
 }
@@ -290,7 +290,7 @@ enum CollectionMode {
 
 impl<'tcx> UsageMap<'tcx> {
     fn new() -> UsageMap<'tcx> {
-        UsageMap { used_map: FxHashMap::default(), user_map: FxHashMap::default() }
+        UsageMap { used_map: Default::default(), user_map: Default::default() }
     }
 
     fn record_used<'a>(
@@ -668,7 +668,7 @@ struct MirUsedCollector<'a, 'tcx> {
     used_items: &'a mut MonoItems<'tcx>,
     /// See the comment in `collect_items_of_instance` for the purpose of this set.
     /// Note that this contains *not-monomorphized* items!
-    used_mentioned_items: &'a mut FxHashSet<MentionedItem<'tcx>>,
+    used_mentioned_items: &'a mut UnordSet<MentionedItem<'tcx>>,
     instance: Instance<'tcx>,
     visiting_call_terminator: bool,
     move_check: move_check::MoveCheckState,
@@ -1272,7 +1272,7 @@ fn collect_items_of_instance<'tcx>(
     // mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
     // added to `used_items` in a hash set, which can efficiently query in the
     // `body.mentioned_items` loop below without even having to monomorphize the item.
-    let mut used_mentioned_items = FxHashSet::<MentionedItem<'tcx>>::default();
+    let mut used_mentioned_items = Default::default();
     let mut collector = MirUsedCollector {
         tcx,
         body,
@@ -1628,10 +1628,10 @@ fn create_mono_items_for_default_impls<'tcx>(
 //=-----------------------------------------------------------------------------
 
 #[instrument(skip(tcx, strategy), level = "debug")]
-pub fn collect_crate_mono_items(
-    tcx: TyCtxt<'_>,
+pub(crate) fn collect_crate_mono_items<'tcx>(
+    tcx: TyCtxt<'tcx>,
     strategy: MonoItemCollectionStrategy,
-) -> (FxHashSet<MonoItem<'_>>, UsageMap<'_>) {
+) -> (Vec<MonoItem<'tcx>>, UsageMap<'tcx>) {
     let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
 
     let roots = tcx
@@ -1641,8 +1641,8 @@ pub fn collect_crate_mono_items(
     debug!("building mono item graph, beginning at roots");
 
     let mut state = SharedState {
-        visited: MTLock::new(FxHashSet::default()),
-        mentioned: MTLock::new(FxHashSet::default()),
+        visited: MTLock::new(UnordSet::default()),
+        mentioned: MTLock::new(UnordSet::default()),
         usage_map: MTLock::new(UsageMap::new()),
     };
     let recursion_limit = tcx.recursion_limit();
@@ -1665,5 +1665,11 @@ pub fn collect_crate_mono_items(
         });
     }
 
-    (state.visited.into_inner(), state.usage_map.into_inner())
+    // The set of MonoItems was created in an inherently indeterministic order because
+    // of parallelism. We sort it here to ensure that the output is deterministic.
+    let mono_items = tcx.with_stable_hashing_context(move |ref hcx| {
+        state.visited.into_inner().into_sorted(hcx, true)
+    });
+
+    (mono_items, state.usage_map.into_inner())
 }
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index b298fe5813f..eb5f8d92603 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,6 +1,5 @@
 #![feature(array_windows)]
 #![feature(is_sorted)]
-#![allow(rustc::potential_query_instability)]
 
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 21d52004728..336341f4e74 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -98,8 +98,9 @@ use std::fs::{self, File};
 use std::io::{BufWriter, Write};
 use std::path::{Path, PathBuf};
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::sync;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathDataName;
@@ -131,7 +132,7 @@ struct PlacedMonoItems<'tcx> {
     /// The codegen units, sorted by name to make things deterministic.
     codegen_units: Vec<CodegenUnit<'tcx>>,
 
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+    internalization_candidates: UnordSet<MonoItem<'tcx>>,
 }
 
 // The output CGUs are sorted by name.
@@ -197,9 +198,9 @@ fn place_mono_items<'tcx, I>(cx: &PartitioningCx<'_, 'tcx>, mono_items: I) -> Pl
 where
     I: Iterator<Item = MonoItem<'tcx>>,
 {
-    let mut codegen_units = FxHashMap::default();
+    let mut codegen_units = UnordMap::default();
     let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
-    let mut internalization_candidates = FxHashSet::default();
+    let mut internalization_candidates = UnordSet::default();
 
     // Determine if monomorphizations instantiated in this crate will be made
     // available to downstream crates. This depends on whether we are in
@@ -209,7 +210,7 @@ where
         cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
 
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-    let cgu_name_cache = &mut FxHashMap::default();
+    let cgu_name_cache = &mut UnordMap::default();
 
     for mono_item in mono_items {
         // Handle only root (GloballyShared) items directly here. Inlined (LocalCopy) items
@@ -260,7 +261,7 @@ where
         // going via another root item. This includes drop-glue, functions from
         // external crates, and local functions the definition of which is
         // marked with `#[inline]`.
-        let mut reachable_inlined_items = FxHashSet::default();
+        let mut reachable_inlined_items = FxIndexSet::default();
         get_reachable_inlined_items(cx.tcx, mono_item, cx.usage_map, &mut reachable_inlined_items);
 
         // Add those inlined items. It's possible an inlined item is reachable
@@ -284,8 +285,9 @@ where
         codegen_units.insert(cgu_name, CodegenUnit::new(cgu_name));
     }
 
-    let mut codegen_units: Vec<_> = codegen_units.into_values().collect();
-    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+    let mut codegen_units: Vec<_> = cx.tcx.with_stable_hashing_context(|ref hcx| {
+        codegen_units.into_items().map(|(_, cgu)| cgu).collect_sorted(hcx, true)
+    });
 
     for cgu in codegen_units.iter_mut() {
         cgu.compute_size_estimate();
@@ -297,7 +299,7 @@ where
         tcx: TyCtxt<'tcx>,
         item: MonoItem<'tcx>,
         usage_map: &UsageMap<'tcx>,
-        visited: &mut FxHashSet<MonoItem<'tcx>>,
+        visited: &mut FxIndexSet<MonoItem<'tcx>>,
     ) {
         usage_map.for_each_inlined_used_item(tcx, item, |inlined_item| {
             let is_new = visited.insert(inlined_item);
@@ -320,7 +322,7 @@ fn merge_codegen_units<'tcx>(
     assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()));
 
     // This map keeps track of what got merged into what.
-    let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
+    let mut cgu_contents: UnordMap<Symbol, Vec<Symbol>> =
         codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
 
     // If N is the maximum number of CGUs, and the CGUs are sorted from largest
@@ -422,22 +424,24 @@ fn merge_codegen_units<'tcx>(
         // For CGUs that contain the code of multiple modules because of the
         // merging done above, we use a concatenation of the names of all
         // contained CGUs.
-        let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
-            .into_iter()
-            // This `filter` makes sure we only update the name of CGUs that
-            // were actually modified by merging.
-            .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
-            .map(|(current_cgu_name, cgu_contents)| {
-                let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
-
-                // Sort the names, so things are deterministic and easy to
-                // predict. We are sorting primitive `&str`s here so we can
-                // use unstable sort.
-                cgu_contents.sort_unstable();
-
-                (current_cgu_name, cgu_contents.join("--"))
-            })
-            .collect();
+        let new_cgu_names = UnordMap::from(
+            cgu_contents
+                .items()
+                // This `filter` makes sure we only update the name of CGUs that
+                // were actually modified by merging.
+                .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+                .map(|(current_cgu_name, cgu_contents)| {
+                    let mut cgu_contents: Vec<&str> =
+                        cgu_contents.iter().map(|s| s.as_str()).collect();
+
+                    // Sort the names, so things are deterministic and easy to
+                    // predict. We are sorting primitive `&str`s here so we can
+                    // use unstable sort.
+                    cgu_contents.sort_unstable();
+
+                    (*current_cgu_name, cgu_contents.join("--"))
+                }),
+        );
 
         for cgu in codegen_units.iter_mut() {
             if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
@@ -511,7 +515,7 @@ fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'t
 fn internalize_symbols<'tcx>(
     cx: &PartitioningCx<'_, 'tcx>,
     codegen_units: &mut [CodegenUnit<'tcx>],
-    internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+    internalization_candidates: UnordSet<MonoItem<'tcx>>,
 ) {
     /// For symbol internalization, we need to know whether a symbol/mono-item
     /// is used from outside the codegen unit it is defined in. This type is
@@ -522,7 +526,7 @@ fn internalize_symbols<'tcx>(
         MultipleCgus,
     }
 
-    let mut mono_item_placements = FxHashMap::default();
+    let mut mono_item_placements = UnordMap::default();
     let single_codegen_unit = codegen_units.len() == 1;
 
     if !single_codegen_unit {
@@ -739,7 +743,7 @@ fn mono_item_linkage_and_visibility<'tcx>(
     (Linkage::External, vis)
 }
 
-type CguNameCache = FxHashMap<(DefId, bool), Symbol>;
+type CguNameCache = UnordMap<(DefId, bool), Symbol>;
 
 fn static_visibility<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -932,7 +936,7 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
         //
         // Also, unreached inlined items won't be counted here. This is fine.
 
-        let mut inlined_items = FxHashSet::default();
+        let mut inlined_items = UnordSet::default();
 
         let mut root_items = 0;
         let mut unique_inlined_items = 0;
@@ -1164,7 +1168,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
     }
 
     if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
-        let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
+        let mut item_to_cgus: UnordMap<_, Vec<_>> = Default::default();
 
         for cgu in codegen_units {
             for (&mono_item, &data) in cgu.items() {
@@ -1240,7 +1244,7 @@ fn dump_mono_items_stats<'tcx>(
     let mut file = BufWriter::new(file);
 
     // Gather instantiated mono items grouped by def_id
-    let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+    let mut items_per_def_id: FxIndexMap<_, Vec<_>> = Default::default();
     for cgu in codegen_units {
         cgu.items()
             .keys()
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index dc13766d145..a3ca9e9f9cf 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
 
     fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
         match ct.const_ {
-            mir::Const::Ty(c) => {
+            mir::Const::Ty(_, c) => {
                 c.visit_with(self);
             }
             mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 8bcc21d82f8..50dbc991f8f 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -4,20 +4,10 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+# tidy-alphabetical-start
 rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
-derivative = "2.2.0"
-rustc_macros = { path = "../rustc_macros", optional = true }
-rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
-rustc_serialize = { path = "../rustc_serialize", optional = true }
-rustc_data_structures = { path = "../rustc_data_structures", optional = true }
-rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
+# tidy-alphabetical-end
 
 [features]
 default = ["nightly"]
-nightly = [
-    "rustc_type_ir/nightly",
-    "rustc_macros",
-    "rustc_serialize",
-    "rustc_data_structures",
-    "rustc_ast_ir/nightly",
-]
+nightly = ["rustc_type_ir/nightly"]
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 127ebde5fec..f22e24ef654 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -386,23 +386,15 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
     }
 
     fn fold_const(&mut self, c: I::Const) -> I::Const {
-        // We could canonicalize all consts with static types, but the only ones we
-        // *really* need to worry about are the ones that we end up putting into `CanonicalVarKind`
-        // since canonical vars can't reference other canonical vars.
-        let ty = c
-            .ty()
-            .fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST });
         let kind = match c.kind() {
             ty::ConstKind::Infer(i) => match i {
                 ty::InferConst::Var(vid) => {
-                    // We compare `kind`s here because we've folded the `ty` with `RegionsToStatic`
-                    // so we'll get a mismatch in types if it actually changed any regions.
                     assert_eq!(
-                        self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(),
-                        c.kind(),
-                        "region vid should have been resolved fully before canonicalization"
+                        self.infcx.opportunistic_resolve_ct_var(vid),
+                        c,
+                        "const vid should have been resolved fully before canonicalization"
                     );
-                    CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
+                    CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap())
                 }
                 ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
                 ty::InferConst::Fresh(_) => todo!(),
@@ -410,23 +402,21 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
-                    ty,
                 ),
                 CanonicalizeMode::Response { .. } => {
-                    CanonicalVarKind::PlaceholderConst(placeholder, ty)
+                    CanonicalVarKind::PlaceholderConst(placeholder)
                 }
             },
             ty::ConstKind::Param(_) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
-                    ty,
                 ),
                 CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
             },
             // FIXME: See comment above -- we could fold the region separately or something.
             ty::ConstKind::Bound(_, _)
             | ty::ConstKind::Unevaluated(_)
-            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Value(_, _)
             | ty::ConstKind::Error(_)
             | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
         };
@@ -440,34 +430,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             }),
         );
 
-        Const::new_anon_bound(self.interner(), self.binder_index, var, ty)
-    }
-}
-
-struct RegionsToStatic<I> {
-    interner: I,
-    binder: ty::DebruijnIndex,
-}
-
-impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
-    fn interner(&self) -> I {
-        self.interner
-    }
-
-    fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
-    where
-        T: TypeFoldable<I>,
-    {
-        self.binder.shift_in(1);
-        let t = t.super_fold_with(self);
-        self.binder.shift_out(1);
-        t
-    }
-
-    fn fold_region(&mut self, r: I::Region) -> I::Region {
-        match r.kind() {
-            ty::ReBound(db, _) if self.binder > db => r,
-            _ => Region::new_static(self.interner()),
-        }
+        Const::new_anon_bound(self.interner(), self.binder_index, var)
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index 1333b4aa7d8..5c00b6978d6 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -7,11 +7,11 @@ use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
 // EAGER RESOLUTION
 
 /// Resolves ty, region, and const vars to their inferred values or their root vars.
-pub struct EagerResolver<
-    'a,
+pub struct EagerResolver<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
+where
     Infcx: InferCtxtLike<Interner = I>,
-    I: Interner = <Infcx as InferCtxtLike>::Interner,
-> {
+    I: Interner,
+{
     infcx: &'a Infcx,
 }
 
@@ -58,8 +58,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerRes
     fn fold_const(&mut self, c: I::Const) -> I::Const {
         match c.kind() {
             ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
-                let ty = c.ty().fold_with(self);
-                let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty);
+                let resolved = self.infcx.opportunistic_resolve_ct_var(vid);
                 if c != resolved && resolved.has_infer() {
                     resolved.fold_with(self)
                 } else {
@@ -67,9 +66,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerRes
                 }
             }
             ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
-                let bool = Ty::new_bool(self.infcx.interner());
-                debug_assert_eq!(c.ty(), bool);
-                self.infcx.opportunistic_resolve_effect_var(vid, bool)
+                self.infcx.opportunistic_resolve_effect_var(vid)
             }
             _ => {
                 if c.has_infer() {
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 04f855e4f55..f678d11213c 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -622,8 +622,6 @@ parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allo
 parse_out_of_range_hex_escape = out of range hex escape
     .label = must be a character in the range [\x00-\x7f]
 
-parse_outer_attr_ambiguous = ambiguous outer attributes
-
 parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
 
 parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 3f08a830b0c..6c1fcbe06fc 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -496,15 +496,6 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_outer_attr_ambiguous)]
-pub(crate) struct AmbiguousOuterAttributes {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub sugg: WrapInParentheses,
-}
-
-#[derive(Diagnostic)]
 #[diag(parse_missing_in_in_for_loop)]
 pub(crate) struct MissingInInForLoop {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index d3a6a033978..43f4963b27a 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -42,7 +42,7 @@ pub(crate) struct UnmatchedDelim {
     pub candidate_span: Option<Span>,
 }
 
-pub(crate) fn parse_token_trees<'psess, 'src>(
+pub(crate) fn lex_token_trees<'psess, 'src>(
     psess: &'psess ParseSess,
     mut src: &'src str,
     mut start_pos: BytePos,
@@ -66,7 +66,7 @@ pub(crate) fn parse_token_trees<'psess, 'src>(
         last_lifetime: None,
     };
     let (stream, res, unmatched_delims) =
-        tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
+        tokentrees::TokenTreesReader::lex_all_token_trees(string_reader);
     match res {
         Ok(()) if unmatched_delims.is_empty() => Ok(stream),
         _ => {
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index eabe0226b2f..f7645446081 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -2,6 +2,7 @@ use super::diagnostics::report_suspicious_mismatch_block;
 use super::diagnostics::same_indentation_level;
 use super::diagnostics::TokenTreeDiagInfo;
 use super::{StringReader, UnmatchedDelim};
+use crate::Parser;
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
@@ -17,7 +18,7 @@ pub(super) struct TokenTreesReader<'psess, 'src> {
 }
 
 impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
-    pub(super) fn parse_all_token_trees(
+    pub(super) fn lex_all_token_trees(
         string_reader: StringReader<'psess, 'src>,
     ) -> (TokenStream, Result<(), Vec<PErr<'psess>>>, Vec<UnmatchedDelim>) {
         let mut tt_reader = TokenTreesReader {
@@ -25,14 +26,13 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
             token: Token::dummy(),
             diag_info: TokenTreeDiagInfo::default(),
         };
-        let (_open_spacing, stream, res) =
-            tt_reader.parse_token_trees(/* is_delimited */ false);
+        let (_open_spacing, stream, res) = tt_reader.lex_token_trees(/* is_delimited */ false);
         (stream, res, tt_reader.diag_info.unmatched_delims)
     }
 
-    // Parse a stream of tokens into a list of `TokenTree`s. The `Spacing` in
-    // the result is that of the opening delimiter.
-    fn parse_token_trees(
+    // Lex into a token stream. The `Spacing` in the result is that of the
+    // opening delimiter.
+    fn lex_token_trees(
         &mut self,
         is_delimited: bool,
     ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'psess>>>) {
@@ -42,12 +42,10 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
         let mut buf = Vec::new();
         loop {
             match self.token.kind {
-                token::OpenDelim(delim) => {
-                    buf.push(match self.parse_token_tree_open_delim(delim) {
-                        Ok(val) => val,
-                        Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)),
-                    })
-                }
+                token::OpenDelim(delim) => buf.push(match self.lex_token_tree_open_delim(delim) {
+                    Ok(val) => val,
+                    Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)),
+                }),
                 token::CloseDelim(delim) => {
                     return (
                         open_spacing,
@@ -95,24 +93,24 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
         err
     }
 
-    fn parse_token_tree_open_delim(
+    fn lex_token_tree_open_delim(
         &mut self,
         open_delim: Delimiter,
     ) -> Result<TokenTree, Vec<PErr<'psess>>> {
-        // The span for beginning of the delimited section
+        // The span for beginning of the delimited section.
         let pre_span = self.token.span;
 
         self.diag_info.open_braces.push((open_delim, self.token.span));
 
-        // Parse the token trees within the delimiters.
+        // Lex the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
         // uses an incorrect delimiter.
-        let (open_spacing, tts, res) = self.parse_token_trees(/* is_delimited */ true);
+        let (open_spacing, tts, res) = self.lex_token_trees(/* is_delimited */ true);
         if let Err(errs) = res {
             return Err(self.unclosed_delim_err(tts, errs));
         }
 
-        // Expand to cover the entire delimited token tree
+        // Expand to cover the entire delimited token tree.
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
         let sm = self.string_reader.psess.source_map();
 
@@ -150,7 +148,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
                     self.diag_info.last_unclosed_found_span = Some(self.token.span);
                     // This is a conservative error: only report the last unclosed
                     // delimiter. The previous unclosed delimiters could actually be
-                    // closed! The parser just hasn't gotten to them yet.
+                    // closed! The lexer just hasn't gotten to them yet.
                     if let Some(&(_, sp)) = self.diag_info.open_braces.last() {
                         unclosed_delimiter = Some(sp);
                     };
@@ -234,11 +232,11 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
     ) -> Vec<PErr<'psess>> {
         // If there are unclosed delims, see if there are diff markers and if so, point them
         // out instead of complaining about the unclosed delims.
-        let mut parser = crate::stream_to_parser(self.string_reader.psess, tts, None);
+        let mut parser = Parser::new(self.string_reader.psess, tts, None);
         let mut diff_errs = vec![];
-        // Suggest removing a `{` we think appears in an `if`/`while` condition
-        // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but
-        // we have no way of tracking this in the lexer itself, so we piggyback on the parser
+        // Suggest removing a `{` we think appears in an `if`/`while` condition.
+        // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition,
+        // but we have no way of tracking this in the lexer itself, so we piggyback on the parser.
         let mut in_cond = false;
         while parser.token != token::Eof {
             if let Err(diff_err) = parser.err_vcs_conflict_marker() {
@@ -249,14 +247,15 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
                 parser.token.kind,
                 token::CloseDelim(Delimiter::Brace) | token::FatArrow
             ) {
-                // end of the `if`/`while` body, or the end of a `match` guard
+                // End of the `if`/`while` body, or the end of a `match` guard.
                 in_cond = false;
             } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) {
                 // Store the `&&` and `let` to use their spans later when creating the diagnostic
                 let maybe_andand = parser.look_ahead(1, |t| t.clone());
                 let maybe_let = parser.look_ahead(2, |t| t.clone());
                 if maybe_andand == token::OpenDelim(Delimiter::Brace) {
-                    // This might be the beginning of the `if`/`while` body (i.e., the end of the condition)
+                    // This might be the beginning of the `if`/`while` body (i.e., the end of the
+                    // condition).
                     in_cond = false;
                 } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) {
                     let mut err = parser.dcx().struct_span_err(
@@ -288,8 +287,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
     }
 
     fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> {
-        // An unexpected closing delimiter (i.e., there is no
-        // matching opening delimiter).
+        // An unexpected closing delimiter (i.e., there is no matching opening delimiter).
         let token_str = token_to_string(&self.token);
         let msg = format!("unexpected closing delimiter: `{token_str}`");
         let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg);
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index c9470151a7b..8eb299108d1 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -129,42 +129,42 @@ pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
     ('。', "Ideographic Full Stop", "."),
     ('︒', "Presentation Form For Vertical Ideographic Full Stop", "."),
 
-    ('՝', "Armenian Comma", "\'"),
-    (''', "Fullwidth Apostrophe", "\'"),
-    ('‘', "Left Single Quotation Mark", "\'"),
-    ('’', "Right Single Quotation Mark", "\'"),
-    ('‛', "Single High-Reversed-9 Quotation Mark", "\'"),
-    ('′', "Prime", "\'"),
-    ('‵', "Reversed Prime", "\'"),
-    ('՚', "Armenian Apostrophe", "\'"),
-    ('׳', "Hebrew Punctuation Geresh", "\'"),
-    ('`', "Grave Accent", "\'"),
-    ('`', "Greek Varia", "\'"),
-    ('`', "Fullwidth Grave Accent", "\'"),
-    ('´', "Acute Accent", "\'"),
-    ('΄', "Greek Tonos", "\'"),
-    ('´', "Greek Oxia", "\'"),
-    ('᾽', "Greek Koronis", "\'"),
-    ('᾿', "Greek Psili", "\'"),
-    ('῾', "Greek Dasia", "\'"),
-    ('ʹ', "Modifier Letter Prime", "\'"),
-    ('ʹ', "Greek Numeral Sign", "\'"),
-    ('ˈ', "Modifier Letter Vertical Line", "\'"),
-    ('ˊ', "Modifier Letter Acute Accent", "\'"),
-    ('ˋ', "Modifier Letter Grave Accent", "\'"),
-    ('˴', "Modifier Letter Middle Grave Accent", "\'"),
-    ('ʻ', "Modifier Letter Turned Comma", "\'"),
-    ('ʽ', "Modifier Letter Reversed Comma", "\'"),
-    ('ʼ', "Modifier Letter Apostrophe", "\'"),
-    ('ʾ', "Modifier Letter Right Half Ring", "\'"),
-    ('ꞌ', "Latin Small Letter Saltillo", "\'"),
-    ('י', "Hebrew Letter Yod", "\'"),
-    ('ߴ', "Nko High Tone Apostrophe", "\'"),
-    ('ߵ', "Nko Low Tone Apostrophe", "\'"),
-    ('ᑊ', "Canadian Syllabics West-Cree P", "\'"),
-    ('ᛌ', "Runic Letter Short-Twig-Sol S", "\'"),
-    ('𖽑', "Miao Sign Aspiration", "\'"),
-    ('𖽒', "Miao Sign Reformed Voicing", "\'"),
+    ('՝', "Armenian Comma", "'"),
+    (''', "Fullwidth Apostrophe", "'"),
+    ('‘', "Left Single Quotation Mark", "'"),
+    ('’', "Right Single Quotation Mark", "'"),
+    ('‛', "Single High-Reversed-9 Quotation Mark", "'"),
+    ('′', "Prime", "'"),
+    ('‵', "Reversed Prime", "'"),
+    ('՚', "Armenian Apostrophe", "'"),
+    ('׳', "Hebrew Punctuation Geresh", "'"),
+    ('`', "Grave Accent", "'"),
+    ('`', "Greek Varia", "'"),
+    ('`', "Fullwidth Grave Accent", "'"),
+    ('´', "Acute Accent", "'"),
+    ('΄', "Greek Tonos", "'"),
+    ('´', "Greek Oxia", "'"),
+    ('᾽', "Greek Koronis", "'"),
+    ('᾿', "Greek Psili", "'"),
+    ('῾', "Greek Dasia", "'"),
+    ('ʹ', "Modifier Letter Prime", "'"),
+    ('ʹ', "Greek Numeral Sign", "'"),
+    ('ˈ', "Modifier Letter Vertical Line", "'"),
+    ('ˊ', "Modifier Letter Acute Accent", "'"),
+    ('ˋ', "Modifier Letter Grave Accent", "'"),
+    ('˴', "Modifier Letter Middle Grave Accent", "'"),
+    ('ʻ', "Modifier Letter Turned Comma", "'"),
+    ('ʽ', "Modifier Letter Reversed Comma", "'"),
+    ('ʼ', "Modifier Letter Apostrophe", "'"),
+    ('ʾ', "Modifier Letter Right Half Ring", "'"),
+    ('ꞌ', "Latin Small Letter Saltillo", "'"),
+    ('י', "Hebrew Letter Yod", "'"),
+    ('ߴ', "Nko High Tone Apostrophe", "'"),
+    ('ߵ', "Nko Low Tone Apostrophe", "'"),
+    ('ᑊ', "Canadian Syllabics West-Cree P", "'"),
+    ('ᛌ', "Runic Letter Short-Twig-Sol S", "'"),
+    ('𖽑', "Miao Sign Aspiration", "'"),
+    ('𖽒', "Miao Sign Reformed Voicing", "'"),
 
     ('᳓', "Vedic Sign Nihshvasa", "\""),
     ('"', "Fullwidth Quotation Mark", "\""),
@@ -298,6 +298,7 @@ pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
     ('〉', "Right Angle Bracket", ">"),
     ('》', "Right Double Angle Bracket", ">"),
     ('>', "Fullwidth Greater-Than Sign", ">"),
+
     ('⩵', "Two Consecutive Equals Signs", "==")
 ];
 
@@ -332,7 +333,7 @@ const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[
     (">", "Greater-Than Sign", Some(token::Gt)),
     // FIXME: Literals are already lexed by this point, so we can't recover gracefully just by
     // spitting the correct token out.
-    ("\'", "Single Quote", None),
+    ("'", "Single Quote", None),
     ("\"", "Quotation Mark", None),
 ];
 
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 322739be3fb..b316327a262 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -34,84 +34,41 @@ mod errors;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
-// A bunch of utility functions of the form `parse_<thing>_from_<source>`
-// where <thing> includes crate, expr, item, stmt, tts, and one that
-// uses a HOF to parse anything, and <source> includes file and
-// `source_str`.
-
-/// A variant of 'panictry!' that works on a `Vec<Diag>` instead of a single `Diag`.
-macro_rules! panictry_buffer {
-    ($e:expr) => {{
-        use std::result::Result::{Err, Ok};
-        match $e {
-            Ok(e) => e,
-            Err(errs) => {
-                for e in errs {
-                    e.emit();
-                }
-                FatalError.raise()
+// Unwrap the result if `Ok`, otherwise emit the diagnostics and abort.
+pub fn unwrap_or_emit_fatal<T>(expr: Result<T, Vec<Diag<'_>>>) -> T {
+    match expr {
+        Ok(expr) => expr,
+        Err(errs) => {
+            for err in errs {
+                err.emit();
             }
+            FatalError.raise()
         }
-    }};
-}
-
-pub fn parse_crate_from_file<'a>(input: &Path, psess: &'a ParseSess) -> PResult<'a, ast::Crate> {
-    let mut parser = new_parser_from_file(psess, input, None);
-    parser.parse_crate_mod()
-}
-
-pub fn parse_crate_attrs_from_file<'a>(
-    input: &Path,
-    psess: &'a ParseSess,
-) -> PResult<'a, ast::AttrVec> {
-    let mut parser = new_parser_from_file(psess, input, None);
-    parser.parse_inner_attributes()
-}
-
-pub fn parse_crate_from_source_str(
-    name: FileName,
-    source: String,
-    psess: &ParseSess,
-) -> PResult<'_, ast::Crate> {
-    new_parser_from_source_str(psess, name, source).parse_crate_mod()
-}
-
-pub fn parse_crate_attrs_from_source_str(
-    name: FileName,
-    source: String,
-    psess: &ParseSess,
-) -> PResult<'_, ast::AttrVec> {
-    new_parser_from_source_str(psess, name, source).parse_inner_attributes()
-}
-
-pub fn parse_stream_from_source_str(
-    name: FileName,
-    source: String,
-    psess: &ParseSess,
-    override_span: Option<Span>,
-) -> TokenStream {
-    source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span)
-}
-
-/// Creates a new parser from a source string.
-pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> {
-    panictry_buffer!(maybe_new_parser_from_source_str(psess, name, source))
+    }
 }
 
-/// Creates a new parser from a source string. Returns any buffered errors from lexing the initial
-/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur
-/// when they are dropped.
-pub fn maybe_new_parser_from_source_str(
+/// Creates a new parser from a source string. On failure, the errors must be consumed via
+/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are
+/// dropped.
+pub fn new_parser_from_source_str(
     psess: &ParseSess,
     name: FileName,
     source: String,
 ) -> Result<Parser<'_>, Vec<Diag<'_>>> {
-    maybe_source_file_to_parser(psess, psess.source_map().new_source_file(name, source))
+    let source_file = psess.source_map().new_source_file(name, source);
+    new_parser_from_source_file(psess, source_file)
 }
 
-/// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on
-/// an error as the source of the problem.
-pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option<Span>) -> Parser<'a> {
+/// Creates a new parser from a filename. On failure, the errors must be consumed via
+/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are
+/// dropped.
+///
+/// If a span is given, that is used on an error as the source of the problem.
+pub fn new_parser_from_file<'a>(
+    psess: &'a ParseSess,
+    path: &Path,
+    sp: Option<Span>,
+) -> Result<Parser<'a>, Vec<Diag<'a>>> {
     let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| {
         let msg = format!("couldn't read {}: {}", path.display(), e);
         let mut err = psess.dcx.struct_fatal(msg);
@@ -120,40 +77,37 @@ pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option<Sp
         }
         err.emit();
     });
-
-    panictry_buffer!(maybe_source_file_to_parser(psess, source_file))
+    new_parser_from_source_file(psess, source_file)
 }
 
 /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing
 /// the initial token stream.
-fn maybe_source_file_to_parser(
+fn new_parser_from_source_file(
     psess: &ParseSess,
     source_file: Lrc<SourceFile>,
 ) -> Result<Parser<'_>, Vec<Diag<'_>>> {
     let end_pos = source_file.end_position();
-    let stream = maybe_file_to_stream(psess, source_file, None)?;
-    let mut parser = stream_to_parser(psess, stream, None);
+    let stream = source_file_to_stream(psess, source_file, None)?;
+    let mut parser = Parser::new(psess, stream, None);
     if parser.token == token::Eof {
         parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
     }
-
     Ok(parser)
 }
 
-// Base abstractions
-
-/// Given a `source_file`, produces a sequence of token trees.
-pub fn source_file_to_stream(
+pub fn source_str_to_stream(
     psess: &ParseSess,
-    source_file: Lrc<SourceFile>,
+    name: FileName,
+    source: String,
     override_span: Option<Span>,
-) -> TokenStream {
-    panictry_buffer!(maybe_file_to_stream(psess, source_file, override_span))
+) -> Result<TokenStream, Vec<Diag<'_>>> {
+    let source_file = psess.source_map().new_source_file(name, source);
+    source_file_to_stream(psess, source_file, override_span)
 }
 
 /// Given a source file, produces a sequence of token trees. Returns any buffered errors from
 /// parsing the token stream.
-fn maybe_file_to_stream<'psess>(
+fn source_file_to_stream<'psess>(
     psess: &'psess ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
@@ -165,16 +119,7 @@ fn maybe_file_to_stream<'psess>(
         ));
     });
 
-    lexer::parse_token_trees(psess, src.as_str(), source_file.start_pos, override_span)
-}
-
-/// Given a stream and the `ParseSess`, produces a parser.
-pub fn stream_to_parser<'a>(
-    psess: &'a ParseSess,
-    stream: TokenStream,
-    subparser_name: Option<&'static str>,
-) -> Parser<'a> {
-    Parser::new(psess, stream, subparser_name)
+    lexer::lex_token_trees(psess, src.as_str(), source_file.start_pos, override_span)
 }
 
 /// Runs the given subparser `f` on the tokens of the given `attr`'s item.
@@ -195,19 +140,28 @@ pub fn parse_in<'a, T>(
 pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream {
     let source = pprust::item_to_string(item);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, psess, Some(item.span))
+    unwrap_or_emit_fatal(source_str_to_stream(psess, filename, source, Some(item.span)))
 }
 
 pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream {
     let source = pprust::crate_to_string_for_macros(krate);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, psess, Some(krate.spans.inner_span))
+    unwrap_or_emit_fatal(source_str_to_stream(
+        psess,
+        filename,
+        source,
+        Some(krate.spans.inner_span),
+    ))
 }
 
 pub fn parse_cfg_attr(
     attr: &Attribute,
     psess: &ParseSess,
 ) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+    const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+    const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+        <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
+
     match attr.get_normal_item().args {
         ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
             if !tokens.is_empty() =>
@@ -222,16 +176,12 @@ pub fn parse_cfg_attr(
                 }
             }
         }
-        _ => error_malformed_cfg_attr_missing(attr.span, psess),
+        _ => {
+            psess.dcx.emit_err(errors::MalformedCfgAttr {
+                span: attr.span,
+                sugg: CFG_ATTR_GRAMMAR_HELP,
+            });
+        }
     }
     None
 }
-
-const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
-const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
-    <https://doc.rust-lang.org/reference/conditional-compilation.html\
-    #the-cfg_attr-attribute>";
-
-fn error_malformed_cfg_attr_missing(span: Span, psess: &ParseSess) {
-    psess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP });
-}
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index a57eb70c705..58fef9b6c45 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -7,7 +7,7 @@ use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Delimiter};
 use rustc_errors::{codes::*, Diag, PResult};
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{sym, symbol::kw, BytePos, Span};
 use thin_vec::ThinVec;
 use tracing::debug;
 
@@ -252,9 +252,23 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtMeta, |attr| attr.into_inner());
 
         let do_parse = |this: &mut Self| {
+            let is_unsafe = this.eat_keyword(kw::Unsafe);
+            let unsafety = if is_unsafe {
+                let unsafe_span = this.prev_token.span;
+                this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
+                this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
+
+                ast::Safety::Unsafe(unsafe_span)
+            } else {
+                ast::Safety::Default
+            };
+
             let path = this.parse_path(PathStyle::Mod)?;
             let args = this.parse_attr_args()?;
-            Ok(ast::AttrItem { path, args, tokens: None })
+            if is_unsafe {
+                this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
+            }
+            Ok(ast::AttrItem { unsafety, path, args, tokens: None })
         };
         // Attr items don't have attributes
         if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }
@@ -265,7 +279,7 @@ impl<'a> Parser<'a> {
     /// terminated by a semicolon.
     ///
     /// Matches `inner_attrs*`.
-    pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
+    pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
         let mut attrs = ast::AttrVec::new();
         loop {
             let start_pos: u32 = self.num_bump_calls.try_into().unwrap();
@@ -375,10 +389,25 @@ impl<'a> Parser<'a> {
         }
 
         let lo = self.token.span;
+        let is_unsafe = self.eat_keyword(kw::Unsafe);
+        let unsafety = if is_unsafe {
+            let unsafe_span = self.prev_token.span;
+            self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
+            self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
+
+            ast::Safety::Unsafe(unsafe_span)
+        } else {
+            ast::Safety::Default
+        };
+
         let path = self.parse_path(PathStyle::Mod)?;
         let kind = self.parse_meta_item_kind()?;
+        if is_unsafe {
+            self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
+        }
         let span = lo.to(self.prev_token.span);
-        Ok(ast::MetaItem { path, kind, span })
+
+        Ok(ast::MetaItem { unsafety, path, kind, span })
     }
 
     pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 9677eea0604..2bb6fb53869 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -130,14 +130,14 @@ pub enum AttemptLocalParseRecovery {
 }
 
 impl AttemptLocalParseRecovery {
-    pub fn yes(&self) -> bool {
+    pub(super) fn yes(&self) -> bool {
         match self {
             AttemptLocalParseRecovery::Yes => true,
             AttemptLocalParseRecovery::No => false,
         }
     }
 
-    pub fn no(&self) -> bool {
+    pub(super) fn no(&self) -> bool {
         match self {
             AttemptLocalParseRecovery::Yes => false,
             AttemptLocalParseRecovery::No => true,
@@ -891,7 +891,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn maybe_suggest_struct_literal(
+    pub(super) fn maybe_suggest_struct_literal(
         &mut self,
         lo: Span,
         s: BlockCheckMode,
@@ -2459,7 +2459,7 @@ impl<'a> Parser<'a> {
     /// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this
     /// case, we emit an error and try to suggest enclosing a const argument in braces if it looks
     /// like the user has forgotten them.
-    pub fn handle_ambiguous_unbraced_const_arg(
+    pub(super) fn handle_ambiguous_unbraced_const_arg(
         &mut self,
         args: &mut ThinVec<AngleBracketedArg>,
     ) -> PResult<'a, bool> {
@@ -2500,7 +2500,7 @@ impl<'a> Parser<'a> {
     /// - Single-segment paths (i.e. standalone generic const parameters).
     /// All other expressions that can be parsed will emit an error suggesting the expression be
     /// wrapped in braces.
-    pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
+    pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
         let start = self.token.span;
         let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
             err.span_label(
@@ -2559,7 +2559,7 @@ impl<'a> Parser<'a> {
         Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
     }
 
-    pub fn recover_const_param_declaration(
+    pub(super) fn recover_const_param_declaration(
         &mut self,
         ty_generics: Option<&Generics>,
     ) -> PResult<'a, Option<GenericArg>> {
@@ -2589,7 +2589,11 @@ impl<'a> Parser<'a> {
     /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
     /// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion
     /// if we think that the resulting expression would be well formed.
-    pub fn recover_const_arg(&mut self, start: Span, mut err: Diag<'a>) -> PResult<'a, GenericArg> {
+    pub(super) fn recover_const_arg(
+        &mut self,
+        start: Span,
+        mut err: Diag<'a>,
+    ) -> PResult<'a, GenericArg> {
         let is_op_or_dot = AssocOp::from_token(&self.token)
             .and_then(|op| {
                 if let AssocOp::Greater
@@ -2690,7 +2694,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Creates a dummy const argument, and reports that the expression must be enclosed in braces
-    pub fn dummy_const_arg_needs_braces(&self, mut err: Diag<'a>, span: Span) -> GenericArg {
+    pub(super) fn dummy_const_arg_needs_braces(&self, mut err: Diag<'a>, span: Span) -> GenericArg {
         err.multipart_suggestion(
             "expressions must be enclosed in braces to be used as const generic \
              arguments",
@@ -2961,7 +2965,7 @@ impl<'a> Parser<'a> {
     /// * `=====`
     /// * `<<<<<`
     ///
-    pub fn is_vcs_conflict_marker(
+    pub(super) fn is_vcs_conflict_marker(
         &mut self,
         long_kind: &TokenKind,
         short_kind: &TokenKind,
@@ -2981,14 +2985,14 @@ impl<'a> Parser<'a> {
         None
     }
 
-    pub fn recover_vcs_conflict_marker(&mut self) {
+    pub(super) fn recover_vcs_conflict_marker(&mut self) {
         if let Err(err) = self.err_vcs_conflict_marker() {
             err.emit();
             FatalError.raise();
         }
     }
 
-    pub fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
+    pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
         let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
         else {
             return Ok(());
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 1b99bc015b6..e15d6ab2123 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -328,9 +328,7 @@ impl<'a> Parser<'a> {
                 this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
             })?;
 
-            self.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
-            let span = lhs_span.to(rhs.span);
-
+            let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
             lhs = match op {
                 AssocOp::Add
                 | AssocOp::Subtract
@@ -429,23 +427,11 @@ impl<'a> Parser<'a> {
         });
     }
 
-    fn error_ambiguous_outer_attrs(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) {
-        if let Some(attr) = lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer) {
-            self.dcx().emit_err(errors::AmbiguousOuterAttributes {
-                span: attr.span.to(rhs_span),
-                sugg: errors::WrapInParentheses::Expression {
-                    left: attr.span.shrink_to_lo(),
-                    right: lhs_span.shrink_to_hi(),
-                },
-            });
-        }
-    }
-
     /// Possibly translate the current token to an associative operator.
     /// The method does not advance the current token.
     ///
     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
-    pub fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
+    pub(super) fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
         let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
             // When parsing const expressions, stop parsing when encountering `>`.
             (
@@ -520,8 +506,7 @@ impl<'a> Parser<'a> {
             None
         };
         let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
-        self.error_ambiguous_outer_attrs(&lhs, lhs.span, rhs_span);
-        let span = lhs.span.to(rhs_span);
+        let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
         let limits =
             if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
         let range = self.mk_range(Some(lhs), rhs, limits);
@@ -739,8 +724,7 @@ impl<'a> Parser<'a> {
         expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
     ) -> PResult<'a, P<Expr>> {
         let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
-            this.error_ambiguous_outer_attrs(&lhs, lhs_span, rhs.span);
-            this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs))
+            this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
         };
 
         // Save the state of the parser before parsing type normally, in case there is a
@@ -1022,7 +1006,11 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
+    pub(super) fn parse_dot_suffix_expr(
+        &mut self,
+        lo: Span,
+        base: P<Expr>,
+    ) -> PResult<'a, P<Expr>> {
         // At this point we've consumed something like `expr.` and `self.token` holds the token
         // after the dot.
         match self.token.uninterpolate().kind {
@@ -3858,6 +3846,16 @@ impl<'a> Parser<'a> {
         self.mk_expr(span, ExprKind::Err(guar))
     }
 
+    /// Create expression span ensuring the span of the parent node
+    /// is larger than the span of lhs and rhs, including the attributes.
+    fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
+        lhs.attrs
+            .iter()
+            .find(|a| a.style == AttrStyle::Outer)
+            .map_or(lhs_span, |a| a.span)
+            .to(rhs_span)
+    }
+
     fn collect_tokens_for_expr(
         &mut self,
         attrs: AttrWrapper,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 53757c38e8b..3f5a4afdad8 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -226,10 +226,11 @@ impl<'a> Parser<'a> {
             self.expect_keyword(kw::Extern)?;
             self.parse_item_foreign_mod(attrs, safety)?
         } else if self.is_static_global() {
+            let safety = self.parse_safety(Case::Sensitive);
             // STATIC ITEM
             self.bump(); // `static`
             let mutability = self.parse_mutability();
-            let (ident, item) = self.parse_static_item(mutability)?;
+            let (ident, item) = self.parse_static_item(safety, mutability)?;
             (ident, ItemKind::Static(Box::new(item)))
         } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
             // CONST ITEM
@@ -952,7 +953,7 @@ impl<'a> Parser<'a> {
                 let kind = match AssocItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
-                        ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
+                        ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
                             self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
                             AssocItemKind::Const(Box::new(ConstItem {
                                 defaultness: Defaultness::Final,
@@ -1221,6 +1222,7 @@ impl<'a> Parser<'a> {
                                 ty,
                                 mutability: Mutability::Not,
                                 expr,
+                                safety: Safety::Default,
                             }))
                         }
                         _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
@@ -1258,7 +1260,10 @@ impl<'a> Parser<'a> {
                 matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
             })
         } else {
-            false
+            let quals: &[Symbol] = &[kw::Unsafe, kw::Safe];
+            // `$qual static`
+            quals.iter().any(|&kw| self.check_keyword(kw))
+                && self.look_ahead(1, |t| t.is_keyword(kw::Static))
         }
     }
 
@@ -1319,7 +1324,11 @@ impl<'a> Parser<'a> {
     /// ```ebnf
     /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
     /// ```
-    fn parse_static_item(&mut self, mutability: Mutability) -> PResult<'a, (Ident, StaticItem)> {
+    fn parse_static_item(
+        &mut self,
+        safety: Safety,
+        mutability: Mutability,
+    ) -> PResult<'a, (Ident, StaticItem)> {
         let ident = self.parse_ident()?;
 
         if self.token.kind == TokenKind::Lt && self.may_recover() {
@@ -1340,7 +1349,7 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((ident, StaticItem { ty, mutability, expr }))
+        Ok((ident, StaticItem { ty, safety, mutability, expr }))
     }
 
     /// Parse a constant item with the prefix `"const"` already parsed.
@@ -2256,7 +2265,7 @@ pub(crate) struct FnParseMode {
     ///     to true.
     ///   * The span is from Edition 2015. In particular, you can get a
     ///     2015 span inside a 2021 crate using macros.
-    pub req_name: ReqName,
+    pub(super) req_name: ReqName,
     /// If this flag is set to `true`, then plain, semicolon-terminated function
     /// prototypes are not allowed here.
     ///
@@ -2275,7 +2284,7 @@ pub(crate) struct FnParseMode {
     /// This field should only be set to false if the item is inside of a trait
     /// definition or extern block. Within an impl block or a module, it should
     /// always be set to true.
-    pub req_body: bool,
+    pub(super) req_body: bool,
 }
 
 /// Parsing of functions and methods.
@@ -2400,9 +2409,9 @@ impl<'a> Parser<'a> {
         // `pub` is added in case users got confused with the ordering like `async pub fn`,
         // only if it wasn't preceded by `default` as `default pub` is invalid.
         let quals: &[Symbol] = if check_pub {
-            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
         } else {
-            &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
+            &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
         };
         self.check_keyword_case(kw::Fn, case) // Definitely an `fn`.
             // `$qual fn` or `$qual $qual`:
@@ -2537,11 +2546,27 @@ impl<'a> Parser<'a> {
                     } else if self.check_keyword(kw::Unsafe) {
                         match safety {
                             Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
+                            Safety::Safe(sp) => {
+                                recover_safety = Safety::Unsafe(self.token.span);
+                                Some(WrongKw::Misplaced(sp))
+                            }
                             Safety::Default => {
                                 recover_safety = Safety::Unsafe(self.token.span);
                                 Some(WrongKw::Misplaced(ext_start_sp))
                             }
                         }
+                    } else if self.check_keyword(kw::Safe) {
+                        match safety {
+                            Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
+                            Safety::Unsafe(sp) => {
+                                recover_safety = Safety::Safe(self.token.span);
+                                Some(WrongKw::Misplaced(sp))
+                            }
+                            Safety::Default => {
+                                recover_safety = Safety::Safe(self.token.span);
+                                Some(WrongKw::Misplaced(ext_start_sp))
+                            }
+                        }
                     } else {
                         None
                     };
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index bab8b6c06eb..adf04fcf224 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -11,22 +11,21 @@ mod stmt;
 mod ty;
 
 use crate::lexer::UnmatchedDelim;
-pub use attr_wrapper::AttrWrapper;
+use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 pub(crate) use expr::ForbiddenLetReason;
 pub(crate) use item::FnParseMode;
 pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-pub use path::PathStyle;
+use path::PathStyle;
 
-use core::fmt;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
-    self as ast, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, Expr,
-    ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
+    self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
+    Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit, Visibility,
     VisibilityKind, DUMMY_NODE_ID,
 };
 use rustc_ast_pretty::pprust;
@@ -37,7 +36,7 @@ use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use std::ops::Range;
-use std::{mem, slice};
+use std::{fmt, mem, slice};
 use thin_vec::ThinVec;
 use tracing::debug;
 
@@ -146,7 +145,7 @@ pub struct Parser<'a> {
     /// The current token.
     pub token: Token,
     /// The spacing for the current token.
-    pub token_spacing: Spacing,
+    token_spacing: Spacing,
     /// The previous token.
     pub prev_token: Token,
     pub capture_cfg: bool,
@@ -187,7 +186,7 @@ pub struct Parser<'a> {
     current_closure: Option<ClosureSpans>,
     /// Whether the parser is allowed to do recovery.
     /// This is disabled when parsing macro arguments, see #103534
-    pub recovery: Recovery,
+    recovery: Recovery,
 }
 
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
@@ -197,10 +196,10 @@ rustc_data_structures::static_assert_size!(Parser<'_>, 264);
 
 /// Stores span information about a closure.
 #[derive(Clone, Debug)]
-pub struct ClosureSpans {
-    pub whole_closure: Span,
-    pub closing_pipe: Span,
-    pub body: Span,
+struct ClosureSpans {
+    whole_closure: Span,
+    closing_pipe: Span,
+    body: Span,
 }
 
 /// Indicates a range of tokens that should be replaced by
@@ -220,13 +219,13 @@ pub struct ClosureSpans {
 /// the first macro inner attribute to invoke a proc-macro).
 /// When create a `TokenStream`, the inner attributes get inserted
 /// into the proper place in the token stream.
-pub type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
+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, Debug)]
-pub enum Capturing {
+enum Capturing {
     /// We aren't performing any capturing - this is the default mode.
     No,
     /// We are capturing tokens
@@ -374,13 +373,13 @@ pub enum FollowedByType {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum Trailing {
+enum Trailing {
     No,
     Yes,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum TokenDescription {
+pub(super) enum TokenDescription {
     ReservedIdentifier,
     Keyword,
     ReservedKeyword,
@@ -388,7 +387,7 @@ pub enum TokenDescription {
 }
 
 impl TokenDescription {
-    pub fn from_token(token: &Token) -> Option<Self> {
+    pub(super) fn from_token(token: &Token) -> Option<Self> {
         match token.kind {
             _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier),
             _ if token.is_used_keyword() => Some(TokenDescription::Keyword),
@@ -502,7 +501,7 @@ impl<'a> Parser<'a> {
     /// Expect next token to be edible or inedible token. If edible,
     /// then consume it; if inedible, then return without consuming
     /// anything. Signal a fatal error if next token is unexpected.
-    pub fn expect_one_of(
+    fn expect_one_of(
         &mut self,
         edible: &[TokenKind],
         inedible: &[TokenKind],
@@ -572,7 +571,7 @@ impl<'a> Parser<'a> {
     /// the main purpose of this function is to reduce the cluttering of the suggestions list
     /// which using the normal eat method could introduce in some cases.
     #[inline]
-    pub fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
+    fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
         let is_present = self.check_noexpect(tok);
         if is_present {
             self.bump()
@@ -1221,6 +1220,8 @@ impl<'a> Parser<'a> {
     fn parse_safety(&mut self, case: Case) -> Safety {
         if self.eat_keyword_case(kw::Unsafe, case) {
             Safety::Unsafe(self.prev_token.uninterpolated_span())
+        } else if self.eat_keyword_case(kw::Safe, case) {
+            Safety::Safe(self.prev_token.uninterpolated_span())
         } else {
             Safety::Default
         }
@@ -1260,9 +1261,12 @@ impl<'a> Parser<'a> {
         }
         self.eat_keyword(kw::Const);
         let (attrs, blk) = self.parse_inner_attrs_and_block()?;
-        let expr = self.mk_expr(blk.span, ExprKind::Block(blk, None));
-        let blk_span = expr.span;
-        Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(expr), attrs))
+        let anon_const = AnonConst {
+            id: DUMMY_NODE_ID,
+            value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
+        };
+        let blk_span = anon_const.value.span;
+        Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
     }
 
     /// Parses mutability (`mut` or nothing).
@@ -1515,7 +1519,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn collect_tokens_no_attrs<R: HasAttrs + HasTokens>(
+    fn collect_tokens_no_attrs<R: HasAttrs + HasTokens>(
         &mut self,
         f: impl FnOnce(&mut Self) -> PResult<'a, R>,
     ) -> PResult<'a, R> {
@@ -1536,8 +1540,10 @@ 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 + '_ {
+    // Debug view of the parser's token stream, up to `{lookahead}` tokens.
+    // Only used when debugging.
+    #[allow(unused)]
+    pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
         struct DebugParser<'dbg> {
             parser: &'dbg Parser<'dbg>,
             lookahead: usize,
@@ -1613,7 +1619,7 @@ pub(crate) fn make_unclosed_delims_error(
 /// is then 'parsed' to build up an `AttrTokenStream` with nested
 /// `AttrTokenTree::Delimited` tokens.
 #[derive(Debug, Clone)]
-pub enum FlatToken {
+enum FlatToken {
     /// A token - this holds both delimiter (e.g. '{' and '}')
     /// and non-delimiter tokens
     Token(Token),
diff --git a/compiler/rustc_parse/src/parser/mut_visit/tests.rs b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
index b3cb28af657..677bcdf7fcd 100644
--- a/compiler/rustc_parse/src/parser/mut_visit/tests.rs
+++ b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
@@ -21,14 +21,12 @@ impl MutVisitor for ToZzIdentMutVisitor {
     }
 }
 
-// Maybe add to `expand.rs`.
-macro_rules! assert_pred {
-    ($pred:expr, $predname:expr, $a:expr , $b:expr) => {{
-        let pred_val = $pred;
+macro_rules! assert_matches_codepattern {
+    ($a:expr , $b:expr) => {{
         let a_val = $a;
         let b_val = $b;
-        if !(pred_val(&a_val, &b_val)) {
-            panic!("expected args satisfying {}, got {} and {}", $predname, a_val, b_val);
+        if !matches_codepattern(&a_val, &b_val) {
+            panic!("expected args satisfying `matches_codepattern`, got {} and {}", a_val, b_val);
         }
     }};
 }
@@ -41,9 +39,7 @@ fn ident_transformation() {
         let mut krate =
             string_to_crate("#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
         zz_visitor.visit_crate(&mut krate);
-        assert_pred!(
-            matches_codepattern,
-            "matches_codepattern",
+        assert_matches_codepattern!(
             print_crate_items(&krate),
             "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()
         );
@@ -61,9 +57,7 @@ fn ident_transformation_in_defs() {
                 .to_string(),
         );
         zz_visitor.visit_crate(&mut krate);
-        assert_pred!(
-            matches_codepattern,
-            "matches_codepattern",
+        assert_matches_codepattern!(
             print_crate_items(&krate),
             "macro_rules! zz{(zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+))}".to_string()
         );
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index fcedc1a4af3..9beecd9849f 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -20,7 +20,7 @@ use tracing::debug;
 
 /// Specifies how to parse a path.
 #[derive(Copy, Clone, PartialEq)]
-pub enum PathStyle {
+pub(super) enum PathStyle {
     /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
     /// with something else. For example, in expressions `segment < ....` can be interpreted
     /// as a comparison and `segment ( ....` can be interpreted as a function call.
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index be539d15386..104aae9b257 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -31,7 +31,7 @@ impl<'a> Parser<'a> {
     /// Parses a statement. This stops just before trailing semicolons on everything but items.
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
     // Public for rustfmt usage.
-    pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
+    pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
         Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
             e.emit();
             self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index a31e350541a..79a6cf1b541 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -1,5 +1,7 @@
 use crate::parser::ForceCollect;
-use crate::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
+use crate::{
+    new_parser_from_source_str, parser::Parser, source_str_to_stream, unwrap_or_emit_fatal,
+};
 use ast::token::IdentIsRaw;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token};
@@ -29,7 +31,11 @@ fn psess() -> ParseSess {
 
 /// Map string to parser (via tts).
 fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
-    new_parser_from_source_str(psess, PathBuf::from("bogofile").into(), source_str)
+    unwrap_or_emit_fatal(new_parser_from_source_str(
+        psess,
+        PathBuf::from("bogofile").into(),
+        source_str,
+    ))
 }
 
 fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
@@ -82,11 +88,12 @@ where
 /// Maps a string to tts, using a made-up filename.
 pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
     let psess = psess();
-    source_file_to_stream(
+    unwrap_or_emit_fatal(source_str_to_stream(
         &psess,
-        psess.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
+        PathBuf::from("bogofile").into(),
+        source_str,
         None,
-    )
+    ))
 }
 
 /// Parses a string, returns a crate.
@@ -1068,7 +1075,8 @@ fn parse_item_from_source_str(
     source: String,
     psess: &ParseSess,
 ) -> PResult<'_, Option<P<ast::Item>>> {
-    new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No)
+    unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source))
+        .parse_item(ForceCollect::No)
 }
 
 // Produces a `rustc_span::span`.
@@ -1349,7 +1357,7 @@ fn ttdelim_span() {
         source: String,
         psess: &ParseSess,
     ) -> PResult<'_, P<ast::Expr>> {
-        new_parser_from_source_str(psess, name, source).parse_expr()
+        unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr()
     }
 
     create_default_session_globals_then(|| {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 2033f387887..5bed0317e5e 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -127,7 +127,7 @@ impl<'a> Parser<'a> {
     /// Parse a type suitable for a field definition.
     /// The difference from `parse_ty` is that this version
     /// allows anonymous structs and unions.
-    pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_for_field_def(&mut self) -> PResult<'a, P<Ty>> {
         if self.can_begin_anon_struct_or_union() {
             self.parse_anon_struct_or_union()
         } else {
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index b91ef1ae1f3..19d6f512572 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -25,15 +25,21 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
     match attr_info {
         // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
         Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
-            check_builtin_attribute(psess, attr, *name, *template)
+            match parse_meta(psess, attr) {
+                Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, *name, *template),
+                Err(err) => {
+                    err.emit();
+                }
+            }
         }
         _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
             // All key-value attributes are restricted to meta-item syntax.
-            parse_meta(psess, attr)
-                .map_err(|err| {
+            match parse_meta(psess, attr) {
+                Ok(_) => {}
+                Err(err) => {
                     err.emit();
-                })
-                .ok();
+                }
+            }
         }
         _ => {}
     }
@@ -42,6 +48,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
 pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
     let item = attr.get_normal_item();
     Ok(MetaItem {
+        unsafety: item.unsafety,
         span: attr.span,
         path: item.path.clone(),
         kind: match &item.args {
@@ -103,7 +110,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
     })
 }
 
-pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
+fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
     if let Delimiter::Parenthesis = delim {
         return;
     }
@@ -113,7 +120,7 @@ pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter
     });
 }
 
-pub fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
+pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
     if let Delimiter::Parenthesis = delim {
         return;
     }
@@ -133,20 +140,6 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
     }
 }
 
-pub fn check_builtin_attribute(
-    psess: &ParseSess,
-    attr: &Attribute,
-    name: Symbol,
-    template: AttributeTemplate,
-) {
-    match parse_meta(psess, attr) {
-        Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, name, template),
-        Err(err) => {
-            err.emit();
-        }
-    }
-}
-
 pub fn check_builtin_meta_item(
     psess: &ParseSess,
     meta: &MetaItem,
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index d850644bb45..07c82065a80 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -384,6 +384,10 @@ passes_invalid_attr_at_crate_level =
 passes_invalid_attr_at_crate_level_item =
     the inner attribute doesn't annotate this {$kind}
 
+passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
+    .suggestion = remove the `unsafe(...)`
+    .note = extraneous unsafe is not allowed in attributes
+
 passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
 
 passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 4fe84b91b8b..6ce7c41acc8 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,9 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::StashKey;
 use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
-use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{
+    is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
+};
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir};
@@ -114,6 +116,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut seen = FxHashMap::default();
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
+            self.check_unsafe_attr(attr);
+
             match attr.path().as_slice() {
                 [sym::diagnostic, sym::do_not_recommend] => {
                     self.check_do_not_recommend(attr.span, hir_id, target)
@@ -308,6 +312,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         true
     }
 
+    /// Checks if `unsafe()` is applied to an invalid attribute.
+    fn check_unsafe_attr(&self, attr: &Attribute) {
+        if !attr.is_doc_comment() {
+            let attr_item = attr.get_normal_item();
+            if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+                if !is_unsafe_attr(attr.name_or_empty()) {
+                    self.dcx().emit_err(errors::InvalidAttrUnsafe {
+                        span: unsafe_span,
+                        name: attr_item.path.clone(),
+                    });
+                }
+            }
+        }
+    }
+
     /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
     fn check_diagnostic_on_unimplemented(
         &self,
@@ -2321,7 +2340,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let param_env = ty::ParamEnv::empty();
 
         let infcx = tcx.infer_ctxt().build();
-        let ocx = ObligationCtxt::new(&infcx);
+        let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
         let span = tcx.def_span(def_id);
         let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id());
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 71f3e8b7b5d..3f6eccbd5a5 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -196,6 +196,11 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
         self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
     }
 
+    fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
+        let kind = Some(hir::ConstContext::Const { inline: true });
+        self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
+    }
+
     fn visit_body(&mut self, body: &hir::Body<'tcx>) {
         let owner = self.tcx.hir().body_owner_def_id(body.id());
         let kind = self.tcx.hir().body_const_context(owner);
@@ -223,11 +228,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
                     self.const_check_violated(expr, e.span);
                 }
             }
-            hir::ExprKind::ConstBlock(expr) => {
-                let kind = Some(hir::ConstContext::Const { inline: true });
-                self.recurse_into(kind, None, |this| intravisit::walk_expr(this, expr));
-                return;
-            }
 
             _ => {}
         }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 0049afff528..2cb3c5d8965 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -15,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, AssocItemContainer, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_session::lint::builtin::DEAD_CODE;
@@ -44,16 +44,63 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     )
 }
 
-fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
+struct Publicness {
+    ty_is_public: bool,
+    ty_and_all_fields_are_public: bool,
+}
+
+impl Publicness {
+    fn new(ty_is_public: bool, ty_and_all_fields_are_public: bool) -> Self {
+        Self { ty_is_public, ty_and_all_fields_are_public }
+    }
+}
+
+fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
+    // treat PhantomData and positional ZST as public,
+    // we don't want to lint types which only have them,
+    // cause it's a common way to use such types to check things like well-formedness
+    tcx.adt_def(id).all_fields().all(|field| {
+        let field_type = tcx.type_of(field.did).instantiate_identity();
+        if field_type.is_phantom_data() {
+            return true;
+        }
+        let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
+        if is_positional
+            && tcx
+                .layout_of(tcx.param_env(field.did).and(field_type))
+                .map_or(true, |layout| layout.is_zst())
+        {
+            return true;
+        }
+        field.vis.is_public()
+    })
+}
+
+/// check struct and its fields are public or not,
+/// for enum and union, just check they are public,
+/// and doesn't solve types like &T for now, just skip them
+fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness {
     if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
         && let Res::Def(def_kind, def_id) = path.res
         && def_id.is_local()
-        && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
     {
-        tcx.visibility(def_id).is_public()
-    } else {
-        true
+        return match def_kind {
+            DefKind::Enum | DefKind::Union => {
+                let ty_is_public = tcx.visibility(def_id).is_public();
+                Publicness::new(ty_is_public, ty_is_public)
+            }
+            DefKind::Struct => {
+                let ty_is_public = tcx.visibility(def_id).is_public();
+                Publicness::new(
+                    ty_is_public,
+                    ty_is_public && struct_all_fields_are_public(tcx, def_id),
+                )
+            }
+            _ => Publicness::new(true, true),
+        };
     }
+
+    Publicness::new(true, true)
 }
 
 /// Determine if a work from the worklist is coming from the a `#[allow]`
@@ -427,9 +474,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                         {
                             if matches!(trait_item.kind, hir::TraitItemKind::Fn(..))
                                 && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
+                                    .ty_and_all_fields_are_public
                             {
-                                // skip methods of private ty,
-                                // they would be solved in `solve_rest_impl_items`
+                                // skip impl-items of non pure pub ty,
+                                // cause we don't know the ty is constructed or not,
+                                // check these later in `solve_rest_impl_items`
                                 continue;
                             }
 
@@ -510,22 +559,21 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             && let Some(local_def_id) = def_id.as_local()
             && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
         {
-            if self.tcx.visibility(impl_item_id).is_public() {
-                // for the public method, we don't know the trait item is used or not,
-                // so we mark the method live if the self is used
-                return self.live_symbols.contains(&local_def_id);
-            }
-
             if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
                 && let Some(local_id) = trait_item_id.as_local()
             {
-                // for the private method, we can know the trait item is used or not,
+                // for the local impl item, we can know the trait item is used or not,
                 // so we mark the method live if the self is used and the trait item is used
-                return self.live_symbols.contains(&local_id)
-                    && self.live_symbols.contains(&local_def_id);
+                self.live_symbols.contains(&local_id) && self.live_symbols.contains(&local_def_id)
+            } else {
+                // for the foreign method and inherent pub method,
+                // we don't know the trait item or the method is used or not,
+                // so we mark the method live if the self is used
+                self.live_symbols.contains(&local_def_id)
             }
+        } else {
+            false
         }
-        false
     }
 }
 
@@ -587,16 +635,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
             hir::ExprKind::OffsetOf(..) => {
                 self.handle_offset_of(expr);
             }
-            hir::ExprKind::ConstBlock(expr) => {
-                // When inline const blocks are used in pattern position, paths
-                // referenced by it should be considered as used.
-                let in_pat = mem::replace(&mut self.in_pat, false);
-
-                intravisit::walk_expr(self, expr);
-
-                self.in_pat = in_pat;
-                return;
-            }
             _ => (),
         }
 
@@ -658,6 +696,17 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
         self.in_pat = in_pat;
     }
+
+    fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
+        // When inline const blocks are used in pattern position, paths
+        // referenced by it should be considered as used.
+        let in_pat = mem::replace(&mut self.in_pat, false);
+
+        self.live_symbols.insert(c.def_id);
+        intravisit::walk_inline_const(self, c);
+
+        self.in_pat = in_pat;
+    }
 }
 
 fn has_allow_dead_code_or_lang_attr(
@@ -746,7 +795,9 @@ fn check_item<'tcx>(
                 .iter()
                 .filter_map(|def_id| def_id.as_local());
 
-            let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
+            let self_ty = tcx.hir().item(id).expect_impl().self_ty;
+            let Publicness { ty_is_public, ty_and_all_fields_are_public } =
+                ty_ref_to_pub_struct(tcx, self_ty);
 
             // And we access the Map here to get HirId from LocalDefId
             for local_def_id in local_def_ids {
@@ -762,18 +813,20 @@ fn check_item<'tcx>(
                 // for trait impl blocks,
                 // mark the method live if the self_ty is public,
                 // or the method is public and may construct self
-                if of_trait
-                    && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
-                        || tcx.visibility(local_def_id).is_public()
-                            && (ty_is_pub || may_construct_self))
+                if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy)
+                    || tcx.visibility(local_def_id).is_public()
+                        && (ty_and_all_fields_are_public || may_construct_self)
                 {
+                    // if the impl item is public,
+                    // and the ty may be constructed or can be constructed in foreign crates,
+                    // mark the impl item live
                     worklist.push((local_def_id, ComesFromAllowExpect::No));
                 } else if let Some(comes_from_allow) =
                     has_allow_dead_code_or_lang_attr(tcx, local_def_id)
                 {
                     worklist.push((local_def_id, comes_from_allow));
-                } else if of_trait {
-                    // private method || public method not constructs self
+                } else if of_trait || tcx.visibility(local_def_id).is_public() && ty_is_public {
+                    // private impl items of traits || public impl items not constructs self
                     unsolved_impl_items.push((id, local_def_id));
                 }
             }
@@ -840,6 +893,14 @@ fn create_and_seed_worklist(
             effective_vis
                 .is_public_at_level(Level::Reachable)
                 .then_some(id)
+                .filter(|&id|
+                    // checks impls, impl-items and pub structs with all public fields later
+                    match tcx.def_kind(id) {
+                        DefKind::Impl { .. } => false,
+                        DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
+                        DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()),
+                        _ => true
+                    })
                 .map(|id| (id, ComesFromAllowExpect::No))
         })
         // Seed entry point
@@ -1112,10 +1173,15 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
             || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
         {
             for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
-                // We have diagnosed unused methods in traits
+                // We have diagnosed unused assoc consts and fns in traits
                 if matches!(def_kind, DefKind::Impl { of_trait: true })
-                    && tcx.def_kind(def_id) == DefKind::AssocFn
-                    || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
+                    && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn)
+                    // skip unused public inherent methods,
+                    // cause we have diagnosed unconstructed struct
+                    || matches!(def_kind, DefKind::Impl { of_trait: false })
+                        && tcx.visibility(def_id).is_public()
+                        && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
+                    || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy
                 {
                     continue;
                 }
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 78653e5f95a..906ecdfe5ab 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -82,7 +82,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
     let mut items = DiagnosticItems::default();
 
     // Collect diagnostic items in other crates.
-    for &cnum in tcx.crates_including_speculative(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
+    for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
         for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id {
             collect_item(tcx, &mut items, name, def_id);
         }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 7fdd9924b51..a935f1ad7d3 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use crate::fluent_generated as fluent;
-use rustc_ast::Label;
+use rustc_ast::{ast, Label};
 use rustc_errors::{
     codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
     MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -863,6 +863,15 @@ pub struct InvalidAttrAtCrateLevel {
     pub item: Option<ItemFollowingInnerAttr>,
 }
 
+#[derive(Diagnostic)]
+#[diag(passes_invalid_attr_unsafe)]
+#[note]
+pub struct InvalidAttrUnsafe {
+    #[primary_span]
+    pub span: Span,
+    pub name: ast::Path,
+}
+
 #[derive(Clone, Copy)]
 pub struct ItemFollowingInnerAttr {
     pub span: Span,
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 82d43f078ee..c9a47650456 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -54,7 +54,7 @@ pub fn ensure_wf<'tcx>(
         pred,
     );
     let infcx = tcx.infer_ctxt().build();
-    let ocx = traits::ObligationCtxt::new(&infcx);
+    let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
     ocx.register_obligation(obligation);
     let errors = ocx.select_all_or_error();
     if !errors.is_empty() {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 698f15015c4..dfa7dfa3398 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -147,11 +147,6 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         return;
     }
 
-    // Don't run for inline consts, they are collected together with their parent
-    if let DefKind::InlineConst = tcx.def_kind(def_id) {
-        return;
-    }
-
     // Don't run unused pass for #[naked]
     if tcx.has_attr(def_id.to_def_id(), sym::naked) {
         return;
@@ -1148,13 +1143,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             }
 
             hir::ExprKind::Lit(..)
+            | hir::ExprKind::ConstBlock(..)
             | hir::ExprKind::Err(_)
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
             | hir::ExprKind::Path(hir::QPath::LangItem(..))
             | hir::ExprKind::OffsetOf(..) => succ,
 
-            hir::ExprKind::ConstBlock(expr) => self.propagate_through_expr(expr, succ),
-
             // Note that labels have been resolved, so we don't need to look
             // at the label ident
             hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(blk, succ),
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 737310e5c04..2587a18b8c8 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -93,6 +93,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
         self.with_context(Constant, |v| intravisit::walk_anon_const(v, c));
     }
 
+    fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) {
+        self.with_context(Constant, |v| intravisit::walk_inline_const(v, c));
+    }
+
     fn visit_fn(
         &mut self,
         fk: hir::intravisit::FnKind<'hir>,
@@ -285,9 +289,6 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                     self.cx_stack.len() - 1,
                 )
             }
-            hir::ExprKind::ConstBlock(expr) => {
-                self.with_context(Constant, |v| intravisit::walk_expr(v, expr));
-            }
             _ => intravisit::walk_expr(self, e),
         }
     }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index ab1dd248556..6dd8eaf7e67 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -32,7 +32,7 @@ use rustc_hir::Node;
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy::{self, Level};
-use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc};
+use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt};
 use rustc_privacy::DefIdVisitor;
@@ -157,6 +157,7 @@ impl<'tcx> ReachableContext<'tcx> {
                 }
                 hir::ImplItemKind::Type(_) => false,
             },
+            Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => true,
             _ => false,
         }
     }
@@ -205,11 +206,24 @@ impl<'tcx> ReachableContext<'tcx> {
                         }
                     }
 
-                    // Reachable constants will be inlined into other crates
-                    // unconditionally, so we need to make sure that their
-                    // contents are also reachable.
                     hir::ItemKind::Const(_, _, init) => {
-                        self.visit_nested_body(init);
+                        // Only things actually ending up in the final constant value are reachable
+                        // for codegen. Everything else is only needed during const-eval, so even if
+                        // const-eval happens in a downstream crate, all they need is
+                        // `mir_for_ctfe`.
+                        match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) {
+                            Ok(alloc) => {
+                                let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory();
+                                self.propagate_from_alloc(alloc);
+                            }
+                            // We can't figure out which value the constant will evaluate to. In
+                            // lieu of that, we have to consider everything mentioned in the const
+                            // initializer reachable, since it *may* end up in the final value.
+                            Err(ErrorHandled::TooGeneric(_)) => self.visit_nested_body(init),
+                            // If there was an error evaluating the const, nothing can be reachable
+                            // via it, and anyway compilation will fail.
+                            Err(ErrorHandled::Reported(..)) => {}
+                        }
                     }
                     hir::ItemKind::Static(..) => {
                         if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 31c709f2eb6..6bdfaf0c908 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1020,7 +1020,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
         // stabilization diagnostic, but it can be avoided when there are no
         // `remaining_lib_features`.
         let mut all_implications = remaining_implications.clone();
-        for &cnum in tcx.used_crates(()) {
+        for &cnum in tcx.crates(()) {
             all_implications
                 .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v)));
         }
@@ -1033,7 +1033,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
             &all_implications,
         );
 
-        for &cnum in tcx.used_crates(()) {
+        for &cnum in tcx.crates(()) {
             if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
                 break;
             }
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index d80addf1236..90691ca1790 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
     }
 
     let mut missing = FxHashSet::default();
-    for &cnum in tcx.used_crates(()).iter() {
+    for &cnum in tcx.crates(()).iter() {
         for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
         }
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index ff68dd81bea..8391c694c64 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -6,11 +6,12 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
+use rustc_middle::ty::{
+    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
@@ -701,9 +702,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     ty::Int(_) => miint.as_finite_int(size.bits()).unwrap(),
                     _ => miint.as_finite_uint().unwrap(),
                 };
-                match Scalar::try_from_uint(bits, size) {
+                match ScalarInt::try_from_uint(bits, size) {
                     Some(scalar) => {
-                        let value = mir::Const::from_scalar(tcx, scalar, ty.inner());
+                        let value = mir::Const::from_scalar(tcx, scalar.into(), ty.inner());
                         PatRangeBoundary::Finite(value)
                     }
                     // The value doesn't fit. Since `x >= 0` and 0 always encodes the minimum value
@@ -737,7 +738,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 // this). We show this to the user as `usize::MAX..` which is slightly incorrect but
                 // probably clear enough.
                 let c = ty.numeric_max_val(cx.tcx).unwrap();
-                let value = mir::Const::from_ty_const(c, cx.tcx);
+                let value = mir::Const::from_ty_const(c, ty.0, cx.tcx);
                 lo = PatRangeBoundary::Finite(value);
             }
             let hi = if let Some(hi) = range.hi.minus_one() {
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index c57f22a0da2..2bb1be22b98 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 # tidy-alphabetical-start
 field-offset = "0.3.5"
 measureme = "11"
-rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
@@ -23,5 +22,5 @@ tracing = "0.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["rustc-rayon-core", "rustc_query_system/rustc_use_parallel_compiler"]
+rustc_use_parallel_compiler = ["rustc_query_system/rustc_use_parallel_compiler"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 76227a78c3d..66fb3136805 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -64,7 +64,6 @@ pub struct MarkFrame<'a> {
     parent: Option<&'a MarkFrame<'a>>,
 }
 
-#[derive(PartialEq)]
 enum DepNodeColor {
     Red,
     Green(DepNodeIndex),
@@ -925,7 +924,7 @@ impl<D: Deps> DepGraph<D> {
     /// Returns true if the given node has been marked as red during the
     /// current compilation session. Used in various assertions
     pub fn is_red(&self, dep_node: &DepNode) -> bool {
-        self.node_color(dep_node) == Some(DepNodeColor::Red)
+        matches!(self.node_color(dep_node), Some(DepNodeColor::Red))
     }
 
     /// Returns true if the given node has been marked as green during the
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index f824e4faf5d..358f25e2334 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -11,6 +11,10 @@ resolve_added_macro_use =
 resolve_ancestor_only =
     visibilities can only be restricted to ancestor modules
 
+resolve_anonymous_livetime_non_gat_report_error =
+    in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+    .label = this lifetime must come from the implemented type
+
 resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here
 
 resolve_associated_const_with_similar_name_exists =
@@ -234,6 +238,10 @@ resolve_items_in_traits_are_not_importable =
 resolve_label_with_similar_name_reachable =
     a label with a similar name is reachable
 
+resolve_lending_iterator_report_error =
+    associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+    .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type.
+
 resolve_lifetime_param_in_enum_discriminant =
     lifetime parameters may not be used in enum discriminant values
 
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index cad10571afe..ca97d10617b 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -2,6 +2,7 @@ use crate::{ImplTraitContext, Resolver};
 use rustc_ast::visit::FnKind;
 use rustc_ast::*;
 use rustc_expand::expand::AstFragment;
+use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::LocalDefId;
 use rustc_span::hygiene::LocalExpnId;
@@ -128,7 +129,11 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ItemKind::Union(..) => DefKind::Union,
             ItemKind::ExternCrate(..) => DefKind::ExternCrate,
             ItemKind::TyAlias(..) => DefKind::TyAlias,
-            ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false },
+            ItemKind::Static(s) => DefKind::Static {
+                safety: hir::Safety::Safe,
+                mutability: s.mutability,
+                nested: false,
+            },
             ItemKind::Const(..) => DefKind::Const,
             ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
             ItemKind::MacroDef(..) => {
@@ -211,8 +216,18 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         let def_kind = match fi.kind {
-            ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability, expr: _ }) => {
-                DefKind::Static { mutability, nested: false }
+            ForeignItemKind::Static(box StaticForeignItem {
+                ty: _,
+                mutability,
+                expr: _,
+                safety,
+            }) => {
+                let safety = match safety {
+                    ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
+                    ast::Safety::Safe(_) => hir::Safety::Safe,
+                };
+
+                DefKind::Static { safety, mutability, nested: false }
             }
             ForeignItemKind::Fn(_) => DefKind::Fn,
             ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
@@ -325,6 +340,16 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ExprKind::Gen(_, _, _) => {
                 self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
             }
+            ExprKind::ConstBlock(ref constant) => {
+                let def = self.create_def(
+                    constant.id,
+                    kw::Empty,
+                    DefKind::InlineConst,
+                    constant.value.span,
+                );
+                self.with_parent(def, |this| visit::walk_anon_const(this, constant));
+                return;
+            }
             _ => self.parent_def,
         };
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 856cfbc01e8..d1541527cf5 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1562,6 +1562,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
             Some(suggestion) => suggestion,
         };
+
+        let mut did_label_def_span = false;
+
         if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
             if span.overlaps(def_span) {
                 // Don't suggest typo suggestion for itself like in the following:
@@ -1595,31 +1598,38 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     errors::DefinedHere::SingleItem { span, candidate_descr, candidate }
                 }
             };
+            did_label_def_span = true;
             err.subdiagnostic(self.tcx.dcx(), label);
         }
 
-        let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
+        let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
             && let Some(span) = suggestion.span
             && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
             && snippet == candidate
         {
+            let candidate = suggestion.candidate;
             // When the suggested binding change would be from `x` to `_x`, suggest changing the
             // original binding definition instead. (#60164)
-            let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate);
-            (span, snippet, post)
-        } else {
-            (span, suggestion.candidate.to_ident_string(), String::new())
-        };
-        let msg = match suggestion.target {
-            SuggestionTarget::SimilarlyNamed => format!(
-                "{} {} with a similar name exists{post}",
-                suggestion.res.article(),
-                suggestion.res.descr()
-            ),
-            SuggestionTarget::SingleItem => {
-                format!("maybe you meant this {}", suggestion.res.descr())
+            let msg = format!(
+                "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
+            );
+            if !did_label_def_span {
+                err.span_label(span, format!("`{candidate}` defined here"));
             }
+            (span, msg, snippet)
+        } else {
+            let msg = match suggestion.target {
+                SuggestionTarget::SimilarlyNamed => format!(
+                    "{} {} with a similar name exists",
+                    suggestion.res.article(),
+                    suggestion.res.descr()
+                ),
+                SuggestionTarget::SingleItem => {
+                    format!("maybe you meant this {}", suggestion.res.descr())
+                }
+            };
+            (span, msg, suggestion.candidate.to_ident_string())
         };
         err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
         true
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index edfeacec7e3..0620f3d709e 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -882,6 +882,23 @@ pub(crate) struct ElidedAnonymousLivetimeReportError {
     pub(crate) suggestion: Option<ElidedAnonymousLivetimeReportErrorSuggestion>,
 }
 
+#[derive(Diagnostic)]
+#[diag(resolve_lending_iterator_report_error)]
+pub(crate) struct LendingIteratorReportError {
+    #[primary_span]
+    pub(crate) lifetime: Span,
+    #[note]
+    pub(crate) ty: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_anonymous_livetime_non_gat_report_error)]
+pub(crate) struct AnonymousLivetimeNonGatReportError {
+    #[primary_span]
+    #[label]
+    pub(crate) lifetime: Span,
+}
+
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(
     resolve_elided_anonymous_lifetime_report_error_suggestion,
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 57db765c07e..b6a23317dc9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -965,6 +965,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // if it can then our result is not determined and can be invalidated.
         for single_import in &resolution.single_imports {
             let Some(import_vis) = single_import.vis.get() else {
+                // This branch handles a cycle in single imports, which occurs
+                // when we've previously captured the `vis` value during an import
+                // process.
+                //
+                // For example:
+                // ```
+                // use a::b;
+                // use b as a;
+                // ```
+                // 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the
+                //    current module.
+                // 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
+                //    and try to find `b` in the current module.
+                // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
+                //    This leads to entering this branch.
                 continue;
             };
             if !self.is_accessible_from(import_vis, parent_scope.module) {
@@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 // named imports.
                 continue;
             }
+
             let Some(module) = single_import.imported_module.get() else {
                 return Err((Undetermined, Weak::No));
             };
-            let ImportKind::Single { source: ident, .. } = single_import.kind else {
+            let ImportKind::Single { source: ident, target, target_bindings, .. } =
+                &single_import.kind
+            else {
                 unreachable!();
             };
+            if (ident != target) && target_bindings.iter().all(|binding| binding.get().is_none()) {
+                // This branch allows the binding to be defined or updated later if the target name
+                // can hide the source but these bindings are not obtained.
+                // avoiding module inconsistency between the resolve process and the finalize process.
+                // See more details in #124840
+                return Err((Undetermined, Weak::No));
+            }
             match self.resolve_ident_in_module(
                 module,
-                ident,
+                *ident,
                 ns,
                 &single_import.parent_scope,
                 None,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 6bbde26db34..6c7afb305ba 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -259,13 +259,18 @@ struct UnresolvedImportError {
 
 // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
 // are permitted for backward-compatibility under a deprecation lint.
-fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool {
+fn pub_use_of_private_extern_crate_hack(
+    import: Import<'_>,
+    binding: NameBinding<'_>,
+) -> Option<NodeId> {
     match (&import.kind, &binding.kind) {
-        (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => {
-            matches!(binding_import.kind, ImportKind::ExternCrate { .. })
-                && import.expect_vis().is_public()
+        (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
+            if let ImportKind::ExternCrate { id, .. } = binding_import.kind
+                && import.expect_vis().is_public() =>
+        {
+            Some(id)
         }
-        _ => false,
+        _ => None,
     }
 }
 
@@ -275,7 +280,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
         let import_vis = import.expect_vis().to_def_id();
         let vis = if binding.vis.is_at_least(import_vis, self.tcx)
-            || pub_use_of_private_extern_crate_hack(import, binding)
+            || pub_use_of_private_extern_crate_hack(import, binding).is_some()
         {
             import_vis
         } else {
@@ -352,9 +357,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     (old_glob @ true, false) | (old_glob @ false, true) => {
                         let (glob_binding, nonglob_binding) =
                             if old_glob { (old_binding, binding) } else { (binding, old_binding) };
-                        if glob_binding.res() != nonglob_binding.res()
-                            && key.ns == MacroNS
+                        if key.ns == MacroNS
                             && nonglob_binding.expansion != LocalExpnId::ROOT
+                            && glob_binding.res() != nonglob_binding.res()
                         {
                             resolution.binding = Some(this.ambiguity(
                                 AmbiguityKind::GlobVsExpanded,
@@ -1253,12 +1258,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // All namespaces must be re-exported with extra visibility for an error to occur.
         if !any_successful_reexport {
             let (ns, binding) = reexport_error.unwrap();
-            if pub_use_of_private_extern_crate_hack(import, binding) {
+            if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import, binding) {
                 self.lint_buffer.buffer_lint(
                     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
                     import_id,
                     import.span,
-                    BuiltinLintDiag::PrivateExternCrateReexport(ident),
+                    BuiltinLintDiag::PrivateExternCrateReexport {
+                        source: ident,
+                        extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)),
+                    },
                 );
             } else {
                 if ns == TypeNS {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index bcf2c9a9206..b0adc3775f6 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -9,7 +9,7 @@
 use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
 use crate::{BindingKey, Used};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
-use crate::{ResolutionError, Resolver, Segment, UseError};
+use crate::{ResolutionError, Resolver, Segment, TyCtxt, UseError};
 
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
@@ -629,6 +629,9 @@ struct DiagMetadata<'ast> {
     in_assignment: Option<&'ast Expr>,
     is_assign_rhs: bool,
 
+    /// If we are setting an associated type in trait impl, is it a non-GAT type?
+    in_non_gat_assoc_type: Option<bool>,
+
     /// Used to detect possible `.` -> `..` typo when calling methods.
     in_range: Option<(&'ast Expr, &'ast Expr)>,
 
@@ -1703,10 +1706,35 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                 break;
                             }
                         }
-                        self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
-                            span: lifetime.ident.span,
-                            suggestion,
-                        });
+
+                        // are we trying to use an anonymous lifetime
+                        // on a non GAT associated trait type?
+                        if !self.in_func_body
+                            && let Some((module, _)) = &self.current_trait_ref
+                            && let Some(ty) = &self.diag_metadata.current_self_type
+                            && Some(true) == self.diag_metadata.in_non_gat_assoc_type
+                            && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
+                        {
+                            if def_id_matches_path(
+                                self.r.tcx,
+                                trait_id,
+                                &["core", "iter", "traits", "iterator", "Iterator"],
+                            ) {
+                                self.r.dcx().emit_err(errors::LendingIteratorReportError {
+                                    lifetime: lifetime.ident.span,
+                                    ty: ty.span(),
+                                });
+                            } else {
+                                self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
+                                    lifetime: lifetime.ident.span,
+                                });
+                            }
+                        } else {
+                            self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
+                                span: lifetime.ident.span,
+                                suggestion,
+                            });
+                        }
                     } else {
                         self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
                             span: lifetime.ident.span,
@@ -3058,6 +3086,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 );
             }
             AssocItemKind::Type(box TyAlias { generics, .. }) => {
+                self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
                 debug!("resolve_implementation AssocItemKind::Type");
                 // We also need a new scope for the impl item type parameters.
                 self.with_generic_param_rib(
@@ -3086,6 +3115,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         });
                     },
                 );
+                self.diag_metadata.in_non_gat_assoc_type = None;
             }
             AssocItemKind::Delegation(box delegation) => {
                 debug!("resolve_implementation AssocItemKind::Delegation");
@@ -4505,10 +4535,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 self.visit_expr(elem);
                 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
             }
-            ExprKind::ConstBlock(ref expr) => {
-                self.resolve_anon_const_manual(false, AnonConstKind::InlineConst, |this| {
-                    this.visit_expr(expr)
-                });
+            ExprKind::ConstBlock(ref ct) => {
+                self.resolve_anon_const(ct, AnonConstKind::InlineConst);
             }
             ExprKind::Index(ref elem, ref idx, _) => {
                 self.resolve_expr(elem, Some(expr));
@@ -4829,3 +4857,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 }
+
+/// Check if definition matches a path
+fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool {
+    let mut path = expected_path.iter().rev();
+    while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) {
+        if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) {
+            return false;
+        }
+        def_id = parent;
+    }
+    return true;
+}
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index ec24eac4a9d..9eeb0da7ed2 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2041,8 +2041,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
                         ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
                         ast::AssocItemKind::Delegation(..)
-                            if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
-                                .has_self =>
+                            if self
+                                .r
+                                .delegation_fn_sigs
+                                .get(&self.r.local_def_id(assoc_item.id))
+                                .map_or(false, |sig| sig.has_self) =>
                         {
                             AssocSuggestion::MethodWithSelf { called }
                         }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index d67132d2dd4..0be8b5d5718 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -68,6 +68,8 @@ fn compress<'tcx>(
 fn encode_args<'tcx>(
     tcx: TyCtxt<'tcx>,
     args: GenericArgsRef<'tcx>,
+    for_def: DefId,
+    has_erased_self: bool,
     dict: &mut FxHashMap<DictKey<'tcx>, usize>,
     options: EncodeTyOptions,
 ) -> String {
@@ -76,7 +78,8 @@ fn encode_args<'tcx>(
     let args: Vec<GenericArg<'_>> = args.iter().collect();
     if !args.is_empty() {
         s.push('I');
-        for arg in args {
+        let def_generics = tcx.generics_of(for_def);
+        for (n, arg) in args.iter().enumerate() {
             match arg.unpack() {
                 GenericArgKind::Lifetime(region) => {
                     s.push_str(&encode_region(region, dict));
@@ -85,7 +88,10 @@ fn encode_args<'tcx>(
                     s.push_str(&encode_ty(tcx, ty, dict, options));
                 }
                 GenericArgKind::Const(c) => {
-                    s.push_str(&encode_const(tcx, c, dict, options));
+                    let n = n + (has_erased_self as usize);
+                    let ct_ty =
+                        tcx.type_of(def_generics.param_at(n, tcx).def_id).instantiate_identity();
+                    s.push_str(&encode_const(tcx, c, ct_ty, dict, options));
                 }
             }
         }
@@ -99,6 +105,7 @@ fn encode_args<'tcx>(
 fn encode_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     c: Const<'tcx>,
+    ct_ty: Ty<'tcx>,
     dict: &mut FxHashMap<DictKey<'tcx>, usize>,
     options: EncodeTyOptions,
 ) -> String {
@@ -111,20 +118,20 @@ fn encode_const<'tcx>(
             // L<element-type>E as literal argument
 
             // Element type
-            s.push_str(&encode_ty(tcx, c.ty(), dict, options));
+            s.push_str(&encode_ty(tcx, ct_ty, dict, options));
         }
 
         // Literal arguments
-        ty::ConstKind::Value(..) => {
+        ty::ConstKind::Value(ct_ty, ..) => {
             // L<element-type>[n]<element-value>E as literal argument
 
             // Element type
-            s.push_str(&encode_ty(tcx, c.ty(), dict, options));
+            s.push_str(&encode_ty(tcx, ct_ty, dict, options));
 
             // The only allowed types of const values are bool, u8, u16, u32,
             // u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
             // bool value false is encoded as 0 and true as 1.
-            match c.ty().kind() {
+            match ct_ty.kind() {
                 ty::Int(ity) => {
                     let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
                     let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
@@ -142,7 +149,7 @@ fn encode_const<'tcx>(
                     let _ = write!(s, "{val}");
                 }
                 _ => {
-                    bug!("encode_const: unexpected type `{:?}`", c.ty());
+                    bug!("encode_const: unexpected type `{:?}`", ct_ty);
                 }
             }
         }
@@ -231,15 +238,21 @@ fn encode_predicate<'tcx>(
         ty::ExistentialPredicate::Trait(trait_ref) => {
             let name = encode_ty_name(tcx, trait_ref.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_args(tcx, trait_ref.args, dict, options));
+            s.push_str(&encode_args(tcx, trait_ref.args, trait_ref.def_id, true, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
             let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_args(tcx, projection.args, dict, options));
+            s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options));
             match projection.term.unpack() {
                 TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
-                TermKind::Const(c) => s.push_str(&encode_const(tcx, c, dict, options)),
+                TermKind::Const(c) => s.push_str(&encode_const(
+                    tcx,
+                    c,
+                    tcx.type_of(projection.def_id).instantiate(tcx, projection.args),
+                    dict,
+                    options,
+                )),
             }
         }
         ty::ExistentialPredicate::AutoTrait(def_id) => {
@@ -485,7 +498,7 @@ pub fn encode_ty<'tcx>(
                 // <subst>, as vendor extended type.
                 let name = encode_ty_name(tcx, def_id);
                 let _ = write!(s, "u{}{}", name.len(), &name);
-                s.push_str(&encode_args(tcx, args, dict, options));
+                s.push_str(&encode_args(tcx, args, def_id, false, dict, options));
                 compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             }
             typeid.push_str(&s);
@@ -529,7 +542,7 @@ pub fn encode_ty<'tcx>(
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
-            s.push_str(&encode_args(tcx, args, dict, options));
+            s.push_str(&encode_args(tcx, args, *def_id, false, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
         }
@@ -541,7 +554,7 @@ pub fn encode_ty<'tcx>(
             let name = encode_ty_name(tcx, *def_id);
             let _ = write!(s, "u{}{}", name.len(), &name);
             let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args());
-            s.push_str(&encode_args(tcx, parent_args, dict, options));
+            s.push_str(&encode_args(tcx, parent_args, *def_id, false, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
         }
@@ -556,6 +569,8 @@ pub fn encode_ty<'tcx>(
             s.push_str(&encode_args(
                 tcx,
                 tcx.mk_args(args.as_coroutine().parent_args()),
+                *def_id,
+                false,
                 dict,
                 options,
             ));
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 62eb07e8287..2fbfb93150e 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -367,7 +367,7 @@ pub fn transform_instance<'tcx>(
             let trait_method = tcx.associated_item(method_id);
             let trait_id = trait_ref.skip_binder().def_id;
             if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
-                && tcx.object_safety_violations(trait_id).is_empty()
+                && tcx.is_object_safe(trait_id)
             {
                 // Trait methods will have a Self polymorphic parameter, where the concreteized
                 // implementatation will not. We need to walk back to the more general trait method
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 9cb8cd836e6..6f63776bedc 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -12,7 +12,7 @@ use tracing::debug;
 pub struct FileSearch<'a> {
     sysroot: &'a Path,
     triple: &'a str,
-    search_paths: &'a [SearchPath],
+    cli_search_paths: &'a [SearchPath],
     tlib_path: &'a SearchPath,
     kind: PathKind,
 }
@@ -20,7 +20,7 @@ pub struct FileSearch<'a> {
 impl<'a> FileSearch<'a> {
     pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
         let kind = self.kind;
-        self.search_paths
+        self.cli_search_paths
             .iter()
             .filter(move |sp| sp.kind.matches(kind))
             .chain(std::iter::once(self.tlib_path))
@@ -37,26 +37,26 @@ impl<'a> FileSearch<'a> {
     pub fn new(
         sysroot: &'a Path,
         triple: &'a str,
-        search_paths: &'a [SearchPath],
+        cli_search_paths: &'a [SearchPath],
         tlib_path: &'a SearchPath,
         kind: PathKind,
     ) -> FileSearch<'a> {
         debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
-        FileSearch { sysroot, triple, search_paths, tlib_path, kind }
+        FileSearch { sysroot, triple, cli_search_paths, tlib_path, kind }
     }
 }
 
 pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
-    PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
+    let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot, target_triple);
+    sysroot.join(rustlib_path).join("lib")
 }
 
 /// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is
 /// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools,
 /// etc.
 pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
-    PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")])
+    let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot, target_triple);
+    sysroot.join(rustlib_path).join("bin")
 }
 
 #[cfg(unix)]
@@ -275,7 +275,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
                 p.pop();
                 p.pop();
                 // Look for the target rustlib directory in the suspected sysroot.
-                let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
+                let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
                 rustlib_path.pop(); // pop off the dummy target.
                 rustlib_path.exists().then_some(p)
             }
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 6ec710f97d1..c33a52f4a7a 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -5,17 +5,17 @@
 
 // Prefer importing stable_mir over internal rustc constructs to make this file more readable.
 use crate::rustc_smir::Tables;
-use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy, TyCtxt};
+use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt};
 use rustc_span::Symbol;
 use stable_mir::abi::Layout;
 use stable_mir::mir::alloc::AllocId;
 use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
 use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety, UnOp};
 use stable_mir::ty::{
-    Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
-    DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
-    GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Pattern, Region, RigidTy, Span,
-    TermKind, TraitRef, Ty, UintTy, VariantDef, VariantIdx,
+    Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind,
+    ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
+    GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy,
+    Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
 };
 use stable_mir::{CrateItem, CrateNum, DefId};
 
@@ -55,7 +55,7 @@ impl RustcInternal for GenericArgKind {
         let arg: rustc_ty::GenericArg<'tcx> = match self {
             GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(),
             GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(),
-            GenericArgKind::Const(cnst) => ty_const(cnst, tables, tcx).into(),
+            GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(),
         };
         tcx.lift(arg).unwrap()
     }
@@ -76,13 +76,20 @@ impl RustcInternal for Ty {
     }
 }
 
+impl RustcInternal for TyConst {
+    type T<'tcx> = InternalConst<'tcx>;
+    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+        tcx.lift(tables.ty_consts[self.id]).unwrap()
+    }
+}
+
 impl RustcInternal for Pattern {
     type T<'tcx> = rustc_ty::Pattern<'tcx>;
     fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
         tcx.mk_pat(match self {
             Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range {
-                start: start.as_ref().map(|c| ty_const(c, tables, tcx)),
-                end: end.as_ref().map(|c| ty_const(c, tables, tcx)),
+                start: start.as_ref().map(|c| c.internal(tables, tcx)),
+                end: end.as_ref().map(|c| c.internal(tables, tcx)),
                 include_end: *include_end,
             },
         })
@@ -101,7 +108,7 @@ impl RustcInternal for RigidTy {
             RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)),
             RigidTy::Never => rustc_ty::TyKind::Never,
             RigidTy::Array(ty, cnst) => {
-                rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx))
+                rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx))
             }
             RigidTy::Pat(ty, pat) => {
                 rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx))
@@ -239,25 +246,14 @@ impl RustcInternal for VariantDef {
     }
 }
 
-fn ty_const<'tcx>(
-    constant: &Const,
-    tables: &mut Tables<'_>,
-    tcx: TyCtxt<'tcx>,
-) -> rustc_ty::Const<'tcx> {
-    match constant.internal(tables, tcx) {
-        rustc_middle::mir::Const::Ty(c) => c,
-        cnst => {
-            panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}")
-        }
-    }
-}
-
-impl RustcInternal for Const {
+impl RustcInternal for MirConst {
     type T<'tcx> = rustc_middle::mir::Const<'tcx>;
     fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        let constant = tables.constants[self.id];
+        let constant = tables.mir_consts[self.id];
         match constant {
-            rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()),
+            rustc_middle::mir::Const::Ty(ty, ct) => {
+                rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap())
+            }
             rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
                 rustc_middle::mir::Const::Unevaluated(
                     tcx.lift(uneval).unwrap(),
@@ -392,7 +388,7 @@ impl RustcInternal for TermKind {
     fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
         match self {
             TermKind::Type(ty) => ty.internal(tables, tcx).into(),
-            TermKind::Const(const_) => ty_const(const_, tables, tcx).into(),
+            TermKind::Const(cnst) => cnst.internal(tables, tcx).into(),
         }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 6e870728baf..810ffc142a0 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -214,7 +214,8 @@ where
         spans: IndexMap::default(),
         types: IndexMap::default(),
         instances: IndexMap::default(),
-        constants: IndexMap::default(),
+        ty_consts: IndexMap::default(),
+        mir_consts: IndexMap::default(),
         layouts: IndexMap::default(),
     }));
     stable_mir::compiler_interface::run(&tables, || init(&tables, f))
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index fa7b2a30ba6..a8688c88601 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -6,7 +6,6 @@
 #![allow(rustc::usage_of_qualified_ty)]
 
 use rustc_abi::HasDataLayout;
-use rustc_middle::ty;
 use rustc_middle::ty::layout::{
     FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers,
 };
@@ -14,6 +13,7 @@ use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
 use rustc_middle::ty::{
     GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree,
 };
+use rustc_middle::{mir, ty};
 use rustc_span::def_id::LOCAL_CRATE;
 use stable_mir::abi::{FnAbi, Layout, LayoutShape};
 use stable_mir::compiler_interface::Context;
@@ -22,9 +22,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef};
 use stable_mir::mir::{BinOp, Body, Place, UnOp};
 use stable_mir::target::{MachineInfo, MachineSize};
 use stable_mir::ty::{
-    AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
-    ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind,
-    UintTy, VariantDef,
+    AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
+    ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty,
+    TyConst, TyKind, UintTy, VariantDef,
 };
 use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
 use std::cell::RefCell;
@@ -126,7 +126,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         iter::once(LOCAL_CRATE)
-            .chain(tables.tcx.used_crates(()).iter().copied())
+            .chain(tables.tcx.crates(()).iter().copied())
             .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter())
             .map(|impl_def_id| tables.impl_def(*impl_def_id))
             .collect()
@@ -201,19 +201,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
 
     fn external_crates(&self) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
-        tables
-            .tcx
-            .used_crates(())
-            .iter()
-            .map(|crate_num| smir_crate(tables.tcx, *crate_num))
-            .collect()
+        tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
     }
 
     fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
         let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
             .iter()
-            .chain(tables.tcx.used_crates(()).iter())
+            .chain(tables.tcx.crates(()).iter())
             .filter_map(|crate_num| {
                 let crate_name = tables.tcx.crate_name(*crate_num).to_string();
                 (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
@@ -360,7 +355,15 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect()
     }
 
-    fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error> {
+    fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let mir_const = cnst.internal(&mut *tables, tcx);
+        mir_const
+            .try_eval_target_usize(tables.tcx, ParamEnv::empty())
+            .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
+    }
+    fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let mir_const = cnst.internal(&mut *tables, tcx);
@@ -369,7 +372,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
     }
 
-    fn try_new_const_zst(&self, ty: Ty) -> Result<Const, Error> {
+    fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty_internal = ty.internal(&mut *tables, tcx);
@@ -390,25 +393,46 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             )));
         }
 
-        Ok(ty::Const::zero_sized(tables.tcx, ty_internal).stable(&mut *tables))
+        Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal))
+            .stable(&mut *tables))
     }
 
-    fn new_const_str(&self, value: &str) -> Const {
+    fn new_const_str(&self, value: &str) -> MirConst {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_static_str(tcx);
         let bytes = value.as_bytes();
         let val_tree = ty::ValTree::from_raw_bytes(tcx, bytes);
 
-        ty::Const::new_value(tcx, val_tree, ty).stable(&mut *tables)
+        let ct = ty::Const::new_value(tcx, val_tree, ty);
+        super::convert::mir_const_from_ty_const(&mut *tables, ct, ty)
     }
 
-    fn new_const_bool(&self, value: bool) -> Const {
+    fn new_const_bool(&self, value: bool) -> MirConst {
         let mut tables = self.0.borrow_mut();
-        ty::Const::from_bool(tables.tcx, value).stable(&mut *tables)
+        let ct = ty::Const::from_bool(tables.tcx, value);
+        let ty = tables.tcx.types.bool;
+        super::convert::mir_const_from_ty_const(&mut *tables, ct, ty)
     }
 
-    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<Const, Error> {
+    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
+        let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
+
+        // We don't use Const::from_bits since it doesn't have any error checking.
+        let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
+            Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`."))
+        })?;
+        let ct = ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty);
+        Ok(super::convert::mir_const_from_ty_const(&mut *tables, ct, ty))
+    }
+    fn try_new_ty_const_uint(
+        &self,
+        value: u128,
+        uint_ty: UintTy,
+    ) -> Result<stable_mir::ty::TyConst, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
@@ -453,7 +477,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .stable(&mut *tables)
     }
 
-    fn const_pretty(&self, cnst: &stable_mir::ty::Const) -> String {
+    fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         cnst.internal(&mut *tables, tcx).to_string()
@@ -474,6 +498,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         tables.types[ty].kind().stable(&mut *tables)
     }
 
+    fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
+        let tables = self.0.borrow_mut();
+        tables.ty_consts[ct].to_string()
+    }
+
     fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index a1a5c09ef0a..bcacf54baf3 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -6,7 +6,7 @@ use rustc_middle::mir::interpret::alloc_range;
 use rustc_middle::mir::mono::MonoItem;
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
-use stable_mir::ty::{Allocation, Const, ConstantKind};
+use stable_mir::ty::{Allocation, ConstantKind, MirConst};
 use stable_mir::{opaque, Error};
 
 use crate::rustc_smir::{alloc, Stable, Tables};
@@ -724,11 +724,16 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
 }
 
 impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
-    type T = stable_mir::ty::Const;
+    type T = stable_mir::ty::MirConst;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+        let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
         match *self {
-            mir::Const::Ty(c) => c.stable(tables),
+            mir::Const::Ty(ty, c) => MirConst::new(
+                stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
+                ty.stable(tables),
+                id,
+            ),
             mir::Const::Unevaluated(unev_const, ty) => {
                 let kind =
                     stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
@@ -737,21 +742,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
                         promoted: unev_const.promoted.map(|u| u.as_u32()),
                     });
                 let ty = ty.stable(tables);
-                let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
-                Const::new(kind, ty, id)
+                MirConst::new(kind, ty, id)
             }
             mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
                 let ty = ty.stable(tables);
-                let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
-                Const::new(ConstantKind::ZeroSized, ty, id)
+                MirConst::new(ConstantKind::ZeroSized, ty, id)
             }
             mir::Const::Val(val, ty) => {
                 let ty = tables.tcx.lift(ty).unwrap();
                 let val = tables.tcx.lift(val).unwrap();
                 let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
                 let ty = ty.stable(tables);
-                let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
-                Const::new(kind, ty, id)
+                MirConst::new(kind, ty, id)
             }
         }
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
index 736378a530f..50687935473 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
@@ -9,6 +9,8 @@ mod error;
 mod mir;
 mod ty;
 
+pub use ty::mir_const_from_ty_const;
+
 impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
     type T = stable_mir::mir::Safety;
     fn stable(&self, _: &mut Tables<'_>) -> Self::T {
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 66708def00f..73bc87dc9ab 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -3,8 +3,7 @@
 use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
 use stable_mir::ty::{
-    AdtKind, Const, ConstantKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy,
-    TyKind, UintTy,
+    AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy,
 };
 
 use crate::rustc_smir::{alloc, Stable, Tables};
@@ -410,45 +409,85 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
     }
 }
 
+pub fn mir_const_from_ty_const<'tcx>(
+    tables: &mut Tables<'tcx>,
+    ty_const: ty::Const<'tcx>,
+    ty: Ty<'tcx>,
+) -> stable_mir::ty::MirConst {
+    let kind = match ty_const.kind() {
+        ty::Value(ty, val) => {
+            let val = match val {
+                ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
+                ty::ValTree::Branch(branch) => {
+                    ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
+                }
+            };
+            let ty = tables.tcx.lift(ty).unwrap();
+            let const_val = tables.tcx.valtree_to_const_val((ty, val));
+            if matches!(const_val, mir::ConstValue::ZeroSized) {
+                stable_mir::ty::ConstantKind::ZeroSized
+            } else {
+                stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
+                    ty, const_val, tables,
+                ))
+            }
+        }
+        ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
+        ty::ErrorCt(_) => unreachable!(),
+        ty::InferCt(_) => unreachable!(),
+        ty::BoundCt(_, _) => unimplemented!(),
+        ty::PlaceholderCt(_) => unimplemented!(),
+        ty::Unevaluated(uv) => {
+            stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
+                def: tables.const_def(uv.def),
+                args: uv.args.stable(tables),
+                promoted: None,
+            })
+        }
+        ty::ExprCt(_) => unimplemented!(),
+    };
+    let stable_ty = tables.intern_ty(ty);
+    let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const));
+    stable_mir::ty::MirConst::new(kind, stable_ty, id)
+}
+
 impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
-    type T = stable_mir::ty::Const;
+    type T = stable_mir::ty::TyConst;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         let kind = match self.kind() {
-            ty::Value(val) => {
+            ty::Value(ty, val) => {
                 let val = match val {
                     ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
                     ty::ValTree::Branch(branch) => {
                         ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
                     }
                 };
-                let ty = tables.tcx.lift(self.ty()).unwrap();
+
+                let ty = tables.tcx.lift(ty).unwrap();
                 let const_val = tables.tcx.valtree_to_const_val((ty, val));
                 if matches!(const_val, mir::ConstValue::ZeroSized) {
-                    ConstantKind::ZeroSized
+                    stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables))
                 } else {
-                    stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
-                        ty, const_val, tables,
-                    ))
+                    stable_mir::ty::TyConstKind::Value(
+                        ty.stable(tables),
+                        alloc::new_allocation(ty, const_val, tables),
+                    )
                 }
             }
-            ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
+            ty::ParamCt(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)),
+            ty::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated(
+                tables.const_def(uv.def),
+                uv.args.stable(tables),
+            ),
             ty::ErrorCt(_) => unreachable!(),
             ty::InferCt(_) => unreachable!(),
             ty::BoundCt(_, _) => unimplemented!(),
             ty::PlaceholderCt(_) => unimplemented!(),
-            ty::Unevaluated(uv) => {
-                stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
-                    def: tables.const_def(uv.def),
-                    args: uv.args.stable(tables),
-                    promoted: None,
-                })
-            }
             ty::ExprCt(_) => unimplemented!(),
         };
-        let ty = self.ty().stable(tables);
-        let id = tables.intern_const(mir::Const::Ty(tables.tcx.lift(*self).unwrap()));
-        Const::new(kind, ty, id)
+        let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap());
+        stable_mir::ty::TyConst::new(kind, id)
     }
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index aba7e7dc9c2..d13e7803326 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use stable_mir::abi::Layout;
 use stable_mir::mir::mono::InstanceDef;
-use stable_mir::ty::{ConstId, Span};
+use stable_mir::ty::{MirConstId, Span, TyConstId};
 use stable_mir::{CtorKind, ItemKind};
 use std::ops::RangeInclusive;
 use tracing::debug;
@@ -33,7 +33,8 @@ pub struct Tables<'tcx> {
     pub(crate) spans: IndexMap<rustc_span::Span, Span>,
     pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
     pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
-    pub(crate) constants: IndexMap<mir::Const<'tcx>, ConstId>,
+    pub(crate) ty_consts: IndexMap<ty::Const<'tcx>, TyConstId>,
+    pub(crate) mir_consts: IndexMap<mir::Const<'tcx>, MirConstId>,
     pub(crate) layouts: IndexMap<rustc_target::abi::Layout<'tcx>, Layout>,
 }
 
@@ -42,8 +43,12 @@ impl<'tcx> Tables<'tcx> {
         self.types.create_or_fetch(ty)
     }
 
-    pub(crate) fn intern_const(&mut self, constant: mir::Const<'tcx>) -> ConstId {
-        self.constants.create_or_fetch(constant)
+    pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId {
+        self.ty_consts.create_or_fetch(ct)
+    }
+
+    pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId {
+        self.mir_consts.create_or_fetch(constant)
     }
 
     pub(crate) fn has_body(&self, instance: Instance<'tcx>) -> bool {
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index b2ca01fe3b9..99fcaf917fe 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -521,7 +521,7 @@ impl SpanData {
         Span::new(self.lo, hi, self.ctxt, self.parent)
     }
     #[inline]
-    pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
+    fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
         Span::new(self.lo, self.hi, ctxt, self.parent)
     }
     #[inline]
@@ -576,8 +576,9 @@ impl Span {
         self.data().with_hi(hi)
     }
     #[inline]
-    pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
-        self.data_untracked().with_ctxt(ctxt)
+    pub fn with_ctxt(mut self, ctxt: SyntaxContext) -> Span {
+        self.update_ctxt(|_| ctxt);
+        self
     }
     #[inline]
     pub fn parent(self) -> Option<LocalDefId> {
@@ -682,6 +683,13 @@ impl Span {
         if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None }
     }
 
+    /// Returns `Some(span)`, where the end is trimmed by the start of `other`.
+    pub fn trim_end(self, other: Span) -> Option<Span> {
+        let span = self.data();
+        let other = other.data();
+        if span.lo < other.lo { Some(span.with_hi(cmp::min(span.hi, other.lo))) } else { None }
+    }
+
     /// Returns the source span -- this is either the supplied span, or the span for
     /// the macro callsite that expanded to it.
     pub fn source_callsite(self) -> Span {
@@ -1051,9 +1059,9 @@ impl Span {
     }
 
     #[inline]
-    pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
-        let span = self.data();
-        span.with_ctxt(span.ctxt.apply_mark(expn_id, transparency))
+    pub fn apply_mark(mut self, expn_id: ExpnId, transparency: Transparency) -> Span {
+        self.update_ctxt(|ctxt| ctxt.apply_mark(expn_id, transparency));
+        self
     }
 
     #[inline]
@@ -1101,15 +1109,15 @@ impl Span {
     }
 
     #[inline]
-    pub fn normalize_to_macros_2_0(self) -> Span {
-        let span = self.data();
-        span.with_ctxt(span.ctxt.normalize_to_macros_2_0())
+    pub fn normalize_to_macros_2_0(mut self) -> Span {
+        self.update_ctxt(|ctxt| ctxt.normalize_to_macros_2_0());
+        self
     }
 
     #[inline]
-    pub fn normalize_to_macro_rules(self) -> Span {
-        let span = self.data();
-        span.with_ctxt(span.ctxt.normalize_to_macro_rules())
+    pub fn normalize_to_macro_rules(mut self) -> Span {
+        self.update_ctxt(|ctxt| ctxt.normalize_to_macro_rules());
+        self
     }
 }
 
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 788a52faf56..52a1267f891 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -87,6 +87,45 @@ pub struct Span {
     ctxt_or_parent_or_marker: u16,
 }
 
+impl Span {
+    #[inline]
+    fn data_inline_ctxt(self) -> SpanData {
+        let len = self.len_with_tag_or_marker as u32;
+        debug_assert!(len <= MAX_LEN);
+        SpanData {
+            lo: BytePos(self.lo_or_index),
+            hi: BytePos(self.lo_or_index.debug_strict_add(len)),
+            ctxt: SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32),
+            parent: None,
+        }
+    }
+    #[inline]
+    fn data_inline_parent(self) -> SpanData {
+        let len = (self.len_with_tag_or_marker & !PARENT_TAG) as u32;
+        debug_assert!(len <= MAX_LEN);
+        let parent = LocalDefId {
+            local_def_index: DefIndex::from_u32(self.ctxt_or_parent_or_marker as u32),
+        };
+        SpanData {
+            lo: BytePos(self.lo_or_index),
+            hi: BytePos(self.lo_or_index.debug_strict_add(len)),
+            ctxt: SyntaxContext::root(),
+            parent: Some(parent),
+        }
+    }
+    #[inline]
+    fn data_partially_interned(self) -> SpanData {
+        SpanData {
+            ctxt: SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32),
+            ..with_span_interner(|interner| interner.spans[self.lo_or_index as usize])
+        }
+    }
+    #[inline]
+    fn data_interned(self) -> SpanData {
+        with_span_interner(|interner| interner.spans[self.lo_or_index as usize])
+    }
+}
+
 // `MAX_LEN` is chosen so that `PARENT_TAG | MAX_LEN` is distinct from
 // `BASE_LEN_INTERNED_MARKER`. (If `MAX_LEN` was 1 higher, this wouldn't be true.)
 const MAX_LEN: u32 = 0b0111_1111_1111_1110;
@@ -111,42 +150,49 @@ impl Span {
             std::mem::swap(&mut lo, &mut hi);
         }
 
-        let (lo2, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32());
-
+        // Small len may enable one of fully inline formats (or may not).
+        let (len, ctxt32) = (hi.0 - lo.0, ctxt.as_u32());
         if len <= MAX_LEN {
-            if ctxt2 <= MAX_CTXT && parent.is_none() {
+            if ctxt32 <= MAX_CTXT && parent.is_none() {
                 // Inline-context format.
                 return Span {
-                    lo_or_index: lo2,
+                    lo_or_index: lo.0,
                     len_with_tag_or_marker: len as u16,
-                    ctxt_or_parent_or_marker: ctxt2 as u16,
+                    ctxt_or_parent_or_marker: ctxt32 as u16,
                 };
-            } else if ctxt2 == SyntaxContext::root().as_u32()
+            } else if ctxt32 == 0
                 && let Some(parent) = parent
-                && let parent2 = parent.local_def_index.as_u32()
-                && parent2 <= MAX_CTXT
+                && let parent32 = parent.local_def_index.as_u32()
+                && parent32 <= MAX_CTXT
             {
                 // Inline-parent format.
                 return Span {
-                    lo_or_index: lo2,
+                    lo_or_index: lo.0,
                     len_with_tag_or_marker: PARENT_TAG | len as u16,
-                    ctxt_or_parent_or_marker: parent2 as u16,
+                    ctxt_or_parent_or_marker: parent32 as u16,
                 };
             }
         }
 
-        // Partially-interned or fully-interned format.
-        let index =
-            with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }));
-        let ctxt_or_parent_or_marker = if ctxt2 <= MAX_CTXT {
-            ctxt2 as u16 // partially-interned
-        } else {
-            CTXT_INTERNED_MARKER // fully-interned
+        // Otherwise small ctxt may enable the partially inline format.
+        let index = |ctxt| {
+            with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }))
         };
-        Span {
-            lo_or_index: index,
-            len_with_tag_or_marker: BASE_LEN_INTERNED_MARKER,
-            ctxt_or_parent_or_marker,
+        if ctxt32 <= MAX_CTXT {
+            // Partially-interned format.
+            Span {
+                // Interned ctxt should never be read, so it can use any value.
+                lo_or_index: index(SyntaxContext::from_u32(u32::MAX)),
+                len_with_tag_or_marker: BASE_LEN_INTERNED_MARKER,
+                ctxt_or_parent_or_marker: ctxt32 as u16,
+            }
+        } else {
+            // Interned format.
+            Span {
+                lo_or_index: index(ctxt),
+                len_with_tag_or_marker: BASE_LEN_INTERNED_MARKER,
+                ctxt_or_parent_or_marker: CTXT_INTERNED_MARKER,
+            }
         }
     }
 
@@ -166,34 +212,17 @@ impl Span {
         if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
             if self.len_with_tag_or_marker & PARENT_TAG == 0 {
                 // Inline-context format.
-                let len = self.len_with_tag_or_marker as u32;
-                debug_assert!(len <= MAX_LEN);
-                SpanData {
-                    lo: BytePos(self.lo_or_index),
-                    hi: BytePos(self.lo_or_index.debug_strict_add(len)),
-                    ctxt: SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32),
-                    parent: None,
-                }
+                self.data_inline_ctxt()
             } else {
                 // Inline-parent format.
-                let len = (self.len_with_tag_or_marker & !PARENT_TAG) as u32;
-                debug_assert!(len <= MAX_LEN);
-                let parent = LocalDefId {
-                    local_def_index: DefIndex::from_u32(self.ctxt_or_parent_or_marker as u32),
-                };
-                SpanData {
-                    lo: BytePos(self.lo_or_index),
-                    hi: BytePos(self.lo_or_index.debug_strict_add(len)),
-                    ctxt: SyntaxContext::root(),
-                    parent: Some(parent),
-                }
+                self.data_inline_parent()
             }
+        } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
+            // Partially-interned format.
+            self.data_partially_interned()
         } else {
-            // Fully-interned or partially-interned format. In either case,
-            // the interned value contains all the data, so we don't need to
-            // distinguish them.
-            let index = self.lo_or_index;
-            with_span_interner(|interner| interner.spans[index as usize])
+            // Interned format.
+            self.data_interned()
         }
     }
 
@@ -214,26 +243,73 @@ impl Span {
         }
     }
 
+    // For optimization we are interested in cases in which the context is inline and the context
+    // update doesn't change format. All non-inline or format changing scenarios require accessing
+    // interner and can fall back to `Span::new`.
+    #[inline]
+    pub fn update_ctxt(&mut self, update: impl FnOnce(SyntaxContext) -> SyntaxContext) {
+        let (updated_ctxt32, data);
+        if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
+            if self.len_with_tag_or_marker & PARENT_TAG == 0 {
+                // Inline-context format.
+                updated_ctxt32 =
+                    update(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)).as_u32();
+                // Any small new context including zero will preserve the format.
+                if updated_ctxt32 <= MAX_CTXT {
+                    self.ctxt_or_parent_or_marker = updated_ctxt32 as u16;
+                    return;
+                }
+                data = self.data_inline_ctxt();
+            } else {
+                // Inline-parent format.
+                updated_ctxt32 = update(SyntaxContext::root()).as_u32();
+                // Only if the new context is zero the format will be preserved.
+                if updated_ctxt32 == 0 {
+                    // Do nothing.
+                    return;
+                }
+                data = self.data_inline_parent();
+            }
+        } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
+            // Partially-interned format.
+            updated_ctxt32 =
+                update(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)).as_u32();
+            // Any small new context excluding zero will preserve the format.
+            // Zero may change the format to `InlineParent` if parent and len are small enough.
+            if updated_ctxt32 <= MAX_CTXT && updated_ctxt32 != 0 {
+                self.ctxt_or_parent_or_marker = updated_ctxt32 as u16;
+                return;
+            }
+            data = self.data_partially_interned();
+        } else {
+            // Interned format.
+            data = self.data_interned();
+            updated_ctxt32 = update(data.ctxt).as_u32();
+        }
+
+        // We could not keep the span in the same inline format, fall back to the complete logic.
+        *self = data.with_ctxt(SyntaxContext::from_u32(updated_ctxt32));
+    }
+
     // Returns either syntactic context, if it can be retrieved without taking the interner lock,
     // or an index into the interner if it cannot.
+    #[inline]
     fn inline_ctxt(self) -> Result<SyntaxContext, usize> {
-        Ok(if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
+        if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
             if self.len_with_tag_or_marker & PARENT_TAG == 0 {
                 // Inline-context format.
-                SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)
+                Ok(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32))
             } else {
-                // Inline-parent format. We know that the SyntaxContext is root.
-                SyntaxContext::root()
+                // Inline-parent format.
+                Ok(SyntaxContext::root())
             }
         } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
-            // Partially-interned format. This path avoids looking up the
-            // interned value, and is the whole point of the
-            // partially-interned format.
-            SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)
+            // Partially-interned format.
+            Ok(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32))
         } else {
-            // Fully-interned format.
-            return Err(self.lo_or_index as usize);
-        })
+            // Interned format.
+            Err(self.lo_or_index as usize)
+        }
     }
 
     /// This function is used as a fast path when decoding the full `SpanData` is not necessary.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 61ca0d54ca4..e245dfb9f5d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -103,6 +103,7 @@ symbols! {
         MacroRules:         "macro_rules",
         Raw:                "raw",
         Reuse:              "reuse",
+        Safe:               "safe",
         Union:              "union",
         Yeet:               "yeet",
     }
@@ -1303,6 +1304,7 @@ symbols! {
         offset_of,
         offset_of_enum,
         offset_of_nested,
+        offset_of_slice,
         ok_or_else,
         omit_gdb_pretty_printer_section,
         on,
@@ -1961,9 +1963,11 @@ symbols! {
         unreachable_display,
         unreachable_macro,
         unrestricted_attribute_tokens,
+        unsafe_attributes,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
         unsafe_cell_raw_get,
+        unsafe_extern_blocks,
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
@@ -2213,6 +2217,7 @@ impl fmt::Display for IdentPrinter {
 pub struct MacroRulesNormalizedIdent(Ident);
 
 impl MacroRulesNormalizedIdent {
+    #[inline]
     pub fn new(ident: Ident) -> Self {
         Self(ident.normalize_to_macro_rules())
     }
diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs
index cb88fa89058..48fa786fb1c 100644
--- a/compiler/rustc_span/src/tests.rs
+++ b/compiler/rustc_span/src/tests.rs
@@ -42,3 +42,60 @@ fn test_normalize_newlines() {
     check("\r\r\n", "\r\n", &[2]);
     check("hello\rworld", "hello\rworld", &[]);
 }
+
+#[test]
+fn test_trim() {
+    let span = |lo: usize, hi: usize| {
+        Span::new(BytePos::from_usize(lo), BytePos::from_usize(hi), SyntaxContext::root(), None)
+    };
+
+    // Various positions, named for their relation to `start` and `end`.
+    let well_before = 1;
+    let before = 3;
+    let start = 5;
+    let mid = 7;
+    let end = 9;
+    let after = 11;
+    let well_after = 13;
+
+    // The resulting span's context should be that of `self`, not `other`.
+    let other = span(start, end).with_ctxt(SyntaxContext::from_u32(999));
+
+    // Test cases for `trim_end`.
+
+    assert_eq!(span(well_before, before).trim_end(other), Some(span(well_before, before)));
+    assert_eq!(span(well_before, start).trim_end(other), Some(span(well_before, start)));
+    assert_eq!(span(well_before, mid).trim_end(other), Some(span(well_before, start)));
+    assert_eq!(span(well_before, end).trim_end(other), Some(span(well_before, start)));
+    assert_eq!(span(well_before, after).trim_end(other), Some(span(well_before, start)));
+
+    assert_eq!(span(start, mid).trim_end(other), None);
+    assert_eq!(span(start, end).trim_end(other), None);
+    assert_eq!(span(start, after).trim_end(other), None);
+
+    assert_eq!(span(mid, end).trim_end(other), None);
+    assert_eq!(span(mid, after).trim_end(other), None);
+
+    assert_eq!(span(end, after).trim_end(other), None);
+
+    assert_eq!(span(after, well_after).trim_end(other), None);
+
+    // Test cases for `trim_start`.
+
+    assert_eq!(span(after, well_after).trim_start(other), Some(span(after, well_after)));
+    assert_eq!(span(end, well_after).trim_start(other), Some(span(end, well_after)));
+    assert_eq!(span(mid, well_after).trim_start(other), Some(span(end, well_after)));
+    assert_eq!(span(start, well_after).trim_start(other), Some(span(end, well_after)));
+    assert_eq!(span(before, well_after).trim_start(other), Some(span(end, well_after)));
+
+    assert_eq!(span(mid, end).trim_start(other), None);
+    assert_eq!(span(start, end).trim_start(other), None);
+    assert_eq!(span(before, end).trim_start(other), None);
+
+    assert_eq!(span(start, mid).trim_start(other), None);
+    assert_eq!(span(before, mid).trim_start(other), None);
+
+    assert_eq!(span(before, start).trim_start(other), None);
+
+    assert_eq!(span(well_before, before).trim_start(other), None);
+}
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 0ed1f67bb82..75cac6c7992 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -270,15 +270,15 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
 
     fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
         // only print integers
-        match (ct.kind(), ct.ty().kind()) {
-            (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
+        match ct.kind() {
+            ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) if ty.is_integral() => {
                 // The `pretty_print_const` formatting depends on -Zverbose-internals
                 // flag, so we cannot reuse it here.
-                let signed = matches!(ct.ty().kind(), ty::Int(_));
+                let signed = matches!(ty.kind(), ty::Int(_));
                 write!(
                     self,
                     "{:#?}",
-                    ty::ConstInt::new(scalar, signed, ct.ty().is_ptr_sized_integral())
+                    ty::ConstInt::new(scalar, signed, ty.is_ptr_sized_integral())
                 )?;
             }
             _ => self.write_str("_")?,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 57b1542ff5a..55479bce6fc 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -541,8 +541,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
     fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
         // We only mangle a typed value if the const can be evaluated.
         let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
-        match ct.kind() {
-            ty::ConstKind::Value(_) => {}
+        let (ct_ty, valtree) = match ct.kind() {
+            ty::ConstKind::Value(ty, val) => (ty, val),
 
             // Placeholders (should be demangled as `_`).
             // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
@@ -559,7 +559,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                 self.push("p");
                 return Ok(());
             }
-        }
+        };
 
         if let Some(&i) = self.consts.get(&ct) {
             self.print_backref(i)?;
@@ -567,16 +567,15 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         }
 
         let start = self.out.len();
-        let ty = ct.ty();
 
-        match ty.kind() {
+        match ct_ty.kind() {
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
-                ty.print(self)?;
+                ct_ty.print(self)?;
 
                 let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
 
                 // Negative integer values are mangled using `n` as a "sign prefix".
-                if let ty::Int(ity) = ty.kind() {
+                if let ty::Int(ity) = ct_ty.kind() {
                     let val =
                         Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
@@ -598,40 +597,32 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
 
                 match inner_ty.kind() {
                     ty::Str if mutbl.is_not() => {
-                        match ct.kind() {
-                            ty::ConstKind::Value(valtree) => {
-                                let slice =
-                                    valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
-                                        bug!(
-                                        "expected to get raw bytes from valtree {:?} for type {:}",
-                                        valtree, ty
-                                    )
-                                    });
-                                let s = std::str::from_utf8(slice)
-                                    .expect("non utf8 str from MIR interpreter");
-
-                                self.push("e");
-
-                                // FIXME(eddyb) use a specialized hex-encoding loop.
-                                for byte in s.bytes() {
-                                    let _ = write!(self.out, "{byte:02x}");
-                                }
-
-                                self.push("_");
-                            }
-
-                            _ => {
-                                bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
-                            }
+                        let slice =
+                            valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| {
+                                bug!(
+                                    "expected to get raw bytes from valtree {:?} for type {:}",
+                                    valtree,
+                                    ct_ty
+                                )
+                            });
+                        let s =
+                            std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
+
+                        self.push("e");
+
+                        // FIXME(eddyb) use a specialized hex-encoding loop.
+                        for byte in s.bytes() {
+                            let _ = write!(self.out, "{byte:02x}");
                         }
+
+                        self.push("_");
                     }
                     _ => {
-                        let pointee_ty = ct
-                            .ty()
+                        let pointee_ty = ct_ty
                             .builtin_deref(true)
                             .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);
+                        let dereferenced_const =
+                            ty::Const::new_value(self.tcx, valtree, pointee_ty);
                         dereferenced_const.print(self)?;
                     }
                 }
@@ -649,7 +640,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                     Ok(())
                 };
 
-                match *ct.ty().kind() {
+                match *ct_ty.kind() {
                     ty::Array(..) | ty::Slice(_) => {
                         self.push("A");
                         print_field_list(self)?;
@@ -698,7 +689,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                 }
             }
             _ => {
-                bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
+                bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct_ty, ct);
             }
         }
 
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 666efd9deca..737e9a8eab0 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -256,29 +256,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         Ty::is_transparent(self)
     }
 
-    pub fn offset_of_subfield<C, I>(self, cx: &C, indices: I) -> Size
-    where
-        Ty: TyAbiInterface<'a, C>,
-        I: Iterator<Item = (VariantIdx, FieldIdx)>,
-    {
-        let mut layout = self;
-        let mut offset = Size::ZERO;
-
-        for (variant, field) in indices {
-            layout = layout.for_variant(cx, variant);
-            let index = field.index();
-            offset += layout.fields.offset(index);
-            layout = layout.field(cx, index);
-            assert!(
-                layout.is_sized(),
-                "offset of unsized field (type {:?}) cannot be computed statically",
-                layout.ty
-            );
-        }
-
-        offset
-    }
-
     /// Finds the one field that is not a 1-ZST.
     /// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
     pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(usize, Self)>
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 46c83be9d95..ecc91ab9a31 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -41,17 +41,13 @@ const RUST_LIB_DIR: &str = "rustlib";
 ///
 /// For example: `target_sysroot_path("/usr", "x86_64-unknown-linux-gnu")` =>
 /// `"lib*/rustlib/x86_64-unknown-linux-gnu"`.
-pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    let libdir = find_libdir(sysroot);
-    PathBuf::from_iter([
-        Path::new(libdir.as_ref()),
-        Path::new(RUST_LIB_DIR),
-        Path::new(target_triple),
-    ])
+pub fn relative_target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
+    let libdir = find_relative_libdir(sysroot);
+    Path::new(libdir.as_ref()).join(RUST_LIB_DIR).join(target_triple)
 }
 
 /// The name of the directory rustc expects libraries to be located.
-fn find_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
+fn find_relative_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
     // FIXME: This is a quick hack to make the rustc binary able to locate
     // Rust libraries in Linux environments where libraries might be installed
     // to lib64/lib32. This would be more foolproof by basing the sysroot off
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 83ee63e2cf2..fe07d116726 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -3367,7 +3367,7 @@ impl Target {
 
                 // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
                 // as a fallback.
-                let rustlib_path = crate::target_rustlib_path(sysroot, target_triple);
+                let rustlib_path = crate::relative_target_rustlib_path(sysroot, target_triple);
                 let p = PathBuf::from_iter([
                     Path::new(sysroot),
                     Path::new(&rustlib_path),
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index fc852293dff..c95649e2ffb 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,14 +1,12 @@
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, ObligationCtxt, SelectionContext};
+use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
 
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::traits::Obligation;
 use rustc_macros::extension;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, Upcast};
 use rustc_span::DUMMY_SP;
@@ -94,7 +92,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
             )) {
                 Ok(Some(selection)) => {
-                    let ocx = ObligationCtxt::new(self);
+                    let ocx = ObligationCtxt::new_with_diagnostics(self);
                     ocx.register_obligations(selection.nested_obligations());
                     Some(ocx.select_all_or_error())
                 }
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 521e4ef0c9e..381da6f7e2a 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -23,7 +23,6 @@
 #![feature(extract_if)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![feature(option_take_if)]
 #![feature(never_type)]
 #![feature(type_alias_impl_trait)]
 #![recursion_limit = "512"] // For rustdoc
diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs
index 5e0d7da4f06..5f986e22f51 100644
--- a/compiler/rustc_trait_selection/src/regions.rs
+++ b/compiler/rustc_trait_selection/src/regions.rs
@@ -1,3 +1,4 @@
+use crate::traits::ScrubbedTraitError;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{InferCtxt, RegionResolutionError};
 use rustc_macros::extension;
@@ -27,7 +28,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     ),
                     ty,
                 )
-                .map_err(|_| NoSolution)
+                .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
             } else {
                 Ok(ty)
             }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index aae6fa9f635..b51efd339c4 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -714,7 +714,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         };
 
         // Do not consider built-in object impls for non-object-safe types.
-        if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
+        if bounds.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) {
             return;
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 48acf2a4e99..98f98d9992d 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -726,7 +726,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
                     )
                     .expect("expected to be able to unify goal projection with dyn's projection"),
             );
-            proj.term.ty().unwrap()
+            proj.term.expect_type()
         } else {
             ty.super_fold_with(self)
         }
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 690c1797f23..0e0b9e98339 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -444,7 +444,7 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt
                 infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
             }
             ty::GenericArgKind::Type(_) => infcx.next_ty_var(span).into(),
-            ty::GenericArgKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
+            ty::GenericArgKind::Const(_) => infcx.next_const_var(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 f18f1f4f8f0..b522022c206 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -37,11 +37,11 @@ pub(super) mod canonical;
 mod probe;
 mod select;
 
-pub struct EvalCtxt<
-    'a,
+pub struct EvalCtxt<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
+where
     Infcx: InferCtxtLike<Interner = I>,
-    I: Interner = <Infcx as InferCtxtLike>::Interner,
-> {
+    I: Interner,
+{
     /// The inference context that backs (mostly) inference and placeholder terms
     /// instantiated while solving goals.
     ///
@@ -609,8 +609,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         ty
     }
 
-    pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
-        let ct = self.infcx.next_const_var(ty, DUMMY_SP);
+    pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> {
+        let ct = self.infcx.next_const_var(DUMMY_SP);
         self.inspect.add_var_value(ct);
         ct
     }
@@ -620,7 +620,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
         match kind.unpack() {
             ty::TermKind::Ty(_) => self.next_ty_infer().into(),
-            ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
+            ty::TermKind::Const(_) => self.next_const_infer().into(),
         }
     }
 
@@ -1037,14 +1037,19 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         &self,
         param_env: ty::ParamEnv<'tcx>,
         unevaluated: ty::UnevaluatedConst<'tcx>,
-        ty: Ty<'tcx>,
     ) -> Option<ty::Const<'tcx>> {
         use rustc_middle::mir::interpret::ErrorHandled;
         match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) {
-            Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, ty)),
+            Ok(Some(val)) => Some(ty::Const::new_value(
+                self.interner(),
+                val,
+                self.interner()
+                    .type_of(unevaluated.def)
+                    .instantiate(self.interner(), unevaluated.args),
+            )),
             Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None,
             Err(ErrorHandled::Reported(e, _)) => {
-                Some(ty::Const::new_error(self.interner(), e.into(), ty))
+                Some(ty::Const::new_error(self.interner(), e.into()))
             }
         }
     }
@@ -1124,7 +1129,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         match ct.kind() {
             ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
-                let infer_ct = self.ecx.next_const_infer(ct.ty());
+                let infer_ct = self.ecx.next_const_infer();
                 let normalizes_to = ty::PredicateKind::AliasRelate(
                     ct.into(),
                     infer_ct.into(),
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index d28cf834032..dc13941e5d7 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,3 +1,4 @@
+use std::marker::PhantomData;
 use std::mem;
 use std::ops::ControlFlow;
 
@@ -5,14 +6,16 @@ use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
-    self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
-    ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
+    self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause,
+    ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
 };
 use rustc_middle::bug;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::sym;
 
+use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError};
+
 use super::eval_ctxt::GenerateProofTree;
 use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
 use super::{Certainty, InferCtxtEvalExt};
@@ -28,7 +31,7 @@ use super::{Certainty, InferCtxtEvalExt};
 ///
 /// It is also likely that we want to use slightly different datastructures
 /// here as this will have to deal with far more root goals than `evaluate_all`.
-pub struct FulfillmentCtxt<'tcx> {
+pub struct FulfillmentCtxt<'tcx, E: 'tcx> {
     obligations: ObligationStorage<'tcx>,
 
     /// The snapshot in which this context was created. Using the context
@@ -36,6 +39,7 @@ pub struct FulfillmentCtxt<'tcx> {
     /// gets rolled back. Because of this we explicitly check that we only
     /// use the context in exactly this snapshot.
     usable_in_snapshot: usize,
+    _errors: PhantomData<E>,
 }
 
 #[derive(Default)]
@@ -89,8 +93,8 @@ impl<'tcx> ObligationStorage<'tcx> {
     }
 }
 
-impl<'tcx> FulfillmentCtxt<'tcx> {
-    pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
+impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> {
+    pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> {
         assert!(
             infcx.next_trait_solver(),
             "new trait solver fulfillment context created when \
@@ -99,6 +103,7 @@ impl<'tcx> FulfillmentCtxt<'tcx> {
         FulfillmentCtxt {
             obligations: Default::default(),
             usable_in_snapshot: infcx.num_open_snapshots(),
+            _errors: PhantomData,
         }
     }
 
@@ -118,7 +123,10 @@ impl<'tcx> FulfillmentCtxt<'tcx> {
     }
 }
 
-impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
+impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentCtxt<'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     #[instrument(level = "trace", skip(self, infcx))]
     fn register_predicate_obligation(
         &mut self,
@@ -129,24 +137,22 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
         self.obligations.register(obligation);
     }
 
-    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
-        let mut errors: Vec<_> = self
-            .obligations
+    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
+        self.obligations
             .pending
             .drain(..)
-            .map(|obligation| fulfillment_error_for_stalled(infcx, obligation))
-            .collect();
-
-        errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            obligation: find_best_leaf_obligation(infcx, &obligation, true),
-            code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
-            root_obligation: obligation,
-        }));
-
-        errors
+            .map(|obligation| NextSolverError::Ambiguity(obligation))
+            .chain(
+                self.obligations
+                    .overflowed
+                    .drain(..)
+                    .map(|obligation| NextSolverError::Overflow(obligation)),
+            )
+            .map(|e| E::from_solver_error(infcx, e))
+            .collect()
     }
 
-    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         let mut errors = Vec::new();
         for i in 0.. {
@@ -164,7 +170,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                 let (changed, certainty) = match result {
                     Ok(result) => result,
                     Err(NoSolution) => {
-                        errors.push(fulfillment_error_for_no_solution(infcx, obligation));
+                        errors.push(E::from_solver_error(
+                            infcx,
+                            NextSolverError::TrueError(obligation),
+                        ));
                         continue;
                     }
                 };
@@ -195,6 +204,39 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
     }
 }
 
+pub enum NextSolverError<'tcx> {
+    TrueError(PredicateObligation<'tcx>),
+    Ambiguity(PredicateObligation<'tcx>),
+    Overflow(PredicateObligation<'tcx>),
+}
+
+impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tcx> {
+    fn from_solver_error(infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self {
+        match error {
+            NextSolverError::TrueError(obligation) => {
+                fulfillment_error_for_no_solution(infcx, obligation)
+            }
+            NextSolverError::Ambiguity(obligation) => {
+                fulfillment_error_for_stalled(infcx, obligation)
+            }
+            NextSolverError::Overflow(obligation) => {
+                fulfillment_error_for_overflow(infcx, obligation)
+            }
+        }
+    }
+}
+
+impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
+    fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self {
+        match error {
+            NextSolverError::TrueError(_) => ScrubbedTraitError::TrueError,
+            NextSolverError::Ambiguity(_) | NextSolverError::Overflow(_) => {
+                ScrubbedTraitError::Ambiguity
+            }
+        }
+    }
+}
+
 fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
     root_obligation: PredicateObligation<'tcx>,
@@ -280,6 +322,17 @@ fn fulfillment_error_for_stalled<'tcx>(
     }
 }
 
+fn fulfillment_error_for_overflow<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    root_obligation: PredicateObligation<'tcx>,
+) -> FulfillmentError<'tcx> {
+    FulfillmentError {
+        obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
+        code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
+        root_obligation,
+    }
+}
+
 fn find_best_leaf_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 1f27978e5a6..19c95dad48c 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -208,7 +208,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
                     let unconstrained_term = match term.unpack() {
                         ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
-                        ty::TermKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
+                        ty::TermKind::Const(_) => infcx.next_const_var(span).into(),
                     };
                     let goal =
                         goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index f9febd290fe..c47b0194964 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -40,7 +40,7 @@ mod search_graph;
 mod trait_goals;
 
 pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
-pub use fulfill::FulfillmentCtxt;
+pub use fulfill::{FulfillmentCtxt, NextSolverError};
 pub(crate) use normalize::deeply_normalize_for_diagnostics;
 pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
 
@@ -133,7 +133,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     }
 
     fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> {
-        if self.interner().check_is_object_safe(trait_def_id) {
+        if self.interner().is_object_safe(trait_def_id) {
             self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         } else {
             Err(NoSolution)
@@ -169,7 +169,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
 
                 // FIXME(generic_const_exprs): Implement handling for generic
                 // const expressions here.
-                if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) {
+                if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv) {
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 } else {
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
@@ -178,7 +178,9 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
             ty::ConstKind::Infer(_) => {
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
             }
-            ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {
+            ty::ConstKind::Placeholder(_)
+            | ty::ConstKind::Value(_, _)
+            | ty::ConstKind::Error(_) => {
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
             // We can freely ICE here as:
@@ -198,29 +200,37 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     ) -> QueryResult<'tcx> {
         let (ct, ty) = goal.predicate;
 
-        // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
-        // other than `ConstKind::Value`. Unfortunately this would require looking in the
-        // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
-        // have not yet gotten around to implementing this though.
-        //
-        // We do still stall on infer vars though as otherwise a goal like:
-        // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
-        // get unified with some const that is not of type `usize`.
-        match ct.kind() {
+        let ct_ty = match ct.kind() {
             // FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
             // and if we stall on the var then we wind up creating ambiguity errors in a probe
             // for this goal which contains an effect var. Which then ends up ICEing.
-            ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
-                self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+            ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
+                return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+            }
+            ty::ConstKind::Infer(_) => {
+                return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
             }
             ty::ConstKind::Error(_) => {
-                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+                return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
             }
-            _ => {
-                self.eq(goal.param_env, ct.ty(), ty)?;
-                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            ty::ConstKind::Unevaluated(uv) => {
+                self.interner().type_of(uv.def).instantiate(self.interner(), uv.args)
             }
-        }
+            ty::ConstKind::Expr(_) => unimplemented!(
+                "`feature(generic_const_exprs)` is not supported in the new trait solver"
+            ),
+            ty::ConstKind::Param(_) => {
+                unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`")
+            }
+            ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
+            ty::ConstKind::Value(ty, _) => ty,
+            ty::ConstKind::Placeholder(placeholder) => {
+                placeholder.find_const_ty_from_env(goal.param_env)
+            }
+        };
+
+        self.eq(goal.param_env, ct_ty, ty)?;
+        self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 5d5161e092e..f42edebfcc4 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,24 +1,27 @@
+use std::fmt::Debug;
+use std::marker::PhantomData;
+
 use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
+use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::TraitEngineExt;
-use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
+use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
 
-use super::FulfillmentCtxt;
+use super::{FulfillmentCtxt, NextSolverError};
 
 /// Deeply normalize all aliases in `value`. This does not handle inference and expects
 /// its input to be already fully resolved.
-pub fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
-    at: At<'_, 'tcx>,
-    value: T,
-) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+pub fn deeply_normalize<'tcx, T, E>(at: At<'_, 'tcx>, value: T) -> Result<T, Vec<E>>
+where
+    T: TypeFoldable<TyCtxt<'tcx>>,
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     assert!(!value.has_escaping_bound_vars());
     deeply_normalize_with_skipped_universes(at, value, vec![])
 }
@@ -29,29 +32,35 @@ pub fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
 /// Additionally takes a list of universes which represents the binders which have been
 /// entered before passing `value` to the function. This is currently needed for
 /// `normalize_erasing_regions`, which skips binders as it walks through a type.
-pub fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
+pub fn deeply_normalize_with_skipped_universes<'tcx, T, E>(
     at: At<'_, 'tcx>,
     value: T,
     universes: Vec<Option<UniverseIndex>>,
-) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+) -> Result<T, Vec<E>>
+where
+    T: TypeFoldable<TyCtxt<'tcx>>,
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let fulfill_cx = FulfillmentCtxt::new(at.infcx);
-    let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes };
+    let mut folder =
+        NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
 
     value.try_fold_with(&mut folder)
 }
 
-struct NormalizationFolder<'me, 'tcx> {
+struct NormalizationFolder<'me, 'tcx, E> {
     at: At<'me, 'tcx>,
-    fulfill_cx: FulfillmentCtxt<'tcx>,
+    fulfill_cx: FulfillmentCtxt<'tcx, E>,
     depth: usize,
     universes: Vec<Option<UniverseIndex>>,
+    _errors: PhantomData<E>,
 }
 
-impl<'tcx> NormalizationFolder<'_, 'tcx> {
-    fn normalize_alias_ty(
-        &mut self,
-        alias_ty: Ty<'tcx>,
-    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
+    fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
         assert!(matches!(alias_ty.kind(), ty::Alias(..)));
 
         let infcx = self.at.infcx;
@@ -100,9 +109,8 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
     fn normalize_unevaluated_const(
         &mut self,
-        ty: Ty<'tcx>,
         uv: ty::UnevaluatedConst<'tcx>,
-    ) -> Result<ty::Const<'tcx>, Vec<FulfillmentError<'tcx>>> {
+    ) -> Result<ty::Const<'tcx>, Vec<E>> {
         let infcx = self.at.infcx;
         let tcx = infcx.tcx;
         let recursion_limit = tcx.recursion_limit();
@@ -117,7 +125,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
 
         self.depth += 1;
 
-        let new_infer_ct = infcx.next_const_var(ty, self.at.cause.span);
+        let new_infer_ct = infcx.next_const_var(self.at.cause.span);
         let obligation = Obligation::new(
             tcx,
             self.at.cause.clone(),
@@ -134,7 +142,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
             let ct = infcx.resolve_vars_if_possible(new_infer_ct);
             ct.try_fold_with(self)?
         } else {
-            ty::Const::new_unevaluated(tcx, uv, ty).try_super_fold_with(self)?
+            ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)?
         };
 
         self.depth -= 1;
@@ -142,8 +150,11 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
     }
 }
 
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
-    type Error = Vec<FulfillmentError<'tcx>>;
+impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>> + Debug,
+{
+    type Error = Vec<E>;
 
     fn interner(&self) -> TyCtxt<'tcx> {
         self.at.infcx.tcx
@@ -202,7 +213,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
         if uv.has_escaping_bound_vars() {
             let (uv, mapped_regions, mapped_types, mapped_consts) =
                 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
-            let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))?;
+            let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
             Ok(PlaceholderReplacer::replace_placeholders(
                 infcx,
                 mapped_regions,
@@ -212,7 +223,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
                 result,
             ))
         } else {
-            ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))
+            ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
         }
     }
 }
@@ -243,7 +254,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
             ty,
             vec![None; ty.outer_exclusive_binder().as_usize()],
         )
-        .unwrap_or_else(|_| ty.super_fold_with(self))
+        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
@@ -252,6 +263,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
             ct,
             vec![None; ct.outer_exclusive_binder().as_usize()],
         )
-        .unwrap_or_else(|_| ct.super_fold_with(self))
+        .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
index 362c4072278..a6e4b6ff4a8 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
@@ -12,10 +12,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         if let Some(normalized_const) = self.try_const_eval_resolve(
             goal.param_env,
             ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args),
-            self.interner()
-                .type_of(goal.predicate.alias.def_id)
-                .no_bound_vars()
-                .expect("const ty should not rely on other generics"),
         ) {
             self.instantiate_normalizes_to_term(goal, normalized_const.into());
             self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
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 8c63bd824bc..787f08a084e 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -201,13 +201,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| {
                 let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
                 let error_term = match assoc_def.item.kind {
-                    ty::AssocKind::Const => ty::Const::new_error(
-                        tcx,
-                        guar,
-                        tcx.type_of(goal.predicate.def_id())
-                            .instantiate(tcx, goal.predicate.alias.args),
-                    )
-                    .into(),
+                    ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(),
                     ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
                     // This makes no sense...
                     ty::AssocKind::Fn => span_bug!(
@@ -253,7 +247,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                         ty::EarlyBinder::bind(
                             ty::Const::new_error_with_message(
                                 tcx,
-                                tcx.type_of(assoc_def.item.def_id).instantiate_identity(),
                                 DUMMY_SP,
                                 "associated const projection is not supported yet",
                             )
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
index 67ec2f3be48..82464470b2a 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
@@ -17,7 +17,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     ) -> QueryResult<'tcx> {
         let tcx = self.interner();
         let opaque_ty = goal.predicate.alias;
-        let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
+        let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
 
         match (goal.param_env.reveal(), self.solver_mode()) {
             (Reveal::UserFacing, SolverMode::Normal) => {
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index e93d5c96b88..a741f488901 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -789,7 +789,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         let Goal { predicate: (a_ty, _), .. } = goal;
 
         // Can only unsize to an object-safe trait.
-        if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
+        if b_data.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) {
             return Err(NoSolution);
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 1ea207cc375..1d32ef2ccd9 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -553,7 +553,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
     }
 
     fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool {
-        if let Some(ty) = p.term().skip_binder().ty() {
+        if let Some(ty) = p.term().skip_binder().as_type() {
             matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_term.expect_ty(self.tcx))
         } else {
             false
@@ -765,7 +765,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                                 unevaluated,
                                 obligation.cause.span,
                             ) {
-                                Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, c.ty())),
+                                Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args))),
                                 Ok(None) => {
                                     let tcx = self.tcx;
                                     let reported =
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index ebdb032dc0e..1ef2f26cd09 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -11,6 +11,7 @@ use crate::solve::{deeply_normalize_for_diagnostics, inspect};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::NormalizeExt;
 use crate::traits::SkipLeakCheck;
+use crate::traits::{util, FulfillmentErrorCode};
 use crate::traits::{
     Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
 };
@@ -19,7 +20,6 @@ use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::{util, FulfillmentErrorCode};
 use rustc_middle::bug;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
@@ -360,7 +360,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
     let infcx = selcx.infcx;
 
     if infcx.next_trait_solver() {
-        let ocx = ObligationCtxt::new(infcx);
+        let ocx = ObligationCtxt::new_with_diagnostics(infcx);
         ocx.register_obligations(obligations.iter().cloned());
         let errors_and_ambiguities = ocx.select_all_or_error();
         // We only care about the obligations that are *definitely* true errors.
@@ -529,7 +529,6 @@ fn plug_infer_with_placeholders<'tcx>(
                         ty::Const::new_placeholder(
                             self.infcx.tcx,
                             ty::Placeholder { universe: self.universe, bound: self.next_var() },
-                            ct.ty(),
                         ),
                     )
                 else {
@@ -924,11 +923,12 @@ where
                 }
             }
 
-            ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => {
-                if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) {
-                    bug!("unexpected ty param in alias ty");
-                }
-
+            // A rigid alias may normalize to anything.
+            // * If it references an infer var, placeholder or bound ty, it may
+            //   normalize to that, so we have to treat it as an uncovered ty param.
+            // * Otherwise it may normalize to any non-type-generic type
+            //   be it local or non-local.
+            ty::Alias(kind, _) => {
                 if ty.has_type_flags(
                     ty::TypeFlags::HAS_TY_PLACEHOLDER
                         | ty::TypeFlags::HAS_TY_BOUND
@@ -948,7 +948,24 @@ where
                         }
                     }
                 } else {
-                    ControlFlow::Continue(())
+                    // Regarding *opaque types* specifically, we choose to treat them as non-local,
+                    // even those that appear within the same crate. This seems somewhat surprising
+                    // at first, but makes sense when you consider that opaque types are supposed
+                    // to hide the underlying type *within the same crate*. When an opaque type is
+                    // used from outside the module where it is declared, it should be impossible to
+                    // observe anything about it other than the traits that it implements.
+                    //
+                    // The alternative would be to look at the underlying type to determine whether
+                    // or not the opaque type itself should be considered local.
+                    //
+                    // However, this could make it a breaking change to switch the underlying hidden
+                    // type from a local type to a remote type. This would violate the rule that
+                    // opaque types should be completely opaque apart from the traits that they
+                    // implement, so we don't use this behavior.
+                    // Addendum: Moreover, revealing the underlying type is likely to cause cycle
+                    // errors as we rely on coherence / the specialization graph during typeck.
+
+                    self.found_non_local_ty(ty)
                 }
             }
 
@@ -990,35 +1007,6 @@ where
             // auto trait impl applies. There will never be multiple impls, so we can just
             // act as if it were a local type here.
             ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
-            ty::Alias(ty::Opaque, ..) => {
-                // This merits some explanation.
-                // Normally, opaque types are not involved when performing
-                // coherence checking, since it is illegal to directly
-                // implement a trait on an opaque type. However, we might
-                // end up looking at an opaque type during coherence checking
-                // if an opaque type gets used within another type (e.g. as
-                // the type of a field) when checking for auto trait or `Sized`
-                // impls. This requires us to decide whether or not an opaque
-                // type should be considered 'local' or not.
-                //
-                // We choose to treat all opaque types as non-local, even
-                // those that appear within the same crate. This seems
-                // somewhat surprising at first, but makes sense when
-                // you consider that opaque types are supposed to hide
-                // the underlying type *within the same crate*. When an
-                // opaque type is used from outside the module
-                // where it is declared, it should be impossible to observe
-                // anything about it other than the traits that it implements.
-                //
-                // The alternative would be to look at the underlying type
-                // to determine whether or not the opaque type itself should
-                // be considered local. However, this could make it a breaking change
-                // to switch the underlying ('defining') type from a local type
-                // to a remote type. This would violate the rule that opaque
-                // types should be completely opaque apart from the traits
-                // that they implement, so we don't use this behavior.
-                self.found_non_local_ty(ty)
-            }
         };
         // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
         // the first type we visit is always the self type.
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 8348482386f..f93bd0a396d 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -34,7 +34,7 @@ pub fn is_const_evaluatable<'tcx>(
         ty::ConstKind::Param(_)
         | ty::ConstKind::Bound(_, _)
         | ty::ConstKind::Placeholder(_)
-        | ty::ConstKind::Value(_)
+        | ty::ConstKind::Value(_, _)
         | ty::ConstKind::Error(_) => return Ok(()),
         ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
     };
@@ -173,8 +173,7 @@ fn satisfied_from_param_env<'tcx>(
             debug!("is_const_evaluatable: candidate={:?}", c);
             if self.infcx.probe(|_| {
                 let ocx = ObligationCtxt::new(self.infcx);
-                ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
-                    && ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
+                ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
                     && ocx.select_all_or_error().is_empty()
             }) {
                 self.single_match = match self.single_match {
@@ -215,7 +214,6 @@ fn satisfied_from_param_env<'tcx>(
 
     if let Some(Ok(c)) = single_match {
         let ocx = ObligationCtxt::new(infcx);
-        assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
         assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
         assert!(ocx.select_all_or_error().is_empty());
         return true;
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 4684c7171d8..811f61d2bf3 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -1,13 +1,16 @@
 use std::cell::RefCell;
 use std::fmt::Debug;
 
-use super::FulfillmentContext;
-use super::TraitEngine;
+use super::{FromSolverError, TraitEngine};
+use super::{FulfillmentContext, ScrubbedTraitError};
 use crate::regions::InferCtxtRegionExt;
 use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
+use crate::solve::NextSolverError;
 use crate::traits::error_reporting::TypeErrCtxtExt;
+use crate::traits::fulfill::OldSolverError;
 use crate::traits::NormalizeExt;
 use crate::traits::StructurallyNormalizeExt;
+use crate::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -18,9 +21,6 @@ use rustc_infer::infer::canonical::{
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::RegionResolutionError;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_infer::traits::{
-    FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
-};
 use rustc_macros::extension;
 use rustc_middle::arena::ArenaAllocatable;
 use rustc_middle::traits::query::NoSolution;
@@ -30,8 +30,11 @@ use rustc_middle::ty::Upcast;
 use rustc_middle::ty::Variance;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-#[extension(pub trait TraitEngineExt<'tcx>)]
-impl<'tcx> dyn TraitEngine<'tcx> {
+#[extension(pub trait TraitEngineExt<'tcx, E>)]
+impl<'tcx, E> dyn TraitEngine<'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
+{
     fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
         if infcx.next_trait_solver() {
             Box::new(NextFulfillmentCtxt::new(infcx))
@@ -49,16 +52,27 @@ impl<'tcx> dyn TraitEngine<'tcx> {
 
 /// Used if you want to have pleasant experience when dealing
 /// with obligations outside of hir or mir typeck.
-pub struct ObligationCtxt<'a, 'tcx> {
+pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError<'tcx>> {
     pub infcx: &'a InferCtxt<'tcx>,
-    engine: RefCell<Box<dyn TraitEngine<'tcx>>>,
+    engine: RefCell<Box<dyn TraitEngine<'tcx, E>>>,
 }
 
-impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
+impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> {
+    pub fn new_with_diagnostics(infcx: &'a InferCtxt<'tcx>) -> Self {
+        Self { infcx, engine: RefCell::new(<dyn TraitEngine<'tcx, _>>::new(infcx)) }
+    }
+}
+
+impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> {
     pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
-        Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx)) }
+        Self { infcx, engine: RefCell::new(<dyn TraitEngine<'tcx, _>>::new(infcx)) }
     }
+}
 
+impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
+where
+    E: 'tcx,
+{
     pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
         self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
     }
@@ -110,26 +124,6 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         self.register_infer_ok_obligations(infer_ok)
     }
 
-    pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        value: T,
-    ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
-        self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
-    }
-
-    pub fn structurally_normalize(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        value: Ty<'tcx>,
-    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
-        self.infcx
-            .at(cause, param_env)
-            .structurally_normalize(value, &mut **self.engine.borrow_mut())
-    }
-
     pub fn eq<T: ToTrace<'tcx>>(
         &self,
         cause: &ObligationCause<'tcx>,
@@ -186,12 +180,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
     }
 
     #[must_use]
-    pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
+    pub fn select_where_possible(&self) -> Vec<E> {
         self.engine.borrow_mut().select_where_possible(self.infcx)
     }
 
     #[must_use]
-    pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
+    pub fn select_all_or_error(&self) -> Vec<E> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
 
@@ -235,7 +229,9 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
     ) -> Vec<RegionResolutionError<'tcx>> {
         self.infcx.resolve_regions(outlives_env)
     }
+}
 
+impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
     pub fn assumed_wf_types_and_report_errors(
         &self,
         param_env: ty::ParamEnv<'tcx>,
@@ -244,12 +240,35 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         self.assumed_wf_types(param_env, def_id)
             .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
     }
+}
+
+impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> {
+    pub fn make_canonicalized_query_response<T>(
+        &self,
+        inference_vars: CanonicalVarValues<'tcx>,
+        answer: T,
+    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
+    where
+        T: Debug + TypeFoldable<TyCtxt<'tcx>>,
+        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
+    {
+        self.infcx.make_canonicalized_query_response(
+            inference_vars,
+            answer,
+            &mut **self.engine.borrow_mut(),
+        )
+    }
+}
 
+impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     pub fn assumed_wf_types(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         def_id: LocalDefId,
-    ) -> Result<FxIndexSet<Ty<'tcx>>, Vec<FulfillmentError<'tcx>>> {
+    ) -> Result<FxIndexSet<Ty<'tcx>>, Vec<E>> {
         let tcx = self.infcx.tcx;
         let mut implied_bounds = FxIndexSet::default();
         let mut errors = Vec::new();
@@ -281,19 +300,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
     }
 
-    pub fn make_canonicalized_query_response<T>(
+    pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
         &self,
-        inference_vars: CanonicalVarValues<'tcx>,
-        answer: T,
-    ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
-    where
-        T: Debug + TypeFoldable<TyCtxt<'tcx>>,
-        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
-    {
-        self.infcx.make_canonicalized_query_response(
-            inference_vars,
-            answer,
-            &mut **self.engine.borrow_mut(),
-        )
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, Vec<E>> {
+        self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
+    }
+
+    pub fn structurally_normalize(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: Ty<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<E>> {
+        self.infcx
+            .at(cause, param_env)
+            .structurally_normalize(value, &mut **self.engine.borrow_mut())
     }
 }
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 3ee33295176..c7da85bd1cc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -28,7 +28,7 @@ use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
 use rustc_macros::extension;
 use rustc_middle::hir::map;
 use rustc_middle::traits::IsConstable;
-use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::print::PrintPolyTraitRefExt;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
@@ -1112,7 +1112,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 {
                                     Some((
                                         DefIdOrName::DefId(def_id),
-                                        pred.kind().rebind(proj.term.ty().unwrap()),
+                                        pred.kind().rebind(proj.term.expect_type()),
                                         pred.kind().rebind(args.as_slice()),
                                     ))
                                 } else {
@@ -1129,7 +1129,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             {
                                 Some((
                                     DefIdOrName::Name("trait object"),
-                                    pred.rebind(proj.term.ty().unwrap()),
+                                    pred.rebind(proj.term.expect_type()),
                                     pred.rebind(args.as_slice()),
                                 ))
                             } else {
@@ -1157,7 +1157,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             {
                                 Some((
                                     name,
-                                    pred.kind().rebind(proj.term.ty().unwrap()),
+                                    pred.kind().rebind(proj.term.expect_type()),
                                     pred.kind().rebind(args.as_slice()),
                                 ))
                             } else {
@@ -3840,9 +3840,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     })
                 } else if let Some(where_pred) = where_pred.as_projection_clause()
                     && let Some(failed_pred) = failed_pred.as_projection_clause()
-                    && let Some(found) = failed_pred.skip_binder().term.ty()
+                    && let Some(found) = failed_pred.skip_binder().term.as_type()
                 {
-                    type_diffs = vec![Sorts(ty::error::ExpectedFound {
+                    type_diffs = vec![TypeError::Sorts(ty::error::ExpectedFound {
                         expected: where_pred
                             .skip_binder()
                             .projection_term
@@ -3985,7 +3985,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 continue;
             };
             for diff in type_diffs {
-                let Sorts(expected_found) = diff else {
+                let TypeError::Sorts(expected_found) = diff else {
                     continue;
                 };
                 if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
@@ -4165,7 +4165,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     };
                     if primary_spans.is_empty()
                         || type_diffs.iter().any(|diff| {
-                            let Sorts(expected_found) = diff else {
+                            let TypeError::Sorts(expected_found) = diff else {
                                 return false;
                             };
                             self.can_eq(param_env, expected_found.found, ty)
@@ -4198,7 +4198,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
                         if !self.can_eq(param_env, ty, *prev_ty) {
                             if type_diffs.iter().any(|diff| {
-                                let Sorts(expected_found) = diff else {
+                                let TypeError::Sorts(expected_found) = diff else {
                                     return false;
                                 };
                                 self.can_eq(param_env, expected_found.found, ty)
@@ -4248,7 +4248,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let ocx = ObligationCtxt::new(self.infcx);
         let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
         for diff in type_diffs {
-            let Sorts(expected_found) = diff else {
+            let TypeError::Sorts(expected_found) = diff else {
                 continue;
             };
             let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
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 da611b748da..46b13788186 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
@@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
                         let trait_predicate = bound_predicate.rebind(trait_predicate);
                         let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-                        let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation);
 
                         // Let's use the root obligation as the main message, when we care about the
                         // most general case ("X doesn't implement Pattern<'_>") over the case that
@@ -877,56 +876,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         }
                     }
 
-                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
+                    // Errors for `ConstEvaluatable` predicates show up as
+                    // `SelectionError::ConstEvalFailure`,
+                    // not `Unimplemented`.
+                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
+                    // Errors for `ConstEquate` predicates show up as
+                    // `SelectionError::ConstEvalFailure`,
+                    // not `Unimplemented`.
+                    | ty::PredicateKind::ConstEquate { .. }
+                    // Ambiguous predicates should never error
+                    | ty::PredicateKind::Ambiguous
+                    | ty::PredicateKind::NormalizesTo { .. }
+                    | ty::PredicateKind::AliasRelate { .. }
+                    | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => {
                         span_bug!(
                             span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            "Unexpected `Predicate` for `SelectionError`: `{:?}`",
                             obligation
                         )
                     }
-
-                    ty::PredicateKind::ConstEquate(..) => {
-                        // Errors for `ConstEquate` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-equate requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-
-                    ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
-
-                    ty::PredicateKind::NormalizesTo(..) => span_bug!(
-                        span,
-                        "NormalizesTo predicate should never be the predicate cause of a SelectionError"
-                    ),
-
-                    ty::PredicateKind::AliasRelate(..) => span_bug!(
-                        span,
-                        "AliasRelate predicate should never be the predicate cause of a SelectionError"
-                    ),
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                        let mut diag = self.dcx().struct_span_err(
-                            span,
-                            format!("the constant `{ct}` is not of type `{ty}`"),
-                        );
-                        self.note_type_err(
-                            &mut diag,
-                            &obligation.cause,
-                            None,
-                            None,
-                            TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
-                            false,
-                            false,
-                        );
-                        diag
-                    }
                 }
             }
 
@@ -989,6 +957,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             Overflow(_) => {
                 bug!("overflow should be handled before the `report_selection_error` path");
             }
+
+            SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
+                let mut diag = self.dcx().struct_span_err(
+                    span,
+                    format!("the constant `{ct}` is not of type `{expected_ty}`"),
+                );
+
+                self.note_type_err(
+                    &mut diag,
+                    &obligation.cause,
+                    None,
+                    None,
+                    TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)),
+                    false,
+                    false,
+                );
+                diag
+            }
         };
 
         self.note_obligation_cause(&mut err, &obligation);
@@ -996,12 +982,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         err.emit()
     }
 
-    fn apply_do_not_recommend(
-        &self,
-        mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
-        obligation: &'_ mut PredicateObligation<'tcx>,
-    ) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> {
+    fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool {
         let mut base_cause = obligation.cause.code().clone();
+        let mut applied_do_not_recommend = false;
         loop {
             if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
                 if self.tcx.has_attrs_with_path(
@@ -1011,7 +994,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     let code = (*c.derived.parent_code).clone();
                     obligation.cause.map_code(|_| code);
                     obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
-                    trait_predicate = c.derived.parent_trait_pred.clone();
+                    applied_do_not_recommend = true;
                 }
             }
             if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
@@ -1021,7 +1004,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         }
 
-        trait_predicate
+        applied_do_not_recommend
     }
 
     fn emit_specialized_closure_kind_error(
@@ -1521,6 +1504,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
+        let mut error = FulfillmentError {
+            obligation: error.obligation.clone(),
+            code: error.code.clone(),
+            root_obligation: error.root_obligation.clone(),
+        };
+        if matches!(
+            error.code,
+            FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented)
+                | FulfillmentErrorCode::Project(_)
+        ) && self.apply_do_not_recommend(&mut error.obligation)
+        {
+            error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented);
+        }
+
         match error.code {
             FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
                 error.obligation.clone(),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e1afc2a3529..bce5c7101cc 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::obligation_forest::ProcessResult;
 use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
 use rustc_infer::infer::DefineOpaqueTypes;
-use rustc_infer::traits::ProjectionCacheKey;
+use rustc_infer::traits::{FromSolverError, ProjectionCacheKey};
 use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ErrorHandled;
@@ -16,13 +16,13 @@ use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
 use std::marker::PhantomData;
 
-use super::const_evaluatable;
 use super::project::{self, ProjectAndUnifyResult};
 use super::select::SelectionContext;
 use super::wf;
 use super::EvaluationResult;
 use super::PredicateObligation;
 use super::Unimplemented;
+use super::{const_evaluatable, ScrubbedTraitError};
 use super::{FulfillmentError, FulfillmentErrorCode};
 
 use crate::traits::project::PolyProjectionObligation;
@@ -50,7 +50,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
 /// along. Once all type inference constraints have been generated, the
 /// method `select_all_or_error` can be used to report any remaining
 /// ambiguous cases as errors.
-pub struct FulfillmentContext<'tcx> {
+pub struct FulfillmentContext<'tcx, E: 'tcx> {
     /// A list of all obligations that have been registered with this
     /// fulfillment context.
     predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
@@ -60,6 +60,8 @@ pub struct FulfillmentContext<'tcx> {
     /// gets rolled back. Because of this we explicitly check that we only
     /// use the context in exactly this snapshot.
     usable_in_snapshot: usize,
+
+    _errors: PhantomData<E>,
 }
 
 #[derive(Clone, Debug)]
@@ -76,9 +78,12 @@ pub struct PendingPredicateObligation<'tcx> {
 #[cfg(target_pointer_width = "64")]
 rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
 
-impl<'tcx> FulfillmentContext<'tcx> {
+impl<'tcx, E> FulfillmentContext<'tcx, E>
+where
+    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
+{
     /// Creates a new fulfillment context.
-    pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> {
+    pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
         assert!(
             !infcx.next_trait_solver(),
             "old trait solver fulfillment context created when \
@@ -87,13 +92,15 @@ impl<'tcx> FulfillmentContext<'tcx> {
         FulfillmentContext {
             predicates: ObligationForest::new(),
             usable_in_snapshot: infcx.num_open_snapshots(),
+            _errors: PhantomData,
         }
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+    fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<E> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
+        let infcx = selcx.infcx;
 
         // Process pending obligations.
         let outcome: Outcome<_, _> =
@@ -102,8 +109,11 @@ impl<'tcx> FulfillmentContext<'tcx> {
         // FIXME: if we kept the original cache key, we could mark projection
         // obligations as complete for the projection cache here.
 
-        let errors: Vec<FulfillmentError<'tcx>> =
-            outcome.errors.into_iter().map(to_fulfillment_error).collect();
+        let errors: Vec<E> = outcome
+            .errors
+            .into_iter()
+            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
+            .collect();
 
         debug!(
             "select({} predicates remaining, {} errors) done",
@@ -115,7 +125,10 @@ impl<'tcx> FulfillmentContext<'tcx> {
     }
 }
 
-impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
+impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E>
+where
+    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
+{
     #[inline]
     fn register_predicate_obligation(
         &mut self,
@@ -134,18 +147,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
 
-    fn collect_remaining_errors(
-        &mut self,
-        _infcx: &InferCtxt<'tcx>,
-    ) -> Vec<FulfillmentError<'tcx>> {
+    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         self.predicates
             .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
             .into_iter()
-            .map(to_fulfillment_error)
+            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
             .collect()
     }
 
-    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         let selcx = SelectionContext::new(infcx);
         self.select(selcx)
     }
@@ -411,7 +421,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) {
+                    if !self.selcx.tcx().is_object_safe(trait_def_id) {
                         ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented))
                     } else {
                         ProcessResult::Changed(vec![])
@@ -429,37 +439,50 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 // This is because this is not ever a useful obligation to report
                 // as the cause of an overflow.
                 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                    // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
-                    // other than `ConstKind::Value`. Unfortunately this would require looking in the
-                    // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
-                    // don't really want to implement this in the old solver so I haven't.
-                    //
-                    // We do still stall on infer vars though as otherwise a goal like:
-                    // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
-                    // get unified with some const that is not of type `usize`.
-                    let ct = self.selcx.infcx.shallow_resolve_const(ct);
-                    match ct.kind() {
-                        ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
+                    let ct = infcx.shallow_resolve_const(ct);
+                    let ct_ty = match ct.kind() {
+                        ty::ConstKind::Infer(var) => {
+                            let var = match var {
+                                ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
+                                ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
+                                ty::InferConst::Fresh(_) => {
+                                    bug!("encountered fresh const in fulfill")
+                                }
+                            };
                             pending_obligation.stalled_on.clear();
-                            pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
-                            ProcessResult::Unchanged
+                            pending_obligation.stalled_on.extend([var]);
+                            return ProcessResult::Unchanged;
                         }
                         ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
-                        _ => {
-                            match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
-                                // Only really excercised by generic_const_exprs
-                                DefineOpaqueTypes::Yes,
-                                ct.ty(),
-                                ty,
-                            ) {
-                                Ok(inf_ok) => {
-                                    ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
-                                }
-                                Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
-                                    SelectionError::Unimplemented,
-                                )),
-                            }
+                        ty::ConstKind::Value(ty, _) => ty,
+                        ty::ConstKind::Unevaluated(uv) => {
+                            infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
                         }
+                        // FIXME(generic_const_exprs): we should construct an alias like
+                        // `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
+                        // `lhs + rhs`.
+                        ty::ConstKind::Expr(_) => {
+                            return ProcessResult::Changed(mk_pending(vec![]));
+                        }
+                        ty::ConstKind::Placeholder(_) => {
+                            bug!("placeholder const {:?} in old solver", ct)
+                        }
+                        ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
+                        ty::ConstKind::Param(param_ct) => {
+                            param_ct.find_ty_from_env(obligation.param_env)
+                        }
+                    };
+
+                    match infcx.at(&obligation.cause, obligation.param_env).eq(
+                        // Only really excercised by generic_const_exprs
+                        DefineOpaqueTypes::Yes,
+                        ct_ty,
+                        ty,
+                    ) {
+                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
+                            SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
+                        )),
                     }
                 }
 
@@ -623,7 +646,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             match self.selcx.infcx.try_const_eval_resolve(
                                 obligation.param_env,
                                 unevaluated,
-                                c.ty(),
                                 obligation.cause.span,
                             ) {
                                 Ok(val) => Ok(val),
@@ -840,13 +862,31 @@ fn args_infer_vars<'a, 'tcx>(
         .filter_map(TyOrConstInferVar::maybe_from_generic_arg)
 }
 
-fn to_fulfillment_error<'tcx>(
-    error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
-) -> FulfillmentError<'tcx> {
-    let mut iter = error.backtrace.into_iter();
-    let obligation = iter.next().unwrap().obligation;
-    // The root obligation is the last item in the backtrace - if there's only
-    // one item, then it's the same as the main obligation
-    let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
-    FulfillmentError::new(obligation, error.error, root_obligation)
+#[derive(Debug)]
+pub struct OldSolverError<'tcx>(
+    Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
+);
+
+impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
+    fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
+        let mut iter = error.0.backtrace.into_iter();
+        let obligation = iter.next().unwrap().obligation;
+        // The root obligation is the last item in the backtrace - if there's only
+        // one item, then it's the same as the main obligation
+        let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
+        FulfillmentError::new(obligation, error.0.error, root_obligation)
+    }
+}
+
+impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
+    fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
+        match error.0.error {
+            FulfillmentErrorCode::Select(_)
+            | FulfillmentErrorCode::Project(_)
+            | FulfillmentErrorCode::Subtype(_, _)
+            | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError,
+            FulfillmentErrorCode::Ambiguity { overflow: _ } => ScrubbedTraitError::Ambiguity,
+            FulfillmentErrorCode::Cycle(cycle) => ScrubbedTraitError::Cycle(cycle),
+        }
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index a1094d98276..baec2268629 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,13 +1,13 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
 use crate::regions::InferCtxtRegionExt;
-use crate::traits::{self, ObligationCause};
+use crate::traits::{self, FulfillmentError, ObligationCause};
 
 use hir::LangItem;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
 
 use super::outlives_bounds::InferCtxtExt;
@@ -137,7 +137,7 @@ pub fn all_fields_implement_trait<'tcx>(
         for field in &variant.fields {
             // Do this per-field to get better error messages.
             let infcx = tcx.infer_ctxt().build();
-            let ocx = traits::ObligationCtxt::new(&infcx);
+            let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
 
             let unnormalized_ty = field.ty(tcx, args);
             if unnormalized_ty.references_error() {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 786ab091e91..eae2f9d1792 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -32,6 +32,7 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast};
@@ -46,7 +47,7 @@ pub use self::coherence::{add_placeholder_note, orphan_check_trait_ref, overlapp
 pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams};
 pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult};
 pub use self::engine::{ObligationCtxt, TraitEngineExt};
-pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
+pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation};
 pub use self::normalize::NormalizeExt;
 pub use self::object_safety::hir_ty_lowering_object_safety_violations;
 pub use self::object_safety::is_vtable_safe_method;
@@ -70,6 +71,80 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh
 
 pub use rustc_infer::traits::*;
 
+pub struct FulfillmentError<'tcx> {
+    pub obligation: PredicateObligation<'tcx>,
+    pub code: FulfillmentErrorCode<'tcx>,
+    /// Diagnostics only: the 'root' obligation which resulted in
+    /// the failure to process `obligation`. This is the obligation
+    /// that was initially passed to `register_predicate_obligation`
+    pub root_obligation: PredicateObligation<'tcx>,
+}
+
+impl<'tcx> FulfillmentError<'tcx> {
+    pub fn new(
+        obligation: PredicateObligation<'tcx>,
+        code: FulfillmentErrorCode<'tcx>,
+        root_obligation: PredicateObligation<'tcx>,
+    ) -> FulfillmentError<'tcx> {
+        FulfillmentError { obligation, code, root_obligation }
+    }
+
+    pub fn is_true_error(&self) -> bool {
+        match self.code {
+            FulfillmentErrorCode::Select(_)
+            | FulfillmentErrorCode::Project(_)
+            | FulfillmentErrorCode::Subtype(_, _)
+            | FulfillmentErrorCode::ConstEquate(_, _) => true,
+            FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
+                false
+            }
+        }
+    }
+}
+
+impl<'tcx> Debug for FulfillmentError<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
+    }
+}
+
+#[derive(Clone)]
+pub enum FulfillmentErrorCode<'tcx> {
+    /// Inherently impossible to fulfill; this trait is implemented if and only
+    /// if it is already implemented.
+    Cycle(Vec<PredicateObligation<'tcx>>),
+    Select(SelectionError<'tcx>),
+    Project(MismatchedProjectionTypes<'tcx>),
+    Subtype(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
+    ConstEquate(ExpectedFound<ty::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
+        /// emitting a fatal error instead.
+        overflow: Option<bool>,
+    },
+}
+
+impl<'tcx> Debug for FulfillmentErrorCode<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match *self {
+            FulfillmentErrorCode::Select(ref e) => write!(f, "{e:?}"),
+            FulfillmentErrorCode::Project(ref e) => write!(f, "{e:?}"),
+            FulfillmentErrorCode::Subtype(ref a, ref b) => {
+                write!(f, "CodeSubtypeError({a:?}, {b:?})")
+            }
+            FulfillmentErrorCode::ConstEquate(ref a, ref b) => {
+                write!(f, "CodeConstEquateError({a:?}, {b:?})")
+            }
+            FulfillmentErrorCode::Ambiguity { overflow: None } => write!(f, "Ambiguity"),
+            FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } => {
+                write!(f, "Overflow({suggest_increasing_limit})")
+            }
+            FulfillmentErrorCode::Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
+        }
+    }
+}
+
 /// Whether to skip the leak check, as part of a future compatibility warning step.
 ///
 /// The "default" for skip-leak-check corresponds to the current
@@ -284,7 +359,7 @@ pub fn normalize_param_env_or_error<'tcx>(
                     // `ty::Const::normalize` can only work with properly preserved binders.
 
                     if c.has_escaping_bound_vars() {
-                        return ty::Const::new_misc_error(self.0, c.ty());
+                        return ty::Const::new_misc_error(self.0);
                     }
                     // While it is pretty sus to be evaluating things with an empty param env, it
                     // should actually be okay since without `feature(generic_const_exprs)` the only
@@ -407,7 +482,7 @@ pub fn fully_normalize<'tcx, T>(
 where
     T: TypeFoldable<TyCtxt<'tcx>>,
 {
-    let ocx = ObligationCtxt::new(infcx);
+    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
     debug!(?value);
     let normalized_value = ocx.normalize(&cause, param_env, value);
     debug!(?normalized_value);
@@ -548,6 +623,7 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
+        specialization_enabled_in: specialize::specialization_enabled_in,
         instantiate_and_check_impossible_predicates,
         is_impossible_associated_item,
         ..*providers
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index d10aee2d4e2..e7ab0b7791c 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -3,11 +3,13 @@ use super::error_reporting::OverflowCause;
 use super::error_reporting::TypeErrCtxtExt;
 use super::SelectionContext;
 use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
+use crate::solve::NextSolverError;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::InferOk;
+use rustc_infer::traits::FromSolverError;
 use rustc_infer::traits::PredicateObligation;
-use rustc_infer::traits::{FulfillmentError, Normalized, Obligation, TraitEngine};
+use rustc_infer::traits::{Normalized, Obligation, TraitEngine};
 use rustc_macros::extension;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder};
@@ -44,11 +46,15 @@ impl<'tcx> At<'_, 'tcx> {
     /// existing fulfillment context in the old solver. Once we also eagerly prove goals with
     /// the old solver or have removed the old solver, remove `traits::fully_normalize` and
     /// rename this function to `At::fully_normalize`.
-    fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+    fn deeply_normalize<T, E>(
         self,
         value: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+        fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
+    ) -> Result<T, Vec<E>>
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+        E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+    {
         if self.infcx.next_trait_solver() {
             crate::solve::deeply_normalize(self, value)
         } else {
@@ -253,7 +259,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                     obligations.len = ?self.obligations.len(),
                     "AssocTypeNormalizer: normalized type"
                 );
-                normalized_ty.ty().unwrap()
+                normalized_ty.expect_type()
             }
 
             ty::Projection => {
@@ -283,7 +289,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                 )
                 .ok()
                 .flatten()
-                .map(|term| term.ty().unwrap())
+                .map(|term| term.expect_type())
                 .map(|normalized_ty| {
                     PlaceholderReplacer::replace_placeholders(
                         infcx,
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0f32b6ef9e3..08355ef55c4 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -13,7 +13,7 @@ use super::elaborate;
 use crate::infer::TyCtxtInferExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, Obligation, ObligationCause};
-use rustc_errors::{FatalError, MultiSpan};
+use rustc_errors::FatalError;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::query::Providers;
@@ -23,7 +23,6 @@ use rustc_middle::ty::{
 };
 use rustc_middle::ty::{GenericArg, GenericArgs};
 use rustc_middle::ty::{TypeVisitableExt, Upcast};
-use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::abi::Abi;
@@ -65,45 +64,14 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object
     )
 }
 
-fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    let violations = tcx.object_safety_violations(trait_def_id);
-
-    if violations.is_empty() {
-        return true;
-    }
-
-    // If the trait contains any other violations, then let the error reporting path
-    // report it instead of emitting a warning here.
-    if violations.iter().all(|violation| {
-        matches!(
-            violation,
-            ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _)
-        )
-    }) {
-        for violation in violations {
-            if let ObjectSafetyViolation::Method(
-                _,
-                MethodViolationCode::WhereClauseReferencesSelf,
-                span,
-            ) = violation
-            {
-                lint_object_unsafe_trait(tcx, *span, trait_def_id, violation);
-            }
-        }
-        return true;
-    }
-
-    false
+fn is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+    tcx.object_safety_violations(trait_def_id).is_empty()
 }
 
 /// We say a method is *vtable safe* if it can be invoked on a trait
 /// object. Note that object-safe traits can have some
 /// non-vtable-safe methods, so long as they require `Self: Sized` or
 /// otherwise ensure that they cannot be used when `Self = Trait`.
-///
-/// [`MethodViolationCode::WhereClauseReferencesSelf`] is considered object safe due to backwards
-/// compatibility, see <https://github.com/rust-lang/rust/issues/51443> and
-/// [`WHERE_CLAUSES_OBJECT_SAFETY`].
 pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
     debug_assert!(tcx.generics_of(trait_def_id).has_self);
     debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
@@ -112,9 +80,7 @@ pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::A
         return false;
     }
 
-    virtual_call_violations_for_method(tcx, trait_def_id, method)
-        .iter()
-        .all(|v| matches!(v, MethodViolationCode::WhereClauseReferencesSelf))
+    virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
 }
 
 fn object_safety_violations_for_trait(
@@ -163,47 +129,6 @@ fn object_safety_violations_for_trait(
     violations
 }
 
-/// Lint object-unsafe trait.
-fn lint_object_unsafe_trait(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    trait_def_id: DefId,
-    violation: &ObjectSafetyViolation,
-) {
-    // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
-    // It's also hard to get a use site span, so we use the method definition span.
-    tcx.node_span_lint(WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, span, |err| {
-        err.primary_message(format!(
-            "the trait `{}` cannot be made into an object",
-            tcx.def_path_str(trait_def_id)
-        ));
-        let node = tcx.hir().get_if_local(trait_def_id);
-        let mut spans = MultiSpan::from_span(span);
-        if let Some(hir::Node::Item(item)) = node {
-            spans.push_span_label(item.ident.span, "this trait cannot be made into an object...");
-            spans.push_span_label(span, format!("...because {}", violation.error_msg()));
-        } else {
-            spans.push_span_label(
-                span,
-                format!(
-                    "the trait cannot be made into an object because {}",
-                    violation.error_msg()
-                ),
-            );
-        };
-        err.span_note(
-            spans,
-            "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>",
-        );
-        if node.is_some() {
-            // Only provide the help if its a local trait, otherwise it's not
-            violation.solution().add_to(err);
-        }
-    });
-}
-
 fn sized_trait_bound_spans<'tcx>(
     tcx: TyCtxt<'tcx>,
     bounds: hir::GenericBounds<'tcx>,
@@ -929,7 +854,7 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         object_safety_violations,
-        check_is_object_safe,
+        is_object_safe,
         generics_require_sized_self,
         ..*providers
     };
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 501d9c9266e..2c9cb79664b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -523,16 +523,9 @@ fn normalize_to_error<'a, 'tcx>(
         | ty::AliasTermKind::InherentTy
         | ty::AliasTermKind::OpaqueTy
         | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
-        ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => selcx
-            .infcx
-            .next_const_var(
-                selcx
-                    .tcx()
-                    .type_of(projection_term.def_id)
-                    .instantiate(selcx.tcx(), projection_term.args),
-                cause.span,
-            )
-            .into(),
+        ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
+            selcx.infcx.next_const_var(cause.span).into()
+        }
     };
     let trait_obligation = Obligation {
         cause,
@@ -744,8 +737,6 @@ fn project<'cx, 'tcx>(
                         obligation.predicate.def_id,
                         obligation.predicate.args,
                     ),
-                    tcx.type_of(obligation.predicate.def_id)
-                        .instantiate(tcx, obligation.predicate.args),
                 )
                 .into(),
                 kind => {
@@ -2071,15 +2062,14 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     // * `args` ends up as `[u32, S]`
     let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
     let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
-    let ty = tcx.type_of(assoc_ty.item.def_id);
     let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
     let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
         let did = assoc_ty.item.def_id;
         let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
         let uv = ty::UnevaluatedConst::new(did, identity_args);
-        ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into())
+        ty::EarlyBinder::bind(ty::Const::new_unevaluated(tcx, uv).into())
     } else {
-        ty.map_bound(|ty| ty.into())
+        tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into())
     };
     if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
         let err = Ty::new_error_with_message(
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 1b5ffeebc01..e170d7cae93 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -8,11 +8,11 @@ use crate::infer::{InferCtxt, InferOk};
 use crate::traits::error_reporting::OverflowCause;
 use crate::traits::error_reporting::TypeErrCtxtExt;
 use crate::traits::normalize::needs_normalization;
-use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
+use crate::traits::Normalized;
+use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
 use crate::traits::{ObligationCause, PredicateObligation, Reveal};
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_infer::traits::Normalized;
 use rustc_macros::extension;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
@@ -76,7 +76,9 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
         };
 
         if self.infcx.next_trait_solver() {
-            match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) {
+            match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError<'tcx>>(
+                self, value, universes,
+            ) {
                 Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
                 Err(_errors) => {
                     return Err(NoSolution);
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 00cc77e71e7..b38841db923 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,4 +1,3 @@
-use crate::solve;
 use crate::traits::query::NoSolution;
 use crate::traits::wf;
 use crate::traits::ObligationCtxt;
@@ -262,11 +261,9 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
                 let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
                 // Need to manually normalize in the new solver as `wf::obligations` does not.
                 if ocx.infcx.next_trait_solver() {
-                    ty_a = solve::deeply_normalize(
-                        ocx.infcx.at(&ObligationCause::dummy(), param_env),
-                        ty_a,
-                    )
-                    .map_err(|_errs| NoSolution)?;
+                    ty_a = ocx
+                        .deeply_normalize(&ObligationCause::dummy(), param_env, ty_a)
+                        .map_err(|_| NoSolution)?;
                 }
                 let mut components = smallvec![];
                 push_outlives_components(tcx, ty_a, &mut components);
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index d513a5d2996..6db5fa0e4e5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -870,7 +870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         if let Some(principal) = data.principal() {
                             if !self.infcx.tcx.features().object_safe_for_dispatch {
                                 principal.with_self_ty(self.tcx(), self_ty)
-                            } else if self.tcx().check_is_object_safe(principal.def_id()) {
+                            } else if self.tcx().is_object_safe(principal.def_id()) {
                                 principal.with_self_ty(self.tcx(), self_ty)
                             } else {
                                 return;
@@ -921,6 +921,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         cause: &ObligationCause<'tcx>,
     ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
+        // Don't drop any candidates in intercrate mode, as it's incomplete.
+        // (Not that it matters, since `Unsize` is not a stable trait.)
+        if self.infcx.intercrate {
+            return None;
+        }
+
         let tcx = self.tcx();
         if tcx.features().trait_upcasting {
             return None;
@@ -946,7 +952,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // since we don't actually use them.
                 &mut vec![],
             )
-            .ty()
+            .as_type()
             .unwrap();
 
             if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index c684f087d32..749081006f3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -665,9 +665,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 tcx,
                                 ty::INNERMOST,
                                 ty::BoundVar::from_usize(bound_vars.len() - 1),
-                                tcx.type_of(param.def_id)
-                                    .no_bound_vars()
-                                    .expect("const parameter types cannot be generic"),
                             )
                             .into()
                         }
@@ -1222,7 +1219,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // `T` -> `Trait`
             (_, &ty::Dynamic(data, r, ty::Dyn)) => {
                 let mut object_dids = data.auto_traits().chain(data.principal_def_id());
-                if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
+                if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
                     return Err(TraitNotObjectSafe(did));
                 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index dcb0875639f..4a935f4a64a 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -32,6 +32,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_infer::infer::relate::MatchAgainstFreshVars;
+use rustc_infer::infer::relate::TypeRelation;
 use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::DefineOpaqueTypes;
@@ -40,10 +42,9 @@ use rustc_middle::bug;
 use rustc_middle::dep_graph::dep_kinds;
 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::error::TypeErrorToStringExt;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
@@ -798,7 +799,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
 
                 ty::PredicateKind::ObjectSafe(trait_def_id) => {
-                    if self.tcx().check_is_object_safe(trait_def_id) {
+                    if self.tcx().is_object_safe(trait_def_id) {
                         Ok(EvaluatedToOk)
                     } else {
                         Ok(EvaluatedToErr)
@@ -947,7 +948,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             match self.infcx.try_const_eval_resolve(
                                 obligation.param_env,
                                 unevaluated,
-                                c.ty(),
                                 obligation.cause.span,
                             ) {
                                 Ok(val) => Ok(val),
@@ -995,21 +995,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
                 ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
                 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                    // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
-                    // other than `ConstKind::Value`. Unfortunately this would require looking in the
-                    // env for any `ConstArgHasType` assumptions for parameters and placeholders. I
-                    // don't really want to implement this in the old solver so I haven't.
-                    //
-                    // We do still stall on infer vars though as otherwise a goal like:
-                    // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
-                    // get unified with some const that is not of type `usize`.
                     let ct = self.infcx.shallow_resolve_const(ct);
                     let ct_ty = match ct.kind() {
-                        ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
+                        ty::ConstKind::Infer(_) => {
                             return Ok(EvaluatedToAmbig);
                         }
                         ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
-                        _ => ct.ty(),
+                        ty::ConstKind::Value(ty, _) => ty,
+                        ty::ConstKind::Unevaluated(uv) => {
+                            self.tcx().type_of(uv.def).instantiate(self.tcx(), uv.args)
+                        }
+                        // FIXME(generic_const_exprs): See comment in `fulfill.rs`
+                        ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk),
+                        ty::ConstKind::Placeholder(_) => {
+                            bug!("placeholder const {:?} in old solver", ct)
+                        }
+                        ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
+                        ty::ConstKind::Param(param_ct) => {
+                            param_ct.find_ty_from_env(obligation.param_env)
+                        }
                     };
 
                     match self.infcx.at(&obligation.cause, obligation.param_env).eq(
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index c2727ae6bfd..c9bb0d330e1 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{codes::*, Diag, EmissionGuarantee};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::bug;
+use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
@@ -136,6 +137,10 @@ pub fn translate_args_with_cause<'tcx>(
     source_args.rebase_onto(infcx.tcx, source_impl, target_args)
 }
 
+pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
+    tcx.features().specialization || tcx.features().min_specialization
+}
+
 /// Is `impl1` a specialization of `impl2`?
 ///
 /// Specialization is determined by the sets of types to which the impls apply;
@@ -143,31 +148,18 @@ pub fn translate_args_with_cause<'tcx>(
 /// to.
 #[instrument(skip(tcx), level = "debug")]
 pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
-    // The feature gate should prevent introducing new specializations, but not
-    // taking advantage of upstream ones.
-    // If specialization is enabled for this crate then no extra checks are needed.
-    // If it's not, and either of the `impl`s is local to this crate, then this definitely
-    // isn't specializing - unless specialization is enabled for the `impl` span,
-    // e.g. if it comes from an `allow_internal_unstable` macro
-    let features = tcx.features();
-    let specialization_enabled = features.specialization || features.min_specialization;
-    if !specialization_enabled {
-        if impl1_def_id.is_local() {
-            let span = tcx.def_span(impl1_def_id);
-            if !span.allows_unstable(sym::specialization)
-                && !span.allows_unstable(sym::min_specialization)
-            {
-                return false;
-            }
-        }
-
-        if impl2_def_id.is_local() {
-            let span = tcx.def_span(impl2_def_id);
-            if !span.allows_unstable(sym::specialization)
-                && !span.allows_unstable(sym::min_specialization)
-            {
-                return false;
-            }
+    // We check that the specializing impl comes from a crate that has specialization enabled,
+    // or if the specializing impl is marked with `allow_internal_unstable`.
+    //
+    // We don't really care if the specialized impl (the parent) is in a crate that has
+    // specialization enabled, since it's not being specialized, and it's already been checked
+    // for coherence.
+    if !tcx.specialization_enabled_in(impl1_def_id.krate) {
+        let span = tcx.def_span(impl1_def_id);
+        if !span.allows_unstable(sym::specialization)
+            && !span.allows_unstable(sym::min_specialization)
+        {
+            return false;
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 96a06e0c169..9d657ade86b 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -1,5 +1,5 @@
 use rustc_infer::infer::at::At;
-use rustc_infer::traits::{FulfillmentError, TraitEngine};
+use rustc_infer::traits::TraitEngine;
 use rustc_macros::extension;
 use rustc_middle::ty::{self, Ty};
 
@@ -7,11 +7,11 @@ use crate::traits::{NormalizeExt, Obligation};
 
 #[extension(pub trait StructurallyNormalizeExt<'tcx>)]
 impl<'tcx> At<'_, 'tcx> {
-    fn structurally_normalize(
+    fn structurally_normalize<E: 'tcx>(
         &self,
         ty: Ty<'tcx>,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+        fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
+    ) -> Result<Ty<'tcx>, Vec<E>> {
         assert!(!ty.is_ty_var(), "should have resolved vars before calling");
 
         if self.infcx.next_trait_solver() {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 5d5a22e189c..960c27b636e 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -483,7 +483,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderConst { universe, bound: bound_const };
                 self.mapped_consts.insert(p, bound_const);
-                ty::Const::new_placeholder(self.infcx.tcx, p, ct.ty())
+                ty::Const::new_placeholder(self.infcx.tcx, p)
             }
             _ => ct.super_fold_with(self),
         }
@@ -626,7 +626,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
                     let db = ty::DebruijnIndex::from_usize(
                         self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                     );
-                    ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty())
+                    ty::Const::new_bound(self.infcx.tcx, db, *replace_var)
                 }
                 None => {
                     if ct.has_infer() {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index f4189ff0902..066755f7b3e 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -286,7 +286,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // implemented, but rather from a "second order" obligation, where an associated
             // type has a projection coming from another associated type.
             // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example.
-            if let Some(term_ty) = proj.term.ty()
+            if let Some(term_ty) = proj.term.as_type()
                 && let Some(impl_item_span) = ty_to_impl_span(term_ty)
             {
                 cause.span = impl_item_span;
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index b96b1b67a74..c73ececd1d1 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -4,13 +4,13 @@
 // general routines.
 
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::FulfillmentErrorCode;
 use rustc_middle::bug;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::{
-    ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented,
+    ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
+    Unimplemented,
 };
 use tracing::debug;
 
@@ -50,6 +50,7 @@ pub fn codegen_select_candidate<'tcx>(
     // Currently, we use a fulfillment context to completely resolve
     // all nested obligations. This is because they can inform the
     // inference of the impl's type parameters.
+    // FIXME(-Znext-solver): Doesn't need diagnostics if new solver.
     let ocx = ObligationCtxt::new(&infcx);
     let impl_source = selection.map(|obligation| {
         ocx.register_obligation(obligation);
@@ -64,7 +65,7 @@ pub fn codegen_select_candidate<'tcx>(
         // Cycle errors are the only post-monomorphization errors possible; emit them now so
         // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
         for err in errors {
-            if let FulfillmentErrorCode::Cycle(cycle) = err.code {
+            if let ScrubbedTraitError::Cycle(cycle) = err {
                 infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index fee13078250..0430e0bb70e 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -7,9 +7,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::query::{
     normalize::NormalizationResult, CanonicalAliasGoal, NoSolution,
 };
-use rustc_trait_selection::traits::{
-    self, FulfillmentErrorCode, ObligationCause, SelectionContext,
-};
+use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext};
 use tracing::debug;
 
 pub(crate) fn provide(p: &mut Providers) {
@@ -49,7 +47,7 @@ fn normalize_canonicalized_projection_ty<'tcx>(
                 // that impl vars are constrained by the signature, for example).
                 if !tcx.sess.opts.actually_rustdoc {
                     for error in &errors {
-                        if let FulfillmentErrorCode::Cycle(cycle) = &error.code {
+                        if let ScrubbedTraitError::Cycle(cycle) = &error {
                             ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
                         }
                     }
@@ -60,7 +58,7 @@ fn normalize_canonicalized_projection_ty<'tcx>(
             // FIXME(associated_const_equality): All users of normalize_canonicalized_projection_ty
             // expected a type, but there is the possibility it could've been a const now.
             // Maybe change it to a Term later?
-            Ok(NormalizationResult { normalized_ty: answer.ty().unwrap() })
+            Ok(NormalizationResult { normalized_ty: answer.expect_type() })
         },
     )
 }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 604b68d2cd4..eae1a9dfaa2 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -420,7 +420,7 @@ pub(crate) mod rustc {
         fn from_tag(tag: ScalarInt, tcx: TyCtxt<'tcx>) -> Self {
             use rustc_target::abi::Endian;
             let size = tag.size();
-            let bits = tag.assert_bits(size);
+            let bits = tag.to_bits(size);
             let bytes: [u8; 16];
             let bytes = match tcx.data_layout.endian {
                 Endian::Little => {
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 8d7d81d8f73..ffebf7b0721 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -135,7 +135,7 @@ mod rustc {
             use rustc_middle::ty::ScalarInt;
             use rustc_span::symbol::sym;
 
-            let Ok(cv) = c.eval(tcx, param_env, DUMMY_SP) else {
+            let Ok((ty, cv)) = c.eval(tcx, param_env, DUMMY_SP) else {
                 return Some(Self {
                     alignment: true,
                     lifetimes: true,
@@ -144,7 +144,7 @@ mod rustc {
                 });
             };
 
-            let adt_def = c.ty().ty_adt_def()?;
+            let adt_def = ty.ty_adt_def()?;
 
             assert_eq!(
                 tcx.require_lang_item(LangItem::TransmuteOpts, None),
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index e9112d232cb..58f812fc7cf 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -23,7 +23,7 @@ fn destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     const_: ty::Const<'tcx>,
 ) -> ty::DestructuredConst<'tcx> {
-    let ty::ConstKind::Value(valtree) = const_.kind() else {
+    let ty::ConstKind::Value(ct_ty, valtree) = const_.kind() else {
         bug!("cannot destructure constant {:?}", const_)
     };
 
@@ -32,7 +32,7 @@ fn destructure_const<'tcx>(
         _ => bug!("cannot destructure constant {:?}", const_),
     };
 
-    let (fields, variant) = match const_.ty().kind() {
+    let (fields, variant) = match ct_ty.kind() {
         ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
             // construct the consts for the elements of the array/slice
             let field_consts = branches
@@ -47,7 +47,7 @@ fn destructure_const<'tcx>(
         ty::Adt(def, args) => {
             let (variant_idx, branches) = if def.is_enum() {
                 let (head, rest) = branches.split_first().unwrap();
-                (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
+                (VariantIdx::from_u32(head.unwrap_leaf().to_u32()), rest)
             } else {
                 (FIRST_VARIANT, branches)
             };
@@ -121,7 +121,7 @@ fn recurse_build<'tcx>(
             let sp = node.span;
             match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
                 Ok(c) => c,
-                Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty),
+                Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar),
                 Err(LitToConstError::TypeError) => {
                     bug!("encountered type error in lit_to_const")
                 }
@@ -137,28 +137,31 @@ fn recurse_build<'tcx>(
         }
         &ExprKind::NamedConst { def_id, args, user_ty: _ } => {
             let uneval = ty::UnevaluatedConst::new(def_id, args);
-            ty::Const::new_unevaluated(tcx, uneval, node.ty)
+            ty::Const::new_unevaluated(tcx, uneval)
         }
-        ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty),
+        ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param),
 
         ExprKind::Call { fun, args, .. } => {
+            let fun_ty = body.exprs[*fun].ty;
             let fun = recurse_build(tcx, body, *fun, root_span)?;
 
             let mut new_args = Vec::<ty::Const<'tcx>>::with_capacity(args.len());
             for &id in args.iter() {
                 new_args.push(recurse_build(tcx, body, id, root_span)?);
             }
-            let new_args = tcx.mk_const_list(&new_args);
-            ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty)
+            ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args))
         }
         &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
+            let lhs_ty = body.exprs[lhs].ty;
             let lhs = recurse_build(tcx, body, lhs, root_span)?;
+            let rhs_ty = body.exprs[rhs].ty;
             let rhs = recurse_build(tcx, body, rhs, root_span)?;
-            ty::Const::new_expr(tcx, Expr::Binop(op, lhs, rhs), node.ty)
+            ty::Const::new_expr(tcx, Expr::new_binop(tcx, op, lhs_ty, rhs_ty, lhs, rhs))
         }
         &ExprKind::Unary { op, arg } if check_unop(op) => {
+            let arg_ty = body.exprs[arg].ty;
             let arg = recurse_build(tcx, body, arg, root_span)?;
-            ty::Const::new_expr(tcx, Expr::UnOp(op, arg), node.ty)
+            ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg_ty, arg))
         }
         // This is necessary so that the following compiles:
         //
@@ -178,12 +181,14 @@ fn recurse_build<'tcx>(
         // "coercion cast" i.e. using a coercion or is a no-op.
         // This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested)
         &ExprKind::Use { source } => {
-            let arg = recurse_build(tcx, body, source, root_span)?;
-            ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty)
+            let value_ty = body.exprs[source].ty;
+            let value = recurse_build(tcx, body, source, root_span)?;
+            ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty))
         }
         &ExprKind::Cast { source } => {
-            let arg = recurse_build(tcx, body, source, root_span)?;
-            ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty)
+            let value_ty = body.exprs[source].ty;
+            let value = recurse_build(tcx, body, source, root_span)?;
+            ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty))
         }
         ExprKind::Borrow { arg, .. } => {
             let arg_node = &body.exprs[*arg];
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 1c30f03c693..61ae36265ec 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -115,8 +115,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
             CanonicalVarKind::PlaceholderTy(_) => false,
             CanonicalVarKind::Region(_) => true,
             CanonicalVarKind::PlaceholderRegion(..) => false,
-            CanonicalVarKind::Const(..) => true,
-            CanonicalVarKind::PlaceholderConst(_, _) => false,
+            CanonicalVarKind::Const(_) => true,
+            CanonicalVarKind::PlaceholderConst(_) => false,
             CanonicalVarKind::Effect => true,
         }
     }
@@ -126,8 +126,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
             CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::PlaceholderTy(_)
-            | CanonicalVarKind::Const(_, _)
-            | CanonicalVarKind::PlaceholderConst(_, _)
+            | CanonicalVarKind::Const(_)
+            | CanonicalVarKind::PlaceholderConst(_)
             | CanonicalVarKind::Effect => false,
         }
     }
@@ -136,12 +136,12 @@ impl<I: Interner> CanonicalVarInfo<I> {
         match self.kind {
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::Region(_)
-            | CanonicalVarKind::Const(_, _)
+            | CanonicalVarKind::Const(_)
             | CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
 
             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
             CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.var().as_usize(),
+            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.var().as_usize(),
         }
     }
 }
@@ -169,13 +169,13 @@ pub enum CanonicalVarKind<I: Interner> {
     PlaceholderRegion(I::PlaceholderRegion),
 
     /// Some kind of const inference variable.
-    Const(UniverseIndex, I::Ty),
+    Const(UniverseIndex),
 
     /// Effect variable `'?E`.
     Effect,
 
     /// A "placeholder" that represents "any const".
-    PlaceholderConst(I::PlaceholderConst, I::Ty),
+    PlaceholderConst(I::PlaceholderConst),
 }
 
 impl<I: Interner> PartialEq for CanonicalVarKind<I> {
@@ -185,10 +185,8 @@ impl<I: Interner> PartialEq for CanonicalVarKind<I> {
             (Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
             (Self::Region(l0), Self::Region(r0)) => l0 == r0,
             (Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
-            (Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1,
-            (Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => {
-                l0 == r0 && l1 == r1
-            }
+            (Self::Const(l0), Self::Const(r0)) => l0 == r0,
+            (Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
             _ => std::mem::discriminant(self) == std::mem::discriminant(other),
         }
     }
@@ -199,10 +197,10 @@ impl<I: Interner> CanonicalVarKind<I> {
         match self {
             CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
             CanonicalVarKind::Region(ui) => ui,
-            CanonicalVarKind::Const(ui, _) => ui,
+            CanonicalVarKind::Const(ui) => ui,
             CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
+            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(),
             CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
                 UniverseIndex::ROOT
             }
@@ -220,7 +218,7 @@ impl<I: Interner> CanonicalVarKind<I> {
                 CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
             }
             CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
-            CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+            CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui),
 
             CanonicalVarKind::PlaceholderTy(placeholder) => {
                 CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
@@ -228,8 +226,8 @@ impl<I: Interner> CanonicalVarKind<I> {
             CanonicalVarKind::PlaceholderRegion(placeholder) => {
                 CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
             }
-            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
-                CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
+            CanonicalVarKind::PlaceholderConst(placeholder) => {
+                CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
             }
             CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
             | CanonicalVarKind::Effect => {
@@ -345,21 +343,14 @@ impl<I: Interner> CanonicalVarValues<I> {
                             Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
-                        CanonicalVarKind::Effect => Const::new_anon_bound(
-                            tcx,
-                            ty::INNERMOST,
-                            ty::BoundVar::from_usize(i),
-                            Ty::new_bool(tcx),
-                        )
-                        .into(),
-                        CanonicalVarKind::Const(_, ty)
-                        | CanonicalVarKind::PlaceholderConst(_, ty) => Const::new_anon_bound(
-                            tcx,
-                            ty::INNERMOST,
-                            ty::BoundVar::from_usize(i),
-                            ty,
-                        )
-                        .into(),
+                        CanonicalVarKind::Effect => {
+                            Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                                .into()
+                        }
+                        CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
+                            Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                                .into()
+                        }
                     }
                 },
             )),
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 7076df2893f..84d48e14c24 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -32,7 +32,7 @@ pub enum ConstKind<I: Interner> {
     Unevaluated(ty::UnevaluatedConst<I>),
 
     /// Used to hold computed value.
-    Value(I::ValueConst),
+    Value(I::Ty, I::ValueConst),
 
     /// A placeholder for a const which could not be computed; this is
     /// propagated to avoid useless error messages.
@@ -51,7 +51,7 @@ impl<I: Interner> PartialEq for ConstKind<I> {
             (Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
             (Placeholder(l0), Placeholder(r0)) => l0 == r0,
             (Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
-            (Value(l0), Value(r0)) => l0 == r0,
+            (Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1,
             (Error(l0), Error(r0)) => l0 == r0,
             (Expr(l0), Expr(r0)) => l0 == r0,
             _ => false,
@@ -80,7 +80,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
             Unevaluated(uv) => {
                 write!(f, "{:?}", &this.wrap(uv))
             }
-            Value(valtree) => write!(f, "{valtree:?}"),
+            Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &this.wrap(ty)),
             Error(_) => write!(f, "{{const error}}"),
             Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
         }
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
index 4e8be1ee4c2..c206f3ccdb5 100644
--- a/compiler/rustc_type_ir/src/debug.rs
+++ b/compiler/rustc_type_ir/src/debug.rs
@@ -38,11 +38,11 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
         panic!("cannot resolve {vid:?}")
     }
 
-    fn opportunistic_resolve_ct_var(&self, vid: ConstVid, _: I::Ty) -> I::Const {
+    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> I::Const {
         panic!("cannot resolve {vid:?}")
     }
 
-    fn opportunistic_resolve_effect_var(&self, vid: EffectVid, _: I::Ty) -> I::Const {
+    fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> I::Const {
         panic!("cannot resolve {vid:?}")
     }
 
diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs
new file mode 100644
index 00000000000..27623ea9cac
--- /dev/null
+++ b/compiler/rustc_type_ir/src/error.rs
@@ -0,0 +1,106 @@
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
+
+use crate::solve::NoSolution;
+use crate::{self as ty, Interner};
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
+pub struct ExpectedFound<T> {
+    pub expected: T,
+    pub found: T,
+}
+
+impl<T> ExpectedFound<T> {
+    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
+        if a_is_expected {
+            ExpectedFound { expected: a, found: b }
+        } else {
+            ExpectedFound { expected: b, found: a }
+        }
+    }
+}
+
+// Data structures used in type unification
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic)]
+#[rustc_pass_by_value]
+pub enum TypeError<I: Interner> {
+    Mismatch,
+    ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
+    PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
+    SafetyMismatch(ExpectedFound<I::Safety>),
+    AbiMismatch(ExpectedFound<I::Abi>),
+    Mutability,
+    ArgumentMutability(usize),
+    TupleSize(ExpectedFound<usize>),
+    FixedArraySize(ExpectedFound<u64>),
+    ArgCount,
+
+    RegionsDoesNotOutlive(I::Region, I::Region),
+    RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region),
+    RegionsPlaceholderMismatch,
+
+    Sorts(ExpectedFound<I::Ty>),
+    ArgumentSorts(ExpectedFound<I::Ty>, usize),
+    Traits(ExpectedFound<I::DefId>),
+    VariadicMismatch(ExpectedFound<bool>),
+
+    /// Instantiating a type variable with the given type would have
+    /// created a cycle (because it appears somewhere within that
+    /// type).
+    CyclicTy(I::Ty),
+    CyclicConst(I::Const),
+    ProjectionMismatched(ExpectedFound<I::DefId>),
+    ExistentialMismatch(ExpectedFound<I::BoundExistentialPredicates>),
+    ConstMismatch(ExpectedFound<I::Const>),
+
+    IntrinsicCast,
+    /// Safe `#[target_feature]` functions are not assignable to safe function pointers.
+    TargetFeatureCast(I::DefId),
+}
+
+impl<I: Interner> TypeError<I> {
+    pub fn involves_regions(self) -> bool {
+        match self {
+            TypeError::RegionsDoesNotOutlive(_, _)
+            | TypeError::RegionsInsufficientlyPolymorphic(_, _)
+            | TypeError::RegionsPlaceholderMismatch => true,
+            _ => false,
+        }
+    }
+
+    pub fn must_include_note(self) -> bool {
+        use self::TypeError::*;
+        match self {
+            CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
+            | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
+            | ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
+
+            Mutability
+            | ArgumentMutability(_)
+            | TupleSize(_)
+            | ArgCount
+            | RegionsDoesNotOutlive(..)
+            | RegionsInsufficientlyPolymorphic(..)
+            | RegionsPlaceholderMismatch
+            | Traits(_)
+            | ProjectionMismatched(_)
+            | ExistentialMismatch(_)
+            | ConstMismatch(_)
+            | IntrinsicCast => true,
+        }
+    }
+}
+
+impl<I: Interner> From<TypeError<I>> for NoSolution {
+    fn from(_: TypeError<I>) -> NoSolution {
+        NoSolution
+    }
+}
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index 501311ff72f..ee3e5ce66d0 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -387,7 +387,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
         match ct.kind() {
             ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty())
+                Const::new_bound(self.tcx, debruijn, bound_ct)
             }
             _ => ct.super_fold_with(self),
         }
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs
index bb5081fb335..24e10722448 100644
--- a/compiler/rustc_type_ir/src/infcx.rs
+++ b/compiler/rustc_type_ir/src/infcx.rs
@@ -12,15 +12,10 @@ pub trait InferCtxtLike {
     fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> <Self::Interner as Interner>::Ty;
     fn opportunistic_resolve_int_var(&self, vid: IntVid) -> <Self::Interner as Interner>::Ty;
     fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> <Self::Interner as Interner>::Ty;
-    fn opportunistic_resolve_ct_var(
-        &self,
-        vid: ConstVid,
-        ty: <Self::Interner as Interner>::Ty,
-    ) -> <Self::Interner as Interner>::Const;
+    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> <Self::Interner as Interner>::Const;
     fn opportunistic_resolve_effect_var(
         &self,
         vid: EffectVid,
-        ty: <Self::Interner as Interner>::Ty,
     ) -> <Self::Interner as Interner>::Const;
     fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> <Self::Interner as Interner>::Region;
 
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index f305ed9b5d7..205a1e5f100 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -7,7 +7,10 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Deref;
 
+use rustc_ast_ir::Mutability;
+
 use crate::fold::{TypeFoldable, TypeSuperFoldable};
+use crate::relate::Relate;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{self as ty, CollectAndApply, DebugWithInfcx, Interner, UpcastFrom};
 
@@ -21,6 +24,7 @@ pub trait Ty<I: Interner<Ty = Self>>:
     + IntoKind<Kind = ty::TyKind<I>>
     + TypeSuperVisitable<I>
     + TypeSuperFoldable<I>
+    + Relate<I>
     + Flags
 {
     fn new_bool(interner: I) -> Self;
@@ -35,8 +39,37 @@ pub trait Ty<I: Interner<Ty = Self>>:
 
     fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
 
+    fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
+
+    fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self;
+
+    fn new_foreign(interner: I, def_id: I::DefId) -> Self;
+
+    fn new_dynamic(
+        interner: I,
+        preds: I::BoundExistentialPredicates,
+        region: I::Region,
+        kind: ty::DynKind,
+    ) -> Self;
+
     fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
 
+    fn new_coroutine_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
+
+    fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
+
+    fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self;
+
+    fn new_slice(interner: I, ty: Self) -> Self;
+
+    fn new_tup(interner: I, tys: &[I::Ty]) -> Self;
+
     fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
     where
         It: Iterator<Item = T>,
@@ -49,6 +82,12 @@ pub trait Ty<I: Interner<Ty = Self>>:
     fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
 
     fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
+
+    fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
+
+    fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
 }
 
 pub trait Tys<I: Interner<Tys = Self>>:
@@ -84,6 +123,7 @@ pub trait Region<I: Interner<Region = Self>>:
     + IntoKind<Kind = ty::RegionKind<I>>
     + Flags
     + TypeVisitable<I>
+    + Relate<I>
 {
     fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
 
@@ -102,24 +142,22 @@ pub trait Const<I: Interner<Const = Self>>:
     + IntoKind<Kind = ty::ConstKind<I>>
     + TypeSuperVisitable<I>
     + TypeSuperFoldable<I>
+    + Relate<I>
     + Flags
 {
-    fn new_infer(interner: I, var: ty::InferConst, ty: I::Ty) -> Self;
+    fn try_to_target_usize(self, interner: I) -> Option<u64>;
 
-    fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self;
+    fn new_infer(interner: I, var: ty::InferConst) -> Self;
 
-    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst, ty: I::Ty) -> Self;
+    fn new_var(interner: I, var: ty::ConstVid) -> Self;
 
-    fn new_anon_bound(
-        interner: I,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-        ty: I::Ty,
-    ) -> Self;
+    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
 
-    fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>, ty: I::Ty) -> Self;
+    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
 
-    fn ty(self) -> I::Ty;
+    fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
+
+    fn new_expr(interner: I, expr: I::ExprConst) -> Self;
 }
 
 pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
@@ -135,13 +173,14 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     + Deref<Target: Deref<Target = [I::GenericArg]>>
     + Default
     + TypeFoldable<I>
+    + Relate<I>
 {
     fn type_at(self, i: usize) -> I::Ty;
 
     fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
 
     fn extend_with_error(
-        tcx: I,
+        interner: I,
         def_id: I::DefId,
         original_args: &[I::GenericArg],
     ) -> I::GenericArgs;
@@ -200,3 +239,11 @@ pub trait BoundVarLike<I: Interner> {
 pub trait ParamLike {
     fn index(self) -> u32;
 }
+
+pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
+    fn def_id(self) -> I::DefId;
+}
+
+pub trait Features<I: Interner>: Copy {
+    fn generic_const_exprs(self) -> bool;
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 6ebb434299b..ad1d2753b28 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -6,6 +6,7 @@ use std::ops::Deref;
 use crate::fold::TypeFoldable;
 use crate::inherent::*;
 use crate::ir_print::IrPrint;
+use crate::relate::Relate;
 use crate::solve::inspect::CanonicalGoalEvaluationStep;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{self as ty, DebugWithInfcx};
@@ -25,8 +26,8 @@ pub trait Interner:
     + IrPrint<ty::CoercePredicate<Self>>
     + IrPrint<ty::FnSig<Self>>
 {
-    type DefId: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
-    type AdtDef: Copy + Debug + Hash + Eq;
+    type DefId: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
+    type AdtDef: AdtDef<Self>;
 
     type GenericArgs: GenericArgs<Self>;
     type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref<Target = [Self::GenericArg]>;
@@ -35,8 +36,15 @@ pub trait Interner:
         + Hash
         + Eq
         + IntoKind<Kind = ty::GenericArgKind<Self>>
-        + TypeVisitable<Self>;
-    type Term: Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<Self>> + TypeVisitable<Self>;
+        + TypeVisitable<Self>
+        + Relate<Self>;
+    type Term: Copy
+        + Debug
+        + Hash
+        + Eq
+        + IntoKind<Kind = ty::TermKind<Self>>
+        + TypeFoldable<Self>
+        + Relate<Self>;
 
     type BoundVarKinds: Copy
         + Debug
@@ -66,11 +74,11 @@ pub trait Interner:
 
     // Things stored inside of tys
     type ErrorGuaranteed: Copy + Debug + Hash + Eq;
-    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
     type AllocId: Copy + Debug + Hash + Eq;
-    type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>;
-    type Safety: Safety<Self>;
-    type Abi: Abi<Self>;
+    type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self> + Relate<Self>;
+    type Safety: Safety<Self> + TypeFoldable<Self> + Relate<Self>;
+    type Abi: Abi<Self> + TypeFoldable<Self> + Relate<Self>;
 
     // Kinds of consts
     type Const: Const<Self>;
@@ -78,7 +86,7 @@ pub trait Interner:
     type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
     type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
     type ValueConst: Copy + Debug + Hash + Eq;
-    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
+    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Eq + Relate<Self>;
 
     // Kinds of regions
     type Region: Region<Self>;
@@ -93,11 +101,16 @@ pub trait Interner:
     type Clause: Clause<Self>;
     type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
 
+    fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;
+
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
 
     type GenericsOf: GenericsOf<Self>;
     fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
 
+    type VariancesOf: Copy + Debug + Deref<Target = [ty::Variance]>;
+    fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf;
+
     // FIXME: Remove after uplifting `EarlyBinder`
     fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Ty>;
 
@@ -112,7 +125,12 @@ pub trait Interner:
     ) -> (ty::TraitRef<Self>, Self::GenericArgsSlice);
 
     fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
-    fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs;
+
+    fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Self::GenericArg, Self::GenericArgs>;
+
     fn check_and_mk_args(
         self,
         def_id: Self::DefId,
@@ -124,9 +142,17 @@ pub trait Interner:
         step: CanonicalGoalEvaluationStep<Self>,
     ) -> Self::CanonicalGoalEvaluationStepRef;
 
+    fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<Self::Ty, Self::Tys>;
+
     fn parent(self, def_id: Self::DefId) -> Self::DefId;
 
     fn recursion_limit(self) -> usize;
+
+    type Features: Features<Self>;
+    fn features(self) -> Self::Features;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 217c056d0ba..73716468930 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -21,18 +21,20 @@ use std::hash::Hash;
 #[cfg(not(feature = "nightly"))]
 use std::sync::Arc as Lrc;
 
+// These modules are `pub` since they are not glob-imported.
 #[macro_use]
 pub mod visit;
 #[cfg(feature = "nightly")]
 pub mod codec;
+pub mod error;
 pub mod fold;
 pub mod inherent;
 pub mod ir_print;
 pub mod lift;
+pub mod relate;
 pub mod solve;
-pub mod ty_info;
-pub mod ty_kind;
 
+// These modules are not `pub` since they are glob-imported.
 #[macro_use]
 mod macros;
 mod binder;
@@ -46,6 +48,8 @@ mod interner;
 mod predicate;
 mod predicate_kind;
 mod region_kind;
+mod ty_info;
+mod ty_kind;
 mod upcast;
 
 pub use binder::*;
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index f2f7b165de5..aae5aeb5fb3 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -48,10 +48,22 @@ TrivialTypeTraversalImpls! {
     u32,
     u64,
     String,
-    crate::DebruijnIndex,
     crate::AliasRelationDirection,
+    crate::AliasTyKind,
+    crate::BoundConstness,
+    crate::DebruijnIndex,
+    crate::FloatTy,
+    crate::InferTy,
+    crate::IntVarValue,
+    crate::PredicatePolarity,
+    crate::RegionVid,
+    crate::solve::BuiltinImplSource,
+    crate::solve::Certainty,
+    crate::solve::GoalSource,
+    crate::solve::MaybeCause,
+    crate::solve::NoSolution,
     crate::UniverseIndex,
-    rustc_ast_ir::Mutability,
+    crate::Variance,
     rustc_ast_ir::Movability,
-    crate::PredicatePolarity,
+    rustc_ast_ir::Mutability,
 }
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index e7039583c91..63a4c2e9d1f 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -567,7 +567,6 @@ impl<I: Interner> AliasTerm<I> {
                 I::Const::new_unevaluated(
                     interner,
                     ty::UnevaluatedConst::new(self.def_id, self.args),
-                    interner.type_of(self.def_id).instantiate(interner, &self.args),
                 )
                 .into()
             }
@@ -794,3 +793,36 @@ pub struct CoercePredicate<I: Interner> {
     pub a: I::Ty,
     pub b: I::Ty,
 }
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
+pub enum BoundConstness {
+    /// `Type: Trait`
+    NotConst,
+    /// `Type: const Trait`
+    Const,
+    /// `Type: ~const Trait`
+    ///
+    /// Requires resolving to const only when we are in a const context.
+    ConstIfConst,
+}
+
+impl BoundConstness {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::NotConst => "",
+            Self::Const => "const",
+            Self::ConstIfConst => "~const",
+        }
+    }
+}
+
+impl fmt::Display for BoundConstness {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotConst => f.write_str("normal"),
+            Self::Const => f.write_str("const"),
+            Self::ConstIfConst => f.write_str("~const"),
+        }
+    }
+}
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
new file mode 100644
index 00000000000..cae1d13020d
--- /dev/null
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -0,0 +1,666 @@
+use std::iter;
+
+use rustc_ast_ir::Mutability;
+use rustc_type_ir::error::{ExpectedFound, TypeError};
+use rustc_type_ir::fold::TypeFoldable;
+use rustc_type_ir::inherent::*;
+use rustc_type_ir::{self as ty, Interner};
+use tracing::{debug, instrument};
+
+pub type RelateResult<I, T> = Result<T, TypeError<I>>;
+
+/// Extra information about why we ended up with a particular variance.
+/// This is only used to add more information to error messages, and
+/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
+/// may lead to confusing notes in error messages, it will never cause
+/// a miscompilation or unsoundness.
+///
+/// When in doubt, use `VarianceDiagInfo::default()`
+#[derive(derivative::Derivative)]
+#[derivative(
+    Copy(bound = ""),
+    Clone(bound = ""),
+    Debug(bound = ""),
+    Default(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+pub enum VarianceDiagInfo<I: Interner> {
+    /// No additional information - this is the default.
+    /// We will not add any additional information to error messages.
+    #[derivative(Default)]
+    None,
+    /// We switched our variance because a generic argument occurs inside
+    /// the invariant generic argument of another type.
+    Invariant {
+        /// The generic type containing the generic parameter
+        /// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
+        ty: I::Ty,
+        /// The index of the generic parameter being used
+        /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
+        param_index: u32,
+    },
+}
+
+impl<I: Interner> VarianceDiagInfo<I> {
+    /// Mirrors `Variance::xform` - used to 'combine' the existing
+    /// and new `VarianceDiagInfo`s when our variance changes.
+    pub fn xform(self, other: VarianceDiagInfo<I>) -> VarianceDiagInfo<I> {
+        // For now, just use the first `VarianceDiagInfo::Invariant` that we see
+        match self {
+            VarianceDiagInfo::None => other,
+            VarianceDiagInfo::Invariant { .. } => self,
+        }
+    }
+}
+
+pub trait TypeRelation<I: Interner>: Sized {
+    fn tcx(&self) -> I;
+
+    /// Returns a static string we can use for printouts.
+    fn tag(&self) -> &'static str;
+
+    /// Generic relation routine suitable for most anything.
+    fn relate<T: Relate<I>>(&mut self, a: T, b: T) -> RelateResult<I, T> {
+        Relate::relate(self, a, b)
+    }
+
+    /// Relate the two args for the given item. The default
+    /// is to look up the variance for the item and proceed
+    /// accordingly.
+    fn relate_item_args(
+        &mut self,
+        item_def_id: I::DefId,
+        a_arg: I::GenericArgs,
+        b_arg: I::GenericArgs,
+    ) -> RelateResult<I, I::GenericArgs> {
+        debug!(
+            "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
+            item_def_id, a_arg, b_arg
+        );
+
+        let tcx = self.tcx();
+        let opt_variances = tcx.variances_of(item_def_id);
+        relate_args_with_variances(self, item_def_id, &opt_variances, a_arg, b_arg, true)
+    }
+
+    /// Switch variance for the purpose of relating `a` and `b`.
+    fn relate_with_variance<T: Relate<I>>(
+        &mut self,
+        variance: ty::Variance,
+        info: VarianceDiagInfo<I>,
+        a: T,
+        b: T,
+    ) -> RelateResult<I, T>;
+
+    // Overridable relations. You shouldn't typically call these
+    // directly, instead call `relate()`, which in turn calls
+    // these. This is both more uniform but also allows us to add
+    // additional hooks for other types in the future if needed
+    // without making older code, which called `relate`, obsolete.
+
+    fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty>;
+
+    fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region>;
+
+    fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const>;
+
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<I, T>,
+        b: ty::Binder<I, T>,
+    ) -> RelateResult<I, ty::Binder<I, T>>
+    where
+        T: Relate<I>;
+}
+
+pub trait Relate<I: Interner>: TypeFoldable<I> + PartialEq + Copy {
+    fn relate<R: TypeRelation<I>>(relation: &mut R, a: Self, b: Self) -> RelateResult<I, Self>;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Relate impls
+
+#[inline]
+pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
+    relation: &mut R,
+    a_arg: I::GenericArgs,
+    b_arg: I::GenericArgs,
+) -> RelateResult<I, I::GenericArgs> {
+    relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
+        relation.relate_with_variance(ty::Variance::Invariant, VarianceDiagInfo::default(), a, b)
+    }))
+}
+
+pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
+    relation: &mut R,
+    ty_def_id: I::DefId,
+    variances: &[ty::Variance],
+    a_arg: I::GenericArgs,
+    b_arg: I::GenericArgs,
+    fetch_ty_for_diag: bool,
+) -> RelateResult<I, I::GenericArgs> {
+    let tcx = relation.tcx();
+
+    let mut cached_ty = None;
+    let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
+        let variance = variances[i];
+        let variance_info = if variance == ty::Variance::Invariant && fetch_ty_for_diag {
+            let ty =
+                *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, &a_arg));
+            VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
+        } else {
+            VarianceDiagInfo::default()
+        };
+        relation.relate_with_variance(variance, variance_info, a, b)
+    });
+
+    tcx.mk_args_from_iter(params)
+}
+
+impl<I: Interner> Relate<I> for ty::FnSig<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::FnSig<I>,
+        b: ty::FnSig<I>,
+    ) -> RelateResult<I, ty::FnSig<I>> {
+        let tcx = relation.tcx();
+
+        if a.c_variadic != b.c_variadic {
+            return Err(TypeError::VariadicMismatch({
+                let a = a.c_variadic;
+                let b = b.c_variadic;
+                ExpectedFound::new(true, a, b)
+            }));
+        }
+        let safety = relation.relate(a.safety, b.safety)?;
+        let abi = relation.relate(a.abi, b.abi)?;
+
+        let a_inputs = a.inputs();
+        let b_inputs = b.inputs();
+
+        if a_inputs.len() != b_inputs.len() {
+            return Err(TypeError::ArgCount);
+        }
+
+        let inputs_and_output = iter::zip(a_inputs.iter(), b_inputs.iter())
+            .map(|(&a, &b)| ((a, b), false))
+            .chain(iter::once(((a.output(), b.output()), true)))
+            .map(|((a, b), is_output)| {
+                if is_output {
+                    relation.relate(a, b)
+                } else {
+                    relation.relate_with_variance(
+                        ty::Variance::Contravariant,
+                        VarianceDiagInfo::default(),
+                        a,
+                        b,
+                    )
+                }
+            })
+            .enumerate()
+            .map(|(i, r)| match r {
+                Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
+                    Err(TypeError::ArgumentSorts(exp_found, i))
+                }
+                Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
+                    Err(TypeError::ArgumentMutability(i))
+                }
+                r => r,
+            });
+        Ok(ty::FnSig {
+            inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
+            c_variadic: a.c_variadic,
+            safety,
+            abi,
+        })
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::BoundConstness {
+    fn relate<R: TypeRelation<I>>(
+        _relation: &mut R,
+        a: ty::BoundConstness,
+        b: ty::BoundConstness,
+    ) -> RelateResult<I, ty::BoundConstness> {
+        if a != b {
+            Err(TypeError::ConstnessMismatch(ExpectedFound::new(true, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::AliasTy<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::AliasTy<I>,
+        b: ty::AliasTy<I>,
+    ) -> RelateResult<I, ty::AliasTy<I>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched({
+                let a = a.def_id;
+                let b = b.def_id;
+                ExpectedFound::new(true, a, b)
+            }))
+        } else {
+            let args = match a.kind(relation.tcx()) {
+                ty::Opaque => relate_args_with_variances(
+                    relation,
+                    a.def_id,
+                    &relation.tcx().variances_of(a.def_id),
+                    a.args,
+                    b.args,
+                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                )?,
+                ty::Projection | ty::Weak | ty::Inherent => {
+                    relate_args_invariantly(relation, a.args, b.args)?
+                }
+            };
+            Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args))
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::AliasTerm<I>,
+        b: ty::AliasTerm<I>,
+    ) -> RelateResult<I, ty::AliasTerm<I>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched({
+                let a = a.def_id;
+                let b = b.def_id;
+                ExpectedFound::new(true, a, b)
+            }))
+        } else {
+            let args = match a.kind(relation.tcx()) {
+                ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
+                    relation,
+                    a.def_id,
+                    &relation.tcx().variances_of(a.def_id),
+                    a.args,
+                    b.args,
+                    false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                )?,
+                ty::AliasTermKind::ProjectionTy
+                | ty::AliasTermKind::WeakTy
+                | ty::AliasTermKind::InherentTy
+                | ty::AliasTermKind::UnevaluatedConst
+                | ty::AliasTermKind::ProjectionConst => {
+                    relate_args_invariantly(relation, a.args, b.args)?
+                }
+            };
+            Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args))
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::ExistentialProjection<I>,
+        b: ty::ExistentialProjection<I>,
+    ) -> RelateResult<I, ty::ExistentialProjection<I>> {
+        if a.def_id != b.def_id {
+            Err(TypeError::ProjectionMismatched({
+                let a = a.def_id;
+                let b = b.def_id;
+                ExpectedFound::new(true, a, b)
+            }))
+        } else {
+            let term = relation.relate_with_variance(
+                ty::Variance::Invariant,
+                VarianceDiagInfo::default(),
+                a.term,
+                b.term,
+            )?;
+            let args = relation.relate_with_variance(
+                ty::Variance::Invariant,
+                VarianceDiagInfo::default(),
+                a.args,
+                b.args,
+            )?;
+            Ok(ty::ExistentialProjection { def_id: a.def_id, args, term })
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::TraitRef<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::TraitRef<I>,
+        b: ty::TraitRef<I>,
+    ) -> RelateResult<I, ty::TraitRef<I>> {
+        // Different traits cannot be related.
+        if a.def_id != b.def_id {
+            Err(TypeError::Traits({
+                let a = a.def_id;
+                let b = b.def_id;
+                ExpectedFound::new(true, a, b)
+            }))
+        } else {
+            let args = relate_args_invariantly(relation, a.args, b.args)?;
+            Ok(ty::TraitRef::new(relation.tcx(), a.def_id, args))
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::ExistentialTraitRef<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::ExistentialTraitRef<I>,
+        b: ty::ExistentialTraitRef<I>,
+    ) -> RelateResult<I, ty::ExistentialTraitRef<I>> {
+        // Different traits cannot be related.
+        if a.def_id != b.def_id {
+            Err(TypeError::Traits({
+                let a = a.def_id;
+                let b = b.def_id;
+                ExpectedFound::new(true, a, b)
+            }))
+        } else {
+            let args = relate_args_invariantly(relation, a.args, b.args)?;
+            Ok(ty::ExistentialTraitRef { def_id: a.def_id, args })
+        }
+    }
+}
+
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of projections, and inference variables have to be
+/// handled by the caller.
+#[instrument(level = "trace", skip(relation), ret)]
+pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
+    relation: &mut R,
+    a: I::Ty,
+    b: I::Ty,
+) -> RelateResult<I, I::Ty> {
+    let tcx = relation.tcx();
+    match (a.kind(), b.kind()) {
+        (ty::Infer(_), _) | (_, ty::Infer(_)) => {
+            // The caller should handle these cases!
+            panic!("var types encountered in structurally_relate_tys")
+        }
+
+        (ty::Bound(..), _) | (_, ty::Bound(..)) => {
+            panic!("bound types encountered in structurally_relate_tys")
+        }
+
+        (ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
+
+        (ty::Never, _)
+        | (ty::Char, _)
+        | (ty::Bool, _)
+        | (ty::Int(_), _)
+        | (ty::Uint(_), _)
+        | (ty::Float(_), _)
+        | (ty::Str, _)
+            if a == b =>
+        {
+            Ok(a)
+        }
+
+        (ty::Param(a_p), ty::Param(b_p)) if a_p.index() == b_p.index() => {
+            // FIXME: Put this back
+            //debug_assert_eq!(a_p.name(), b_p.name(), "param types with same index differ in name");
+            Ok(a)
+        }
+
+        (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
+
+        (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
+            let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?;
+            Ok(Ty::new_adt(tcx, a_def, args))
+        }
+
+        (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
+
+        (ty::Dynamic(a_obj, a_region, a_repr), ty::Dynamic(b_obj, b_region, b_repr))
+            if a_repr == b_repr =>
+        {
+            Ok(Ty::new_dynamic(
+                tcx,
+                relation.relate(a_obj, b_obj)?,
+                relation.relate(a_region, b_region)?,
+                a_repr,
+            ))
+        }
+
+        (ty::Coroutine(a_id, a_args), ty::Coroutine(b_id, b_args)) if a_id == b_id => {
+            // All Coroutine types with the same id represent
+            // the (anonymous) type of the same coroutine expression. So
+            // all of their regions should be equated.
+            let args = relate_args_invariantly(relation, a_args, b_args)?;
+            Ok(Ty::new_coroutine(tcx, a_id, args))
+        }
+
+        (ty::CoroutineWitness(a_id, a_args), ty::CoroutineWitness(b_id, b_args))
+            if a_id == b_id =>
+        {
+            // All CoroutineWitness types with the same id represent
+            // the (anonymous) type of the same coroutine expression. So
+            // all of their regions should be equated.
+            let args = relate_args_invariantly(relation, a_args, b_args)?;
+            Ok(Ty::new_coroutine_witness(tcx, a_id, args))
+        }
+
+        (ty::Closure(a_id, a_args), ty::Closure(b_id, b_args)) if a_id == b_id => {
+            // All Closure types with the same id represent
+            // the (anonymous) type of the same closure expression. So
+            // all of their regions should be equated.
+            let args = relate_args_invariantly(relation, a_args, b_args)?;
+            Ok(Ty::new_closure(tcx, a_id, args))
+        }
+
+        (ty::CoroutineClosure(a_id, a_args), ty::CoroutineClosure(b_id, b_args))
+            if a_id == b_id =>
+        {
+            let args = relate_args_invariantly(relation, a_args, b_args)?;
+            Ok(Ty::new_coroutine_closure(tcx, a_id, args))
+        }
+
+        (ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
+            if a_mutbl != b_mutbl {
+                return Err(TypeError::Mutability);
+            }
+
+            let (variance, info) = match a_mutbl {
+                Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
+                Mutability::Mut => {
+                    (ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
+                }
+            };
+
+            let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
+
+            Ok(Ty::new_ptr(tcx, ty, a_mutbl))
+        }
+
+        (ty::Ref(a_r, a_ty, a_mutbl), ty::Ref(b_r, b_ty, b_mutbl)) => {
+            if a_mutbl != b_mutbl {
+                return Err(TypeError::Mutability);
+            }
+
+            let (variance, info) = match a_mutbl {
+                Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
+                Mutability::Mut => {
+                    (ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
+                }
+            };
+
+            let r = relation.relate(a_r, b_r)?;
+            let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
+
+            Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
+        }
+
+        (ty::Array(a_t, sz_a), ty::Array(b_t, sz_b)) => {
+            let t = relation.relate(a_t, b_t)?;
+            match relation.relate(sz_a, sz_b) {
+                Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
+                Err(err) => {
+                    // Check whether the lengths are both concrete/known values,
+                    // but are unequal, for better diagnostics.
+                    let sz_a = sz_a.try_to_target_usize(tcx);
+                    let sz_b = sz_b.try_to_target_usize(tcx);
+
+                    match (sz_a, sz_b) {
+                        (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
+                            TypeError::FixedArraySize(ExpectedFound::new(true, sz_a_val, sz_b_val)),
+                        ),
+                        _ => Err(err),
+                    }
+                }
+            }
+        }
+
+        (ty::Slice(a_t), ty::Slice(b_t)) => {
+            let t = relation.relate(a_t, b_t)?;
+            Ok(Ty::new_slice(tcx, t))
+        }
+
+        (ty::Tuple(as_), ty::Tuple(bs)) => {
+            if as_.len() == bs.len() {
+                Ok(Ty::new_tup_from_iter(
+                    tcx,
+                    iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
+                )?)
+            } else if !(as_.is_empty() || bs.is_empty()) {
+                Err(TypeError::TupleSize(ExpectedFound::new(true, as_.len(), bs.len())))
+            } else {
+                Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
+            }
+        }
+
+        (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
+            let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
+            Ok(Ty::new_fn_def(tcx, a_def_id, args))
+        }
+
+        (ty::FnPtr(a_fty), ty::FnPtr(b_fty)) => {
+            let fty = relation.relate(a_fty, b_fty)?;
+            Ok(Ty::new_fn_ptr(tcx, fty))
+        }
+
+        // Alias tend to mostly already be handled downstream due to normalization.
+        (ty::Alias(a_kind, a_data), ty::Alias(b_kind, b_data)) => {
+            let alias_ty = relation.relate(a_data, b_data)?;
+            assert_eq!(a_kind, b_kind);
+            Ok(Ty::new_alias(tcx, a_kind, alias_ty))
+        }
+
+        (ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => {
+            let ty = relation.relate(a_ty, b_ty)?;
+            let pat = relation.relate(a_pat, b_pat)?;
+            Ok(Ty::new_pat(tcx, ty, pat))
+        }
+
+        _ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))),
+    }
+}
+
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
+/// to be handled by the caller.
+///
+/// FIXME: This is not totally structual, which probably should be fixed.
+/// See the HACKs below.
+pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
+    relation: &mut R,
+    mut a: I::Const,
+    mut b: I::Const,
+) -> RelateResult<I, I::Const> {
+    debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
+    let tcx = relation.tcx();
+
+    if tcx.features().generic_const_exprs() {
+        a = tcx.expand_abstract_consts(a);
+        b = tcx.expand_abstract_consts(b);
+    }
+
+    debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
+    // Currently, the values that can be unified are primitive types,
+    // and those that derive both `PartialEq` and `Eq`, corresponding
+    // to structural-match types.
+    let is_match = match (a.kind(), b.kind()) {
+        (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
+            // The caller should handle these cases!
+            panic!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
+        }
+
+        (ty::ConstKind::Error(_), _) => return Ok(a),
+        (_, ty::ConstKind::Error(_)) => return Ok(b),
+
+        (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index() == b_p.index() => {
+            // FIXME: Put this back
+            // debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name");
+            true
+        }
+        (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
+        (ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
+
+        // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
+        // and is the better alternative to waiting until `generic_const_exprs` can
+        // be stabilized.
+        (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
+            if cfg!(debug_assertions) {
+                let a_ty = tcx.type_of(au.def).instantiate(tcx, &au.args);
+                let b_ty = tcx.type_of(bu.def).instantiate(tcx, &bu.args);
+                assert_eq!(a_ty, b_ty);
+            }
+
+            let args = relation.relate_with_variance(
+                ty::Variance::Invariant,
+                VarianceDiagInfo::default(),
+                au.args,
+                bu.args,
+            )?;
+            return Ok(Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
+        }
+        (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
+            let expr = relation.relate(ae, be)?;
+            return Ok(Const::new_expr(tcx, expr));
+        }
+        _ => false,
+    };
+    if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))) }
+}
+
+impl<I: Interner, T: Relate<I>> Relate<I> for ty::Binder<I, T> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::Binder<I, T>,
+        b: ty::Binder<I, T>,
+    ) -> RelateResult<I, ty::Binder<I, T>> {
+        relation.binders(a, b)
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::PredicatePolarity {
+    fn relate<R: TypeRelation<I>>(
+        _relation: &mut R,
+        a: ty::PredicatePolarity,
+        b: ty::PredicatePolarity,
+    ) -> RelateResult<I, ty::PredicatePolarity> {
+        if a != b {
+            Err(TypeError::PolarityMismatch(ExpectedFound::new(true, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+}
+
+impl<I: Interner> Relate<I> for ty::TraitPredicate<I> {
+    fn relate<R: TypeRelation<I>>(
+        relation: &mut R,
+        a: ty::TraitPredicate<I>,
+        b: ty::TraitPredicate<I>,
+    ) -> RelateResult<I, ty::TraitPredicate<I>> {
+        Ok(ty::TraitPredicate {
+            trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
+            polarity: relation.relate(a.polarity, b.polarity)?,
+        })
+    }
+}
diff --git a/compiler/rustc_type_ir/src/solve.rs b/compiler/rustc_type_ir/src/solve.rs
index 3c24e851d7b..45125fe6191 100644
--- a/compiler/rustc_type_ir/src/solve.rs
+++ b/compiler/rustc_type_ir/src/solve.rs
@@ -20,7 +20,6 @@ pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
 pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>;
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub struct NoSolution;
 
@@ -60,7 +59,7 @@ impl<I: Interner, P> Goal<I, P> {
 ///
 /// This is necessary as we treat nested goals different depending on
 /// their source.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeVisitable_Generic, TypeFoldable_Generic)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum GoalSource {
     Misc,
@@ -170,7 +169,6 @@ pub enum CandidateSource<I: Interner> {
 }
 
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
 pub enum BuiltinImplSource {
     /// Some builtin impl we don't need to differentiate. This should be used
@@ -214,7 +212,6 @@ pub struct Response<I: Interner> {
 }
 
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum Certainty {
     Yes,
@@ -252,7 +249,6 @@ impl Certainty {
 
 /// Why we failed to evaluate a goal.
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum MaybeCause {
     /// We failed due to ambiguity. This ambiguity can either
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 6569f3123aa..71f3862226d 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,7 +1,7 @@
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
-use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
+use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
@@ -717,14 +717,44 @@ impl FloatTy {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum IntVarValue {
+    Unknown,
     IntType(IntTy),
     UintType(UintTy),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct FloatVarValue(pub FloatTy);
+impl IntVarValue {
+    pub fn is_known(self) -> bool {
+        match self {
+            IntVarValue::IntType(_) | IntVarValue::UintType(_) => true,
+            IntVarValue::Unknown => false,
+        }
+    }
+
+    pub fn is_unknown(self) -> bool {
+        !self.is_known()
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum FloatVarValue {
+    Unknown,
+    Known(FloatTy),
+}
+
+impl FloatVarValue {
+    pub fn is_known(self) -> bool {
+        match self {
+            FloatVarValue::Known(_) => true,
+            FloatVarValue::Unknown => false,
+        }
+    }
+
+    pub fn is_unknown(self) -> bool {
+        !self.is_known()
+    }
+}
 
 rustc_index::newtype_index! {
     /// A **ty**pe **v**ariable **ID**.
@@ -809,11 +839,28 @@ impl UnifyKey for TyVid {
 }
 
 #[cfg(feature = "nightly")]
-impl EqUnifyValue for IntVarValue {}
+impl UnifyValue for IntVarValue {
+    type Error = NoError;
+
+    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
+        match (*value1, *value2) {
+            (IntVarValue::Unknown, IntVarValue::Unknown) => Ok(IntVarValue::Unknown),
+            (
+                IntVarValue::Unknown,
+                known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)),
+            )
+            | (
+                known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)),
+                IntVarValue::Unknown,
+            ) => Ok(known),
+            _ => panic!("differing ints should have been resolved first"),
+        }
+    }
+}
 
 #[cfg(feature = "nightly")]
 impl UnifyKey for IntVid {
-    type Value = Option<IntVarValue>;
+    type Value = IntVarValue;
     #[inline] // make this function eligible for inlining - it is quite hot.
     fn index(&self) -> u32 {
         self.as_u32()
@@ -828,11 +875,26 @@ impl UnifyKey for IntVid {
 }
 
 #[cfg(feature = "nightly")]
-impl EqUnifyValue for FloatVarValue {}
+impl UnifyValue for FloatVarValue {
+    type Error = NoError;
+
+    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
+        match (*value1, *value2) {
+            (FloatVarValue::Unknown, FloatVarValue::Unknown) => Ok(FloatVarValue::Unknown),
+            (FloatVarValue::Unknown, FloatVarValue::Known(known))
+            | (FloatVarValue::Known(known), FloatVarValue::Unknown) => {
+                Ok(FloatVarValue::Known(known))
+            }
+            (FloatVarValue::Known(_), FloatVarValue::Known(_)) => {
+                panic!("differing floats should have been resolved first")
+            }
+        }
+    }
+}
 
 #[cfg(feature = "nightly")]
 impl UnifyKey for FloatVid {
-    type Value = Option<FloatVarValue>;
+    type Value = FloatVarValue;
     #[inline]
     fn index(&self) -> u32 {
         self.as_u32()
@@ -860,21 +922,6 @@ impl<CTX> HashStable<CTX> for InferTy {
     }
 }
 
-impl fmt::Debug for IntVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            IntVarValue::IntType(ref v) => v.fmt(f),
-            IntVarValue::UintType(ref v) => v.fmt(f),
-        }
-    }
-}
-
-impl fmt::Debug for FloatVarValue {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
 impl fmt::Display for InferTy {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use InferTy::*;
diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml
index c61e217bf9f..4ed61152736 100644
--- a/compiler/stable_mir/Cargo.toml
+++ b/compiler/stable_mir/Cargo.toml
@@ -4,5 +4,4 @@ version = "0.1.0-preview"
 edition = "2021"
 
 [dependencies]
-tracing = "0.1"
 scoped-tls = "1.0"
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index 858ce5301d8..085dfd9ea89 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -11,10 +11,10 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef};
 use crate::mir::{BinOp, Body, Place, UnOp};
 use crate::target::MachineInfo;
 use crate::ty::{
-    AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
+    AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
     ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
-    ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty,
-    TyKind, UintTy, VariantDef,
+    ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl,
+    TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef,
 };
 use crate::{
     mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind,
@@ -109,19 +109,21 @@ pub trait Context {
     fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef>;
 
     /// Evaluate constant as a target usize.
-    fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error>;
+    fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error>;
+    fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error>;
 
     /// Create a new zero-sized constant.
-    fn try_new_const_zst(&self, ty: Ty) -> Result<Const, Error>;
+    fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error>;
 
     /// Create a new constant that represents the given string value.
-    fn new_const_str(&self, value: &str) -> Const;
+    fn new_const_str(&self, value: &str) -> MirConst;
 
     /// Create a new constant that represents the given boolean value.
-    fn new_const_bool(&self, value: bool) -> Const;
+    fn new_const_bool(&self, value: bool) -> MirConst;
 
     /// Create a new constant that represents the given value.
-    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<Const, Error>;
+    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error>;
+    fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error>;
 
     /// Create a new type from the given kind.
     fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
@@ -136,11 +138,13 @@ pub trait Context {
     fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
 
     /// Returns literal value of a const as a string.
-    fn const_pretty(&self, cnst: &Const) -> String;
+    fn mir_const_pretty(&self, cnst: &MirConst) -> String;
 
     /// `Span` of an item
     fn span_of_an_item(&self, def_id: DefId) -> Span;
 
+    fn ty_const_pretty(&self, ct: TyConstId) -> String;
+
     /// Obtain the representation of a type.
     fn ty_pretty(&self, ty: Ty) -> String;
 
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 4c779ae96a8..43e4682dc10 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,8 +1,8 @@
 use crate::compiler_interface::with;
 use crate::mir::pretty::function_body;
 use crate::ty::{
-    AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
-    VariantIdx,
+    AdtDef, ClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty,
+    TyConst, TyKind, VariantIdx,
 };
 use crate::{Error, Opaque, Span, Symbol};
 use std::io;
@@ -524,7 +524,7 @@ pub enum Rvalue {
     /// Corresponds to source code like `[x; 32]`.
     ///
     /// [#74836]: https://github.com/rust-lang/rust/issues/74836
-    Repeat(Operand, Const),
+    Repeat(Operand, TyConst),
 
     /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
     ///
@@ -718,7 +718,7 @@ pub enum VarDebugInfoContents {
 pub struct ConstOperand {
     pub span: Span,
     pub user_ty: Option<UserTypeAnnotationIndex>,
-    pub const_: Const,
+    pub const_: MirConst,
 }
 
 // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
@@ -833,7 +833,7 @@ type UserTypeAnnotationIndex = usize;
 pub struct Constant {
     pub span: Span,
     pub user_ty: Option<UserTypeAnnotationIndex>,
-    pub literal: Const,
+    pub literal: MirConst,
 }
 
 /// The possible branch sites of a [TerminatorKind::SwitchInt].
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 580dc1a2b88..2fb180b84c7 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -1,5 +1,5 @@
 use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
-use crate::ty::{Const, IndexedVal, Ty};
+use crate::ty::{IndexedVal, MirConst, Ty, TyConst};
 use crate::{with, Body, Mutability};
 use fmt::{Display, Formatter};
 use std::fmt::Debug;
@@ -46,7 +46,7 @@ pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -
             VarDebugInfoContents::Place(place) => {
                 format!("{place:?}")
             }
-            VarDebugInfoContents::Const(constant) => pretty_const(&constant.const_),
+            VarDebugInfoContents::Const(constant) => pretty_mir_const(&constant.const_),
         };
         writeln!(writer, "    debug {} => {};", info.name, content)
     })?;
@@ -310,12 +310,16 @@ fn pretty_operand(operand: &Operand) -> String {
         Operand::Move(mv) => {
             format!("move {:?}", mv)
         }
-        Operand::Constant(cnst) => pretty_const(&cnst.literal),
+        Operand::Constant(cnst) => pretty_mir_const(&cnst.literal),
     }
 }
 
-fn pretty_const(literal: &Const) -> String {
-    with(|cx| cx.const_pretty(literal))
+fn pretty_mir_const(literal: &MirConst) -> String {
+    with(|cx| cx.mir_const_pretty(literal))
+}
+
+fn pretty_ty_const(ct: &TyConst) -> String {
+    with(|cx| cx.ty_const_pretty(ct.id))
 }
 
 fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
@@ -359,7 +363,7 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
             write!(writer, "{kind}{:?}", place)
         }
         Rvalue::Repeat(op, cnst) => {
-            write!(writer, "{} \" \" {}", &pretty_operand(op), cnst.ty())
+            write!(writer, "{} \" \" {}", &pretty_operand(op), &pretty_ty_const(cnst))
         }
         Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::ThreadLocalRef(item) => {
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index 24296e9e877..10f30083dc2 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -36,7 +36,7 @@
 //! variant argument) that does not require visiting.
 
 use crate::mir::*;
-use crate::ty::{Const, GenericArgs, Region, Ty};
+use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst};
 use crate::{Error, Opaque, Span};
 
 pub trait MirVisitor {
@@ -112,8 +112,13 @@ pub trait MirVisitor {
         self.super_constant(constant, location)
     }
 
-    fn visit_const(&mut self, constant: &Const, location: Location) {
-        self.super_const(constant, location)
+    fn visit_mir_const(&mut self, constant: &MirConst, location: Location) {
+        self.super_mir_const(constant, location)
+    }
+
+    fn visit_ty_const(&mut self, constant: &TyConst, location: Location) {
+        let _ = location;
+        self.super_ty_const(constant)
     }
 
     fn visit_region(&mut self, region: &Region, location: Location) {
@@ -339,7 +344,7 @@ pub trait MirVisitor {
             }
             Rvalue::Repeat(op, constant) => {
                 self.visit_operand(op, location);
-                self.visit_const(constant, location);
+                self.visit_ty_const(constant, location);
             }
             Rvalue::ShallowInitBox(op, ty) => {
                 self.visit_ty(ty, location);
@@ -378,14 +383,18 @@ pub trait MirVisitor {
     fn super_constant(&mut self, constant: &Constant, location: Location) {
         let Constant { span, user_ty: _, literal } = constant;
         self.visit_span(span);
-        self.visit_const(literal, location);
+        self.visit_mir_const(literal, location);
     }
 
-    fn super_const(&mut self, constant: &Const, location: Location) {
-        let Const { kind: _, ty, id: _ } = constant;
+    fn super_mir_const(&mut self, constant: &MirConst, location: Location) {
+        let MirConst { kind: _, ty, id: _ } = constant;
         self.visit_ty(ty, location);
     }
 
+    fn super_ty_const(&mut self, constant: &TyConst) {
+        let _ = constant;
+    }
+
     fn super_region(&mut self, region: &Region) {
         let _ = region;
     }
@@ -407,7 +416,7 @@ pub trait MirVisitor {
                 self.visit_place(place, PlaceContext::NON_USE, location);
             }
             VarDebugInfoContents::Const(constant) => {
-                self.visit_const(&constant.const_, location);
+                self.visit_mir_const(&constant.const_, location);
             }
         }
     }
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 50bf0a5d74e..bcbe87f7303 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -28,11 +28,11 @@ impl Ty {
 
     /// Create a new array type.
     pub fn try_new_array(elem_ty: Ty, size: u64) -> Result<Ty, Error> {
-        Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?)))
+        Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?)))
     }
 
     /// Create a new array type from Const length.
-    pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty {
+    pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty {
         Ty::from_rigid_kind(RigidTy::Array(elem_ty, len))
     }
 
@@ -101,24 +101,66 @@ impl Ty {
 /// Represents a pattern in the type system
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub enum Pattern {
-    Range { start: Option<Const>, end: Option<Const>, include_end: bool },
+    Range { start: Option<TyConst>, end: Option<TyConst>, include_end: bool },
 }
 
-/// Represents a constant in MIR or from the Type system.
+/// Represents a constant in the type system
 #[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Const {
+pub struct TyConst {
+    pub(crate) kind: TyConstKind,
+    pub id: TyConstId,
+}
+
+impl TyConst {
+    pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst {
+        Self { kind, id }
+    }
+
+    /// Retrieve the constant kind.
+    pub fn kind(&self) -> &TyConstKind {
+        &self.kind
+    }
+
+    /// Creates an interned usize constant.
+    fn try_from_target_usize(val: u64) -> Result<Self, Error> {
+        with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize))
+    }
+
+    /// Try to evaluate to a target `usize`.
+    pub fn eval_target_usize(&self) -> Result<u64, Error> {
+        with(|cx| cx.eval_target_usize_ty(self))
+    }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum TyConstKind {
+    Param(ParamConst),
+    Bound(DebruijnIndex, BoundVar),
+    Unevaluated(ConstDef, GenericArgs),
+
+    // FIXME: These should be a valtree
+    Value(Ty, Allocation),
+    ZSTValue(Ty),
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct TyConstId(usize);
+
+/// Represents a constant in MIR
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct MirConst {
     /// The constant kind.
     pub(crate) kind: ConstantKind,
     /// The constant type.
     pub(crate) ty: Ty,
     /// Used for internal tracking of the internal constant.
-    pub id: ConstId,
+    pub id: MirConstId,
 }
 
-impl Const {
+impl MirConst {
     /// Build a constant. Note that this should only be used by the compiler.
-    pub fn new(kind: ConstantKind, ty: Ty, id: ConstId) -> Const {
-        Const { kind, ty, id }
+    pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst {
+        MirConst { kind, ty, id }
     }
 
     /// Retrieve the constant kind.
@@ -131,11 +173,6 @@ impl Const {
         self.ty
     }
 
-    /// Creates an interned usize constant.
-    fn try_from_target_usize(val: u64) -> Result<Self, Error> {
-        with(|cx| cx.try_new_const_uint(val.into(), UintTy::Usize))
-    }
-
     /// Try to evaluate to a target `usize`.
     pub fn eval_target_usize(&self) -> Result<u64, Error> {
         with(|cx| cx.eval_target_usize(self))
@@ -143,7 +180,7 @@ impl Const {
 
     /// Create a constant that represents a new zero-sized constant of type T.
     /// Fails if the type is not a ZST or if it doesn't have a known size.
-    pub fn try_new_zero_sized(ty: Ty) -> Result<Const, Error> {
+    pub fn try_new_zero_sized(ty: Ty) -> Result<MirConst, Error> {
         with(|cx| cx.try_new_const_zst(ty))
     }
 
@@ -152,23 +189,23 @@ impl Const {
     /// Note that there is no guarantee today about duplication of the same constant.
     /// I.e.: Calling this function multiple times with the same argument may or may not return
     /// the same allocation.
-    pub fn from_str(value: &str) -> Const {
+    pub fn from_str(value: &str) -> MirConst {
         with(|cx| cx.new_const_str(value))
     }
 
     /// Build a new constant that represents the given boolean value.
-    pub fn from_bool(value: bool) -> Const {
+    pub fn from_bool(value: bool) -> MirConst {
         with(|cx| cx.new_const_bool(value))
     }
 
     /// Build a new constant that represents the given unsigned integer.
-    pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<Const, Error> {
+    pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
         with(|cx| cx.try_new_const_uint(value, uint_ty))
     }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct ConstId(usize);
+pub struct MirConstId(usize);
 
 type Ident = Opaque;
 
@@ -484,7 +521,7 @@ pub enum RigidTy {
     Adt(AdtDef, GenericArgs),
     Foreign(ForeignDef),
     Str,
-    Array(Ty, Const),
+    Array(Ty, TyConst),
     Pat(Ty, Pattern),
     Slice(Ty),
     RawPtr(Ty, Mutability),
@@ -866,7 +903,7 @@ impl std::ops::Index<ParamTy> for GenericArgs {
 }
 
 impl std::ops::Index<ParamConst> for GenericArgs {
-    type Output = Const;
+    type Output = TyConst;
 
     fn index(&self, index: ParamConst) -> &Self::Output {
         self.0[index.index as usize].expect_const()
@@ -877,7 +914,7 @@ impl std::ops::Index<ParamConst> for GenericArgs {
 pub enum GenericArgKind {
     Lifetime(Region),
     Type(Ty),
-    Const(Const),
+    Const(TyConst),
 }
 
 impl GenericArgKind {
@@ -894,7 +931,7 @@ impl GenericArgKind {
     /// Panic if this generic argument is not a const, otherwise
     /// return the const.
     #[track_caller]
-    pub fn expect_const(&self) -> &Const {
+    pub fn expect_const(&self) -> &TyConst {
         match self {
             GenericArgKind::Const(c) => c,
             _ => panic!("{self:?}"),
@@ -913,7 +950,7 @@ impl GenericArgKind {
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub enum TermKind {
     Type(Ty),
-    Const(Const),
+    Const(TyConst),
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -1202,6 +1239,7 @@ impl Allocation {
 
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub enum ConstantKind {
+    Ty(TyConst),
     Allocated(Allocation),
     Unevaluated(UnevaluatedConst),
     Param(ParamConst),
@@ -1335,7 +1373,7 @@ pub enum PredicateKind {
     ObjectSafe(TraitDef),
     SubType(SubtypePredicate),
     Coerce(CoercePredicate),
-    ConstEquate(Const, Const),
+    ConstEquate(TyConst, TyConst),
     Ambiguous,
     AliasRelate(TermKind, TermKind, AliasRelationDirection),
 }
@@ -1346,9 +1384,9 @@ pub enum ClauseKind {
     RegionOutlives(RegionOutlivesPredicate),
     TypeOutlives(TypeOutlivesPredicate),
     Projection(ProjectionPredicate),
-    ConstArgHasType(Const, Ty),
+    ConstArgHasType(TyConst, Ty),
     WellFormed(GenericArgKind),
-    ConstEvaluatable(Const),
+    ConstEvaluatable(TyConst),
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -1426,7 +1464,8 @@ macro_rules! index_impl {
     };
 }
 
-index_impl!(ConstId);
+index_impl!(TyConstId);
+index_impl!(MirConstId);
 index_impl!(Ty);
 index_impl!(Span);
 
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index 2d7159f87fe..fc1da8fafe4 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -1,10 +1,10 @@
 use std::ops::ControlFlow;
 
-use crate::Opaque;
+use crate::{ty::TyConst, Opaque};
 
 use super::ty::{
-    Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs,
-    Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst,
+    Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs,
+    MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst,
 };
 
 pub trait Visitor: Sized {
@@ -12,7 +12,7 @@ pub trait Visitor: Sized {
     fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break> {
         ty.super_visit(self)
     }
-    fn visit_const(&mut self, c: &Const) -> ControlFlow<Self::Break> {
+    fn visit_const(&mut self, c: &TyConst) -> ControlFlow<Self::Break> {
         c.super_visit(self)
     }
     fn visit_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break> {
@@ -42,12 +42,32 @@ impl Visitable for Ty {
     }
 }
 
-impl Visitable for Const {
+impl Visitable for TyConst {
     fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
         visitor.visit_const(self)
     }
     fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
+        match &self.kind {
+            crate::ty::TyConstKind::Param(_) => {}
+            crate::ty::TyConstKind::Bound(_, _) => {}
+            crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?,
+            crate::ty::TyConstKind::Value(ty, alloc) => {
+                alloc.visit(visitor)?;
+                ty.visit(visitor)?;
+            }
+            crate::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?,
+        }
+        ControlFlow::Continue(())
+    }
+}
+
+impl Visitable for MirConst {
+    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
+        self.super_visit(visitor)
+    }
+    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
         match &self.kind() {
+            super::ty::ConstantKind::Ty(ct) => ct.visit(visitor)?,
             super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?,
             super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?,
             super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {}
diff --git a/config.example.toml b/config.example.toml
index 61655dad638..fb45493ec4a 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -389,8 +389,8 @@
 # a Nix toolchain on non-NixOS distributions.
 #patch-binaries-for-nix = false
 
-# Collect information and statistics about the current build and writes it to
-# disk. Enabling this or not has no impact on the resulting build output. The
+# Collect information and statistics about the current build, and write it to
+# disk. Enabling this has no impact on the resulting build output. The
 # schema of the file generated by the build metrics feature is unstable, and
 # this is not intended to be used during local development.
 #metrics = false
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 0b04fb4a274..a391141827e 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -1216,7 +1216,6 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(binary_heap_as_slice)]
     /// use std::collections::BinaryHeap;
     /// use std::io::{self, Write};
     ///
@@ -1225,7 +1224,7 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
     /// io::sink().write(heap.as_slice()).unwrap();
     /// ```
     #[must_use]
-    #[unstable(feature = "binary_heap_as_slice", issue = "83659")]
+    #[stable(feature = "binary_heap_as_slice", since = "CURRENT_RUSTC_VERSION")]
     pub fn as_slice(&self) -> &[T] {
         self.data.as_slice()
     }
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 1c90c171a15..01510a61405 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -1705,7 +1705,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
         unsafe {
             self.current = unlinked_node.as_ref().next;
             self.list.unlink_node(unlinked_node);
-            let unlinked_node = Box::from_raw(unlinked_node.as_ptr());
+            let unlinked_node = Box::from_raw_in(unlinked_node.as_ptr(), &self.list.alloc);
             Some(unlinked_node.element)
         }
     }
@@ -1946,7 +1946,7 @@ where
                 if (self.pred)(&mut node.as_mut().element) {
                     // `unlink_node` is okay with aliasing `element` references.
                     self.list.unlink_node(node);
-                    return Some(Box::from_raw(node.as_ptr()).element);
+                    return Some(Box::from_raw_in(node.as_ptr(), &self.list.alloc).element);
                 }
             }
         }
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index 8dcd59d12d9..d3744c5a9d0 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -1164,3 +1164,42 @@ fn test_drop_panic() {
 
     assert_eq!(unsafe { DROPS }, 8);
 }
+
+#[test]
+fn test_allocator() {
+    use core::alloc::AllocError;
+    use core::alloc::Allocator;
+    use core::alloc::Layout;
+    use core::cell::Cell;
+
+    struct A {
+        has_allocated: Cell<bool>,
+        has_deallocated: Cell<bool>,
+    }
+
+    unsafe impl Allocator for A {
+        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            assert!(!self.has_allocated.get());
+            self.has_allocated.set(true);
+
+            Global.allocate(layout)
+        }
+
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            assert!(!self.has_deallocated.get());
+            self.has_deallocated.set(true);
+
+            unsafe { Global.deallocate(ptr, layout) }
+        }
+    }
+
+    let alloc = &A { has_allocated: Cell::new(false), has_deallocated: Cell::new(false) };
+    {
+        let mut list = LinkedList::new_in(alloc);
+        list.push_back(5u32);
+        list.remove(0);
+    }
+
+    assert!(alloc.has_allocated.get());
+    assert!(alloc.has_deallocated.get());
+}
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 4ac0c9b15be..4749b8880fb 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -121,7 +121,6 @@
 #![feature(deref_pure_trait)]
 #![feature(dispatch_from_dyn)]
 #![feature(error_generic_member_access)]
-#![feature(error_in_core)]
 #![feature(exact_size_is_empty)]
 #![feature(extend_one)]
 #![feature(fmt_internals)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 875c24c28e4..f3a4803e0d4 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -257,8 +257,6 @@ use core::intrinsics::abort;
 #[cfg(not(no_global_oom_handling))]
 use core::iter;
 use core::marker::{PhantomData, Unsize};
-#[cfg(not(no_global_oom_handling))]
-use core::mem::size_of_val;
 use core::mem::{self, align_of_val_raw, forget, ManuallyDrop};
 use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 7dcaa59dcd1..5a4f9df614e 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -18,8 +18,6 @@ use core::intrinsics::abort;
 #[cfg(not(no_global_oom_handling))]
 use core::iter;
 use core::marker::{PhantomData, Unsize};
-#[cfg(not(no_global_oom_handling))]
-use core::mem::size_of_val;
 use core::mem::{self, align_of_val_raw};
 use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 8451be63c2b..89538f272f0 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -24,7 +24,6 @@
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(binary_heap_drain_sorted)]
 #![feature(slice_ptr_get)]
-#![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs
index c11f4556da9..8b516ddbc5c 100644
--- a/library/alloc/tests/vec_deque_alloc_error.rs
+++ b/library/alloc/tests/vec_deque_alloc_error.rs
@@ -8,6 +8,7 @@ use std::{
 };
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_shrink_to_unwind() {
     // This tests that `shrink_to` leaves the deque in a consistent state when
     // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
diff --git a/library/backtrace b/library/backtrace
-Subproject 5e05efa87905fb5b351a2bc5644d60c57d6d932
+Subproject 72265bea210891ae47bbe6d4f17b493ef060661
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index ac026de95da..efa0fd7b56c 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -82,6 +82,20 @@
 //!
 //! The corresponding [`Sync`] version of `OnceCell<T>` is [`OnceLock<T>`].
 //!
+//! ## `LazyCell<T, F>`
+//!
+//! A common pattern with OnceCell is, for a given OnceCell, to use the same function on every
+//! call to [`OnceCell::get_or_init`] with that cell. This is what is offered by [`LazyCell`],
+//! which pairs cells of `T` with functions of `F`, and always calls `F` before it yields `&T`.
+//! This happens implicitly by simply attempting to dereference the LazyCell to get its contents,
+//! so its use is much more transparent with a place which has been initialized by a constant.
+//!
+//! More complicated patterns that don't fit this description can be built on `OnceCell<T>` instead.
+//!
+//! `LazyCell` works by providing an implementation of `impl Deref` that calls the function,
+//! so you can just use it by dereference (e.g. `*lazy_cell` or `lazy_cell.deref()`).
+//!
+//! The corresponding [`Sync`] version of `LazyCell<T, F>` is [`LazyLock<T, F>`].
 //!
 //! # When to choose interior mutability
 //!
@@ -230,6 +244,7 @@
 //! [`RwLock<T>`]: ../../std/sync/struct.RwLock.html
 //! [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
 //! [`OnceLock<T>`]: ../../std/sync/struct.OnceLock.html
+//! [`LazyLock<T, F>`]: ../../std/sync/struct.LazyLock.html
 //! [`Sync`]: ../../std/marker/trait.Sync.html
 //! [`atomic`]: crate::sync::atomic
 
@@ -238,7 +253,7 @@
 use crate::cmp::Ordering;
 use crate::fmt::{self, Debug, Display};
 use crate::marker::{PhantomData, Unsize};
-use crate::mem::{self, size_of};
+use crate::mem;
 use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
 use crate::ptr::{self, NonNull};
 
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index a7c3dfc982d..872b4da4dbf 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -2,12 +2,12 @@ use crate::cell::UnsafeCell;
 use crate::fmt;
 use crate::mem;
 
-/// A cell which can be written to only once.
+/// A cell which can nominally be written to only once.
 ///
 /// This allows obtaining a shared `&T` reference to its inner value without copying or replacing
 /// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However,
 /// only immutable references can be obtained unless one has a mutable reference to the cell
-/// itself.
+/// itself. In the same vein, the cell can only be re-initialized with such a mutable reference.
 ///
 /// For a thread-safe version of this struct, see [`std::sync::OnceLock`].
 ///
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index a3f2b767054..da18fdc6e1d 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1,5 +1,5 @@
 #![doc = include_str!("error.md")]
-#![unstable(feature = "error_in_core", issue = "103765")]
+#![stable(feature = "error_in_core", since = "CURRENT_RUSTC_VERSION")]
 
 #[cfg(test)]
 mod tests;
@@ -130,7 +130,6 @@ pub trait Error: Debug + Display {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     /// use core::fmt;
     /// use core::error::{request_ref, Request};
     ///
@@ -361,8 +360,7 @@ impl dyn Error {
 /// Get a string value from an error.
 ///
 /// ```rust
-/// # #![feature(error_generic_member_access)]
-/// # #![feature(error_in_core)]
+/// #![feature(error_generic_member_access)]
 /// use std::error::Error;
 /// use core::error::request_value;
 ///
@@ -385,8 +383,7 @@ where
 /// Get a string reference from an error.
 ///
 /// ```rust
-/// # #![feature(error_generic_member_access)]
-/// # #![feature(error_in_core)]
+/// #![feature(error_generic_member_access)]
 /// use core::error::Error;
 /// use core::error::request_ref;
 ///
@@ -458,7 +455,6 @@ where
 ///
 /// ```
 /// #![feature(error_generic_member_access)]
-/// #![feature(error_in_core)]
 /// use core::fmt;
 /// use core::error::Request;
 /// use core::error::request_ref;
@@ -529,7 +525,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     ///
@@ -564,7 +559,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     ///
@@ -600,7 +594,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     ///
@@ -633,7 +626,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     ///
@@ -700,7 +692,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     /// use core::error::request_value;
@@ -788,7 +779,6 @@ impl<'a> Request<'a> {
     ///
     /// ```rust
     /// #![feature(error_generic_member_access)]
-    /// #![feature(error_in_core)]
     ///
     /// use core::error::Request;
     /// use core::error::request_ref;
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index ab2158394bf..3a5a5af8bf5 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -212,6 +212,7 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
 
 macro_rules! impl_Display {
     ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
+        #[cfg(not(feature = "optimize_for_size"))]
         fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             // 2^128 is about 3*10^38, so 39 gives an extra byte of space
             let mut buf = [MaybeUninit::<u8>::uninit(); 39];
@@ -277,6 +278,38 @@ macro_rules! impl_Display {
             f.pad_integral(is_nonnegative, "", buf_slice)
         }
 
+        #[cfg(feature = "optimize_for_size")]
+        fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            // 2^128 is about 3*10^38, so 39 gives an extra byte of space
+            let mut buf = [MaybeUninit::<u8>::uninit(); 39];
+            let mut curr = buf.len();
+            let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
+
+            // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning
+            // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
+            // each step this is kept the same as `n` is divided. Since `n` is always
+            // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
+            // is safe to access.
+            unsafe {
+                loop {
+                    curr -= 1;
+                    buf_ptr.add(curr).write((n % 10) as u8 + b'0');
+                    n /= 10;
+
+                    if n == 0 {
+                        break;
+                    }
+                }
+            }
+
+            // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid UTF-8
+            let buf_slice = unsafe {
+                str::from_utf8_unchecked(
+                    slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
+            };
+            f.pad_integral(is_nonnegative, "", buf_slice)
+        }
+
         $(#[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Display for $t {
             #[allow(unused_comparisons)]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 89e0b670995..28397fe4619 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -65,7 +65,6 @@
 
 use crate::marker::DiscriminantKind;
 use crate::marker::Tuple;
-use crate::mem::align_of;
 use crate::ptr;
 use crate::ub_checks;
 
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index fa5bb28adff..ec8488009b9 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -20,7 +20,7 @@
 //!
 //! #[custom_mir(dialect = "built")]
 //! pub fn simple(x: i32) -> i32 {
-//!     mir!(
+//!     mir! {
 //!         let temp2: i32;
 //!
 //!         {
@@ -33,7 +33,7 @@
 //!             RET = temp2;
 //!             Return()
 //!         }
-//!     )
+//!     }
 //! }
 //! ```
 //!
@@ -71,7 +71,7 @@
 //!
 //! #[custom_mir(dialect = "built")]
 //! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
-//!     mir!(
+//!     mir! {
 //!         {
 //!             match c {
 //!                 true => t,
@@ -93,20 +93,22 @@
 //!             RET = *temp;
 //!             Return()
 //!         }
-//!     )
+//!     }
 //! }
 //!
 //! #[custom_mir(dialect = "built")]
 //! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
-//!     mir!({
-//!         RET = Move(Field(Variant(opt, 1), 0));
-//!         Return()
-//!     })
+//!     mir! {
+//!         {
+//!             RET = Move(Field(Variant(opt, 1), 0));
+//!             Return()
+//!         }
+//!     }
 //! }
 //!
 //! #[custom_mir(dialect = "runtime", phase = "optimized")]
 //! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
-//!     mir!(
+//!     mir! {
 //!         let _unused;
 //!         let popped;
 //!
@@ -125,19 +127,19 @@
 //!         ret = {
 //!             Return()
 //!         }
-//!     )
+//!     }
 //! }
 //!
 //! #[custom_mir(dialect = "runtime", phase = "optimized")]
 //! fn annotated_return_type() -> (i32, bool) {
-//!     mir!(
+//!     mir! {
 //!         type RET = (i32, bool);
 //!         {
 //!             RET.0 = 1;
 //!             RET.1 = true;
 //!             Return()
 //!         }
-//!     )
+//!     }
 //! }
 //! ```
 //!
@@ -152,7 +154,7 @@
 //!
 //! #[custom_mir(dialect = "built")]
 //! fn borrow_error(should_init: bool) -> i32 {
-//!     mir!(
+//!     mir! {
 //!         let temp: i32;
 //!
 //!         {
@@ -171,7 +173,7 @@
 //!             RET = temp;
 //!             Return()
 //!         }
-//!     )
+//!     }
 //! }
 //! ```
 //!
@@ -179,7 +181,7 @@
 //! error[E0381]: used binding is possibly-uninitialized
 //!   --> test.rs:24:13
 //!    |
-//! 8  | /     mir!(
+//! 8  | /     mir! {
 //! 9  | |         let temp: i32;
 //! 10 | |
 //! 11 | |         {
@@ -191,7 +193,7 @@
 //!    | |             ^^^^^^^^^^ value used here but it is possibly-uninitialized
 //! 25 | |             Return()
 //! 26 | |         }
-//! 27 | |     )
+//! 27 | |     }
 //!    | |_____- binding declared here but left uninitialized
 //!
 //! error: aborting due to 1 previous error
@@ -407,18 +409,22 @@ define!(
     ///
     /// #[custom_mir(dialect = "built")]
     /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
-    ///     mir!({
-    ///         RET = *Field::<&i32>(Variant(opt, 1), 0);
-    ///         Return()
-    ///     })
+    ///     mir! {
+    ///         {
+    ///             RET = *Field::<&i32>(Variant(opt, 1), 0);
+    ///             Return()
+    ///         }
+    ///     }
     /// }
     ///
     /// #[custom_mir(dialect = "built")]
     /// fn set(opt: &mut Option<i32>) {
-    ///     mir!({
-    ///         place!(Field(Variant(*opt, 1), 0)) = 5;
-    ///         Return()
-    ///     })
+    ///     mir! {
+    ///         {
+    ///             place!(Field(Variant(*opt, 1), 0)) = 5;
+    ///             Return()
+    ///         }
+    ///     }
     /// }
     /// ```
     fn Field<F>(place: (), field: u32) -> F
@@ -455,7 +461,7 @@ define!(
 /// your MIR into something that is easier to parse in the compiler.
 #[rustc_macro_transparency = "transparent"]
 pub macro mir {
-    (
+    {
         $(type RET = $ret_ty:ty ;)?
         $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
         $(debug $dbg_name:ident => $dbg_data:expr ;)*
@@ -469,7 +475,7 @@ pub macro mir {
                 $($block:tt)*
             }
         )*
-    ) => {{
+    } => {{
         // First, we declare all basic blocks.
         __internal_declare_basic_blocks!($(
             $block_name $(($block_cleanup))?
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index bcaac2f42cf..dad3d79acb1 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -4,8 +4,8 @@ use crate::ops::Try;
 
 /// An iterator that links two iterators together, in a chain.
 ///
-/// This `struct` is created by [`Iterator::chain`]. See its documentation
-/// for more.
+/// This `struct` is created by [`chain`] or [`Iterator::chain`]. See their
+/// documentation for more.
 ///
 /// # Examples
 ///
@@ -38,6 +38,39 @@ impl<A, B> Chain<A, B> {
     }
 }
 
+/// Converts the arguments to iterators and links them together, in a chain.
+///
+/// See the documentation of [`Iterator::chain`] for more.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(iter_chain)]
+///
+/// use std::iter::chain;
+///
+/// let a = [1, 2, 3];
+/// let b = [4, 5, 6];
+///
+/// let mut iter = chain(a, b);
+///
+/// assert_eq!(iter.next(), Some(1));
+/// assert_eq!(iter.next(), Some(2));
+/// assert_eq!(iter.next(), Some(3));
+/// assert_eq!(iter.next(), Some(4));
+/// assert_eq!(iter.next(), Some(5));
+/// assert_eq!(iter.next(), Some(6));
+/// assert_eq!(iter.next(), None);
+/// ```
+#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
+pub fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
+where
+    A: IntoIterator,
+    B: IntoIterator<Item = A::Item>,
+{
+    Chain::new(a.into_iter(), b.into_iter())
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B> Iterator for Chain<A, B>
 where
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index cc514bd914f..05a5f268905 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -41,6 +41,9 @@ pub use self::array_chunks::ArrayChunks;
 #[unstable(feature = "std_internals", issue = "none")]
 pub use self::by_ref_sized::ByRefSized;
 
+#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
+pub use self::chain::chain;
+
 #[stable(feature = "iter_cloned", since = "1.1.0")]
 pub use self::cloned::Cloned;
 
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 44fef3e145b..921c75c85f1 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -428,6 +428,8 @@ pub use self::traits::{
     DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
 };
 
+#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
+pub use self::adapters::chain;
 #[stable(feature = "iter_zip", since = "1.59.0")]
 pub use self::adapters::zip;
 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 2ddedfa37fe..0d4ca4d5f01 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1569,7 +1569,12 @@ pub(crate) mod builtin {
     #[rustc_builtin_macro]
     #[macro_export]
     #[rustc_diagnostic_item = "assert_macro"]
-    #[allow_internal_unstable(panic_internals, edition_panic, generic_assert_internals)]
+    #[allow_internal_unstable(
+        core_intrinsics,
+        panic_internals,
+        edition_panic,
+        generic_assert_internals
+    )]
     macro_rules! assert {
         ($cond:expr $(,)?) => {{ /* compiler built-in */ }};
         ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 026e21586d4..4175d4a3329 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -120,12 +120,8 @@ use crate::slice;
 /// use std::mem::{self, MaybeUninit};
 ///
 /// let data = {
-///     // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
-///     // safe because the type we are claiming to have initialized here is a
-///     // bunch of `MaybeUninit`s, which do not require initialization.
-///     let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
-///         MaybeUninit::uninit().assume_init()
-///     };
+///     // Create an uninitialized array of `MaybeUninit`.
+///     let mut data: [MaybeUninit<Vec<u32>>; 1000] = [const { MaybeUninit::uninit() }; 1000];
 ///
 ///     // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
 ///     // we have a memory leak, but there is no memory safety issue.
@@ -147,10 +143,8 @@ use crate::slice;
 /// ```
 /// use std::mem::MaybeUninit;
 ///
-/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
-/// // safe because the type we are claiming to have initialized here is a
-/// // bunch of `MaybeUninit`s, which do not require initialization.
-/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
+/// // Create an uninitialized array of `MaybeUninit`.
+/// let mut data: [MaybeUninit<String>; 1000] = [const { MaybeUninit::uninit() }; 1000];
 /// // Count the number of elements we have assigned.
 /// let mut data_len: usize = 0;
 ///
@@ -348,8 +342,7 @@ impl<T> MaybeUninit<T> {
     #[must_use]
     #[inline(always)]
     pub const fn uninit_array<const N: usize>() -> [Self; N] {
-        // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
-        unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
+        [const { MaybeUninit::uninit() }; N]
     }
 
     /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 9362dc87654..129f62fb43d 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -68,6 +68,13 @@ pub mod consts {
     pub const FRAC_1_SQRT_PI: f128 =
         0.564189583547756286948079451560772585844050629328998856844086_f128;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f128 =
+        0.398942280401432677939946059934381868475858631164934657665926_f128;
+
     /// 2/π
     #[unstable(feature = "f128", issue = "116909")]
     pub const FRAC_2_PI: f128 = 0.636619772367581343075535053490057448137838582961825794990669_f128;
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index c4d4584544b..7a488cd6bf6 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -67,6 +67,12 @@ pub mod consts {
     // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f16 = 0.398942280401432677939946059934381868_f16;
+
     /// 2/π
     #[unstable(feature = "f16", issue = "116909")]
     pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16;
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 22b24937cbc..9d34d3da9e9 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -327,6 +327,11 @@ pub mod consts {
     #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f32 = 0.398942280401432677939946059934381868_f32;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 34357d1b05a..95f021b2541 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -327,6 +327,11 @@ pub mod consts {
     #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f64 = 0.398942280401432677939946059934381868_f64;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index fcdd983343d..863f0d61df3 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -517,9 +517,13 @@ macro_rules! nonzero_integer {
             /// ```
             /// # use std::num::NonZero;
             /// #
-            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(", $leading_zeros_test, ").unwrap();")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(", $leading_zeros_test, ")?;")]
             ///
             /// assert_eq!(n.leading_zeros(), 0);
+            /// # Some(())
+            /// # }
             /// ```
             #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
             #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
@@ -545,9 +549,13 @@ macro_rules! nonzero_integer {
             /// ```
             /// # use std::num::NonZero;
             /// #
-            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(0b0101000).unwrap();")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::new(0b0101000)?;")]
             ///
             /// assert_eq!(n.trailing_zeros(), 3);
+            /// # Some(())
+            /// # }
             /// ```
             #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
             #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
@@ -1101,9 +1109,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// ```
         /// # 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);")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("assert_eq!(NonZero::new(7", stringify!($Int), ")?.ilog2(), 2);")]
+        #[doc = concat!("assert_eq!(NonZero::new(8", stringify!($Int), ")?.ilog2(), 3);")]
+        #[doc = concat!("assert_eq!(NonZero::new(9", stringify!($Int), ")?.ilog2(), 3);")]
+        /// # Some(())
+        /// # }
         /// ```
         #[stable(feature = "int_log", since = "1.67.0")]
         #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
@@ -1126,9 +1138,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// ```
         /// # 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);")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("assert_eq!(NonZero::new(99", stringify!($Int), ")?.ilog10(), 1);")]
+        #[doc = concat!("assert_eq!(NonZero::new(100", stringify!($Int), ")?.ilog10(), 2);")]
+        #[doc = concat!("assert_eq!(NonZero::new(101", stringify!($Int), ")?.ilog10(), 2);")]
+        /// # Some(())
+        /// # }
         /// ```
         #[stable(feature = "int_log", since = "1.67.0")]
         #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
@@ -1187,10 +1203,16 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         /// Basic usage:
         ///
         /// ```
-        #[doc = concat!("let eight = std::num::NonZero::new(8", stringify!($Int), ").unwrap();")]
+        /// # use std::num::NonZero;
+        /// #
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let eight = NonZero::new(8", stringify!($Int), ")?;")]
         /// assert!(eight.is_power_of_two());
-        #[doc = concat!("let ten = std::num::NonZero::new(10", stringify!($Int), ").unwrap();")]
+        #[doc = concat!("let ten = NonZero::new(10", stringify!($Int), ")?;")]
         /// assert!(!ten.is_power_of_two());
+        /// # Some(())
+        /// # }
         /// ```
         #[must_use]
         #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 9a527073602..e253cfd2822 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1708,8 +1708,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_take_if)]
-    ///
     /// let mut x = Some(42);
     ///
     /// let prev = x.take_if(|v| if *v == 42 {
@@ -1726,7 +1724,7 @@ impl<T> Option<T> {
     /// assert_eq!(prev, Some(43));
     /// ```
     #[inline]
-    #[unstable(feature = "option_take_if", issue = "98934")]
+    #[stable(feature = "option_take_if", since = "CURRENT_RUSTC_VERSION")]
     pub fn take_if<P>(&mut self, predicate: P) -> Option<T>
     where
         P: FnOnce(&mut T) -> bool,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index d8fc3b7177f..0d2aa3070a1 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -184,7 +184,7 @@
 //! requires at least a level of pointer indirection each time a new object is added to the mix
 //! (and, practically, a heap allocation).
 //!
-//! Although there were other reason as well, this issue of expensive composition is the key thing
+//! Although there were other reasons as well, this issue of expensive composition is the key thing
 //! that drove Rust towards adopting a different model. It is particularly a problem
 //! when one considers, for example, the implications of composing together the [`Future`]s which
 //! will eventually make up an asynchronous task (including address-sensitive `async fn` state
diff --git a/library/core/src/prelude/common.rs b/library/core/src/prelude/common.rs
index afc6817aa1d..2a0331ef7b2 100644
--- a/library/core/src/prelude/common.rs
+++ b/library/core/src/prelude/common.rs
@@ -14,6 +14,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use crate::mem::drop;
+#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")]
+#[doc(no_inline)]
+pub use crate::mem::{align_of, align_of_val, size_of, size_of_val};
 
 // Re-exported types and traits
 #[stable(feature = "core_prelude", since = "1.4.0")]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 8e3447d0b1b..6661f6ee78b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -415,7 +415,7 @@ use crate::intrinsics;
 use crate::marker::FnPtr;
 use crate::ub_checks;
 
-use crate::mem::{self, align_of, size_of, MaybeUninit};
+use crate::mem::{self, MaybeUninit};
 
 mod alignment;
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 29a12f106c5..3f4305866e6 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -1,7 +1,6 @@
 //! Free functions to create `&[T]` and `&mut [T]`.
 
 use crate::array;
-use crate::mem::{align_of, size_of};
 use crate::ops::Range;
 use crate::ptr;
 use crate::ub_checks;
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 232ec589093..482bd19705c 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1296,7 +1296,6 @@ impl<T> AtomicPtr<T> {
     #[cfg(target_has_atomic_equal_alignment = "ptr")]
     #[unstable(feature = "atomic_from_mut", issue = "76314")]
     pub fn from_mut(v: &mut *mut T) -> &mut Self {
-        use crate::mem::align_of;
         let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()];
         // SAFETY:
         //  - the mutable reference guarantees unique ownership.
@@ -2286,7 +2285,6 @@ macro_rules! atomic_int {
             #[$cfg_align]
             #[unstable(feature = "atomic_from_mut", issue = "76314")]
             pub fn from_mut(v: &mut $int_type) -> &mut Self {
-                use crate::mem::align_of;
                 let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
                 // SAFETY:
                 //  - the mutable reference guarantees unique ownership.
@@ -2354,7 +2352,6 @@ macro_rules! atomic_int {
             #[$cfg_align]
             #[unstable(feature = "atomic_from_mut", issue = "76314")]
             pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] {
-                use crate::mem::align_of;
                 let [] = [(); align_of::<Self>() - align_of::<$int_type>()];
                 // SAFETY:
                 //  - the mutable reference guarantees unique ownership.
diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs
index b2429588de1..c93510df524 100644
--- a/library/core/tests/iter/adapters/chain.rs
+++ b/library/core/tests/iter/adapters/chain.rs
@@ -3,6 +3,14 @@ use core::iter::*;
 use core::num::NonZero;
 
 #[test]
+fn test_chain() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let ys = [30, 40, 50, 60];
+    let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+    assert_eq!(Vec::from_iter(chain(xs, ys)), expected);
+}
+
+#[test]
 fn test_iterator_chain() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index e0f82c91663..f632883b563 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -75,6 +75,7 @@
 #![feature(ip)]
 #![feature(iter_advance_by)]
 #![feature(iter_array_chunks)]
+#![feature(iter_chain)]
 #![feature(iter_collect_into)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_intersperse)]
@@ -111,7 +112,6 @@
 #![feature(const_slice_from_ref)]
 #![feature(waker_getters)]
 #![feature(error_generic_member_access)]
-#![feature(error_in_core)]
 #![feature(trait_upcasting)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
index 0f1719206c9..cbffbc564cf 100644
--- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
@@ -96,7 +96,7 @@ where
     fn cast<U>(self) -> Self::CastPtr<U> {
         // SimdElement currently requires zero-sized metadata, so this should never fail.
         // If this ever changes, `simd_cast_ptr` should produce a post-mono error.
-        use core::{mem::size_of, ptr::Pointee};
+        use core::ptr::Pointee;
         assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
         assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);
 
diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
index 7ba996d149c..6bc6ca3ac42 100644
--- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
@@ -93,7 +93,7 @@ where
     fn cast<U>(self) -> Self::CastPtr<U> {
         // SimdElement currently requires zero-sized metadata, so this should never fail.
         // If this ever changes, `simd_cast_ptr` should produce a post-mono error.
-        use core::{mem::size_of, ptr::Pointee};
+        use core::ptr::Pointee;
         assert_eq!(size_of::<<T as Pointee>::Metadata>(), 0);
         assert_eq!(size_of::<<U as Pointee>::Metadata>(), 0);
 
diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs
index f9f74c63fc4..9fb79eabd05 100644
--- a/library/proc_macro/src/bridge/fxhash.rs
+++ b/library/proc_macro/src/bridge/fxhash.rs
@@ -7,7 +7,6 @@
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use std::hash::Hasher;
-use std::mem::size_of;
 use std::ops::BitXor;
 
 /// Type alias for a hashmap using the `fx` hash algorithm.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 79a504c5a5e..68bba5c2be1 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -34,10 +34,10 @@ addr2line = { version = "0.22.0", optional = true, default-features = false }
 libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
-object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
+object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
 
 [target.'cfg(target_os = "aix")'.dependencies]
-object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] }
+object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] }
 
 [dev-dependencies]
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 5039f0b6bb2..fcd1c307b5a 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1218,7 +1218,7 @@ where
     /// will cause the map to produce seemingly random results. Higher-level and
     /// more foolproof APIs like `entry` should be preferred when possible.
     ///
-    /// In particular, the hash used to initialized the raw entry must still be
+    /// In particular, the hash used to initialize the raw entry must still be
     /// consistent with the hash of the key that is ultimately stored in the entry.
     /// This is because implementations of HashMap may need to recompute hashes
     /// when resizing, at which point only the keys are available.
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 9dd3d7d3fa1..f6b9de26c1c 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -533,6 +533,25 @@ impl OsString {
         unsafe { Box::from_raw(rw) }
     }
 
+    /// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
+    /// `&'a mut OsStr`.
+    ///
+    /// The caller has free choice over the returned lifetime, including 'static.
+    /// Indeed, this function is ideally used for data that lives for the remainder of
+    /// the program’s life, as dropping the returned reference will cause a memory leak.
+    ///
+    /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
+    /// unused capacity that is not part of the returned slice. If you want to discard excess
+    /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
+    /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
+    ///
+    /// [`into_boxed_os_str`]: Self::into_boxed_os_str
+    #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
+    #[inline]
+    pub fn leak<'a>(self) -> &'a mut OsStr {
+        OsStr::from_inner_mut(self.inner.leak())
+    }
+
     /// Part of a hack to make PathBuf::push/pop more efficient.
     #[inline]
     pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index b020e05eaab..5b39b9e34d8 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -24,6 +24,15 @@ fn test_os_string_clear() {
 }
 
 #[test]
+fn test_os_string_leak() {
+    let os_string = OsString::from("have a cake");
+    let (len, cap) = (os_string.len(), os_string.capacity());
+    let leaked = os_string.leak();
+    assert_eq!(leaked.as_encoded_bytes(), b"have a cake");
+    unsafe { drop(String::from_raw_parts(leaked as *mut OsStr as _, len, cap)) }
+}
+
+#[test]
 fn test_os_string_capacity() {
     let os_string = OsString::with_capacity(0);
     assert_eq!(0, os_string.capacity());
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index 6f8d5e37775..c9d3934ad70 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -104,7 +104,6 @@
 
 use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
 use core::marker::PhantomData;
-use core::mem::{align_of, size_of};
 use core::ptr::{self, NonNull};
 
 // The 2 least-significant bits are used as tag.
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index c8968b74b12..9aee2bb5e1c 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -1190,9 +1190,8 @@ pub trait IsTerminal: crate::sealed::Sealed {
     ///
     /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable`
     ///   it will print: `Hello foo`.
-    /// - If you instead run the example interactively by running the executable directly, it will
-    ///   panic with the message "Expected input to be piped to the process".
-    ///
+    /// - If you instead run the example interactively by running `path/to/executable` directly, it will
+    ///   prompt for input.
     ///
     /// [changes]: io#platform-specific-behavior
     /// [`Stdin`]: crate::io::Stdin
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 9d6576fa841..1c226f9f08f 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -324,7 +324,6 @@
 #![feature(core_io_borrowed_buf)]
 #![feature(duration_constants)]
 #![feature(error_generic_member_access)]
-#![feature(error_in_core)]
 #![feature(error_iter)]
 #![feature(exact_size_is_empty)]
 #![feature(exclusive_wrapper)]
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs
index 0597fdcbd72..fe8e2be9372 100644
--- a/library/std/src/os/unix/net/ancillary.rs
+++ b/library/std/src/os/unix/net/ancillary.rs
@@ -3,7 +3,7 @@
 use super::{sockaddr_un, SocketAddr};
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::marker::PhantomData;
-use crate::mem::{size_of, zeroed};
+use crate::mem::zeroed;
 use crate::os::unix::io::RawFd;
 use crate::path::Path;
 use crate::ptr::{eq, read_unaligned};
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index f4e1e2a38c1..adbcdcd2e67 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1226,6 +1226,25 @@ impl PathBuf {
         self
     }
 
+    /// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents,
+    /// `&'a mut Path`.
+    ///
+    /// The caller has free choice over the returned lifetime, including 'static.
+    /// Indeed, this function is ideally used for data that lives for the remainder of
+    /// the program’s life, as dropping the returned reference will cause a memory leak.
+    ///
+    /// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include
+    /// unused capacity that is not part of the returned slice. If you want to discard excess
+    /// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead.
+    /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
+    ///
+    /// [`into_boxed_path`]: Self::into_boxed_path
+    #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
+    #[inline]
+    pub fn leak<'a>(self) -> &'a mut Path {
+        Path::from_inner_mut(self.inner.leak())
+    }
+
     /// Extends `self` with `path`.
     ///
     /// If `path` is absolute, it replaces the current path.
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index 2d8e50d1f88..92702b395df 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -127,6 +127,16 @@ fn into() {
 }
 
 #[test]
+fn test_pathbuf_leak() {
+    let string = "/have/a/cake".to_owned();
+    let (len, cap) = (string.len(), string.capacity());
+    let buf = PathBuf::from(string);
+    let leaked = buf.leak();
+    assert_eq!(leaked.as_os_str().as_encoded_bytes(), b"/have/a/cake");
+    unsafe { drop(String::from_raw_parts(leaked.as_mut_os_str() as *mut OsStr as _, len, cap)) }
+}
+
+#[test]
 #[cfg(unix)]
 pub fn test_decompositions_unix() {
     t!("",
diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs
index 01936734d75..ceee3e33c3e 100644
--- a/library/std/src/prelude/common.rs
+++ b/library/std/src/prelude/common.rs
@@ -14,6 +14,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::mem::drop;
+#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")]
+#[doc(no_inline)]
+pub use crate::mem::{align_of, align_of_val, size_of, size_of_val};
 
 // Re-exported types and traits
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 0bdbab716ad..2d4639342bf 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -36,6 +36,10 @@
 //!   operations for both destructors and overloading `()`.
 //! * <code>[std::mem]::[drop]</code>, a convenience function for explicitly
 //!   dropping a value.
+//! * <code>[std::mem]::{[size_of], [size_of_val]}</code>, to get the size of
+//!   a type or value.
+//! * <code>[std::mem]::{[align_of], [align_of_val]}</code>, to get the
+//!   alignment of a type or value.
 //! * <code>[std::boxed]::[Box]</code>, a way to allocate values on the heap.
 //! * <code>[std::borrow]::[ToOwned]</code>, the conversion trait that defines
 //!   [`to_owned`], the generic method for creating an owned type from a
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index d3bb3bfdff9..7a2eed93dd4 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -29,34 +29,26 @@ union Data<T, F> {
 /// # Examples
 ///
 /// Initialize static variables with `LazyLock`.
-///
 /// ```
-/// use std::collections::HashMap;
-///
 /// use std::sync::LazyLock;
 ///
-/// static HASHMAP: LazyLock<HashMap<i32, String>> = LazyLock::new(|| {
-///     println!("initializing");
-///     let mut m = HashMap::new();
-///     m.insert(13, "Spica".to_string());
-///     m.insert(74, "Hoyten".to_string());
-///     m
+/// // n.b. static items do not call [`Drop`] on program termination, so this won't be deallocated.
+/// // this is fine, as the OS can deallocate the terminated program faster than we can free memory
+/// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
+/// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
+/// # mod another_crate {
+/// #     pub fn great_question() -> String { "42".to_string() }
+/// # }
+///     // M3 Ultra takes about 16 million years in --release config
+///     another_crate::great_question()
 /// });
 ///
-/// fn main() {
-///     println!("ready");
-///     std::thread::spawn(|| {
-///         println!("{:?}", HASHMAP.get(&13));
-///     }).join().unwrap();
-///     println!("{:?}", HASHMAP.get(&74));
-///
-///     // Prints:
-///     //   ready
-///     //   initializing
-///     //   Some("Spica")
-///     //   Some("Hoyten")
-/// }
+/// // The `String` is built, stored in the `LazyLock`, and returned as `&String`.
+/// let _ = &*DEEP_THOUGHT;
+/// // The `String` is retrieved from the `LazyLock` and returned as `&String`.
+/// let _ = &*DEEP_THOUGHT;
 /// ```
+///
 /// Initialize fields with `LazyLock`.
 /// ```
 /// use std::sync::LazyLock;
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index fb7d601b094..70e8f5f90c6 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -136,7 +136,10 @@
 //! - [`Once`]: Used for a thread-safe, one-time global initialization routine
 //!
 //! - [`OnceLock`]: Used for thread-safe, one-time initialization of a
-//!   global variable.
+//!   variable, with potentially different initializers based on the caller.
+//!
+//! - [`LazyLock`]: Used for thread-safe, one-time initialization of a
+//!   variable, using one nullary initializer function provided at creation.
 //!
 //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
 //!   multiple readers at the same time, while allowing only one
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index fc830bacced..f52b9e52c54 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -5,50 +5,20 @@ use crate::mem::MaybeUninit;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sync::Once;
 
-/// A synchronization primitive which can be written to only once.
+/// A synchronization primitive which can nominally be written to only once.
 ///
 /// This type is a thread-safe [`OnceCell`], and can be used in statics.
+/// In many simple cases, you can use [`LazyLock<T, F>`] instead to get the benefits of this type
+/// with less effort: `LazyLock<T, F>` "looks like" `&T` because it initializes with `F` on deref!
+/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
+/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`].
 ///
 /// [`OnceCell`]: crate::cell::OnceCell
+/// [`LazyLock<T, F>`]: crate::sync::LazyLock
+/// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new
 ///
 /// # Examples
 ///
-/// Using `OnceLock` to store a function’s previously computed value (a.k.a.
-/// ‘lazy static’ or ‘memoizing’):
-///
-/// ```
-/// use std::sync::OnceLock;
-///
-/// struct DeepThought {
-///     answer: String,
-/// }
-///
-/// impl DeepThought {
-/// #   fn great_question() -> String {
-/// #       "42".to_string()
-/// #   }
-/// #
-///     fn new() -> Self {
-///         Self {
-///             // M3 Ultra takes about 16 million years in --release config
-///             answer: Self::great_question(),
-///         }
-///     }
-/// }
-///
-/// fn computation() -> &'static DeepThought {
-///     // n.b. static items do not call [`Drop`] on program termination, so if
-///     // [`DeepThought`] impls Drop, that will not be used for this instance.
-///     static COMPUTATION: OnceLock<DeepThought> = OnceLock::new();
-///     COMPUTATION.get_or_init(|| DeepThought::new())
-/// }
-///
-/// // The `DeepThought` is built, stored in the `OnceLock`, and returned.
-/// let _ = computation().answer;
-/// // The `DeepThought` is retrieved from the `OnceLock` and returned.
-/// let _ = computation().answer;
-/// ```
-///
 /// Writing to a `OnceLock` from a separate thread:
 ///
 /// ```
@@ -73,6 +43,55 @@ use crate::sync::Once;
 ///     Some(&12345),
 /// );
 /// ```
+///
+/// You can use `OnceLock` to implement a type that requires "append-only" logic:
+///
+/// ```
+/// use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}};
+/// use std::thread;
+///
+/// struct OnceList<T> {
+///     data: OnceLock<T>,
+///     next: OnceLock<Box<OnceList<T>>>,
+/// }
+/// impl<T> OnceList<T> {
+///     const fn new() -> OnceList<T> {
+///         OnceList { data: OnceLock::new(), next: OnceLock::new() }
+///     }
+///     fn push(&self, value: T) {
+///         // FIXME: this impl is concise, but is also slow for long lists or many threads.
+///         // as an exercise, consider how you might improve on it while preserving the behavior
+///         if let Err(value) = self.data.set(value) {
+///             let next = self.next.get_or_init(|| Box::new(OnceList::new()));
+///             next.push(value)
+///         };
+///     }
+///     fn contains(&self, example: &T) -> bool
+///     where
+///         T: PartialEq,
+///     {
+///         self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| {
+///             self.next.get().map(|next| next.contains(example)).unwrap_or(false)
+///         })
+///     }
+/// }
+///
+/// // Let's exercise this new Sync append-only list by doing a little counting
+/// static LIST: OnceList<u32> = OnceList::new();
+/// static COUNTER: AtomicU32 = AtomicU32::new(0);
+///
+/// let vec = (0..thread::available_parallelism().unwrap().get()).map(|_| thread::spawn(|| {
+///     while let i @ 0..=1000 = COUNTER.fetch_add(1, Ordering::Relaxed) {
+///         LIST.push(i);
+///     }
+/// })).collect::<Vec<thread::JoinHandle<_>>>();
+/// vec.into_iter().for_each(|handle| handle.join().unwrap());
+///
+/// for i in 0..=1000 {
+///     assert!(LIST.contains(&i));
+/// }
+///
+/// ```
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub struct OnceLock<T> {
     once: Once,
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 18b969bca85..f7c6b0877aa 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -177,6 +177,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn leak<'a>(self) -> &'a mut Slice {
+        unsafe { mem::transmute(self.inner.leak()) }
+    }
+
+    #[inline]
     pub fn into_box(self) -> Box<Slice> {
         unsafe { mem::transmute(self.inner.into_boxed_slice()) }
     }
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index b3ceb55802d..dfff4dd4fb0 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -139,6 +139,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn leak<'a>(self) -> &'a mut Slice {
+        unsafe { mem::transmute(self.inner.leak()) }
+    }
+
+    #[inline]
     pub fn into_box(self) -> Box<Slice> {
         unsafe { mem::transmute(self.inner.into_box()) }
     }
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index 7d271e6d2b6..446cdd18b7e 100644
--- a/library/std/src/sys/pal/sgx/thread.rs
+++ b/library/std/src/sys/pal/sgx/thread.rs
@@ -15,7 +15,7 @@ pub use self::task_queue::JoinNotifier;
 
 mod task_queue {
     use super::wait_notify;
-    use crate::sync::{Mutex, MutexGuard, Once};
+    use crate::sync::{Mutex, MutexGuard};
 
     pub type JoinHandle = wait_notify::Waiter;
 
@@ -28,12 +28,12 @@ mod task_queue {
     }
 
     pub(super) struct Task {
-        p: Box<dyn FnOnce()>,
+        p: Box<dyn FnOnce() + Send>,
         done: JoinNotifier,
     }
 
     impl Task {
-        pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
+        pub(super) fn new(p: Box<dyn FnOnce() + Send>) -> (Task, JoinHandle) {
             let (done, recv) = wait_notify::new();
             let done = JoinNotifier(Some(done));
             (Task { p, done }, recv)
@@ -46,17 +46,11 @@ mod task_queue {
     }
 
     #[cfg_attr(test, linkage = "available_externally")]
-    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
-    static TASK_QUEUE_INIT: Once = Once::new();
-    #[cfg_attr(test, linkage = "available_externally")]
     #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
-    static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
+    static TASK_QUEUE: Mutex<Vec<Task>> = Mutex::new(Vec::new());
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
-        unsafe {
-            TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()));
-            TASK_QUEUE.as_ref().unwrap().lock().unwrap()
-        }
+        TASK_QUEUE.lock().unwrap()
     }
 }
 
@@ -101,7 +95,7 @@ pub mod wait_notify {
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
+    pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce() + Send>) -> io::Result<Thread> {
         let mut queue_lock = task_queue::lock();
         unsafe { usercalls::launch_thread()? };
         let (task, handle) = task_queue::Task::new(p);
diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs
index edc736978a1..7d4006ff4b2 100644
--- a/library/std/src/sys/pal/uefi/thread.rs
+++ b/library/std/src/sys/pal/uefi/thread.rs
@@ -7,7 +7,7 @@ use crate::time::Duration;
 
 pub struct Thread(!);
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index fbbd40bfb79..56a0f8e39c4 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -1481,29 +1481,33 @@ impl FromRawFd for File {
 
 impl fmt::Debug for File {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[cfg(any(
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "illumos",
-            target_os = "solaris"
-        ))]
+        #[cfg(any(target_os = "linux", target_os = "illumos", target_os = "solaris"))]
         fn get_path(fd: c_int) -> Option<PathBuf> {
             let mut p = PathBuf::from("/proc/self/fd");
             p.push(&fd.to_string());
             readlink(&p).ok()
         }
 
-        #[cfg(target_vendor = "apple")]
+        #[cfg(any(target_vendor = "apple", target_os = "netbsd"))]
         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 Apple targets define `fcntl`
+            // is inevitable in this case because Apple targets and NetBSD 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];
             let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
             if n == -1 {
-                return None;
+                cfg_if::cfg_if! {
+                    if #[cfg(target_os = "netbsd")] {
+                        // fallback to procfs as last resort
+                        let mut p = PathBuf::from("/proc/self/fd");
+                        p.push(&fd.to_string());
+                        return readlink(&p).ok();
+                    } else {
+                        return None;
+                    }
+                }
             }
             let l = buf.iter().position(|&c| c == 0).unwrap();
             buf.truncate(l as usize);
@@ -1557,6 +1561,8 @@ impl fmt::Debug for File {
             target_os = "netbsd",
             target_os = "openbsd",
             target_os = "vxworks",
+            target_os = "solaris",
+            target_os = "illumos",
             target_vendor = "apple",
         ))]
         fn get_mode(fd: c_int) -> Option<(bool, bool)> {
@@ -1579,6 +1585,8 @@ impl fmt::Debug for File {
             target_os = "netbsd",
             target_os = "openbsd",
             target_os = "vxworks",
+            target_os = "solaris",
+            target_os = "illumos",
             target_vendor = "apple",
         )))]
         fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
@@ -1910,8 +1918,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
             // The code below ensures that `FreeOnDrop` is never a null pointer
             unsafe {
                 // `copyfile_state_free` returns -1 if the `to` or `from` files
-                // cannot be closed. However, this is not considered this an
-                // error.
+                // cannot be closed. However, this is not considered an error.
                 libc::copyfile_state_free(self.0);
             }
         }
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index b5c7d30da7b..2e71ceceb58 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -462,21 +462,21 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(target_os = "haiku")]
 pub fn current_exe() -> io::Result<PathBuf> {
+    let mut name = vec![0; libc::PATH_MAX as usize];
     unsafe {
-        let mut info: mem::MaybeUninit<libc::image_info> = mem::MaybeUninit::uninit();
-        let mut cookie: i32 = 0;
-        // the executable can be found at team id 0
-        let result = libc::_get_next_image_info(
-            0,
-            &mut cookie,
-            info.as_mut_ptr(),
-            mem::size_of::<libc::image_info>(),
+        let result = libc::find_path(
+            crate::ptr::null_mut(),
+            libc::path_base_directory::B_FIND_PATH_IMAGE_PATH,
+            crate::ptr::null_mut(),
+            name.as_mut_ptr(),
+            name.len(),
         );
-        if result != 0 {
+        if result != libc::B_OK {
             use crate::io::ErrorKind;
             Err(io::const_io_error!(ErrorKind::Uncategorized, "Error getting executable path"))
         } else {
-            let name = CStr::from_ptr((*info.as_ptr()).name.as_ptr()).to_bytes();
+            // find_path adds the null terminator.
+            let name = CStr::from_ptr(name.as_ptr()).to_bytes();
             Ok(PathBuf::from(OsStr::from_bytes(name)))
         }
     }
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index e2fca8c7e63..72bda90a9ba 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -1053,6 +1053,10 @@ fn signal_string(signal: i32) -> &'static str {
         libc::SIGINFO => " (SIGINFO)",
         #[cfg(target_os = "hurd")]
         libc::SIGLOST => " (SIGLOST)",
+        #[cfg(target_os = "freebsd")]
+        libc::SIGTHR => " (SIGTHR)",
+        #[cfg(target_os = "freebsd")]
+        libc::SIGLIBRT => " (SIGLIBRT)",
         _ => "",
     }
 }
diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs
index ea939247199..89f8bad7026 100644
--- a/library/std/src/sys/pal/unsupported/thread.rs
+++ b/library/std/src/sys/pal/unsupported/thread.rs
@@ -6,7 +6,7 @@ use crate::time::Duration;
 
 pub struct Thread(!);
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index d45fb28b67e..975eef2451f 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -66,7 +66,7 @@ cfg_if::cfg_if! {
     }
 }
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index 49f936f1449..484bd08495e 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -6,7 +6,7 @@ use crate::time::Duration;
 
 pub struct Thread(!);
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/windows/api.rs b/library/std/src/sys/pal/windows/api.rs
index 555ad581b85..17a0e47ad59 100644
--- a/library/std/src/sys/pal/windows/api.rs
+++ b/library/std/src/sys/pal/windows/api.rs
@@ -251,3 +251,39 @@ pub fn get_last_error() -> WinError {
 pub struct WinError {
     pub code: u32,
 }
+impl WinError {
+    const fn new(code: u32) -> Self {
+        Self { code }
+    }
+}
+
+// Error code constants.
+// The constant names should be the same as the winapi constants except for the leading `ERROR_`.
+// Due to the sheer number of codes, error codes should only be added here on an as-needed basis.
+// However, they should never be removed as the assumption is they may be useful again in the future.
+#[allow(unused)]
+impl WinError {
+    /// Success is not an error.
+    /// Some Windows APIs do use this to distinguish between a zero return and an error return
+    /// but we should never return this to users as an error.
+    pub const SUCCESS: Self = Self::new(c::ERROR_SUCCESS);
+    // tidy-alphabetical-start
+    pub const ACCESS_DENIED: Self = Self::new(c::ERROR_ACCESS_DENIED);
+    pub const ALREADY_EXISTS: Self = Self::new(c::ERROR_ALREADY_EXISTS);
+    pub const CANT_ACCESS_FILE: Self = Self::new(c::ERROR_CANT_ACCESS_FILE);
+    pub const DELETE_PENDING: Self = Self::new(c::ERROR_DELETE_PENDING);
+    pub const DIRECTORY: Self = Self::new(c::ERROR_DIRECTORY);
+    pub const FILE_NOT_FOUND: Self = Self::new(c::ERROR_FILE_NOT_FOUND);
+    pub const INSUFFICIENT_BUFFER: Self = Self::new(c::ERROR_INSUFFICIENT_BUFFER);
+    pub const INVALID_FUNCTION: Self = Self::new(c::ERROR_INVALID_FUNCTION);
+    pub const INVALID_HANDLE: Self = Self::new(c::ERROR_INVALID_HANDLE);
+    pub const INVALID_PARAMETER: Self = Self::new(c::ERROR_INVALID_PARAMETER);
+    pub const NO_MORE_FILES: Self = Self::new(c::ERROR_NO_MORE_FILES);
+    pub const NOT_FOUND: Self = Self::new(c::ERROR_NOT_FOUND);
+    pub const NOT_SUPPORTED: Self = Self::new(c::ERROR_NOT_SUPPORTED);
+    pub const OPERATION_ABORTED: Self = Self::new(c::ERROR_OPERATION_ABORTED);
+    pub const PATH_NOT_FOUND: Self = Self::new(c::ERROR_PATH_NOT_FOUND);
+    pub const SHARING_VIOLATION: Self = Self::new(c::ERROR_SHARING_VIOLATION);
+    pub const TIMEOUT: Self = Self::new(c::ERROR_TIMEOUT);
+    // tidy-alphabetical-end
+}
diff --git a/library/std/src/sys/pal/windows/c/README.md b/library/std/src/sys/pal/windows/c/README.md
index d458e55efbc..efefc5faba7 100644
--- a/library/std/src/sys/pal/windows/c/README.md
+++ b/library/std/src/sys/pal/windows/c/README.md
@@ -3,7 +3,7 @@ be edited manually.
 
 To add bindings, edit `bindings.txt` then regenerate using the following command:
 
-    ./x run generate-windows-sys && ./x fmt library/std
+    ./x run generate-windows-sys && ./x fmt
 
 If you need to override generated functions or types then add them to
 `library/std/src/sys/pal/windows/c.rs`.
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs
index e92c5e80eac..629ff114b5a 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -18,7 +18,8 @@ use crate::sys::{c, cvt, Align8};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::thread;
 
-use super::{api, to_u16s, IoResult};
+use super::api::{self, WinError};
+use super::{to_u16s, IoResult};
 use crate::sys::path::maybe_verbatim;
 
 pub struct File {
@@ -130,10 +131,11 @@ impl Iterator for ReadDir {
             let mut wfd = mem::zeroed();
             loop {
                 if c::FindNextFileW(self.handle.0, &mut wfd) == 0 {
-                    if api::get_last_error().code == c::ERROR_NO_MORE_FILES {
-                        return None;
-                    } else {
-                        return Some(Err(Error::last_os_error()));
+                    match api::get_last_error() {
+                        WinError::NO_MORE_FILES => return None,
+                        WinError { code } => {
+                            return Some(Err(Error::from_raw_os_error(code as i32)));
+                        }
                     }
                 }
                 if let Some(e) = DirEntry::new(&self.root, &wfd) {
@@ -244,8 +246,6 @@ impl OpenOptions {
     }
 
     fn get_access_mode(&self) -> io::Result<c::DWORD> {
-        const ERROR_INVALID_PARAMETER: i32 = 87;
-
         match (self.read, self.write, self.append, self.access_mode) {
             (.., Some(mode)) => Ok(mode),
             (true, false, false, None) => Ok(c::GENERIC_READ),
@@ -255,23 +255,23 @@ impl OpenOptions {
             (true, _, true, None) => {
                 Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA))
             }
-            (false, false, false, None) => Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER)),
+            (false, false, false, None) => {
+                Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32))
+            }
         }
     }
 
     fn get_creation_mode(&self) -> io::Result<c::DWORD> {
-        const ERROR_INVALID_PARAMETER: i32 = 87;
-
         match (self.write, self.append) {
             (true, false) => {}
             (false, false) => {
                 if self.truncate || self.create || self.create_new {
-                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                    return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32));
                 }
             }
             (_, true) => {
                 if self.truncate && !self.create_new {
-                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                    return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32));
                 }
             }
         }
@@ -315,7 +315,7 @@ impl File {
             // Manual truncation. See #115745.
             if opts.truncate
                 && creation == c::OPEN_ALWAYS
-                && unsafe { c::GetLastError() } == c::ERROR_ALREADY_EXISTS
+                && api::get_last_error() == WinError::ALREADY_EXISTS
             {
                 unsafe {
                     // This originally used `FileAllocationInfo` instead of
@@ -845,7 +845,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<
             // We make a special exception for `STATUS_DELETE_PENDING` because
             // otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is
             // very unhelpful.
-            Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as _))
+            Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as i32))
         } else if status == c::STATUS_INVALID_PARAMETER
             && ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE
         {
@@ -1097,7 +1097,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
             //
             // See issue #120040: https://github.com/rust-lang/rust/issues/120040.
             let last_error = api::get_last_error();
-            if last_error.code == c::ERROR_FILE_NOT_FOUND {
+            if last_error == WinError::FILE_NOT_FOUND {
                 return Ok(ReadDir {
                     handle: FindNextFileHandle(find_handle),
                     root: Arc::new(root),
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
index bc19c402d9c..08b7fe300dc 100644
--- a/library/std/src/sys/pal/windows/futex.rs
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -1,4 +1,4 @@
-use super::api;
+use super::api::{self, WinError};
 use crate::sys::c;
 use crate::sys::dur2timeout;
 use core::ffi::c_void;
@@ -72,7 +72,7 @@ pub fn wake_by_address_all<T>(address: &T) {
 
 pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<Duration>) -> bool {
     // return false only on timeout
-    wait_on_address(futex, expected, timeout) || api::get_last_error().code != c::ERROR_TIMEOUT
+    wait_on_address(futex, expected, timeout) || api::get_last_error() != WinError::TIMEOUT
 }
 
 pub fn futex_wake<T>(futex: &T) -> bool {
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 483b8b0072c..62199c16bfe 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -17,7 +17,8 @@ use crate::ptr;
 use crate::slice;
 use crate::sys::{c, cvt};
 
-use super::{api, to_u16s};
+use super::api::{self, WinError};
+use super::to_u16s;
 
 pub fn errno() -> i32 {
     api::get_last_error().code as i32
@@ -333,7 +334,7 @@ fn home_dir_crt() -> Option<PathBuf> {
                     buf,
                     &mut sz,
                 ) {
-                    0 if api::get_last_error().code != c::ERROR_INSUFFICIENT_BUFFER => 0,
+                    0 if api::get_last_error() != WinError::INSUFFICIENT_BUFFER => 0,
                     0 => sz,
                     _ => sz - 1, // sz includes the null terminator
                 }
@@ -358,7 +359,7 @@ fn home_dir_crt() -> Option<PathBuf> {
         super::fill_utf16_buf(
             |buf, mut sz| {
                 match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
-                    0 if api::get_last_error().code != c::ERROR_INSUFFICIENT_BUFFER => 0,
+                    0 if api::get_last_error() != WinError::INSUFFICIENT_BUFFER => 0,
                     0 => sz,
                     _ => sz - 1, // sz includes the null terminator
                 }
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index dfa938d4d57..67ef3ca82da 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -12,6 +12,7 @@ use crate::sys::c;
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::handle::Handle;
 use crate::sys::hashmap_random_keys;
+use crate::sys::pal::windows::api::{self, WinError};
 use crate::sys_common::{FromInner, IntoInner};
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -124,20 +125,19 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
             // testing strategy
             // For more info, see https://github.com/rust-lang/rust/pull/37677.
             if handle == c::INVALID_HANDLE_VALUE {
-                let err = io::Error::last_os_error();
-                let raw_os_err = err.raw_os_error();
+                let error = api::get_last_error();
                 if tries < 10 {
-                    if raw_os_err == Some(c::ERROR_ACCESS_DENIED as i32) {
+                    if error == WinError::ACCESS_DENIED {
                         continue;
                     } else if reject_remote_clients_flag != 0
-                        && raw_os_err == Some(c::ERROR_INVALID_PARAMETER as i32)
+                        && error == WinError::INVALID_PARAMETER
                     {
                         reject_remote_clients_flag = 0;
                         tries -= 1;
                         continue;
                     }
                 }
-                return Err(err);
+                return Err(io::Error::from_raw_os_error(error.code as i32));
             }
             ours = Handle::from_raw_handle(handle);
             break;
diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs
index e4ab2ca7da1..2da986a1494 100644
--- a/library/std/src/sys/pal/windows/process.rs
+++ b/library/std/src/sys/pal/windows/process.rs
@@ -31,6 +31,8 @@ use crate::sys_common::IntoInner;
 
 use core::ffi::c_void;
 
+use super::api::{self, WinError};
+
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
@@ -645,12 +647,12 @@ impl Process {
     pub fn kill(&mut self) -> io::Result<()> {
         let result = unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) };
         if result == c::FALSE {
-            let error = unsafe { c::GetLastError() };
+            let error = api::get_last_error();
             // TerminateProcess returns ERROR_ACCESS_DENIED if the process has already been
             // terminated (by us, or for any other reason). So check if the process was actually
             // terminated, and if so, do not return an error.
-            if error != c::ERROR_ACCESS_DENIED || self.try_wait().is_err() {
-                return Err(crate::io::Error::from_raw_os_error(error as i32));
+            if error != WinError::ACCESS_DENIED || self.try_wait().is_err() {
+                return Err(crate::io::Error::from_raw_os_error(error.code as i32));
             }
         }
         Ok(())
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index 96c23f82aec..690b60d1dec 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -1,6 +1,6 @@
 #![unstable(issue = "none", feature = "windows_stdio")]
 
-use super::api;
+use super::api::{self, WinError};
 use crate::cmp;
 use crate::io;
 use crate::mem::MaybeUninit;
@@ -370,7 +370,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
 
         // ReadConsoleW returns success with ERROR_OPERATION_ABORTED for Ctrl-C or Ctrl-Break.
         // Explicitly check for that case here and try again.
-        if amount == 0 && api::get_last_error().code == c::ERROR_OPERATION_ABORTED {
+        if amount == 0 && api::get_last_error() == WinError::OPERATION_ABORTED {
             continue;
         }
         break;
diff --git a/library/std/src/sys/thread_local/fast_local/eager.rs b/library/std/src/sys/thread_local/fast_local/eager.rs
index c2bc580530b..b97bd9cc88c 100644
--- a/library/std/src/sys/thread_local/fast_local/eager.rs
+++ b/library/std/src/sys/thread_local/fast_local/eager.rs
@@ -21,43 +21,35 @@ impl<T> Storage<T> {
         Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) }
     }
 
-    /// Get a reference to the TLS value. If the TLS variable has been destroyed,
-    /// `None` is returned.
+    /// Get a pointer to the TLS value. If the TLS variable has been destroyed,
+    /// a null pointer is returned.
     ///
-    /// # Safety
-    /// * The `self` reference must remain valid until the TLS destructor has been
-    ///   run.
-    /// * The returned reference may only be used until thread destruction occurs
-    ///   and may not be used after reentrant initialization has occurred.
+    /// The resulting pointer may not be used after thread destruction has
+    /// occurred.
     ///
-    // FIXME(#110897): return NonNull instead of lying about the lifetime.
+    /// # Safety
+    /// The `self` reference must remain valid until the TLS destructor is run.
     #[inline]
-    pub unsafe fn get(&self) -> Option<&'static T> {
+    pub unsafe fn get(&self) -> *const T {
         match self.state.get() {
-            // SAFETY: as the state is not `Destroyed`, the value cannot have
-            // been destroyed yet. The reference fulfills the terms outlined
-            // above.
-            State::Alive => unsafe { Some(&*self.val.get()) },
-            State::Destroyed => None,
+            State::Alive => self.val.get(),
+            State::Destroyed => ptr::null(),
             State::Initial => unsafe { self.initialize() },
         }
     }
 
     #[cold]
-    unsafe fn initialize(&self) -> Option<&'static T> {
+    unsafe fn initialize(&self) -> *const T {
         // Register the destructor
 
         // SAFETY:
-        // * the destructor will be called at thread destruction.
-        // * the caller guarantees that `self` will be valid until that time.
+        // The caller guarantees that `self` will be valid until thread destruction.
         unsafe {
             register_dtor(ptr::from_ref(self).cast_mut().cast(), destroy::<T>);
         }
+
         self.state.set(State::Alive);
-        // SAFETY: as the state is not `Destroyed`, the value cannot have
-        // been destroyed yet. The reference fulfills the terms outlined
-        // above.
-        unsafe { Some(&*self.val.get()) }
+        self.val.get()
     }
 }
 
diff --git a/library/std/src/sys/thread_local/fast_local/lazy.rs b/library/std/src/sys/thread_local/fast_local/lazy.rs
index c2e9a171454..c1ada35d484 100644
--- a/library/std/src/sys/thread_local/fast_local/lazy.rs
+++ b/library/std/src/sys/thread_local/fast_local/lazy.rs
@@ -39,49 +39,31 @@ where
         Storage { state: UnsafeCell::new(State::Initial) }
     }
 
-    /// Get a reference to the TLS value, potentially initializing it with the
-    /// provided parameters. If the TLS variable has been destroyed, `None` is
-    /// returned.
+    /// Get a pointer to the TLS value, potentially initializing it with the
+    /// provided parameters. If the TLS variable has been destroyed, a null
+    /// pointer is returned.
     ///
-    /// # Safety
-    /// * The `self` reference must remain valid until the TLS destructor is run,
-    ///   at which point the returned reference is invalidated.
-    /// * The returned reference may only be used until thread destruction occurs
-    ///   and may not be used after reentrant initialization has occurred.
+    /// The resulting pointer may not be used after reentrant inialialization
+    /// or thread destruction has occurred.
     ///
-    // FIXME(#110897): return NonNull instead of lying about the lifetime.
+    /// # Safety
+    /// The `self` reference must remain valid until the TLS destructor is run.
     #[inline]
-    pub unsafe fn get_or_init(
-        &self,
-        i: Option<&mut Option<T>>,
-        f: impl FnOnce() -> T,
-    ) -> Option<&'static T> {
-        // SAFETY:
-        // No mutable reference to the inner value exists outside the calls to
-        // `replace`. The lifetime of the returned reference fulfills the terms
-        // outlined above.
+    pub unsafe fn get_or_init(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
         let state = unsafe { &*self.state.get() };
         match state {
-            State::Alive(v) => Some(v),
-            State::Destroyed(_) => None,
+            State::Alive(v) => v,
+            State::Destroyed(_) => ptr::null(),
             State::Initial => unsafe { self.initialize(i, f) },
         }
     }
 
     #[cold]
-    unsafe fn initialize(
-        &self,
-        i: Option<&mut Option<T>>,
-        f: impl FnOnce() -> T,
-    ) -> Option<&'static T> {
+    unsafe fn initialize(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
         // Perform initialization
 
         let v = i.and_then(Option::take).unwrap_or_else(f);
 
-        // SAFETY:
-        // If references to the inner value exist, they were created in `f`
-        // and are invalidated here. The caller promises to never use them
-        // after this.
         let old = unsafe { self.state.get().replace(State::Alive(v)) };
         match old {
             // If the variable is not being recursively initialized, register
@@ -92,12 +74,10 @@ where
             val => drop(val),
         }
 
-        // SAFETY:
-        // Initialization was completed and the state was set to `Alive`, so the
-        // reference fulfills the terms outlined above.
+        // SAFETY: the state was just set to `Alive`
         unsafe {
             let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() };
-            Some(v)
+            v
         }
     }
 }
diff --git a/library/std/src/sys/thread_local/fast_local/mod.rs b/library/std/src/sys/thread_local/fast_local/mod.rs
index 152137d9270..575d60de4ee 100644
--- a/library/std/src/sys/thread_local/fast_local/mod.rs
+++ b/library/std/src/sys/thread_local/fast_local/mod.rs
@@ -52,32 +52,26 @@ pub macro thread_local_inner {
     (@key $t:ty, const $init:expr) => {{
         const __INIT: $t = $init;
 
-        #[inline]
-        #[deny(unsafe_op_in_unsafe_fn)]
-        unsafe fn __getit(
-            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-        ) -> $crate::option::Option<&'static $t> {
-            use $crate::thread::local_impl::EagerStorage;
+        unsafe {
             use $crate::mem::needs_drop;
-            use $crate::ptr::addr_of;
+            use $crate::thread::LocalKey;
+            use $crate::thread::local_impl::EagerStorage;
 
-            if needs_drop::<$t>() {
-                #[thread_local]
-                static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
-                unsafe {
-                    VAL.get()
+            LocalKey::new(const {
+                if needs_drop::<$t>() {
+                    |_| {
+                        #[thread_local]
+                        static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
+                        VAL.get()
+                    }
+                } else {
+                    |_| {
+                        #[thread_local]
+                        static VAL: $t = __INIT;
+                        &VAL
+                    }
                 }
-            } else {
-                #[thread_local]
-                static VAL: $t = __INIT;
-                unsafe {
-                    $crate::option::Option::Some(&*addr_of!(VAL))
-                }
-            }
-        }
-
-        unsafe {
-            $crate::thread::LocalKey::new(__getit)
+            })
         }
     }},
 
@@ -88,31 +82,26 @@ pub macro thread_local_inner {
             $init
         }
 
-        #[inline]
-        #[deny(unsafe_op_in_unsafe_fn)]
-        unsafe fn __getit(
-            init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-        ) -> $crate::option::Option<&'static $t> {
-            use $crate::thread::local_impl::LazyStorage;
+        unsafe {
             use $crate::mem::needs_drop;
+            use $crate::thread::LocalKey;
+            use $crate::thread::local_impl::LazyStorage;
 
-            if needs_drop::<$t>() {
-                #[thread_local]
-                static VAL: LazyStorage<$t, ()> = LazyStorage::new();
-                unsafe {
-                    VAL.get_or_init(init, __init)
+            LocalKey::new(const {
+                if needs_drop::<$t>() {
+                    |init| {
+                        #[thread_local]
+                        static VAL: LazyStorage<$t, ()> = LazyStorage::new();
+                        VAL.get_or_init(init, __init)
+                    }
+                } else {
+                    |init| {
+                        #[thread_local]
+                        static VAL: LazyStorage<$t, !> = LazyStorage::new();
+                        VAL.get_or_init(init, __init)
+                    }
                 }
-            } else {
-                #[thread_local]
-                static VAL: LazyStorage<$t, !> = LazyStorage::new();
-                unsafe {
-                    VAL.get_or_init(init, __init)
-                }
-            }
-        }
-
-        unsafe {
-            $crate::thread::LocalKey::new(__getit)
+            })
         }
     }},
     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
diff --git a/library/std/src/sys/thread_local/os_local.rs b/library/std/src/sys/thread_local/os_local.rs
index d6ddbb78a9c..ee5adef66ea 100644
--- a/library/std/src/sys/thread_local/os_local.rs
+++ b/library/std/src/sys/thread_local/os_local.rs
@@ -16,30 +16,22 @@ pub macro thread_local_inner {
     },
 
     // used to generate the `LocalKey` value for `thread_local!`
-    (@key $t:ty, $init:expr) => {
-        {
-            #[inline]
-            fn __init() -> $t { $init }
+    (@key $t:ty, $init:expr) => {{
+        #[inline]
+        fn __init() -> $t { $init }
 
-            // `#[inline] does not work on windows-gnu due to linking errors around dllimports.
-            // See https://github.com/rust-lang/rust/issues/109797.
-            #[cfg_attr(not(windows), inline)]
-            unsafe fn __getit(
-                init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-            ) -> $crate::option::Option<&'static $t> {
-                use $crate::thread::local_impl::Key;
-
-                static __KEY: Key<$t> = Key::new();
-                unsafe {
-                    __KEY.get(init, __init)
-                }
-            }
+        unsafe {
+            use $crate::thread::LocalKey;
+            use $crate::thread::local_impl::Key;
 
-            unsafe {
-                $crate::thread::LocalKey::new(__getit)
-            }
+            // Inlining does not work on windows-gnu due to linking errors around
+            // dllimports. See https://github.com/rust-lang/rust/issues/109797.
+            LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
+                static VAL: Key<$t> = Key::new();
+                VAL.get(init, __init)
+            })
         }
-    },
+    }},
     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
         $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
             $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
@@ -67,38 +59,33 @@ impl<T: 'static> Key<T> {
         Key { os: OsKey::new(Some(destroy_value::<T>)), marker: PhantomData }
     }
 
-    /// Get the value associated with this key, initializating it if necessary.
+    /// Get a pointer to the TLS value, potentially initializing it with the
+    /// provided parameters. If the TLS variable has been destroyed, a null
+    /// pointer is returned.
     ///
-    /// # Safety
-    /// * the returned reference must not be used after recursive initialization
-    /// or thread destruction occurs.
-    pub unsafe fn get(
-        &'static self,
-        i: Option<&mut Option<T>>,
-        f: impl FnOnce() -> T,
-    ) -> Option<&'static T> {
+    /// The resulting pointer may not be used after reentrant inialialization
+    /// or thread destruction has occurred.
+    pub fn get(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
         // SAFETY: (FIXME: get should actually be safe)
         let ptr = unsafe { self.os.get() as *mut Value<T> };
         if ptr.addr() > 1 {
             // SAFETY: the check ensured the pointer is safe (its destructor
             // is not running) + it is coming from a trusted source (self).
-            unsafe { Some(&(*ptr).value) }
+            unsafe { &(*ptr).value }
         } else {
-            // SAFETY: At this point we are sure we have no value and so
-            // initializing (or trying to) is safe.
-            unsafe { self.try_initialize(ptr, i, f) }
+            self.try_initialize(ptr, i, f)
         }
     }
 
-    unsafe fn try_initialize(
+    fn try_initialize(
         &'static self,
         ptr: *mut Value<T>,
         i: Option<&mut Option<T>>,
         f: impl FnOnce() -> T,
-    ) -> Option<&'static T> {
+    ) -> *const T {
         if ptr.addr() == 1 {
             // destructor is running
-            return None;
+            return ptr::null();
         }
 
         let value = i.and_then(Option::take).unwrap_or_else(f);
@@ -119,7 +106,7 @@ impl<T: 'static> Key<T> {
         }
 
         // SAFETY: We just created this value above.
-        unsafe { Some(&(*ptr).value) }
+        unsafe { &(*ptr).value }
     }
 }
 
diff --git a/library/std/src/sys/thread_local/static_local.rs b/library/std/src/sys/thread_local/static_local.rs
index 6beda2e7188..0f08cab1ae4 100644
--- a/library/std/src/sys/thread_local/static_local.rs
+++ b/library/std/src/sys/thread_local/static_local.rs
@@ -13,19 +13,14 @@ pub macro thread_local_inner {
     (@key $t:ty, const $init:expr) => {{
         const __INIT: $t = $init;
 
-        #[inline]
-        #[deny(unsafe_op_in_unsafe_fn)]
-        unsafe fn __getit(
-            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-        ) -> $crate::option::Option<&'static $t> {
+        unsafe {
+            use $crate::thread::LocalKey;
             use $crate::thread::local_impl::EagerStorage;
 
-            static VAL: EagerStorage<$t> = EagerStorage { value: __INIT };
-            $crate::option::Option::Some(&VAL.value)
-        }
-
-        unsafe {
-            $crate::thread::LocalKey::new(__getit)
+            LocalKey::new(|_| {
+                static VAL: EagerStorage<$t> = EagerStorage { value: __INIT };
+                &VAL.value
+            })
         }
     }},
 
@@ -34,19 +29,14 @@ pub macro thread_local_inner {
         #[inline]
         fn __init() -> $t { $init }
 
-        #[inline]
-        #[deny(unsafe_op_in_unsafe_fn)]
-        unsafe fn __getit(
-            init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-        ) -> $crate::option::Option<&'static $t> {
+        unsafe {
+            use $crate::thread::LocalKey;
             use $crate::thread::local_impl::LazyStorage;
 
-            static VAL: LazyStorage<$t> = LazyStorage::new();
-            unsafe { $crate::option::Option::Some(VAL.get(init, __init)) }
-        }
-
-        unsafe {
-            $crate::thread::LocalKey::new(__getit)
+            LocalKey::new(|init| {
+                static VAL: LazyStorage<$t> = LazyStorage::new();
+                VAL.get(init, __init)
+            })
         }
     }},
     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
@@ -73,16 +63,13 @@ impl<T> LazyStorage<T> {
         LazyStorage { value: UnsafeCell::new(None) }
     }
 
-    /// Gets a reference to the contained value, initializing it if necessary.
+    /// Get a pointer to the TLS value, potentially initializing it with the
+    /// provided parameters.
     ///
-    /// # Safety
-    /// The returned reference may not be used after reentrant initialization has occurred.
+    /// The resulting pointer may not be used after reentrant inialialization
+    /// has occurred.
     #[inline]
-    pub unsafe fn get(
-        &'static self,
-        i: Option<&mut Option<T>>,
-        f: impl FnOnce() -> T,
-    ) -> &'static T {
+    pub fn get(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
         let value = unsafe { &*self.value.get() };
         match value {
             Some(v) => v,
@@ -91,11 +78,7 @@ impl<T> LazyStorage<T> {
     }
 
     #[cold]
-    unsafe fn initialize(
-        &'static self,
-        i: Option<&mut Option<T>>,
-        f: impl FnOnce() -> T,
-    ) -> &'static T {
+    fn initialize(&'static self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
         let value = i.and_then(Option::take).unwrap_or_else(f);
         // Destroy the old value, after updating the TLS variable as the
         // destructor might reference it.
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 38e15f9f549..bb1e505285b 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -325,6 +325,11 @@ impl Wtf8Buf {
         self.bytes.shrink_to(min_capacity)
     }
 
+    #[inline]
+    pub fn leak<'a>(self) -> &'a mut Wtf8 {
+        unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
+    }
+
     /// Returns the number of bytes that this string buffer can hold without reallocating.
     #[inline]
     pub fn capacity(&self) -> usize {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index c1b4440e560..aed185637fd 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -123,7 +123,7 @@ pub struct LocalKey<T: 'static> {
     // trivially devirtualizable by LLVM because the value of `inner` never
     // changes and the constant should be readonly within a crate. This mainly
     // only runs into problems when TLS statics are exported across crates.
-    inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
+    inner: fn(Option<&mut Option<T>>) -> *const T,
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
@@ -238,9 +238,7 @@ impl<T: 'static> LocalKey<T> {
         issue = "none"
     )]
     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
-    pub const unsafe fn new(
-        inner: unsafe fn(Option<&mut Option<T>>) -> Option<&'static T>,
-    ) -> LocalKey<T> {
+    pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> {
         LocalKey { inner }
     }
 
@@ -281,8 +279,7 @@ impl<T: 'static> LocalKey<T> {
     where
         F: FnOnce(&T) -> R,
     {
-        // SAFETY: `inner` is safe to call within the lifetime of the thread
-        let thread_local = unsafe { (self.inner)(None).ok_or(AccessError)? };
+        let thread_local = unsafe { (self.inner)(None).as_ref().ok_or(AccessError)? };
         Ok(f(thread_local))
     }
 
@@ -304,9 +301,8 @@ impl<T: 'static> LocalKey<T> {
     {
         let mut init = Some(init);
 
-        // SAFETY: `inner` is safe to call within the lifetime of the thread
         let reference = unsafe {
-            (self.inner)(Some(&mut init)).expect(
+            (self.inner)(Some(&mut init)).as_ref().expect(
                 "cannot access a Thread Local Storage value \
                  during or after destruction",
             )
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 22215873933..83e27dfb746 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -561,7 +561,8 @@ impl Builder {
         let main = Box::new(main);
         // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the
         // lifetime change is justified.
-        let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) };
+        let main =
+            unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) };
 
         Ok(JoinInner {
             // SAFETY:
@@ -1544,7 +1545,7 @@ struct Packet<'scope, T> {
 // The type `T` should already always be Send (otherwise the thread could not
 // have been created) and the Packet is Sync because all access to the
 // `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync.
-unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}
+unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {}
 
 impl<'scope, T> Drop for Packet<'scope, T> {
     fn drop(&mut self) {
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index 0e2409f63ab..75cc7c00e38 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -7,8 +7,6 @@ edition = "2021"
 getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
 std = { path = "../std" }
 core = { path = "../core" }
-panic_unwind = { path = "../panic_unwind" }
-panic_abort = { path = "../panic_abort" }
 
 [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
 libc = { version = "0.2.150", default-features = false }
diff --git a/rustfmt.toml b/rustfmt.toml
index 2b502cf9bc6..b15ffdca38a 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -10,27 +10,18 @@ ignore = [
     "/build-*/",
     "/vendor/",
 
-    # Some tests are not formatted, for multiple reasons:
-    # - some contain syntax errors that cause rustfmt to give an error
-    # - some UI tests are broken by different formatting
-    # - some require special comments in a particular position (e.g. `EMIT_MIR` comments)
+    # Some tests are not formatted, for various reasons.
     "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted.
-    "/tests/crashes/",                # Many tests contain syntax errors.
-    "/tests/debuginfo/",              # Tests are somewhat sensitive to source code layout.
-    "/tests/incremental/",            # Tests are somewhat sensitive to source code layout.
-    "/tests/mir-opt/",
-    "/tests/pretty/",
-    "/tests/run-make/translation/test.rs", # Contains syntax errors.
-    "/tests/run-make-fulldeps/",
-    "/tests/run-pass-valgrind/",
-    "/tests/rustdoc/",
-    "/tests/rustdoc-gui/",
-    "/tests/rustdoc-js/",
-    "/tests/rustdoc-json/",
-    "/tests/rustdoc-js-std/",
-    "/tests/rustdoc-ui/",
-    "/tests/ui/",
-    "/tests/ui-fulldeps/",
+    "/tests/crashes/",                # Many of these tests contain syntax errors.
+    "/tests/debuginfo/",              # These tests are somewhat sensitive to source code layout.
+    "/tests/incremental/",            # These tests are somewhat sensitive to source code layout.
+    "/tests/pretty/",                 # These tests are very sensitive to source code layout.
+    "/tests/run-make/translation/test.rs", # This test contains syntax errors.
+    "/tests/rustdoc/",                # Some have syntax errors, some are whitespace-sensitive.
+    "/tests/rustdoc-gui/",            # Some tests are sensitive to source code layout.
+    "/tests/rustdoc-ui/",             # Some have syntax errors, some are whitespace-sensitive.
+    "/tests/ui/",                     # Some have syntax errors, some are whitespace-sensitive.
+    "/tests/ui-fulldeps/",            # Some are whitespace-sensitive (e.g. `// ~ERROR` comments).
 
     # Do not format submodules.
     # FIXME: sync submodule list with tidy/bootstrap/etc
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index ca0d1fa5bd0..32dd3efa7a6 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -7,6 +7,7 @@ default-run = "bootstrap"
 
 [features]
 build-metrics = ["sysinfo"]
+bootstrap-self-test = [] # enabled in the bootstrap unit tests
 
 [lib]
 path = "src/lib.rs"
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index e60e8f0aa1f..9861121aac0 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -599,6 +599,12 @@ class RustBuild(object):
                 print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs')
             p = Pool(pool_size)
             try:
+                # FIXME: A cheap workaround for https://github.com/rust-lang/rust/issues/125578,
+                # remove this once the issue is closed.
+                bootstrap_out = self.bootstrap_out()
+                if os.path.exists(bootstrap_out):
+                    shutil.rmtree(bootstrap_out)
+
                 p.map(unpack_component, tarballs_download_info)
             finally:
                 p.close()
@@ -864,6 +870,16 @@ class RustBuild(object):
             return line[start + 1:end]
         return None
 
+    def bootstrap_out(self):
+        """Return the path of the bootstrap build artifacts
+
+        >>> rb = RustBuild()
+        >>> rb.build_dir = "build"
+        >>> rb.bootstrap_binary() == os.path.join("build", "bootstrap")
+        True
+        """
+        return os.path.join(self.build_dir, "bootstrap")
+
     def bootstrap_binary(self):
         """Return the path of the bootstrap binary
 
@@ -873,7 +889,7 @@ class RustBuild(object):
         ... "debug", "bootstrap")
         True
         """
-        return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap")
+        return os.path.join(self.bootstrap_out(), "debug", "bootstrap")
 
     def build_bootstrap(self):
         """Build bootstrap"""
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index fc433bc5843..cab37e0da47 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -59,17 +59,18 @@ check-aux:
 		library/alloc \
 		--no-doc
 	# Some doctests have intentional memory leaks.
+	# Some use file system operations to demonstrate dealing with `Result`.
 	$(Q)MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 \
 		library/core \
 		library/alloc \
 		--doc
-	# In `std` we cannot test everything.
-	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \
+	# In `std` we cannot test everything, so we skip some modules.
+	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 library/std \
 		--no-doc -- \
 		--skip fs:: --skip net:: --skip process:: --skip sys::pal::
-	$(Q)MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \
+	$(Q)MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 library/std \
 		--doc -- \
 		--skip fs:: --skip net:: --skip process:: --skip sys::pal::
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 91039d0c8dc..60b1ff3e441 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1041,6 +1041,21 @@ impl Step for PlainSourceTarball {
                 .env("RUSTC_BOOTSTRAP", "1")
                 .current_dir(plain_dst_src);
 
+            // Vendor packages that are required by opt-dist to collect PGO profiles.
+            let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
+                .iter()
+                .chain(build_helper::RUSTC_PGO_CRATES)
+                .map(|pkg| {
+                    let mut manifest_path =
+                        builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
+                    manifest_path.push(pkg);
+                    manifest_path.push("Cargo.toml");
+                    manifest_path
+                });
+            for manifest_path in pkgs_for_pgo_training {
+                cmd.arg("--sync").arg(manifest_path);
+            }
+
             let config = if !builder.config.dry_run() {
                 t!(String::from_utf8(t!(cmd.output()).stdout))
             } else {
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 30b3edfd3ae..b37b2b5bcef 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -29,7 +29,7 @@ macro_rules! submodule_helper {
 }
 
 macro_rules! book {
-    ($($name:ident, $path:expr, $book_name:expr $(, submodule $(= $submodule:literal)? )? ;)+) => {
+    ($($name:ident, $path:expr, $book_name:expr, $lang:expr $(, submodule $(= $submodule:literal)? )? ;)+) => {
         $(
             #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         pub struct $name {
@@ -61,6 +61,7 @@ macro_rules! book {
                     name: $book_name.to_owned(),
                     src: builder.src.join($path),
                     parent: Some(self),
+                    languages: $lang.into(),
                 })
             }
         }
@@ -74,15 +75,15 @@ macro_rules! book {
 // FIXME: Make checking for a submodule automatic somehow (maybe by having a list of all submodules
 // and checking against it?).
 book!(
-    CargoBook, "src/tools/cargo/src/doc", "cargo", submodule = "src/tools/cargo";
-    ClippyBook, "src/tools/clippy/book", "clippy";
-    EditionGuide, "src/doc/edition-guide", "edition-guide", submodule;
-    EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule;
-    Nomicon, "src/doc/nomicon", "nomicon", submodule;
-    Reference, "src/doc/reference", "reference", submodule;
-    RustByExample, "src/doc/rust-by-example", "rust-by-example", submodule;
-    RustdocBook, "src/doc/rustdoc", "rustdoc";
-    StyleGuide, "src/doc/style-guide", "style-guide";
+    CargoBook, "src/tools/cargo/src/doc", "cargo", &[], submodule = "src/tools/cargo";
+    ClippyBook, "src/tools/clippy/book", "clippy", &[];
+    EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule;
+    EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule;
+    Nomicon, "src/doc/nomicon", "nomicon", &[], submodule;
+    Reference, "src/doc/reference", "reference", &[], submodule;
+    RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule;
+    RustdocBook, "src/doc/rustdoc", "rustdoc", &[];
+    StyleGuide, "src/doc/style-guide", "style-guide", &[];
 );
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -110,6 +111,7 @@ impl Step for UnstableBook {
             name: "unstable-book".to_owned(),
             src: builder.md_doc_out(self.target).join("unstable-book"),
             parent: Some(self),
+            languages: vec![],
         })
     }
 }
@@ -120,6 +122,7 @@ struct RustbookSrc<P: Step> {
     name: String,
     src: PathBuf,
     parent: Option<P>,
+    languages: Vec<&'static str>,
 }
 
 impl<P: Step> Step for RustbookSrc<P> {
@@ -151,7 +154,19 @@ impl<P: Step> Step for RustbookSrc<P> {
             builder.info(&format!("Rustbook ({target}) - {name}"));
             let _ = fs::remove_dir_all(&out);
 
-            builder.run(rustbook_cmd.arg("build").arg(src).arg("-d").arg(out));
+            builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out));
+
+            for lang in &self.languages {
+                let out = out.join(lang);
+
+                builder.info(&format!("Rustbook ({target}) - {name} - {lang}"));
+                let _ = fs::remove_dir_all(&out);
+
+                let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
+                builder.run(
+                    rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).arg("-l").arg(lang),
+                );
+            }
         }
 
         if self.parent.is_some() {
@@ -214,6 +229,7 @@ impl Step for TheBook {
             name: "book".to_owned(),
             src: absolute_path.clone(),
             parent: Some(self),
+            languages: vec![],
         });
 
         // building older edition redirects
@@ -225,6 +241,7 @@ impl Step for TheBook {
                 // There should only be one book that is marked as the parent for each target, so
                 // treat the other editions as not having a parent.
                 parent: Option::<Self>::None,
+                languages: vec![],
             });
         }
 
@@ -1208,6 +1225,7 @@ impl Step for RustcBook {
             name: "rustc".to_owned(),
             src: out_base,
             parent: Some(self),
+            languages: vec![],
         });
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 601e4e55e09..0caa39d78ac 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -118,7 +118,9 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
 
 pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
     if !paths.is_empty() {
-        eprintln!("fmt error: path arguments are not accepted");
+        eprintln!(
+            "fmt error: path arguments are no longer accepted; use `--all` to format everything"
+        );
         crate::exit!(1);
     };
     if build.config.dry_run() {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 29b3d1669b4..29cd90222b2 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1101,6 +1101,8 @@ impl Step for Tidy {
     /// Once tidy passes, this step also runs `fmt --check` if tests are being run
     /// for the `dev` or `nightly` channels.
     fn run(self, builder: &Builder<'_>) {
+        builder.build.update_submodule(Path::new("src/tools/rustc-perf"));
+
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(&builder.src);
         cmd.arg(&builder.initial_cargo);
@@ -1487,12 +1489,6 @@ impl Step for RunMake {
     }
 }
 
-host_test!(RunMakeFullDeps {
-    path: "tests/run-make-fulldeps",
-    mode: "run-make",
-    suite: "run-make-fulldeps"
-});
-
 default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" });
 
 /// Coverage tests are a bit more complicated than other test suites, because
@@ -1973,9 +1969,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                 add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd);
             }
 
-            if !builder.config.dry_run()
-                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "coverage-run")
-            {
+            if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
                 // The llvm/bin directory contains many useful cross-platform
                 // tools. Pass the path to run-make tests so they can use them.
                 // (The coverage-run tests also need these tools to process
@@ -1987,7 +1981,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
             }
 
-            if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
+            if !builder.config.dry_run() && mode == "run-make" {
                 // If LLD is available, add it to the PATH
                 if builder.config.lld_enabled {
                     let lld_install_root =
@@ -2007,7 +2001,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
         // Only pass correct values for these flags for the `run-make` suite as it
         // requires that a C++ compiler was configured which isn't always the case.
-        if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
+        if !builder.config.dry_run() && mode == "run-make" {
             cmd.arg("--cc")
                 .arg(builder.cc(target))
                 .arg("--cxx")
@@ -3053,6 +3047,7 @@ impl Step for Bootstrap {
 
         let mut cmd = Command::new(&builder.initial_cargo);
         cmd.arg("test")
+            .args(["--features", "bootstrap-self-test"])
             .current_dir(builder.src.join("src/bootstrap"))
             .env("RUSTFLAGS", "-Cdebuginfo=2")
             .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 2db3f8f7936..9df4698f21f 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -9,7 +9,7 @@ use crate::core::builder;
 use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::utils::channel::GitInfo;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::helpers::output;
 use crate::utils::helpers::{add_dylib_path, exe, t};
 use crate::Compiler;
 use crate::Mode;
@@ -109,9 +109,8 @@ impl Step for ToolBuild {
             &self.target,
         );
 
-        let mut cargo = Command::from(cargo);
         // we check this below
-        let build_success = builder.run_cmd(BootstrapCommand::from(&mut cargo).allow_failure());
+        let build_success = compile::stream_cargo(builder, cargo, vec![], &mut |_| {});
 
         builder.save_toolstate(
             tool,
@@ -804,6 +803,59 @@ impl Step for LlvmBitcodeLinker {
     }
 }
 
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct LibcxxVersionTool {
+    pub target: TargetSelection,
+}
+
+#[allow(dead_code)]
+#[derive(Debug, Clone)]
+pub enum LibcxxVersion {
+    Gnu(usize),
+    Llvm(usize),
+}
+
+impl Step for LibcxxVersionTool {
+    type Output = LibcxxVersion;
+    const DEFAULT: bool = false;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never()
+    }
+
+    fn run(self, builder: &Builder<'_>) -> LibcxxVersion {
+        let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version");
+        let _ = fs::remove_dir_all(&out_dir);
+        t!(fs::create_dir_all(&out_dir));
+
+        let compiler = builder.cxx(self.target).unwrap();
+        let mut cmd = Command::new(compiler);
+
+        let executable = out_dir.join(exe("libcxx-version", self.target));
+        cmd.arg("-o").arg(&executable).arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
+
+        builder.run_cmd(&mut cmd);
+
+        if !executable.exists() {
+            panic!("Something went wrong. {} is not present", executable.display());
+        }
+
+        let version_output = output(&mut Command::new(executable));
+
+        let version_str = version_output.split_once("version:").unwrap().1;
+        let version = version_str.trim().parse::<usize>().unwrap();
+
+        if version_output.starts_with("libstdc++") {
+            LibcxxVersion::Gnu(version)
+        } else if version_output.starts_with("libc++") {
+            LibcxxVersion::Llvm(version)
+        } else {
+            panic!("Coudln't recognize the standard library version.");
+        }
+    }
+}
+
 macro_rules! tool_extended {
     (($sel:ident, $builder:ident),
        $($name:ident,
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index b3d8465cda9..12d2bb18ab7 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -332,7 +332,6 @@ const PATH_REMAP: &[(&str, &[&str])] = &[
             "tests/mir-opt",
             "tests/pretty",
             "tests/run-make",
-            "tests/run-make-fulldeps",
             "tests/run-pass-valgrind",
             "tests/rustdoc",
             "tests/rustdoc-gui",
@@ -828,7 +827,6 @@ impl<'a> Builder<'a> {
                 test::RustAnalyzer,
                 test::ErrorIndex,
                 test::Distcheck,
-                test::RunMakeFullDeps,
                 test::Nomicon,
                 test::Reference,
                 test::RustdocBook,
@@ -1038,14 +1036,26 @@ impl<'a> Builder<'a> {
     }
 
     pub fn doc_rust_lang_org_channel(&self) -> String {
-        let channel = match &*self.config.channel {
-            "stable" => &self.version,
-            "beta" => "beta",
-            "nightly" | "dev" => "nightly",
-            // custom build of rustdoc maybe? link to the latest stable docs just in case
-            _ => "stable",
+        // When using precompiled compiler from CI, we need to use CI rustc's channel and
+        // ignore `rust.channel` from the configuration. Otherwise most of the rustdoc tests
+        // will fail due to incompatible `DOC_RUST_LANG_ORG_CHANNEL`.
+        let channel = if let Some(commit) = self.config.download_rustc_commit() {
+            self.config
+                .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit)
+                .trim()
+                .to_owned()
+        } else {
+            match &*self.config.channel {
+                "stable" => &self.version,
+                "beta" => "beta",
+                "nightly" | "dev" => "nightly",
+                // custom build of rustdoc maybe? link to the latest stable docs just in case
+                _ => "stable",
+            }
+            .to_owned()
         };
-        "https://doc.rust-lang.org/".to_owned() + channel
+
+        format!("https://doc.rust-lang.org/{channel}")
     }
 
     fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 70d32f2f6d9..36b44d0169c 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -22,8 +22,6 @@ use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::channel::{self, GitInfo};
 use crate::utils::helpers::{exe, output, t};
 use build_helper::exit;
-use build_helper::util::fail;
-use semver::Version;
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 
@@ -1610,19 +1608,8 @@ impl Config {
             set(&mut config.channel, channel);
 
             config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
-            // This list is incomplete, please help by expanding it!
-            if config.download_rustc_commit.is_some() {
-                // We need the channel used by the downloaded compiler to match the one we set for rustdoc;
-                // otherwise rustdoc-ui tests break.
-                if config.channel != ci_channel
-                    && !(config.channel == "dev" && ci_channel == "nightly")
-                {
-                    panic!(
-                        "setting rust.channel={} is incompatible with download-rustc",
-                        config.channel
-                    );
-                }
-            }
+
+            // FIXME: handle download-rustc incompatible options.
 
             debug = debug_toml;
             debug_assertions = debug_assertions_toml;
@@ -2136,17 +2123,29 @@ impl Config {
         args
     }
 
+    /// Returns the content of the given file at a specific commit.
+    pub(crate) fn read_file_by_commit(&self, file: &Path, commit: &str) -> String {
+        assert!(
+            self.rust_info.is_managed_git_subrepository(),
+            "`Config::read_file_by_commit` is not supported in non-git sources."
+        );
+
+        let mut git = self.git();
+        git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
+        output(&mut git)
+    }
+
     /// Bootstrap embeds a version number into the name of shared libraries it uploads in CI.
     /// Return the version it would have used for the given commit.
     pub(crate) fn artifact_version_part(&self, commit: &str) -> String {
         let (channel, version) = if self.rust_info.is_managed_git_subrepository() {
-            let mut channel = self.git();
-            channel.arg("show").arg(format!("{commit}:src/ci/channel"));
-            let channel = output(&mut channel);
-            let mut version = self.git();
-            version.arg("show").arg(format!("{commit}:src/version"));
-            let version = output(&mut version);
-            (channel.trim().to_owned(), version.trim().to_owned())
+            let channel = self
+                .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit)
+                .trim()
+                .to_owned();
+            let version =
+                self.read_file_by_commit(&PathBuf::from("src/version"), commit).trim().to_owned();
+            (channel, version)
         } else {
             let channel = fs::read_to_string(self.src.join("src/ci/channel"));
             let version = fs::read_to_string(self.src.join("src/version"));
@@ -2382,8 +2381,14 @@ impl Config {
         }
     }
 
-    // check rustc/cargo version is same or lower with 1 apart from the building one
+    #[cfg(feature = "bootstrap-self-test")]
+    pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {}
+
+    /// check rustc/cargo version is same or lower with 1 apart from the building one
+    #[cfg(not(feature = "bootstrap-self-test"))]
     pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) {
+        use build_helper::util::fail;
+
         if self.dry_run() {
             return;
         }
@@ -2400,11 +2405,12 @@ impl Config {
         }
 
         let stage0_version =
-            Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
-                .unwrap();
-        let source_version =
-            Version::parse(fs::read_to_string(self.src.join("src/version")).unwrap().trim())
+            semver::Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim())
                 .unwrap();
+        let source_version = semver::Version::parse(
+            fs::read_to_string(self.src.join("src/version")).unwrap().trim(),
+        )
+        .unwrap();
         if !(source_version == stage0_version
             || (source_version.major == stage0_version.major
                 && (source_version.minor == stage0_version.minor
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index c4073910623..bfb2c02860d 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -14,16 +14,9 @@ use std::{
 };
 
 fn parse(config: &str) -> Config {
-    Config::parse_inner(
-        &[
-            "check".to_string(),
-            "--set=build.rustc=/does/not/exist".to_string(),
-            "--set=build.cargo=/does/not/exist".to_string(),
-            "--config=/does/not/exist".to_string(),
-            "--skip-stage0-validation".to_string(),
-        ],
-        |&_| toml::from_str(&config).unwrap(),
-    )
+    Config::parse_inner(&["check".to_string(), "--config=/does/not/exist".to_string()], |&_| {
+        toml::from_str(&config).unwrap()
+    })
 }
 
 #[test]
@@ -212,10 +205,7 @@ fn override_toml_duplicate() {
     Config::parse_inner(
         &[
             "check".to_owned(),
-            "--set=build.rustc=/does/not/exist".to_string(),
-            "--set=build.cargo=/does/not/exist".to_string(),
-            "--config=/does/not/exist".to_owned(),
-            "--skip-stage0-validation".to_owned(),
+            "--config=/does/not/exist".to_string(),
             "--set=change-id=1".to_owned(),
             "--set=change-id=2".to_owned(),
         ],
@@ -238,15 +228,7 @@ fn profile_user_dist() {
             .and_then(|table: toml::Value| TomlConfig::deserialize(table))
             .unwrap()
     }
-    Config::parse_inner(
-        &[
-            "check".to_owned(),
-            "--set=build.rustc=/does/not/exist".to_string(),
-            "--set=build.cargo=/does/not/exist".to_string(),
-            "--skip-stage0-validation".to_string(),
-        ],
-        get_toml,
-    );
+    Config::parse_inner(&["check".to_owned()], get_toml);
 }
 
 #[test]
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 60f48c5923e..2b11b8c3d4f 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -9,11 +9,10 @@ use std::{
 };
 
 use build_helper::ci::CiEnv;
-use build_helper::stage0_parser::VersionMetadata;
 use xz2::bufread::XzDecoder;
 
+use crate::utils::helpers::hex_encode;
 use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
-use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
 use crate::{t, Config};
 
 static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
@@ -405,9 +404,17 @@ impl Config {
         cargo_clippy
     }
 
+    #[cfg(feature = "bootstrap-self-test")]
+    pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
+        None
+    }
+
     /// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't
     /// reuse target directories or artifacts
+    #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
+        use build_helper::stage0_parser::VersionMetadata;
+
         let VersionMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
         let channel = format!("{version}-{date}");
 
@@ -487,6 +494,10 @@ impl Config {
         );
     }
 
+    #[cfg(feature = "bootstrap-self-test")]
+    pub(crate) fn download_beta_toolchain(&self) {}
+
+    #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn download_beta_toolchain(&self) {
         self.verbose(|| println!("downloading stage0 beta artifacts"));
 
@@ -665,7 +676,13 @@ download-rustc = false
         self.unpack(&tarball, &bin_root, prefix);
     }
 
+    #[cfg(feature = "bootstrap-self-test")]
+    pub(crate) fn maybe_download_ci_llvm(&self) {}
+
+    #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn maybe_download_ci_llvm(&self) {
+        use crate::core::build_steps::llvm::detect_llvm_sha;
+
         if !self.llvm_from_ci {
             return;
         }
@@ -707,6 +724,7 @@ download-rustc = false
         }
     }
 
+    #[cfg(not(feature = "bootstrap-self-test"))]
     fn download_ci_llvm(&self, llvm_sha: &str) {
         let llvm_assertions = self.llvm_assertions;
 
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 8ffa97ab78b..b5f17b9f54e 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -8,13 +8,19 @@
 //! In theory if we get past this phase it's a bug if a build fails, but in
 //! practice that's likely not true!
 
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
-use walkdir::WalkDir;
+
+#[cfg(not(feature = "bootstrap-self-test"))]
+use crate::builder::Builder;
+#[cfg(not(feature = "bootstrap-self-test"))]
+use crate::core::build_steps::tool;
+#[cfg(not(feature = "bootstrap-self-test"))]
+use std::collections::HashSet;
 
 use crate::builder::Kind;
 use crate::core::config::Target;
@@ -31,10 +37,16 @@ pub struct Finder {
 // it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list.
 //
 // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
+#[cfg(not(feature = "bootstrap-self-test"))]
 const STAGE0_MISSING_TARGETS: &[&str] = &[
     // just a dummy comment so the list doesn't get onelined
 ];
 
+/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
+/// from CI (with`llvm.download-ci-llvm` option).
+#[cfg(not(feature = "bootstrap-self-test"))]
+const LIBSTDCXX_MIN_VERSION_THRESHOLD: usize = 8;
+
 impl Finder {
     pub fn new() -> Self {
         Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
@@ -99,6 +111,31 @@ pub fn check(build: &mut Build) {
         cmd_finder.must_have("git");
     }
 
+    // Ensure that a compatible version of libstdc++ is available on the system when using `llvm.download-ci-llvm`.
+    #[cfg(not(feature = "bootstrap-self-test"))]
+    if !build.config.dry_run() && !build.build.is_msvc() && build.config.llvm_from_ci {
+        let builder = Builder::new(build);
+        let libcxx_version = builder.ensure(tool::LibcxxVersionTool { target: build.build });
+
+        match libcxx_version {
+            tool::LibcxxVersion::Gnu(version) => {
+                if LIBSTDCXX_MIN_VERSION_THRESHOLD > version {
+                    eprintln!(
+                        "\nYour system's libstdc++ version is too old for the `llvm.download-ci-llvm` option."
+                    );
+                    eprintln!("Current version detected: '{}'", version);
+                    eprintln!("Minimum required version: '{}'", LIBSTDCXX_MIN_VERSION_THRESHOLD);
+                    eprintln!(
+                        "Consider upgrading libstdc++ or disabling the `llvm.download-ci-llvm` option."
+                    );
+                }
+            }
+            tool::LibcxxVersion::Llvm(_) => {
+                // FIXME: Handle libc++ version check.
+            }
+        }
+    }
+
     // We need cmake, but only if we're actually building LLVM or sanitizers.
     let building_llvm = build
         .hosts
@@ -167,6 +204,7 @@ than building it.
         .map(|p| cmd_finder.must_have(p))
         .or_else(|| cmd_finder.maybe_have("reuse"));
 
+    #[cfg(not(feature = "bootstrap-self-test"))]
     let stage0_supported_target_list: HashSet<String> =
         output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"]))
             .lines()
@@ -193,11 +231,11 @@ than building it.
             continue;
         }
 
-        let target_str = target.to_string();
-
         // Ignore fake targets that are only used for unit tests in bootstrap.
-        if !["A-A", "B-B", "C-C"].contains(&target_str.as_str()) {
+        #[cfg(not(feature = "bootstrap-self-test"))]
+        {
             let mut has_target = false;
+            let target_str = target.to_string();
 
             let missing_targets_hashset: HashSet<_> =
                 STAGE0_MISSING_TARGETS.iter().map(|t| t.to_string()).collect();
@@ -226,7 +264,7 @@ than building it.
                     target_filename.push(".json");
 
                     // Recursively traverse through nested directories.
-                    let walker = WalkDir::new(custom_target_path).into_iter();
+                    let walker = walkdir::WalkDir::new(custom_target_path).into_iter();
                     for entry in walker.filter_map(|e| e.ok()) {
                         has_target |= entry.file_name() == target_filename;
                     }
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 9af368ef445..824c904e17f 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -233,7 +233,7 @@ For targets: `aarch64-unknown-linux-gnu`
 - Operating System > Linux kernel version = 4.1.49
 - Binary utilities > Version of binutils = 2.29.1
 - C-library > glibc version = 2.17 -- aarch64 support was introduced in this version
-- C compiler > gcc version = 8.5.0
+- C compiler > gcc version = 13.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
 ### `i586-linux-gnu.defconfig`
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig
index 47e984ef85a..520b1667c8b 100644
--- a/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig
+++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/aarch64-linux-gnu.defconfig
@@ -6,7 +6,5 @@ CT_ARCH_ARM=y
 CT_ARCH_64=y
 CT_KERNEL_LINUX=y
 CT_LINUX_V_4_1=y
-CT_BINUTILS_V_2_29=y
 CT_GLIBC_V_2_17=y
-CT_GCC_V_8=y
 CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh
index 3939b4b7c41..d046b539036 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh
@@ -54,7 +54,7 @@ apt-get clean
 # This makes all those symlinks.
 for lib in $(find -name '*.so.*'); do
   target=${lib%.so.*}.so
-  [ -e $target ] || ln -s ${lib##*/} $target
+  ln -s ${lib##*/} $target || echo "warning: silenced error symlinking $lib"
 done
 
 # Remove Solaris 11 functions that are optionally used by libbacktrace.
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index d0da7d30660..0d9c21c4487 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -61,8 +61,8 @@ ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builti
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
            reuse --include-submodules lint && \
-           # Runs checks to ensure that there are no ES5 issues in our JS code.
-           es-check es8 ../src/librustdoc/html/static/js/*.js && \
+           # Runs checks to ensure that there are no issues in our JS code.
+           es-check es2019 ../src/librustdoc/html/static/js/*.js && \
            eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
            eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
            eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js
diff --git a/src/ci/docker/host-x86_64/rfl/Dockerfile b/src/ci/docker/host-x86_64/rfl/Dockerfile
new file mode 100644
index 00000000000..97298519cf2
--- /dev/null
+++ b/src/ci/docker/host-x86_64/rfl/Dockerfile
@@ -0,0 +1,40 @@
+FROM ubuntu:22.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+# libclang1 is required for libclang.so, required by bindgen
+# clang, llvm and lld is required by RfL to compile host code
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python3 \
+  git \
+  cmake \
+  flex \
+  bison \
+  bc \
+  clang-15 \
+  libclang1-15 \
+  llvm-15 \
+  lld-15 \
+  libelf-dev \
+  libedit-dev \
+  libssl-dev \
+  pkg-config \
+  zlib1g-dev \
+  && rm -rf /var/lib/apt/lists/*
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# RfL needs access to cland, lld and llvm tools
+ENV PATH="${PATH}:/usr/lib/llvm-15/bin"
+
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
+
+COPY /scripts/rfl-build.sh /tmp/rfl-build.sh
+ENV SCRIPT bash /tmp/rfl-build.sh
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
index b0c17d9a296..dacf531e404 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
+++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "r-efi"
-version = "4.4.0"
+version = "4.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c47196f636c4cc0634b73b0405323d177753c2e15e866952c64ea22902567a34"
+checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3"
 
 [[package]]
 name = "uefi_qemu_test"
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index e4534d0f840..fa31801269a 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -44,6 +44,14 @@ ENV RUST_CONFIGURE_ARGS \
       --set target.x86_64-unknown-linux-gnu.cc=clang \
       --set target.x86_64-unknown-linux-gnu.cxx=clang++
 
+# This job appears to be checking two separate things:
+# - That we can build the compiler with `--enable-debug`
+#   (without necessarily testing the result).
+# - That the tests with `//@ needs-force-clang-based-tests` pass, since they
+#   don't run by default unless RUSTBUILD_FORCE_CLANG_BASED_TESTS is set.
+#   - FIXME(https://github.com/rust-lang/rust/pull/126155#issuecomment-2156314273):
+#     Currently we only run the subset of tests with "clang" in their name.
+
 ENV SCRIPT \
   python3 ../x.py --stage 2 build && \
-  python3 ../x.py --stage 2 test tests/run-make-fulldeps --test-args clang
+  python3 ../x.py --stage 2 test tests/run-make --test-args clang
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
index c8c754914aa..d228dfc87eb 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
@@ -1,3 +1,6 @@
+# This job builds a toolchain capable of building Fuchsia, and then builds
+# Fuchsia. See the build-fuchsia.sh script in this directory for more details.
+
 FROM ubuntu:22.04
 
 ARG DEBIAN_FRONTEND=noninteractive
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
index 9cc508fe928..913a0b0c09c 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
@@ -2,50 +2,87 @@
 
 # Downloads and builds the Fuchsia operating system using a toolchain installed
 # in $RUST_INSTALL_DIR.
+#
+# You may run this script locally using Docker with the following command:
+#
+# $ src/ci/docker/run.sh x86_64-gnu-integration
+#
+# Alternatively, from within the container with --dev, assuming you have made it
+# as far as building the toolchain with the above command:
+#
+# $ src/ci/docker/run.sh --dev x86_64-gnu-integration
+# docker# git config --global --add safe.directory /checkout/obj/fuchsia
+# docker# ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
+#
+# Also see the docs in the rustc-dev-guide for more info:
+# https://github.com/rust-lang/rustc-dev-guide/pull/1989
 
 set -euf -o pipefail
 
-INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
+# Set this variable to 1 to disable updating the Fuchsia checkout. This is
+# useful for making local changes. You can find the Fuchsia checkout in
+# `obj/x86_64-gnu-integration/fuchsia` in your local checkout after running this
+# job for the first time.
+KEEP_CHECKOUT=
+
+# Any upstream refs that should be cherry-picked. This can be used to include
+# Gerrit changes from https://fxrev.dev during development (click the "Download"
+# button on a changelist to see the cherry pick ref). Example:
+# PICK_REFS=(refs/changes/71/1054071/2 refs/changes/74/1054574/2)
 PICK_REFS=()
 
+# The commit hash of Fuchsia's integration.git to check out. This controls the
+# commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
+# addition to versions of prebuilts. It should be bumped regularly by the
+# Fuchsia team – we aim for every 1-2 months.
+INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
+
 checkout=fuchsia
 jiri=.jiri_root/bin/jiri
 
 set -x
 
-# This script will:
-# - create a directory named "fuchsia" if it does not exist
-# - download "jiri" to "fuchsia/.jiri_root/bin"
-curl -s "https://fuchsia.googlesource.com/jiri/+/HEAD/scripts/bootstrap_jiri?format=TEXT" \
-    | base64 --decode \
-    | bash -s $checkout
-
-cd $checkout
-
-$jiri init \
-    -partial=true \
-    -analytics-opt=false \
-    .
-
-$jiri import \
-    -name=integration \
-    -revision=$INTEGRATION_SHA \
-    -overwrite=true \
-    flower \
-    "https://fuchsia.googlesource.com/integration"
-
-if [ -d ".git" ]; then
-    # Wipe out any local changes if we're reusing a checkout.
-    git checkout --force JIRI_HEAD
-fi
+if [ -z "$KEEP_CHECKOUT" ]; then
+    # This script will:
+    # - create a directory named "fuchsia" if it does not exist
+    # - download "jiri" to "fuchsia/.jiri_root/bin"
+    curl -s "https://fuchsia.googlesource.com/jiri/+/HEAD/scripts/bootstrap_jiri?format=TEXT" \
+        | base64 --decode \
+        | bash -s $checkout
 
-$jiri update -autoupdate=false
+    cd $checkout
 
-echo integration commit = $(git -C integration rev-parse HEAD)
+    $jiri init \
+        -partial=true \
+        -analytics-opt=false \
+        .
 
-for git_ref in "${PICK_REFS[@]}"; do
-    git fetch https://fuchsia.googlesource.com/fuchsia $git_ref
-    git cherry-pick --no-commit FETCH_HEAD
-done
+    $jiri import \
+        -name=integration \
+        -revision=$INTEGRATION_SHA \
+        -overwrite=true \
+        flower \
+        "https://fuchsia.googlesource.com/integration"
+
+    if [ -d ".git" ]; then
+        # Wipe out any local changes if we're reusing a checkout.
+        git checkout --force JIRI_HEAD
+    fi
+
+    $jiri update -autoupdate=false
+
+    echo integration commit = $(git -C integration rev-parse HEAD)
+
+    for git_ref in "${PICK_REFS[@]}"; do
+        git fetch https://fuchsia.googlesource.com/fuchsia $git_ref
+        git cherry-pick --no-commit FETCH_HEAD
+    done
+else
+    echo Reusing existing Fuchsia checkout
+    cd $checkout
+fi
 
+# Run the script inside the Fuchsia checkout responsible for building Fuchsia.
+# You can change arguments to the build by setting KEEP_CHECKOUT=1 above and
+# modifying them in build_fuchsia_from_rust_ci.sh.
 bash scripts/rust/build_fuchsia_from_rust_ci.sh
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 22dcb808c74..a4c59b3067e 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -270,7 +270,6 @@ else
   args="$args --volume $root_dir:/checkout$SRC_MOUNT_OPTION"
   args="$args --volume $objdir:/checkout/obj"
   args="$args --volume $HOME/.cargo:/cargo"
-  args="$args --volume $HOME/rustsrc:$HOME/rustsrc"
   args="$args --volume /tmp/toolstate:/tmp/toolstate"
 
   id=$(id -u)
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
new file mode 100755
index 00000000000..da7b029ca73
--- /dev/null
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+set -euo pipefail
+
+LINUX_VERSION=c13320499ba0efd93174ef6462ae8a7a2933f6e7
+
+# Build rustc, rustdoc and cargo
+../x.py build --stage 1 library rustdoc
+../x.py build --stage 0 cargo
+
+# Install rustup so that we can use the built toolchain easily, and also
+# install bindgen in an easy way.
+curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
+sh rustup.sh -y --default-toolchain none
+
+source /cargo/env
+
+BUILD_DIR=$(realpath ./build)
+rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage1
+rustup default local
+
+mkdir -p rfl
+cd rfl
+
+# Remove existing directory to make local builds easier
+rm -rf linux || true
+
+# Download Linux at a specific commit
+mkdir -p linux
+git -C linux init
+git -C linux remote add origin https://github.com/torvalds/linux.git
+git -C linux fetch --depth 1 origin ${LINUX_VERSION}
+git -C linux checkout FETCH_HEAD
+
+# Install bindgen
+"${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage0/bin/cargo install \
+  --version $(linux/scripts/min-tool-version.sh bindgen) \
+  bindgen-cli
+
+# Configure Rust for Linux
+cat <<EOF > linux/kernel/configs/rfl-for-rust-ci.config
+# CONFIG_WERROR is not set
+
+CONFIG_RUST=y
+
+CONFIG_SAMPLES=y
+CONFIG_SAMPLES_RUST=y
+
+CONFIG_SAMPLE_RUST_MINIMAL=m
+CONFIG_SAMPLE_RUST_PRINT=y
+
+CONFIG_RUST_PHYLIB_ABSTRACTIONS=y
+CONFIG_AX88796B_PHY=y
+CONFIG_AX88796B_RUST_PHY=y
+
+CONFIG_KUNIT=y
+CONFIG_RUST_KERNEL_DOCTESTS=y
+EOF
+
+make -C linux LLVM=1 -j$(($(nproc) + 1)) \
+    rustavailable \
+    defconfig \
+    rfl-for-rust-ci.config
+
+make -C linux LLVM=1 -j$(($(nproc) + 1)) \
+    samples/rust/rust_minimal.o \
+    samples/rust/rust_print.o \
+    drivers/net/phy/ax88796b_rust.o
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
index 876b300d35c..b3921f11421 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
@@ -4,13 +4,7 @@ set -ex
 
 # Only run the stage 1 tests on merges, not on PR CI jobs.
 if [[ -z "${PR_CI_JOB}" ]]; then
-    # When running gcc backend tests, we need to install `libgccjit` and to not run llvm codegen
-    # tests as it will fail them.
-    if [[ "${ENABLE_GCC_CODEGEN}" == "1" ]]; then
-        ../x.py --stage 1 test --skip src/tools/tidy --skip tests/codegen
-    else
-        ../x.py --stage 1 test --skip src/tools/tidy
-    fi
+    ../x.py --stage 1 test --skip src/tools/tidy
 
     # Run the `mir-opt` tests again but this time for a 32-bit target.
     # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
@@ -29,14 +23,8 @@ if [[ -z "${PR_CI_JOB}" ]]; then
         --rustc-args "--cfg feature=\"optimize_for_size\""
 fi
 
-# When running gcc backend tests, we need to install `libgccjit` and to not run llvm codegen
-# tests as it will fail them.
 # NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
-if [[ "${ENABLE_GCC_CODEGEN}" == "1" ]]; then
-    ../x.py --stage 2 test --skip src/tools/tidy --skip tests/codegen
-else
-    ../x.py --stage 2 test --skip src/tools/tidy
-fi
+../x.py --stage 2 test --skip src/tools/tidy
 
 # Run the `mir-opt` tests again but this time for a 32-bit target.
 # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index ca86f3f0110..1db763735e6 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -33,11 +33,11 @@ runners:
     <<: *base-job
 
   - &job-aarch64-linux
-    os: [ self-hosted, ARM64, linux ]
+    os: ubuntu-22.04-arm64-8core-32gb
 
 envs:
   env-x86_64-apple-tests: &env-x86_64-apple-tests
-    SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps
+    SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc
     RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
     RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
     MACOSX_DEPLOYMENT_TARGET: 10.12
@@ -58,9 +58,16 @@ envs:
     CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
     ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
     AWS_REGION: us-west-1
+    TOOLSTATE_PUBLISH: 1
 
   try:
     <<: *production
+    # The following env var activates faster `try` builds in `opt-dist` by, e.g.
+    # - building only the more commonly useful components (we rarely need e.g. rust-docs in try
+    #   builds)
+    # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain
+    #
+    # If you *want* these to happen however, temporarily uncomment it before triggering a try build.
     DIST_TRY_BUILD: 1
 
   auto:
@@ -287,7 +294,7 @@ auto:
 
   - image: x86_64-apple-2
     env:
-      SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps
+      SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc
       <<: *env-x86_64-apple-tests
     <<: *job-macos-xl
 
@@ -458,3 +465,8 @@ auto:
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
     <<: *job-windows-8c
+
+  # Tests integration with Rust for Linux.
+  # Builds stage 1 compiler and tries to compile a few RfL examples with it.
+  - image: rfl
+    <<: *job-linux-8c
diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh
index 691df04e754..e828365c416 100755
--- a/src/ci/publish_toolstate.sh
+++ b/src/ci/publish_toolstate.sh
@@ -24,8 +24,8 @@ cd rust-toolstate
 FAILURE=1
 for RETRY_COUNT in 1 2 3 4 5; do
     # The purpose of this is to publish the new "current" toolstate in the toolstate repo.
-    # This happens post-landing, on master.
-    # (Publishing the per-commit test results happens pre-landing in src/bootstrap/toolstate.rs).
+    # This happens at the end of auto builds.
+    # (Publishing the per-commit test results happens in src/bootstrap/toolstate.rs).
     "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \
         "$GIT_COMMIT_MSG" \
         "$MESSAGE_FILE" \
diff --git a/src/doc/book b/src/doc/book
-Subproject 85442a608426d3667f1c9458ad457b241a36b56
+Subproject 5228bfac8267ad24659a81b92ec5417976b5edb
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject 0c68e90acaae5a611f8f5098a3c2980de9845ab
+Subproject bbaabbe088e21a81a0d9ae6757705020d5d7b41
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject dd962bb82865a5284f2404e5234f1e3222b9c02
+Subproject b10c6acaf0f43481f6600e95d4b5013446e29f7
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 0d5f88475fe285affa6dbbc806e9e44d730797c
+Subproject 0ebdacadbda8ce2cd8fbf93985e15af61a7ab89
diff --git a/src/doc/reference b/src/doc/reference
-Subproject e356977fceaa8591c762312d8d446769166d4b3
+Subproject 6019b76f5b28938565b251bbba0bf5cc5c43d86
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 20482893d1a502df72f76762c97aed88854cdf8
+Subproject 4840dca06cadf48b305d3ce0aeafde7f80933f8
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject b6d4a4940bab85cc91eec70cc2e3096dd48da62
+Subproject 6a7374bd87cbac0f8be4fd4877d8186d9c31398
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 4ef2fcebe92..201ace5ce3a 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -30,10 +30,15 @@
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
     - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
     - [arm-none-eabi](platform-support/arm-none-eabi.md)
-    - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
-    - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
-    - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md)
-    - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md)
+      - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
+      - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
+      - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md)
+      - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md)
+      - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md)
+      - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md)
+      - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md)
+      - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md)
+      - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md)
     - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
     - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
@@ -60,11 +65,6 @@
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
-    - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md)
-    - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md)
-    - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md)
-    - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md)
-    - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
     - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md
index bfa60161926..bd4bebbc874 100644
--- a/src/doc/rustc/src/check-cfg/cargo-specifics.md
+++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md
@@ -3,12 +3,12 @@
 <!--
 This page is currently (as of May 2024) the canonical place for describing the interaction
 between Cargo and --check-cfg. It is placed in the rustc book rather than the Cargo book
-since check-cfg is primarely a Rust/rustc feature and is therefor consider by T-cargo to
+since check-cfg is primarily a Rust/rustc feature and is therefore considered by T-cargo to
 be an implementation detail, at least --check-cfg and the unexpected_cfgs are owned by
 rustc, not Cargo.
 -->
 
-This document is intented to summarize the principal ways Cargo interacts with
+This document is intended to summarize the principal ways Cargo interacts with
 the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide
 individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and
 to the [Cargo book](../../cargo/index.html).
@@ -17,7 +17,7 @@ to the [Cargo book](../../cargo/index.html).
 
 *See the [`[features]` section in the Cargo book][cargo-features] for more details.*
 
-With the `[features]` table Cargo provides a mechanism to express conditional compilation and
+With the `[features]` table, Cargo provides a mechanism to express conditional compilation and
 optional dependencies. Cargo *automatically* declares corresponding cfgs for every feature as
 expected.
 
@@ -32,16 +32,16 @@ my_feature = []
 
 ## `check-cfg` in `[lints.rust]` table
 
-<!-- Note that T-Cargo considers `[lints.rust.unexpected_cfgs.check-cfg]` to be an
-implementation detail and is therefor not documented in Cargo, we therefor do that ourself -->
+<!-- Note that T-Cargo considers `lints.rust.unexpected_cfgs.check-cfg` to be an
+implementation detail and is therefore documented here and not in Cargo. -->
 
 *See the [`[lints]` section in the Cargo book][cargo-lints-table] for more details.*
 
-When using a staticlly known custom config (ie. not dependant on a build-script), Cargo provides
+When using a statically known custom config (i.e., not dependent on a build-script), Cargo provides
 the custom lint config `check-cfg` under `[lints.rust.unexpected_cfgs]`.
 
 It can be used to set custom static [`--check-cfg`](../check-cfg.md) args, it is mainly useful when
-the list of expected cfgs is known is advance.
+the list of expected cfgs is known in advance.
 
 `Cargo.toml`:
 ```toml
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 3e1ac2fa8ad..72ab8ab5ce9 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -213,21 +213,39 @@ The valid emit kinds are:
   `CRATE_NAME.o`.
 
 The output filename can be set with the [`-o` flag](#option-o-output). A
-suffix may be added to the filename with the [`-C extra-filename`
-flag](codegen-options/index.md#extra-filename). The files are written to the
-current directory unless the [`--out-dir` flag](#option-out-dir) is used. Each
-emission type may also specify the output filename with the form `KIND=PATH`,
-which takes precedence over the `-o` flag.
-Specifying `-o -` or `--emit KIND=-` asks rustc to emit to stdout.
-Text output types (`asm`, `dep-info`, `llvm-ir` and `mir`) can be written to
-stdout despite it being a tty or not. This will result in an error if any
-binary output type is written to stdout that is a tty.
-This will also result in an error if multiple output types
-would be written to stdout, because they would be all mixed together.
+suffix may be added to the filename with the
+[`-C extra-filename` flag](codegen-options/index.md#extra-filename).
+
+Output files are written to the current directory unless the
+[`--out-dir` flag](#option-out-dir) is used.
 
 [LLVM bitcode]: https://llvm.org/docs/BitCodeFormat.html
 [LLVM IR]: https://llvm.org/docs/LangRef.html
 
+### Custom paths for individual emit kinds
+
+Each emit type can optionally be followed by `=` to specify an explicit output
+path that only applies to the output of that type. For example:
+
+- `--emit=link,dep-info=/path/to/dep-info.d`
+  - Emit the crate itself as normal,
+    and also emit dependency info to the specified path.
+- `--emit=llvm-ir=-,mir`
+  - Emit MIR to the default filename (based on crate name),
+    and emit LLVM IR to stdout.
+
+### Emitting to stdout
+
+When using `--emit` or [`-o`](#option-o-output), output can be sent to stdout
+by specifying `-` as the path (e.g. `-o -`).
+
+Binary output types can only be written to stdout if it is not a tty.
+Text output types (`asm`, `dep-info`, `llvm-ir` and `mir`) can be written to
+stdout regardless of whether it is a tty or not.
+
+Only one type of output can be written to stdout. Attempting to write multiple
+types to stdout at the same time will result in an error.
+
 <a id="option-print"></a>
 ## `--print`: print compiler information
 
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
index 32083b2f731..c853f34ee03 100644
--- a/src/doc/rustc/src/json.md
+++ b/src/doc/rustc/src/json.md
@@ -217,7 +217,8 @@ Diagnostics have the following format:
 Artifact notifications are emitted when the [`--json=artifacts`
 flag][option-json] is used. They indicate that a file artifact has been saved
 to disk. More information about emit kinds may be found in the [`--emit`
-flag][option-emit] documentation.
+flag][option-emit] documentation. Notifications can contain more than one file
+for each type, for example when using multiple codegen units.
 
 ```javascript
 {
@@ -229,6 +230,11 @@ flag][option-emit] documentation.
        - "link": The generated crate as specified by the crate-type.
        - "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
        - "metadata": The Rust `.rmeta` file containing metadata about the crate.
+       - "asm": The `.s` file with generated assembly
+       - "llvm-ir": The `.ll` file with generated textual LLVM IR
+       - "llvm-bc": The `.bc` file with generated LLVM bitcode
+       - "mir": The `.mir` file with rustc's mid-level intermediate representation.
+       - "obj": The `.o` file with generated native object code
     */
     "emit": "link"
 }
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 77859956c95..633c26a4f56 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,12 +33,12 @@ All tier 1 targets with host tools support the full standard library.
 target | notes
 -------|-------
 `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+)
-`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^x86_32-floats-return-ABI]
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI]
 `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
 [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+)
-`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+)
-`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+)
+`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+, Windows Server 2016+)
+`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+, Windows Server 2016+)
 `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+)
 
 [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md
index 0b1b10e4762..de0ef322fa6 100644
--- a/src/doc/rustc/src/platform-support/arm-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md
@@ -1,6 +1,15 @@
 # `{arm,thumb}*-none-eabi(hf)?`
 
-## Tier 2 Target List
+## Common Target Details
+
+This documentation covers details that apply to a range of bare-metal targets
+for 32-bit Arm CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is
+often used to assist compilation to these targets.
+
+Details that apply only to only a specific target in this group are covered in
+their own document.
+
+### Tier 2 Target List
 
 - Arm A-Profile Architectures
   - `armv7a-none-eabi`
@@ -16,7 +25,7 @@
 - *Legacy* Arm Architectures
   - None
 
-## Tier 3 Target List
+### Tier 3 Target List
 
 - Arm A-Profile Architectures
   - `armv7a-none-eabihf`
@@ -28,24 +37,21 @@
   - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md)
   - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md)
 
-## Common Target Details
-
-This documentation covers details that apply to a range of bare-metal targets
-for 32-bit Arm CPUs. In addition, target specific details may be covered in
-their own document.
+## Instruction Sets
 
 There are two 32-bit instruction set architectures (ISAs) defined by Arm:
 
 - The [*A32 ISA*][a32-isa], with fixed-width 32-bit instructions. Previously
-  known as the *Arm* ISA, this originated with the original ARM1 of 1985 and has
+  known as the *Arm* ISA, this originated with the original Arm1 of 1985 and has
   been updated by various revisions to the architecture specifications ever
   since.
 - The [*T32 ISA*][t32-isa], with a mix of 16-bit and 32-bit width instructions.
   Note that this term includes both the original 16-bit width *Thumb* ISA
   introduced with the Armv4T architecture in 1994, and the later 16/32-bit sized
-  *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. Again, these
-  ISAs have been revised by subsequent revisions to the relevant Arm
-  architecture specifications.
+  *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003.
+
+Again, these ISAs have been revised by subsequent revisions to the relevant Arm
+architecture specifications.
 
 There is also a 64-bit ISA with fixed-width 32-bit instructions called the *A64
 ISA*, but targets which implement that instruction set generally start with
diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
index f4c8dd46f1d..0c5129d0efb 100644
--- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
@@ -1,20 +1,18 @@
-# armv4t-none-eabi
+# armv4t-none-eabi / thumbv4t-none-eabi
 
 Tier 3
 
-Bare-metal target for any cpu in the Armv4T architecture family, supporting
-ARM/Thumb code interworking (aka `A32`/`T32`), with ARM code as the default code
-generation.
+These two targets are part of the [`arm-none-eabi`](arm-none-eabi.md) target
+group, and all the information there applies.
 
-In particular this supports the Game Boy Advance (GBA), but there's nothing
-GBA-specific with this target, so any Armv4T device should work fine.
-
-See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
-`arm-none-eabi` targets.
+Both of these targets can be used on the Game Boy Advance (GBA), among other
+things. On the GBA, one should usually use the `thumb` target to get the best
+overall performance.
 
 ## Target Maintainers
 
 * [@Lokathor](https://github.com/lokathor)
+* [@corwinkuiper](https://github.com/corwinkuiper)
 
 ## Testing
 
@@ -23,6 +21,6 @@ This is a cross-compiled target that you will need to emulate during testing.
 Because this is a device-agnostic target, and the exact emulator that you'll
 need depends on the specific device you want to run your code on.
 
-For example, when programming for the Gameboy Advance, the
-[mgba-test-runner](https://github.com/agbrs/agb) program could be used to make a
-normal set of rust tests be run within the `mgba` emulator.
+* When building for the GBA, [mgba-test-runner](https://github.com/agbrs/agb)
+  can be used to make a normal set of rust tests be run within the `mgba`
+  emulator.
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 3e1db692f50..5643c6a0188 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -10,9 +10,9 @@ updatable, and performant.
 The [Fuchsia team]:
 
 - Tyler Mandry ([@tmandry](https://github.com/tmandry))
-- Dan Johnson ([@computerdruid](https://github.com/computerdruid))
 - David Koloski ([@djkoloski](https://github.com/djkoloski))
-- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
+- Julia Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
+- Erick Tryzelaar ([@erickt](https://github.com/erickt))
 
 As the team evolves over time, the specific members listed here may differ from
 the members reported by the API. The API should be considered to be
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index 56070c2ec34..51a397a38d2 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -160,8 +160,7 @@ export exclude_tests='
     --exclude src/tools/linkchecker
     --exclude tests/ui-fulldeps
     --exclude rustc
-    --exclude rustdoc
-    --exclude tests/run-make-fulldeps'
+    --exclude rustdoc'
 
 env $build_env \
     ./x.py test \
diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-backend.md b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md
index 67634be6993..7e4be9841f4 100644
--- a/src/doc/unstable-book/src/compiler-flags/codegen-backend.md
+++ b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md
@@ -12,8 +12,9 @@ backend. The library must be of crate type `dylib` and must contain a function
 named `__rustc_codegen_backend` with a signature of `fn() -> Box<dyn rustc_codegen_ssa::traits::CodegenBackend>`.
 
 ## Example
-See also the [`hotplug_codegen_backend`](https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/hotplug_codegen_backend) test
-for a full example.
+See also the [`codegen-backend/hotplug`] test for a working example.
+
+[`codegen-backend/hotplug`]: https://github.com/rust-lang/rust/tree/master/tests/ui-fulldeps/codegen-backend/hotplug.rs
 
 ```rust,ignore (partial-example)
 use rustc_codegen_ssa::traits::CodegenBackend;
diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md
index e55165b5374..ab63c986e85 100644
--- a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md
+++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md
@@ -1,6 +1,6 @@
 # `print=check-cfg`
 
-The tracking issue for this feature is: [#XXXXXX](https://github.com/rust-lang/rust/issues/XXXXXX).
+The tracking issue for this feature is: [#125704](https://github.com/rust-lang/rust/issues/125704).
 
 ------------------------
 
@@ -15,6 +15,7 @@ This print option works similarly to `--print=cfg` (modulo check-cfg specifics):
  - `cfg(feature, values("foo", "bar"))`: `feature="foo"` and `feature="bar"`
  - `cfg(feature, values(none(), ""))`: `feature` and `feature=""`
  - `cfg(feature, values(any()))`: `feature=any()`
+ - `cfg(feature, values())`: `feature=`
  - `cfg(any())`: `any()`
  - *nothing*: `any()=any()`
 
diff --git a/src/doc/unstable-book/src/language-features/abi-vectorcall.md b/src/doc/unstable-book/src/language-features/abi-vectorcall.md
new file mode 100644
index 00000000000..56273bfdb79
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-vectorcall.md
@@ -0,0 +1,19 @@
+# `abi_vectorcall`
+
+The tracking issue for this feature is: [#124485]
+
+[#124485]: https://github.com/rust-lang/rust/issues/124485
+
+------------------------
+
+Adds support for the Windows `"vectorcall"` ABI, the equivalent of `__vectorcall` in MSVC.
+
+```rust,ignore (only-windows-or-x86-or-x86-64)
+extern "vectorcall" {
+    fn add_f64s(x: f64, y: f64) -> f64;
+}
+
+fn main() {
+    println!("{}", add_f64s(2.0, 4.0));
+}
+```
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 20bcf1abf41..2857f74c744 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,6 +1,6 @@
 use super::*;
 
-use rustc_ast::{MetaItemLit, Path, StrStyle};
+use rustc_ast::{MetaItemLit, Path, Safety, StrStyle};
 use rustc_span::create_default_session_globals_then;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::DUMMY_SP;
@@ -16,6 +16,7 @@ fn name_value_cfg(name: &str, value: &str) -> Cfg {
 
 fn dummy_meta_item_word(name: &str) -> MetaItem {
     MetaItem {
+        unsafety: Safety::Default,
         path: Path::from_ident(Ident::from_str(name)),
         kind: MetaItemKind::Word,
         span: DUMMY_SP,
@@ -25,6 +26,7 @@ fn dummy_meta_item_word(name: &str) -> MetaItem {
 fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
     let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
     MetaItem {
+        unsafety: Safety::Default,
         path: Path::from_ident(Ident::from_str(name)),
         kind: MetaItemKind::NameValue(lit),
         span: DUMMY_SP,
@@ -34,6 +36,7 @@ fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> Meta
 macro_rules! dummy_meta_item_list {
     ($name:ident, [$($list:ident),* $(,)?]) => {
         MetaItem {
+            unsafety: Safety::Default,
             path: Path::from_ident(Ident::from_str(stringify!($name))),
             kind: MetaItemKind::List(thin_vec![
                 $(
@@ -48,6 +51,7 @@ macro_rules! dummy_meta_item_list {
 
     ($name:ident, [$($list:expr),* $(,)?]) => {
         MetaItem {
+            unsafety: Safety::Default,
             path: Path::from_ident(Ident::from_str(stringify!($name))),
             kind: MetaItemKind::List(thin_vec![
                 $(
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index c7366ce1a68..0024e246ef0 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -130,7 +130,10 @@ pub(crate) fn try_inline(
         }
         Res::Def(DefKind::Const, did) => {
             record_extern_fqn(cx, did, ItemType::Constant);
-            cx.with_param_env(did, |cx| clean::ConstantItem(build_const(cx, did)))
+            cx.with_param_env(did, |cx| {
+                let (generics, ty, ct) = build_const_item(cx, did);
+                clean::ConstantItem(generics, Box::new(ty), ct)
+            })
         }
         Res::Def(DefKind::Macro(kind), did) => {
             let is_doc_hidden = cx.tcx.is_doc_hidden(did)
@@ -717,21 +720,20 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
     }
 }
 
-fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
+fn build_const_item(
+    cx: &mut DocContext<'_>,
+    def_id: DefId,
+) -> (clean::Generics, clean::Type, clean::Constant) {
     let mut generics =
         clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
     clean::simplify::move_bounds_to_generic_parameters(&mut generics);
-
-    clean::Constant {
-        type_: Box::new(clean_middle_ty(
-            ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
-            cx,
-            Some(def_id),
-            None,
-        )),
-        generics,
-        kind: clean::ConstantKind::Extern { def_id },
-    }
+    let ty = clean_middle_ty(
+        ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
+        cx,
+        None,
+        None,
+    );
+    (generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } })
 }
 
 fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 839bfdf44af..2dcbbf0d150 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -283,31 +283,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 
 pub(crate) fn clean_const<'tcx>(
     constant: &hir::ConstArg<'_>,
-    cx: &mut DocContext<'tcx>,
+    _cx: &mut DocContext<'tcx>,
 ) -> Constant {
-    let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
-    Constant {
-        type_: Box::new(clean_middle_ty(
-            ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
-            cx,
-            Some(def_id),
-            None,
-        )),
-        generics: Generics::default(),
-        kind: ConstantKind::Anonymous { body: constant.value.body },
-    }
+    Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
     constant: ty::Binder<'tcx, ty::Const<'tcx>>,
-    cx: &mut DocContext<'tcx>,
+    _cx: &mut DocContext<'tcx>,
 ) -> Constant {
     // FIXME: instead of storing the stringified expression, store `self` directly instead.
-    Constant {
-        type_: Box::new(clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None)),
-        generics: Generics::default(),
-        kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
-    }
+    Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } }
 }
 
 pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
@@ -2738,11 +2724,11 @@ fn clean_maybe_renamed_item<'tcx>(
             ItemKind::Static(ty, mutability, body_id) => {
                 StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
             }
-            ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
-                type_: Box::new(clean_ty(ty, cx)),
-                generics: clean_generics(generics, cx),
-                kind: ConstantKind::Local { body: body_id, def_id },
-            }),
+            ItemKind::Const(ty, generics, body_id) => ConstantItem(
+                clean_generics(generics, cx),
+                Box::new(clean_ty(ty, cx)),
+                Constant { kind: ConstantKind::Local { body: body_id, def_id } },
+            ),
             ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
                 bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
                 generics: clean_generics(ty.generics, cx),
@@ -3089,7 +3075,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
     let def_id = item.owner_id.to_def_id();
     cx.with_param_env(def_id, |cx| {
         let kind = match item.kind {
-            hir::ForeignItemKind::Fn(decl, names, generics) => {
+            // FIXME(missing_unsafe_on_extern) handle safety of foreign fns.
+            // Safety was added as part of the implementation of unsafe extern blocks PR #124482
+            hir::ForeignItemKind::Fn(decl, names, generics, _) => {
                 let (generics, decl) = enter_impl_trait(cx, |cx| {
                     // NOTE: generics must be cleaned before args
                     let generics = clean_generics(generics, cx);
@@ -3099,7 +3087,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
                 });
                 ForeignFunctionItem(Box::new(Function { decl, generics }))
             }
-            hir::ForeignItemKind::Static(ty, mutability) => {
+            // FIXME(missing_unsafe_on_extern) handle safety of foreign statics.
+            // Safety was added as part of the implementation of unsafe extern blocks PR #124482
+            hir::ForeignItemKind::Static(ty, mutability, _) => {
                 ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None })
             }
             hir::ForeignItemKind::Type => ForeignTypeItem,
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index 5ac1b742c38..995919f73f8 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -65,7 +65,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
     let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
     let file_name = source_map.span_to_filename(span);
     let mut parser =
-        match rustc_parse::maybe_new_parser_from_source_str(&psess, file_name, snippet.clone()) {
+        match rustc_parse::new_parser_from_source_str(&psess, file_name, snippet.clone()) {
             Ok(parser) => parser,
             Err(errs) => {
                 errs.into_iter().for_each(|err| err.cancel());
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3f84da310dd..69678b727c1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -830,7 +830,6 @@ pub(crate) enum ItemKind {
     TypeAliasItem(Box<TypeAlias>),
     OpaqueTyItem(OpaqueTy),
     StaticItem(Static),
-    ConstantItem(Constant),
     TraitItem(Box<Trait>),
     TraitAliasItem(TraitAlias),
     ImplItem(Box<Impl>),
@@ -853,6 +852,7 @@ pub(crate) enum ItemKind {
     PrimitiveItem(PrimitiveType),
     /// A required associated constant in a trait declaration.
     TyAssocConstItem(Generics, Box<Type>),
+    ConstantItem(Generics, Box<Type>, Constant),
     /// An associated constant in a trait impl or a provided one in a trait declaration.
     AssocConstItem(Generics, Box<Type>, ConstantKind),
     /// A required associated type in a trait declaration.
@@ -888,7 +888,7 @@ impl ItemKind {
             | TypeAliasItem(_)
             | OpaqueTyItem(_)
             | StaticItem(_)
-            | ConstantItem(_)
+            | ConstantItem(_, _, _)
             | TraitAliasItem(_)
             | TyMethodItem(_)
             | MethodItem(_, _)
@@ -922,7 +922,7 @@ impl ItemKind {
                 | TypeAliasItem(_)
                 | OpaqueTyItem(_)
                 | StaticItem(_)
-                | ConstantItem(_)
+                | ConstantItem(_, _, _)
                 | TraitAliasItem(_)
                 | ForeignFunctionItem(_)
                 | ForeignStaticItem(_)
@@ -1451,7 +1451,7 @@ impl Trait {
         tcx.trait_def(self.def_id).safety
     }
     pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool {
-        tcx.check_is_object_safe(self.def_id)
+        tcx.is_object_safe(self.def_id)
     }
 }
 
@@ -1936,7 +1936,7 @@ impl PrimitiveType {
             let mut primitive_locations = FxHashMap::default();
             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
             // This is a degenerate case that I don't plan to support.
-            for &crate_num in tcx.crates_including_speculative(()) {
+            for &crate_num in tcx.crates(()) {
                 let e = ExternalCrate { crate_num };
                 let crate_name = e.name(tcx);
                 debug!(?crate_num, ?crate_name);
@@ -2364,8 +2364,6 @@ pub(crate) struct Static {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub(crate) struct Constant {
-    pub(crate) type_: Box<Type>,
-    pub(crate) generics: Generics,
     pub(crate) kind: ConstantKind,
 }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 24a01414c70..7c83d438719 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -353,8 +353,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
             s
         }
         // array lengths are obviously usize
-        ty::ConstKind::Value(ty::ValTree::Leaf(scalar))
-            if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) =>
+        ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar))
+            if *ty.kind() == ty::Uint(ty::UintTy::Usize) =>
         {
             scalar.to_string()
         }
@@ -431,8 +431,7 @@ fn print_const_with_custom_print_scalar<'tcx>(
         (mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
             let ty = ct.ty();
             let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
-            let data = int.assert_bits(size);
-            let sign_extended_data = size.sign_extend(data) as i128;
+            let sign_extended_data = int.assert_scalar_int().to_int(size);
             let mut output = if with_underscores {
                 format_integer_with_underscore_sep(&sign_extended_data.to_string())
             } else {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 012afada1e5..78d4129f642 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -128,6 +128,8 @@ pub(crate) struct Options {
     pub(crate) enable_per_target_ignores: bool,
     /// Do not run doctests, compile them if should_test is active.
     pub(crate) no_run: bool,
+    /// What sources are being mapped.
+    pub(crate) remap_path_prefix: Vec<(PathBuf, PathBuf)>,
 
     /// The path to a rustc-like binary to build tests with. If not set, we
     /// default to loading from `$sysroot/bin/rustc`.
@@ -211,6 +213,7 @@ impl fmt::Debug for Options {
             .field("run_check", &self.run_check)
             .field("no_run", &self.no_run)
             .field("test_builder_wrappers", &self.test_builder_wrappers)
+            .field("remap-file-prefix", &self.remap_path_prefix)
             .field("nocapture", &self.nocapture)
             .field("scrape_examples_options", &self.scrape_examples_options)
             .field("unstable_features", &self.unstable_features)
@@ -372,6 +375,13 @@ impl Options {
         let codegen_options = CodegenOptions::build(early_dcx, matches);
         let unstable_opts = UnstableOptions::build(early_dcx, matches);
 
+        let remap_path_prefix = match parse_remap_path_prefix(&matches) {
+            Ok(prefix_mappings) => prefix_mappings,
+            Err(err) => {
+                early_dcx.early_fatal(err);
+            }
+        };
+
         let dcx = new_dcx(error_format, None, diagnostic_width, &unstable_opts);
 
         // check for deprecated options
@@ -772,6 +782,7 @@ impl Options {
             run_check,
             no_run,
             test_builder_wrappers,
+            remap_path_prefix,
             nocapture,
             crate_name,
             output_format,
@@ -820,6 +831,21 @@ impl Options {
     }
 }
 
+fn parse_remap_path_prefix(
+    matches: &getopts::Matches,
+) -> Result<Vec<(PathBuf, PathBuf)>, &'static str> {
+    matches
+        .opt_strs("remap-path-prefix")
+        .into_iter()
+        .map(|remap| {
+            remap
+                .rsplit_once('=')
+                .ok_or("--remap-path-prefix must contain '=' between FROM and TO")
+                .map(|(from, to)| (PathBuf::from(from), PathBuf::from(to)))
+        })
+        .collect()
+}
+
 /// Prints deprecation warnings for deprecated options
 fn check_deprecated_options(matches: &getopts::Matches, dcx: &rustc_errors::DiagCtxt) {
     let deprecated_flags = [];
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index ccd5dadb20a..ce098a1bcfb 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt(
         show_coverage,
     };
 
-    for cnum in tcx.crates_including_speculative(()) {
+    for cnum in tcx.crates(()) {
         crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id());
     }
 
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index a536a713921..81a7463deca 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1,27 +1,23 @@
+mod make;
+mod markdown;
+mod rust;
+
+pub(crate) use make::make_test;
+pub(crate) use markdown::test as test_markdown;
+
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::Lrc;
-use rustc_errors::emitter::stderr_destination;
 use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError};
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::CRATE_HIR_ID;
 use rustc_interface::interface;
-use rustc_middle::hir::map::Map;
-use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::TyCtxt;
-use rustc_parse::maybe_new_parser_from_source_str;
-use rustc_parse::parser::attr::InnerAttrPolicy;
-use rustc_resolve::rustdoc::span_of_fragments;
 use rustc_session::config::{self, CrateType, ErrorOutputType};
-use rustc_session::parse::ParseSess;
-use rustc_session::{lint, Session};
+use rustc_session::lint;
 use rustc_span::edition::Edition;
-use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
-use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
+use rustc_span::FileName;
 use rustc_target::spec::{Target, TargetTriple};
 
-use std::env;
 use std::fs::File;
 use std::io::{self, Write};
 use std::panic;
@@ -33,14 +29,17 @@ use std::sync::{Arc, Mutex};
 
 use tempfile::{Builder as TempFileBuilder, TempDir};
 
-use crate::clean::{types::AttributesExt, Attributes};
 use crate::config::Options as RustdocOptions;
-use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
+use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine};
 use crate::lint::init_lints;
 
+use self::rust::HirCollector;
+
 /// Options that apply to all doctests in a crate or Markdown file (for `rustdoc foo.md`).
-#[derive(Clone, Default)]
+#[derive(Clone)]
 pub(crate) struct GlobalTestOptions {
+    /// Name of the crate (for regular `rustdoc`) or Markdown file (for `rustdoc foo.md`).
+    pub(crate) crate_name: String,
     /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     pub(crate) no_crate_inject: bool,
     /// Whether inserting extra indent spaces in code block,
@@ -48,6 +47,8 @@ pub(crate) struct GlobalTestOptions {
     pub(crate) insert_indent_space: bool,
     /// Additional crate-level attributes to add to doctests.
     pub(crate) attrs: Vec<String>,
+    /// Path to file containing arguments for the invocation of rustc.
+    pub(crate) args_file: PathBuf,
 }
 
 pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
@@ -80,7 +81,7 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
 
     let content = content.join("\n");
 
-    file.write(content.as_bytes())
+    file.write_all(content.as_bytes())
         .map_err(|error| format!("failed to write arguments to temporary file: {error:?}"))?;
     Ok(())
 }
@@ -128,6 +129,7 @@ pub(crate) fn run(
         edition: options.edition,
         target_triple: options.target.clone(),
         crate_name: options.crate_name.clone(),
+        remap_path_prefix: options.remap_path_prefix.clone(),
         ..config::Options::default()
     };
 
@@ -166,43 +168,28 @@ pub(crate) fn run(
         Ok(temp_dir) => temp_dir,
         Err(error) => return crate::wrap_return(dcx, Err(error)),
     };
-    let file_path = temp_dir.path().join("rustdoc-cfgs");
-    crate::wrap_return(dcx, generate_args_file(&file_path, &options))?;
+    let args_path = temp_dir.path().join("rustdoc-cfgs");
+    crate::wrap_return(dcx, generate_args_file(&args_path, &options))?;
 
     let (tests, unused_extern_reports, compiling_test_count) =
         interface::run_compiler(config, |compiler| {
             compiler.enter(|queries| {
                 let collector = queries.global_ctxt()?.enter(|tcx| {
+                    let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
                     let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
-
-                    let opts = scrape_test_config(crate_attrs);
+                    let opts = scrape_test_config(crate_name, crate_attrs, args_path);
                     let enable_per_target_ignores = options.enable_per_target_ignores;
-                    let mut collector = Collector::new(
-                        tcx.crate_name(LOCAL_CRATE).to_string(),
-                        options,
-                        false,
-                        opts,
-                        Some(compiler.sess.psess.clone_source_map()),
-                        None,
-                        enable_per_target_ignores,
-                        file_path,
-                    );
 
-                    let mut hir_collector = HirCollector {
-                        sess: &compiler.sess,
-                        collector: &mut collector,
-                        map: tcx.hir(),
-                        codes: ErrorCodes::from(
-                            compiler.sess.opts.unstable_features.is_nightly_build(),
-                        ),
+                    let mut collector = CreateRunnableDoctests::new(options, opts);
+                    let hir_collector = HirCollector::new(
+                        &compiler.sess,
+                        tcx.hir(),
+                        ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()),
+                        enable_per_target_ignores,
                         tcx,
-                    };
-                    hir_collector.visit_testable(
-                        "".to_string(),
-                        CRATE_DEF_ID,
-                        tcx.hir().span(CRATE_HIR_ID),
-                        |this| tcx.hir().walk_toplevel_module(this),
                     );
+                    let tests = hir_collector.collect_crate();
+                    tests.into_iter().for_each(|t| collector.add_test(t));
 
                     collector
                 });
@@ -273,11 +260,20 @@ pub(crate) fn run_tests(
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
-fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
+fn scrape_test_config(
+    crate_name: String,
+    attrs: &[ast::Attribute],
+    args_file: PathBuf,
+) -> GlobalTestOptions {
     use rustc_ast_pretty::pprust;
 
-    let mut opts =
-        GlobalTestOptions { no_crate_inject: false, attrs: Vec::new(), insert_indent_space: false };
+    let mut opts = GlobalTestOptions {
+        crate_name,
+        no_crate_inject: false,
+        attrs: Vec::new(),
+        insert_indent_space: false,
+        args_file,
+    };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -370,30 +366,25 @@ fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Com
     command
 }
 
+struct RunnableDoctest {
+    full_test_code: String,
+    full_test_line_offset: usize,
+    test_opts: IndividualTestOptions,
+    global_opts: GlobalTestOptions,
+    scraped_test: ScrapedDoctest,
+}
+
 fn run_test(
-    test: &str,
-    crate_name: &str,
-    line: usize,
-    rustdoc_options: IndividualTestOptions,
-    mut lang_string: LangString,
-    no_run: bool,
-    opts: &GlobalTestOptions,
-    edition: Edition,
-    path: PathBuf,
+    doctest: RunnableDoctest,
+    rustdoc_options: &RustdocOptions,
+    supports_color: bool,
     report_unused_externs: impl Fn(UnusedExterns),
 ) -> Result<(), TestFailure> {
-    let (test, line_offset, supports_color) = make_test(
-        test,
-        Some(crate_name),
-        lang_string.test_harness,
-        opts,
-        edition,
-        Some(&rustdoc_options.test_id),
-    );
-
+    let scraped_test = &doctest.scraped_test;
+    let langstr = &scraped_test.langstr;
     // Make sure we emit well-formed executable names for our target.
     let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
-    let output_file = rustdoc_options.outdir.path().join(rust_out);
+    let output_file = doctest.test_opts.outdir.path().join(rust_out);
 
     let rustc_binary = rustdoc_options
         .test_builder
@@ -401,33 +392,41 @@ fn run_test(
         .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
     let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
 
-    compiler.arg(&format!("@{}", rustdoc_options.arg_file.display()));
+    compiler.arg(&format!("@{}", doctest.global_opts.args_file.display()));
 
     if let Some(sysroot) = &rustdoc_options.maybe_sysroot {
         compiler.arg(format!("--sysroot={}", sysroot.display()));
     }
 
-    compiler.arg("--edition").arg(&edition.to_string());
-    compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
-    compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
+    compiler.arg("--edition").arg(&scraped_test.edition(rustdoc_options).to_string());
+    compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
+    compiler.env(
+        "UNSTABLE_RUSTDOC_TEST_LINE",
+        format!("{}", scraped_test.line as isize - doctest.full_test_line_offset as isize),
+    );
     compiler.arg("-o").arg(&output_file);
-    if lang_string.test_harness {
+    if langstr.test_harness {
         compiler.arg("--test");
     }
-    if rustdoc_options.is_json_unused_externs_enabled && !lang_string.compile_fail {
+    if rustdoc_options.json_unused_externs.is_enabled() && !langstr.compile_fail {
         compiler.arg("--error-format=json");
         compiler.arg("--json").arg("unused-externs");
         compiler.arg("-W").arg("unused_crate_dependencies");
         compiler.arg("-Z").arg("unstable-options");
     }
 
-    if no_run && !lang_string.compile_fail && rustdoc_options.should_persist_doctests {
+    if scraped_test.no_run(rustdoc_options)
+        && !langstr.compile_fail
+        && rustdoc_options.persist_doctests.is_none()
+    {
+        // FIXME: why does this code check if it *shouldn't* persist doctests
+        //        -- shouldn't it be the negation?
         compiler.arg("--emit=metadata");
     }
-    compiler.arg("--target").arg(match rustdoc_options.target {
+    compiler.arg("--target").arg(match &rustdoc_options.target {
         TargetTriple::TargetTriple(s) => s,
         TargetTriple::TargetJson { path_for_rustdoc, .. } => {
-            path_for_rustdoc.to_str().expect("target path must be valid unicode").to_string()
+            path_for_rustdoc.to_str().expect("target path must be valid unicode")
         }
     });
     if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {
@@ -459,7 +458,7 @@ fn run_test(
     let mut child = compiler.spawn().expect("Failed to spawn rustc process");
     {
         let stdin = child.stdin.as_mut().expect("Failed to open stdin");
-        stdin.write_all(test.as_bytes()).expect("could write out test sources");
+        stdin.write_all(doctest.full_test_code.as_bytes()).expect("could write out test sources");
     }
     let output = child.wait_with_output().expect("Failed to read stdout");
 
@@ -490,20 +489,26 @@ fn run_test(
     }
 
     let _bomb = Bomb(&out);
-    match (output.status.success(), lang_string.compile_fail) {
+    match (output.status.success(), langstr.compile_fail) {
         (true, true) => {
             return Err(TestFailure::UnexpectedCompilePass);
         }
         (true, false) => {}
         (false, true) => {
-            if !lang_string.error_codes.is_empty() {
+            if !langstr.error_codes.is_empty() {
                 // We used to check if the output contained "error[{}]: " but since we added the
                 // colored output, we can't anymore because of the color escape characters before
                 // the ":".
-                lang_string.error_codes.retain(|err| !out.contains(&format!("error[{err}]")));
-
-                if !lang_string.error_codes.is_empty() {
-                    return Err(TestFailure::MissingErrorCodes(lang_string.error_codes));
+                let missing_codes: Vec<String> = scraped_test
+                    .langstr
+                    .error_codes
+                    .iter()
+                    .filter(|err| !out.contains(&format!("error[{err}]")))
+                    .cloned()
+                    .collect();
+
+                if !missing_codes.is_empty() {
+                    return Err(TestFailure::MissingErrorCodes(missing_codes));
                 }
             }
         }
@@ -512,7 +517,7 @@ fn run_test(
         }
     }
 
-    if no_run {
+    if scraped_test.no_run(rustdoc_options) {
         return Ok(());
     }
 
@@ -520,15 +525,15 @@ fn run_test(
     let mut cmd;
 
     let output_file = make_maybe_absolute_path(output_file);
-    if let Some(tool) = rustdoc_options.runtool {
+    if let Some(tool) = &rustdoc_options.runtool {
         let tool = make_maybe_absolute_path(tool.into());
         cmd = Command::new(tool);
-        cmd.args(rustdoc_options.runtool_args);
+        cmd.args(&rustdoc_options.runtool_args);
         cmd.arg(output_file);
     } else {
         cmd = Command::new(output_file);
     }
-    if let Some(run_directory) = rustdoc_options.test_run_directory {
+    if let Some(run_directory) = &rustdoc_options.test_run_directory {
         cmd.current_dir(run_directory);
     }
 
@@ -544,9 +549,9 @@ fn run_test(
     match result {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
         Ok(out) => {
-            if lang_string.should_panic && out.status.success() {
+            if langstr.should_panic && out.status.success() {
                 return Err(TestFailure::UnexpectedRunPass);
-            } else if !lang_string.should_panic && !out.status.success() {
+            } else if !langstr.should_panic && !out.status.success() {
                 return Err(TestFailure::ExecutionFailure(out));
             }
         }
@@ -568,389 +573,14 @@ fn make_maybe_absolute_path(path: PathBuf) -> PathBuf {
         std::env::current_dir().map(|c| c.join(&path)).unwrap_or_else(|_| path)
     }
 }
-
-/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
-/// lines before the test code begins as well as if the output stream supports colors or not.
-pub(crate) fn make_test(
-    s: &str,
-    crate_name: Option<&str>,
-    dont_insert_main: bool,
-    opts: &GlobalTestOptions,
-    edition: Edition,
-    test_id: Option<&str>,
-) -> (String, usize, bool) {
-    let (crate_attrs, everything_else, crates) = partition_source(s, edition);
-    let everything_else = everything_else.trim();
-    let mut line_offset = 0;
-    let mut prog = String::new();
-    let mut supports_color = false;
-
-    if opts.attrs.is_empty() {
-        // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
-        // lints that are commonly triggered in doctests. The crate-level test attributes are
-        // commonly used to make tests fail in case they trigger warnings, so having this there in
-        // that case may cause some tests to pass when they shouldn't have.
-        prog.push_str("#![allow(unused)]\n");
-        line_offset += 1;
-    }
-
-    // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
-    for attr in &opts.attrs {
-        prog.push_str(&format!("#![{attr}]\n"));
-        line_offset += 1;
-    }
-
-    // Now push any outer attributes from the example, assuming they
-    // are intended to be crate attributes.
-    prog.push_str(&crate_attrs);
-    prog.push_str(&crates);
-
-    // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
-    // crate already is included.
-    let result = rustc_driver::catch_fatal_errors(|| {
-        rustc_span::create_session_if_not_set_then(edition, |_| {
-            use rustc_errors::emitter::{Emitter, HumanEmitter};
-            use rustc_errors::DiagCtxt;
-            use rustc_parse::parser::ForceCollect;
-            use rustc_span::source_map::FilePathMapping;
-
-            let filename = FileName::anon_source_code(s);
-            let source = crates + everything_else;
-
-            // Any errors in parsing should also appear when the doctest is compiled for real, so just
-            // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
-            let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-                false,
-            );
-            supports_color =
-                HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone())
-                    .supports_color();
-
-            let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
-
-            // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
-            let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
-            let psess = ParseSess::with_dcx(dcx, sm);
-
-            let mut found_main = false;
-            let mut found_extern_crate = crate_name.is_none();
-            let mut found_macro = false;
-
-            let mut parser = match maybe_new_parser_from_source_str(&psess, filename, source) {
-                Ok(p) => p,
-                Err(errs) => {
-                    errs.into_iter().for_each(|err| err.cancel());
-                    return (found_main, found_extern_crate, found_macro);
-                }
-            };
-
-            loop {
-                match parser.parse_item(ForceCollect::No) {
-                    Ok(Some(item)) => {
-                        if !found_main
-                            && let ast::ItemKind::Fn(..) = item.kind
-                            && item.ident.name == sym::main
-                        {
-                            found_main = true;
-                        }
-
-                        if !found_extern_crate
-                            && let ast::ItemKind::ExternCrate(original) = item.kind
-                        {
-                            // This code will never be reached if `crate_name` is none because
-                            // `found_extern_crate` is initialized to `true` if it is none.
-                            let crate_name = crate_name.unwrap();
-
-                            match original {
-                                Some(name) => found_extern_crate = name.as_str() == crate_name,
-                                None => found_extern_crate = item.ident.as_str() == crate_name,
-                            }
-                        }
-
-                        if !found_macro && let ast::ItemKind::MacCall(..) = item.kind {
-                            found_macro = true;
-                        }
-
-                        if found_main && found_extern_crate {
-                            break;
-                        }
-                    }
-                    Ok(None) => break,
-                    Err(e) => {
-                        e.cancel();
-                        break;
-                    }
-                }
-
-                // The supplied item is only used for diagnostics,
-                // which are swallowed here anyway.
-                parser.maybe_consume_incorrect_semicolon(None);
-            }
-
-            // Reset errors so that they won't be reported as compiler bugs when dropping the
-            // dcx. Any errors in the tests will be reported when the test file is compiled,
-            // Note that we still need to cancel the errors above otherwise `Diag` will panic on
-            // drop.
-            psess.dcx.reset_err_count();
-
-            (found_main, found_extern_crate, found_macro)
-        })
-    });
-    let Ok((already_has_main, already_has_extern_crate, found_macro)) = result else {
-        // If the parser panicked due to a fatal error, pass the test code through unchanged.
-        // The error will be reported during compilation.
-        return (s.to_owned(), 0, false);
-    };
-
-    // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
-    // see it. In that case, run the old text-based scan to see if they at least have a main
-    // function written inside a macro invocation. See
-    // https://github.com/rust-lang/rust/issues/56898
-    let already_has_main = if found_macro && !already_has_main {
-        s.lines()
-            .map(|line| {
-                let comment = line.find("//");
-                if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line }
-            })
-            .any(|code| code.contains("fn main"))
-    } else {
-        already_has_main
-    };
-
-    // Don't inject `extern crate std` because it's already injected by the
-    // compiler.
-    if !already_has_extern_crate && !opts.no_crate_inject && crate_name != Some("std") {
-        if let Some(crate_name) = crate_name {
-            // Don't inject `extern crate` if the crate is never used.
-            // NOTE: this is terribly inaccurate because it doesn't actually
-            // parse the source, but only has false positives, not false
-            // negatives.
-            if s.contains(crate_name) {
-                // rustdoc implicitly inserts an `extern crate` item for the own crate
-                // which may be unused, so we need to allow the lint.
-                prog.push_str("#[allow(unused_extern_crates)]\n");
-
-                prog.push_str(&format!("extern crate r#{crate_name};\n"));
-                line_offset += 1;
-            }
-        }
-    }
-
-    // FIXME: This code cannot yet handle no_std test cases yet
-    if dont_insert_main || already_has_main || prog.contains("![no_std]") {
-        prog.push_str(everything_else);
-    } else {
-        let returns_result = everything_else.trim_end().ends_with("(())");
-        // Give each doctest main function a unique name.
-        // This is for example needed for the tooling around `-C instrument-coverage`.
-        let inner_fn_name = if let Some(test_id) = test_id {
-            format!("_doctest_main_{test_id}")
-        } else {
-            "_inner".into()
-        };
-        let inner_attr = if test_id.is_some() { "#[allow(non_snake_case)] " } else { "" };
-        let (main_pre, main_post) = if returns_result {
-            (
-                format!(
-                    "fn main() {{ {inner_attr}fn {inner_fn_name}() -> Result<(), impl core::fmt::Debug> {{\n",
-                ),
-                format!("\n}} {inner_fn_name}().unwrap() }}"),
-            )
-        } else if test_id.is_some() {
-            (
-                format!("fn main() {{ {inner_attr}fn {inner_fn_name}() {{\n",),
-                format!("\n}} {inner_fn_name}() }}"),
-            )
-        } else {
-            ("fn main() {\n".into(), "\n}".into())
-        };
-        // Note on newlines: We insert a line/newline *before*, and *after*
-        // the doctest and adjust the `line_offset` accordingly.
-        // In the case of `-C instrument-coverage`, this means that the generated
-        // inner `main` function spans from the doctest opening codeblock to the
-        // closing one. For example
-        // /// ``` <- start of the inner main
-        // /// <- code under doctest
-        // /// ``` <- end of the inner main
-        line_offset += 1;
-
-        // add extra 4 spaces for each line to offset the code block
-        let content = if opts.insert_indent_space {
-            everything_else
-                .lines()
-                .map(|line| format!("    {}", line))
-                .collect::<Vec<String>>()
-                .join("\n")
-        } else {
-            everything_else.to_string()
-        };
-        prog.extend([&main_pre, content.as_str(), &main_post].iter().cloned());
-    }
-
-    debug!("final doctest:\n{prog}");
-
-    (prog, line_offset, supports_color)
-}
-
-fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
-    if source.is_empty() {
-        // Empty content so nothing to check in here...
-        return true;
-    }
-    rustc_driver::catch_fatal_errors(|| {
-        rustc_span::create_session_if_not_set_then(edition, |_| {
-            use rustc_errors::emitter::HumanEmitter;
-            use rustc_errors::DiagCtxt;
-            use rustc_span::source_map::FilePathMapping;
-
-            let filename = FileName::anon_source_code(source);
-            // Any errors in parsing should also appear when the doctest is compiled for real, so just
-            // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
-            let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-                false,
-            );
-
-            let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
-
-            let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
-            let psess = ParseSess::with_dcx(dcx, sm);
-            let mut parser =
-                match maybe_new_parser_from_source_str(&psess, filename, source.to_owned()) {
-                    Ok(p) => p,
-                    Err(errs) => {
-                        errs.into_iter().for_each(|err| err.cancel());
-                        // If there is an unclosed delimiter, an error will be returned by the
-                        // tokentrees.
-                        return false;
-                    }
-                };
-            // If a parsing error happened, it's very likely that the attribute is incomplete.
-            if let Err(e) = parser.parse_attribute(InnerAttrPolicy::Permitted) {
-                e.cancel();
-                return false;
-            }
-            true
-        })
-    })
-    .unwrap_or(false)
-}
-
-fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
-    #[derive(Copy, Clone, PartialEq)]
-    enum PartitionState {
-        Attrs,
-        Crates,
-        Other,
-    }
-    let mut state = PartitionState::Attrs;
-    let mut before = String::new();
-    let mut crates = String::new();
-    let mut after = String::new();
-
-    let mut mod_attr_pending = String::new();
-
-    for line in s.lines() {
-        let trimline = line.trim();
-
-        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
-        // shunted into "everything else"
-        match state {
-            PartitionState::Attrs => {
-                state = if trimline.starts_with("#![") {
-                    if !check_if_attr_is_complete(line, edition) {
-                        mod_attr_pending = line.to_owned();
-                    } else {
-                        mod_attr_pending.clear();
-                    }
-                    PartitionState::Attrs
-                } else if trimline.chars().all(|c| c.is_whitespace())
-                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
-                {
-                    PartitionState::Attrs
-                } else if trimline.starts_with("extern crate")
-                    || trimline.starts_with("#[macro_use] extern crate")
-                {
-                    PartitionState::Crates
-                } else {
-                    // First we check if the previous attribute was "complete"...
-                    if !mod_attr_pending.is_empty() {
-                        // If not, then we append the new line into the pending attribute to check
-                        // if this time it's complete...
-                        mod_attr_pending.push_str(line);
-                        if !trimline.is_empty()
-                            && check_if_attr_is_complete(&mod_attr_pending, edition)
-                        {
-                            // If it's complete, then we can clear the pending content.
-                            mod_attr_pending.clear();
-                        }
-                        // In any case, this is considered as `PartitionState::Attrs` so it's
-                        // prepended before rustdoc's inserts.
-                        PartitionState::Attrs
-                    } else {
-                        PartitionState::Other
-                    }
-                };
-            }
-            PartitionState::Crates => {
-                state = if trimline.starts_with("extern crate")
-                    || trimline.starts_with("#[macro_use] extern crate")
-                    || trimline.chars().all(|c| c.is_whitespace())
-                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
-                {
-                    PartitionState::Crates
-                } else {
-                    PartitionState::Other
-                };
-            }
-            PartitionState::Other => {}
-        }
-
-        match state {
-            PartitionState::Attrs => {
-                before.push_str(line);
-                before.push('\n');
-            }
-            PartitionState::Crates => {
-                crates.push_str(line);
-                crates.push('\n');
-            }
-            PartitionState::Other => {
-                after.push_str(line);
-                after.push('\n');
-            }
-        }
-    }
-
-    debug!("before:\n{before}");
-    debug!("crates:\n{crates}");
-    debug!("after:\n{after}");
-
-    (before, after, crates)
-}
-
-pub(crate) struct IndividualTestOptions {
-    test_builder: Option<PathBuf>,
-    test_builder_wrappers: Vec<PathBuf>,
-    is_json_unused_externs_enabled: bool,
-    should_persist_doctests: bool,
-    error_format: ErrorOutputType,
-    test_run_directory: Option<PathBuf>,
-    nocapture: bool,
-    arg_file: PathBuf,
+struct IndividualTestOptions {
     outdir: DirState,
-    runtool: Option<String>,
-    runtool_args: Vec<String>,
-    target: TargetTriple,
     test_id: String,
-    maybe_sysroot: Option<PathBuf>,
+    path: PathBuf,
 }
 
 impl IndividualTestOptions {
-    fn new(options: &RustdocOptions, arg_file: &Path, test_id: String) -> Self {
+    fn new(options: &RustdocOptions, test_id: String, test_path: PathBuf) -> Self {
         let outdir = if let Some(ref path) = options.persist_doctests {
             let mut path = path.clone();
             path.push(&test_id);
@@ -965,148 +595,75 @@ impl IndividualTestOptions {
             DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir"))
         };
 
-        Self {
-            test_builder: options.test_builder.clone(),
-            test_builder_wrappers: options.test_builder_wrappers.clone(),
-            is_json_unused_externs_enabled: options.json_unused_externs.is_enabled(),
-            should_persist_doctests: options.persist_doctests.is_none(),
-            error_format: options.error_format,
-            test_run_directory: options.test_run_directory.clone(),
-            nocapture: options.nocapture,
-            arg_file: arg_file.into(),
-            outdir,
-            runtool: options.runtool.clone(),
-            runtool_args: options.runtool_args.clone(),
-            target: options.target.clone(),
-            test_id,
-            maybe_sysroot: options.maybe_sysroot.clone(),
-        }
+        Self { outdir, test_id, path: test_path }
     }
 }
 
-pub(crate) trait Tester {
-    fn add_test(&mut self, test: String, config: LangString, line: usize);
-    fn get_line(&self) -> usize {
-        0
+/// A doctest scraped from the code, ready to be turned into a runnable test.
+struct ScrapedDoctest {
+    filename: FileName,
+    line: usize,
+    logical_path: Vec<String>,
+    langstr: LangString,
+    text: String,
+}
+
+impl ScrapedDoctest {
+    fn edition(&self, opts: &RustdocOptions) -> Edition {
+        self.langstr.edition.unwrap_or(opts.edition)
+    }
+
+    fn no_run(&self, opts: &RustdocOptions) -> bool {
+        self.langstr.no_run || opts.no_run
     }
-    fn register_header(&mut self, _name: &str, _level: u32) {}
 }
 
-pub(crate) struct Collector {
-    pub(crate) tests: Vec<test::TestDescAndFn>,
-
-    // The name of the test displayed to the user, separated by `::`.
-    //
-    // In tests from Rust source, this is the path to the item
-    // e.g., `["std", "vec", "Vec", "push"]`.
-    //
-    // In tests from a markdown file, this is the titles of all headers (h1~h6)
-    // of the sections that contain the code block, e.g., if the markdown file is
-    // written as:
-    //
-    // ``````markdown
-    // # Title
-    //
-    // ## Subtitle
-    //
-    // ```rust
-    // assert!(true);
-    // ```
-    // ``````
-    //
-    // the `names` vector of that test will be `["Title", "Subtitle"]`.
-    names: Vec<String>,
-
-    rustdoc_options: RustdocOptions,
-    use_headers: bool,
-    enable_per_target_ignores: bool,
-    crate_name: String,
+pub(crate) trait DoctestVisitor {
+    fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine);
+    fn visit_header(&mut self, _name: &str, _level: u32) {}
+}
+
+struct CreateRunnableDoctests {
+    tests: Vec<test::TestDescAndFn>,
+
+    rustdoc_options: Arc<RustdocOptions>,
     opts: GlobalTestOptions,
-    position: Span,
-    source_map: Option<Lrc<SourceMap>>,
-    filename: Option<PathBuf>,
     visited_tests: FxHashMap<(String, usize), usize>,
     unused_extern_reports: Arc<Mutex<Vec<UnusedExterns>>>,
     compiling_test_count: AtomicUsize,
-    arg_file: PathBuf,
 }
 
-impl Collector {
-    pub(crate) fn new(
-        crate_name: String,
-        rustdoc_options: RustdocOptions,
-        use_headers: bool,
-        opts: GlobalTestOptions,
-        source_map: Option<Lrc<SourceMap>>,
-        filename: Option<PathBuf>,
-        enable_per_target_ignores: bool,
-        arg_file: PathBuf,
-    ) -> Collector {
-        Collector {
+impl CreateRunnableDoctests {
+    fn new(rustdoc_options: RustdocOptions, opts: GlobalTestOptions) -> CreateRunnableDoctests {
+        CreateRunnableDoctests {
             tests: Vec::new(),
-            names: Vec::new(),
-            rustdoc_options,
-            use_headers,
-            enable_per_target_ignores,
-            crate_name,
+            rustdoc_options: Arc::new(rustdoc_options),
             opts,
-            position: DUMMY_SP,
-            source_map,
-            filename,
             visited_tests: FxHashMap::default(),
             unused_extern_reports: Default::default(),
             compiling_test_count: AtomicUsize::new(0),
-            arg_file,
         }
     }
 
-    fn generate_name(&self, line: usize, filename: &FileName) -> String {
-        let mut item_path = self.names.join("::");
+    fn generate_name(&self, filename: &FileName, line: usize, logical_path: &[String]) -> String {
+        let mut item_path = logical_path.join("::");
         item_path.retain(|c| c != ' ');
         if !item_path.is_empty() {
             item_path.push(' ');
         }
-        format!("{} - {item_path}(line {line})", filename.prefer_local())
-    }
-
-    pub(crate) fn set_position(&mut self, position: Span) {
-        self.position = position;
-    }
-
-    fn get_filename(&self) -> FileName {
-        if let Some(ref source_map) = self.source_map {
-            let filename = source_map.span_to_filename(self.position);
-            if let FileName::Real(ref filename) = filename
-                && let Ok(cur_dir) = env::current_dir()
-                && let Some(local_path) = filename.local_path()
-                && let Ok(path) = local_path.strip_prefix(&cur_dir)
-            {
-                return path.to_owned().into();
-            }
-            filename
-        } else if let Some(ref filename) = self.filename {
-            filename.clone().into()
-        } else {
-            FileName::Custom("input".to_owned())
-        }
+        format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly())
     }
-}
 
-impl Tester for Collector {
-    fn add_test(&mut self, test: String, config: LangString, line: usize) {
-        let filename = self.get_filename();
-        let name = self.generate_name(line, &filename);
-        let crate_name = self.crate_name.clone();
+    fn add_test(&mut self, test: ScrapedDoctest) {
+        let name = self.generate_name(&test.filename, test.line, &test.logical_path);
         let opts = self.opts.clone();
-        let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
         let target_str = self.rustdoc_options.target.to_string();
         let unused_externs = self.unused_extern_reports.clone();
-        let no_run = config.no_run || self.rustdoc_options.no_run;
-        if !config.compile_fail {
+        if !test.langstr.compile_fail {
             self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
         }
 
-        let path = match &filename {
+        let path = match &test.filename {
             FileName::Real(path) => {
                 if let Some(local_path) = path.local_path() {
                     local_path.to_path_buf()
@@ -1119,7 +676,8 @@ impl Tester for Collector {
         };
 
         // For example `module/file.rs` would become `module_file_rs`
-        let file = filename
+        let file = test
+            .filename
             .prefer_local()
             .to_string_lossy()
             .chars()
@@ -1128,22 +686,25 @@ impl Tester for Collector {
         let test_id = format!(
             "{file}_{line}_{number}",
             file = file,
-            line = line,
+            line = test.line,
             number = {
                 // Increases the current test number, if this file already
                 // exists or it creates a new entry with a test number of 0.
-                self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
+                self.visited_tests
+                    .entry((file.clone(), test.line))
+                    .and_modify(|v| *v += 1)
+                    .or_insert(0)
             },
         );
 
-        let rustdoc_test_options =
-            IndividualTestOptions::new(&self.rustdoc_options, &self.arg_file, test_id);
+        let rustdoc_options = self.rustdoc_options.clone();
+        let rustdoc_test_options = IndividualTestOptions::new(&self.rustdoc_options, test_id, path);
 
-        debug!("creating test {name}: {test}");
+        debug!("creating test {name}: {}", test.text);
         self.tests.push(test::TestDescAndFn {
             desc: test::TestDesc {
                 name: test::DynTestName(name),
-                ignore: match config.ignore {
+                ignore: match test.langstr.ignore {
                     Ignore::All => true,
                     Ignore::None => false,
                     Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)),
@@ -1156,252 +717,103 @@ impl Tester for Collector {
                 end_col: 0,
                 // compiler failures are test failures
                 should_panic: test::ShouldPanic::No,
-                compile_fail: config.compile_fail,
-                no_run,
+                compile_fail: test.langstr.compile_fail,
+                no_run: test.no_run(&rustdoc_options),
                 test_type: test::TestType::DocTest,
             },
             testfn: test::DynTestFn(Box::new(move || {
-                let report_unused_externs = |uext| {
-                    unused_externs.lock().unwrap().push(uext);
-                };
-                let res = run_test(
-                    &test,
-                    &crate_name,
-                    line,
-                    rustdoc_test_options,
-                    config,
-                    no_run,
-                    &opts,
-                    edition,
-                    path,
-                    report_unused_externs,
-                );
-
-                if let Err(err) = res {
-                    match err {
-                        TestFailure::CompileError => {
-                            eprint!("Couldn't compile the test.");
-                        }
-                        TestFailure::UnexpectedCompilePass => {
-                            eprint!("Test compiled successfully, but it's marked `compile_fail`.");
-                        }
-                        TestFailure::UnexpectedRunPass => {
-                            eprint!("Test executable succeeded, but it's marked `should_panic`.");
-                        }
-                        TestFailure::MissingErrorCodes(codes) => {
-                            eprint!("Some expected error codes were not found: {codes:?}");
-                        }
-                        TestFailure::ExecutionError(err) => {
-                            eprint!("Couldn't run the test: {err}");
-                            if err.kind() == io::ErrorKind::PermissionDenied {
-                                eprint!(" - maybe your tempdir is mounted with noexec?");
-                            }
-                        }
-                        TestFailure::ExecutionFailure(out) => {
-                            eprintln!("Test executable failed ({reason}).", reason = out.status);
-
-                            // FIXME(#12309): An unfortunate side-effect of capturing the test
-                            // executable's output is that the relative ordering between the test's
-                            // stdout and stderr is lost. However, this is better than the
-                            // alternative: if the test executable inherited the parent's I/O
-                            // handles the output wouldn't be captured at all, even on success.
-                            //
-                            // The ordering could be preserved if the test process' stderr was
-                            // redirected to stdout, but that functionality does not exist in the
-                            // standard library, so it may not be portable enough.
-                            let stdout = str::from_utf8(&out.stdout).unwrap_or_default();
-                            let stderr = str::from_utf8(&out.stderr).unwrap_or_default();
-
-                            if !stdout.is_empty() || !stderr.is_empty() {
-                                eprintln!();
-
-                                if !stdout.is_empty() {
-                                    eprintln!("stdout:\n{stdout}");
-                                }
-
-                                if !stderr.is_empty() {
-                                    eprintln!("stderr:\n{stderr}");
-                                }
-                            }
-                        }
-                    }
-
-                    panic::resume_unwind(Box::new(()));
-                }
-                Ok(())
+                doctest_run_fn(rustdoc_test_options, opts, test, rustdoc_options, unused_externs)
             })),
         });
     }
+}
 
-    fn get_line(&self) -> usize {
-        if let Some(ref source_map) = self.source_map {
-            let line = self.position.lo().to_usize();
-            let line = source_map.lookup_char_pos(BytePos(line as u32)).line;
-            if line > 0 { line - 1 } else { line }
-        } else {
-            0
-        }
-    }
+fn doctest_run_fn(
+    test_opts: IndividualTestOptions,
+    global_opts: GlobalTestOptions,
+    scraped_test: ScrapedDoctest,
+    rustdoc_options: Arc<RustdocOptions>,
+    unused_externs: Arc<Mutex<Vec<UnusedExterns>>>,
+) -> Result<(), String> {
+    let report_unused_externs = |uext| {
+        unused_externs.lock().unwrap().push(uext);
+    };
+    let edition = scraped_test.edition(&rustdoc_options);
+    let (full_test_code, full_test_line_offset, supports_color) = make_test(
+        &scraped_test.text,
+        Some(&global_opts.crate_name),
+        scraped_test.langstr.test_harness,
+        &global_opts,
+        edition,
+        Some(&test_opts.test_id),
+    );
+    let runnable_test = RunnableDoctest {
+        full_test_code,
+        full_test_line_offset,
+        test_opts,
+        global_opts,
+        scraped_test,
+    };
+    let res = run_test(runnable_test, &rustdoc_options, supports_color, report_unused_externs);
 
-    fn register_header(&mut self, name: &str, level: u32) {
-        if self.use_headers {
-            // We use these headings as test names, so it's good if
-            // they're valid identifiers.
-            let name = name
-                .chars()
-                .enumerate()
-                .map(|(i, c)| {
-                    if (i == 0 && rustc_lexer::is_id_start(c))
-                        || (i != 0 && rustc_lexer::is_id_continue(c))
-                    {
-                        c
-                    } else {
-                        '_'
-                    }
-                })
-                .collect::<String>();
-
-            // Here we try to efficiently assemble the header titles into the
-            // test name in the form of `h1::h2::h3::h4::h5::h6`.
-            //
-            // Suppose that originally `self.names` contains `[h1, h2, h3]`...
-            let level = level as usize;
-            if level <= self.names.len() {
-                // ... Consider `level == 2`. All headers in the lower levels
-                // are irrelevant in this new level. So we should reset
-                // `self.names` to contain headers until <h2>, and replace that
-                // slot with the new name: `[h1, name]`.
-                self.names.truncate(level);
-                self.names[level - 1] = name;
-            } else {
-                // ... On the other hand, consider `level == 5`. This means we
-                // need to extend `self.names` to contain five headers. We fill
-                // in the missing level (<h4>) with `_`. Thus `self.names` will
-                // become `[h1, h2, h3, "_", name]`.
-                if level - 1 > self.names.len() {
-                    self.names.resize(level - 1, "_".to_owned());
+    if let Err(err) = res {
+        match err {
+            TestFailure::CompileError => {
+                eprint!("Couldn't compile the test.");
+            }
+            TestFailure::UnexpectedCompilePass => {
+                eprint!("Test compiled successfully, but it's marked `compile_fail`.");
+            }
+            TestFailure::UnexpectedRunPass => {
+                eprint!("Test executable succeeded, but it's marked `should_panic`.");
+            }
+            TestFailure::MissingErrorCodes(codes) => {
+                eprint!("Some expected error codes were not found: {codes:?}");
+            }
+            TestFailure::ExecutionError(err) => {
+                eprint!("Couldn't run the test: {err}");
+                if err.kind() == io::ErrorKind::PermissionDenied {
+                    eprint!(" - maybe your tempdir is mounted with noexec?");
                 }
-                self.names.push(name);
             }
-        }
-    }
-}
-
-#[cfg(test)] // used in tests
-impl Tester for Vec<usize> {
-    fn add_test(&mut self, _test: String, _config: LangString, line: usize) {
-        self.push(line);
-    }
-}
-
-struct HirCollector<'a, 'hir, 'tcx> {
-    sess: &'a Session,
-    collector: &'a mut Collector,
-    map: Map<'hir>,
-    codes: ErrorCodes,
-    tcx: TyCtxt<'tcx>,
-}
+            TestFailure::ExecutionFailure(out) => {
+                eprintln!("Test executable failed ({reason}).", reason = out.status);
+
+                // FIXME(#12309): An unfortunate side-effect of capturing the test
+                // executable's output is that the relative ordering between the test's
+                // stdout and stderr is lost. However, this is better than the
+                // alternative: if the test executable inherited the parent's I/O
+                // handles the output wouldn't be captured at all, even on success.
+                //
+                // The ordering could be preserved if the test process' stderr was
+                // redirected to stdout, but that functionality does not exist in the
+                // standard library, so it may not be portable enough.
+                let stdout = str::from_utf8(&out.stdout).unwrap_or_default();
+                let stderr = str::from_utf8(&out.stderr).unwrap_or_default();
+
+                if !stdout.is_empty() || !stderr.is_empty() {
+                    eprintln!();
+
+                    if !stdout.is_empty() {
+                        eprintln!("stdout:\n{stdout}");
+                    }
 
-impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
-    fn visit_testable<F: FnOnce(&mut Self)>(
-        &mut self,
-        name: String,
-        def_id: LocalDefId,
-        sp: Span,
-        nested: F,
-    ) {
-        let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
-        if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
-            if !cfg.matches(&self.sess.psess, Some(self.tcx.features())) {
-                return;
+                    if !stderr.is_empty() {
+                        eprintln!("stderr:\n{stderr}");
+                    }
+                }
             }
         }
 
-        let has_name = !name.is_empty();
-        if has_name {
-            self.collector.names.push(name);
-        }
-
-        // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
-        // anything else, this will combine them for us.
-        let attrs = Attributes::from_ast(ast_attrs);
-        if let Some(doc) = attrs.opt_doc_value() {
-            // Use the outermost invocation, so that doctest names come from where the docs were written.
-            let span = ast_attrs
-                .iter()
-                .find(|attr| attr.doc_str().is_some())
-                .map(|attr| attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span))
-                .unwrap_or(DUMMY_SP);
-            self.collector.set_position(span);
-            markdown::find_testable_code(
-                &doc,
-                self.collector,
-                self.codes,
-                self.collector.enable_per_target_ignores,
-                Some(&crate::html::markdown::ExtraInfo::new(
-                    self.tcx,
-                    def_id.to_def_id(),
-                    span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
-                )),
-            );
-        }
-
-        nested(self);
-
-        if has_name {
-            self.collector.names.pop();
-        }
+        panic::resume_unwind(Box::new(()));
     }
+    Ok(())
 }
 
-impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.map
-    }
-
-    fn visit_item(&mut self, item: &'hir hir::Item<'_>) {
-        let name = match &item.kind {
-            hir::ItemKind::Impl(impl_) => {
-                rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
-            }
-            _ => item.ident.to_string(),
-        };
-
-        self.visit_testable(name, item.owner_id.def_id, item.span, |this| {
-            intravisit::walk_item(this, item);
-        });
-    }
-
-    fn visit_trait_item(&mut self, item: &'hir hir::TraitItem<'_>) {
-        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
-            intravisit::walk_trait_item(this, item);
-        });
-    }
-
-    fn visit_impl_item(&mut self, item: &'hir hir::ImplItem<'_>) {
-        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
-            intravisit::walk_impl_item(this, item);
-        });
-    }
-
-    fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem<'_>) {
-        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
-            intravisit::walk_foreign_item(this, item);
-        });
-    }
-
-    fn visit_variant(&mut self, v: &'hir hir::Variant<'_>) {
-        self.visit_testable(v.ident.to_string(), v.def_id, v.span, |this| {
-            intravisit::walk_variant(this, v);
-        });
-    }
-
-    fn visit_field_def(&mut self, f: &'hir hir::FieldDef<'_>) {
-        self.visit_testable(f.ident.to_string(), f.def_id, f.span, |this| {
-            intravisit::walk_field_def(this, f);
-        });
+#[cfg(test)] // used in tests
+impl DoctestVisitor for Vec<usize> {
+    fn visit_test(&mut self, _test: String, _config: LangString, rel_line: MdRelLine) {
+        self.push(1 + rel_line.offset());
     }
 }
 
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
new file mode 100644
index 00000000000..599611407ed
--- /dev/null
+++ b/src/librustdoc/doctest/make.rs
@@ -0,0 +1,393 @@
+//! Logic for transforming the raw code given by the user into something actually
+//! runnable, e.g. by adding a `main` function if it doesn't already exist.
+
+use std::io;
+
+use rustc_ast as ast;
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::emitter::stderr_destination;
+use rustc_errors::{ColorConfig, FatalError};
+use rustc_parse::new_parser_from_source_str;
+use rustc_parse::parser::attr::InnerAttrPolicy;
+use rustc_session::parse::ParseSess;
+use rustc_span::edition::Edition;
+use rustc_span::source_map::SourceMap;
+use rustc_span::symbol::sym;
+use rustc_span::FileName;
+
+use super::GlobalTestOptions;
+
+/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
+/// lines before the test code begins as well as if the output stream supports colors or not.
+pub(crate) fn make_test(
+    s: &str,
+    crate_name: Option<&str>,
+    dont_insert_main: bool,
+    opts: &GlobalTestOptions,
+    edition: Edition,
+    test_id: Option<&str>,
+) -> (String, usize, bool) {
+    let (crate_attrs, everything_else, crates) = partition_source(s, edition);
+    let everything_else = everything_else.trim();
+    let mut line_offset = 0;
+    let mut prog = String::new();
+    let mut supports_color = false;
+
+    if opts.attrs.is_empty() {
+        // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
+        // lints that are commonly triggered in doctests. The crate-level test attributes are
+        // commonly used to make tests fail in case they trigger warnings, so having this there in
+        // that case may cause some tests to pass when they shouldn't have.
+        prog.push_str("#![allow(unused)]\n");
+        line_offset += 1;
+    }
+
+    // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
+    for attr in &opts.attrs {
+        prog.push_str(&format!("#![{attr}]\n"));
+        line_offset += 1;
+    }
+
+    // Now push any outer attributes from the example, assuming they
+    // are intended to be crate attributes.
+    prog.push_str(&crate_attrs);
+    prog.push_str(&crates);
+
+    // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
+    // crate already is included.
+    let Ok((already_has_main, already_has_extern_crate)) =
+        check_for_main_and_extern_crate(crate_name, s.to_owned(), edition, &mut supports_color)
+    else {
+        // If the parser panicked due to a fatal error, pass the test code through unchanged.
+        // The error will be reported during compilation.
+        return (s.to_owned(), 0, false);
+    };
+
+    // Don't inject `extern crate std` because it's already injected by the
+    // compiler.
+    if !already_has_extern_crate && !opts.no_crate_inject && crate_name != Some("std") {
+        if let Some(crate_name) = crate_name {
+            // Don't inject `extern crate` if the crate is never used.
+            // NOTE: this is terribly inaccurate because it doesn't actually
+            // parse the source, but only has false positives, not false
+            // negatives.
+            if s.contains(crate_name) {
+                // rustdoc implicitly inserts an `extern crate` item for the own crate
+                // which may be unused, so we need to allow the lint.
+                prog.push_str("#[allow(unused_extern_crates)]\n");
+
+                prog.push_str(&format!("extern crate r#{crate_name};\n"));
+                line_offset += 1;
+            }
+        }
+    }
+
+    // FIXME: This code cannot yet handle no_std test cases yet
+    if dont_insert_main || already_has_main || prog.contains("![no_std]") {
+        prog.push_str(everything_else);
+    } else {
+        let returns_result = everything_else.trim_end().ends_with("(())");
+        // Give each doctest main function a unique name.
+        // This is for example needed for the tooling around `-C instrument-coverage`.
+        let inner_fn_name = if let Some(test_id) = test_id {
+            format!("_doctest_main_{test_id}")
+        } else {
+            "_inner".into()
+        };
+        let inner_attr = if test_id.is_some() { "#[allow(non_snake_case)] " } else { "" };
+        let (main_pre, main_post) = if returns_result {
+            (
+                format!(
+                    "fn main() {{ {inner_attr}fn {inner_fn_name}() -> Result<(), impl core::fmt::Debug> {{\n",
+                ),
+                format!("\n}} {inner_fn_name}().unwrap() }}"),
+            )
+        } else if test_id.is_some() {
+            (
+                format!("fn main() {{ {inner_attr}fn {inner_fn_name}() {{\n",),
+                format!("\n}} {inner_fn_name}() }}"),
+            )
+        } else {
+            ("fn main() {\n".into(), "\n}".into())
+        };
+        // Note on newlines: We insert a line/newline *before*, and *after*
+        // the doctest and adjust the `line_offset` accordingly.
+        // In the case of `-C instrument-coverage`, this means that the generated
+        // inner `main` function spans from the doctest opening codeblock to the
+        // closing one. For example
+        // /// ``` <- start of the inner main
+        // /// <- code under doctest
+        // /// ``` <- end of the inner main
+        line_offset += 1;
+
+        // add extra 4 spaces for each line to offset the code block
+        let content = if opts.insert_indent_space {
+            everything_else
+                .lines()
+                .map(|line| format!("    {}", line))
+                .collect::<Vec<String>>()
+                .join("\n")
+        } else {
+            everything_else.to_string()
+        };
+        prog.extend([&main_pre, content.as_str(), &main_post].iter().cloned());
+    }
+
+    debug!("final doctest:\n{prog}");
+
+    (prog, line_offset, supports_color)
+}
+
+fn check_for_main_and_extern_crate(
+    crate_name: Option<&str>,
+    source: String,
+    edition: Edition,
+    supports_color: &mut bool,
+) -> Result<(bool, bool), FatalError> {
+    let result = rustc_driver::catch_fatal_errors(|| {
+        rustc_span::create_session_if_not_set_then(edition, |_| {
+            use rustc_errors::emitter::{Emitter, HumanEmitter};
+            use rustc_errors::DiagCtxt;
+            use rustc_parse::parser::ForceCollect;
+            use rustc_span::source_map::FilePathMapping;
+
+            let filename = FileName::anon_source_code(&source);
+
+            // Any errors in parsing should also appear when the doctest is compiled for real, so just
+            // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
+            let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+                false,
+            );
+            *supports_color =
+                HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone())
+                    .supports_color();
+
+            let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
+
+            // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
+            let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
+            let psess = ParseSess::with_dcx(dcx, sm);
+
+            let mut found_main = false;
+            let mut found_extern_crate = crate_name.is_none();
+            let mut found_macro = false;
+
+            let mut parser = match new_parser_from_source_str(&psess, filename, source.clone()) {
+                Ok(p) => p,
+                Err(errs) => {
+                    errs.into_iter().for_each(|err| err.cancel());
+                    return (found_main, found_extern_crate, found_macro);
+                }
+            };
+
+            loop {
+                match parser.parse_item(ForceCollect::No) {
+                    Ok(Some(item)) => {
+                        if !found_main
+                            && let ast::ItemKind::Fn(..) = item.kind
+                            && item.ident.name == sym::main
+                        {
+                            found_main = true;
+                        }
+
+                        if !found_extern_crate
+                            && let ast::ItemKind::ExternCrate(original) = item.kind
+                        {
+                            // This code will never be reached if `crate_name` is none because
+                            // `found_extern_crate` is initialized to `true` if it is none.
+                            let crate_name = crate_name.unwrap();
+
+                            match original {
+                                Some(name) => found_extern_crate = name.as_str() == crate_name,
+                                None => found_extern_crate = item.ident.as_str() == crate_name,
+                            }
+                        }
+
+                        if !found_macro && let ast::ItemKind::MacCall(..) = item.kind {
+                            found_macro = true;
+                        }
+
+                        if found_main && found_extern_crate {
+                            break;
+                        }
+                    }
+                    Ok(None) => break,
+                    Err(e) => {
+                        e.cancel();
+                        break;
+                    }
+                }
+
+                // The supplied item is only used for diagnostics,
+                // which are swallowed here anyway.
+                parser.maybe_consume_incorrect_semicolon(None);
+            }
+
+            // Reset errors so that they won't be reported as compiler bugs when dropping the
+            // dcx. Any errors in the tests will be reported when the test file is compiled,
+            // Note that we still need to cancel the errors above otherwise `Diag` will panic on
+            // drop.
+            psess.dcx.reset_err_count();
+
+            (found_main, found_extern_crate, found_macro)
+        })
+    });
+    let (already_has_main, already_has_extern_crate, found_macro) = result?;
+
+    // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
+    // see it. In that case, run the old text-based scan to see if they at least have a main
+    // function written inside a macro invocation. See
+    // https://github.com/rust-lang/rust/issues/56898
+    let already_has_main = if found_macro && !already_has_main {
+        source
+            .lines()
+            .map(|line| {
+                let comment = line.find("//");
+                if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line }
+            })
+            .any(|code| code.contains("fn main"))
+    } else {
+        already_has_main
+    };
+
+    Ok((already_has_main, already_has_extern_crate))
+}
+
+fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
+    if source.is_empty() {
+        // Empty content so nothing to check in here...
+        return true;
+    }
+    rustc_driver::catch_fatal_errors(|| {
+        rustc_span::create_session_if_not_set_then(edition, |_| {
+            use rustc_errors::emitter::HumanEmitter;
+            use rustc_errors::DiagCtxt;
+            use rustc_span::source_map::FilePathMapping;
+
+            let filename = FileName::anon_source_code(source);
+            // Any errors in parsing should also appear when the doctest is compiled for real, so just
+            // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
+            let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+                false,
+            );
+
+            let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
+
+            let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
+            let psess = ParseSess::with_dcx(dcx, sm);
+            let mut parser = match new_parser_from_source_str(&psess, filename, source.to_owned()) {
+                Ok(p) => p,
+                Err(errs) => {
+                    errs.into_iter().for_each(|err| err.cancel());
+                    // If there is an unclosed delimiter, an error will be returned by the
+                    // tokentrees.
+                    return false;
+                }
+            };
+            // If a parsing error happened, it's very likely that the attribute is incomplete.
+            if let Err(e) = parser.parse_attribute(InnerAttrPolicy::Permitted) {
+                e.cancel();
+                return false;
+            }
+            true
+        })
+    })
+    .unwrap_or(false)
+}
+
+fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
+    #[derive(Copy, Clone, PartialEq)]
+    enum PartitionState {
+        Attrs,
+        Crates,
+        Other,
+    }
+    let mut state = PartitionState::Attrs;
+    let mut before = String::new();
+    let mut crates = String::new();
+    let mut after = String::new();
+
+    let mut mod_attr_pending = String::new();
+
+    for line in s.lines() {
+        let trimline = line.trim();
+
+        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
+        // shunted into "everything else"
+        match state {
+            PartitionState::Attrs => {
+                state = if trimline.starts_with("#![") {
+                    if !check_if_attr_is_complete(line, edition) {
+                        mod_attr_pending = line.to_owned();
+                    } else {
+                        mod_attr_pending.clear();
+                    }
+                    PartitionState::Attrs
+                } else if trimline.chars().all(|c| c.is_whitespace())
+                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Attrs
+                } else if trimline.starts_with("extern crate")
+                    || trimline.starts_with("#[macro_use] extern crate")
+                {
+                    PartitionState::Crates
+                } else {
+                    // First we check if the previous attribute was "complete"...
+                    if !mod_attr_pending.is_empty() {
+                        // If not, then we append the new line into the pending attribute to check
+                        // if this time it's complete...
+                        mod_attr_pending.push_str(line);
+                        if !trimline.is_empty()
+                            && check_if_attr_is_complete(&mod_attr_pending, edition)
+                        {
+                            // If it's complete, then we can clear the pending content.
+                            mod_attr_pending.clear();
+                        }
+                        // In any case, this is considered as `PartitionState::Attrs` so it's
+                        // prepended before rustdoc's inserts.
+                        PartitionState::Attrs
+                    } else {
+                        PartitionState::Other
+                    }
+                };
+            }
+            PartitionState::Crates => {
+                state = if trimline.starts_with("extern crate")
+                    || trimline.starts_with("#[macro_use] extern crate")
+                    || trimline.chars().all(|c| c.is_whitespace())
+                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
+                {
+                    PartitionState::Crates
+                } else {
+                    PartitionState::Other
+                };
+            }
+            PartitionState::Other => {}
+        }
+
+        match state {
+            PartitionState::Attrs => {
+                before.push_str(line);
+                before.push('\n');
+            }
+            PartitionState::Crates => {
+                crates.push_str(line);
+                crates.push('\n');
+            }
+            PartitionState::Other => {
+                after.push_str(line);
+                after.push('\n');
+            }
+        }
+    }
+
+    debug!("before:\n{before}");
+    debug!("crates:\n{crates}");
+    debug!("after:\n{after}");
+
+    (before, after, crates)
+}
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
new file mode 100644
index 00000000000..b8ab7adb36e
--- /dev/null
+++ b/src/librustdoc/doctest/markdown.rs
@@ -0,0 +1,125 @@
+//! Doctest functionality used only for doctests in `.md` Markdown files.
+
+use std::fs::read_to_string;
+
+use rustc_span::FileName;
+use tempfile::tempdir;
+
+use super::{
+    generate_args_file, CreateRunnableDoctests, DoctestVisitor, GlobalTestOptions, ScrapedDoctest,
+};
+use crate::config::Options;
+use crate::html::markdown::{find_testable_code, ErrorCodes, LangString, MdRelLine};
+
+struct MdCollector {
+    tests: Vec<ScrapedDoctest>,
+    cur_path: Vec<String>,
+    filename: FileName,
+}
+
+impl DoctestVisitor for MdCollector {
+    fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) {
+        let filename = self.filename.clone();
+        // First line of Markdown is line 1.
+        let line = 1 + rel_line.offset();
+        self.tests.push(ScrapedDoctest {
+            filename,
+            line,
+            logical_path: self.cur_path.clone(),
+            langstr: config,
+            text: test,
+        });
+    }
+
+    fn visit_header(&mut self, name: &str, level: u32) {
+        // We use these headings as test names, so it's good if
+        // they're valid identifiers.
+        let name = name
+            .chars()
+            .enumerate()
+            .map(|(i, c)| {
+                if (i == 0 && rustc_lexer::is_id_start(c))
+                    || (i != 0 && rustc_lexer::is_id_continue(c))
+                {
+                    c
+                } else {
+                    '_'
+                }
+            })
+            .collect::<String>();
+
+        // Here we try to efficiently assemble the header titles into the
+        // test name in the form of `h1::h2::h3::h4::h5::h6`.
+        //
+        // Suppose that originally `self.cur_path` contains `[h1, h2, h3]`...
+        let level = level as usize;
+        if level <= self.cur_path.len() {
+            // ... Consider `level == 2`. All headers in the lower levels
+            // are irrelevant in this new level. So we should reset
+            // `self.names` to contain headers until <h2>, and replace that
+            // slot with the new name: `[h1, name]`.
+            self.cur_path.truncate(level);
+            self.cur_path[level - 1] = name;
+        } else {
+            // ... On the other hand, consider `level == 5`. This means we
+            // need to extend `self.names` to contain five headers. We fill
+            // in the missing level (<h4>) with `_`. Thus `self.names` will
+            // become `[h1, h2, h3, "_", name]`.
+            if level - 1 > self.cur_path.len() {
+                self.cur_path.resize(level - 1, "_".to_owned());
+            }
+            self.cur_path.push(name);
+        }
+    }
+}
+
+/// Runs any tests/code examples in the markdown file `options.input`.
+pub(crate) fn test(options: Options) -> Result<(), String> {
+    use rustc_session::config::Input;
+    let input_str = match &options.input {
+        Input::File(path) => {
+            read_to_string(&path).map_err(|err| format!("{}: {err}", path.display()))?
+        }
+        Input::Str { name: _, input } => input.clone(),
+    };
+
+    // Obviously not a real crate name, but close enough for purposes of doctests.
+    let crate_name = options.input.filestem().to_string();
+    let temp_dir =
+        tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
+    let args_file = temp_dir.path().join("rustdoc-cfgs");
+    generate_args_file(&args_file, &options)?;
+
+    let opts = GlobalTestOptions {
+        crate_name,
+        no_crate_inject: true,
+        insert_indent_space: false,
+        attrs: vec![],
+        args_file,
+    };
+
+    let mut md_collector = MdCollector {
+        tests: vec![],
+        cur_path: vec![],
+        filename: options
+            .input
+            .opt_path()
+            .map(ToOwned::to_owned)
+            .map(FileName::from)
+            .unwrap_or(FileName::Custom("input".to_owned())),
+    };
+    let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
+
+    find_testable_code(
+        &input_str,
+        &mut md_collector,
+        codes,
+        options.enable_per_target_ignores,
+        None,
+    );
+
+    let mut collector = CreateRunnableDoctests::new(options.clone(), opts);
+    md_collector.tests.into_iter().for_each(|t| collector.add_test(t));
+    crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests);
+    Ok(())
+}
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
new file mode 100644
index 00000000000..fc8e119ccc2
--- /dev/null
+++ b/src/librustdoc/doctest/rust.rs
@@ -0,0 +1,200 @@
+//! Doctest functionality used only for doctests in `.rs` source files.
+
+use std::env;
+
+use rustc_data_structures::{fx::FxHashSet, sync::Lrc};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
+use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::TyCtxt;
+use rustc_resolve::rustdoc::span_of_fragments;
+use rustc_session::Session;
+use rustc_span::source_map::SourceMap;
+use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
+
+use super::{DoctestVisitor, ScrapedDoctest};
+use crate::clean::{types::AttributesExt, Attributes};
+use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine};
+
+struct RustCollector {
+    source_map: Lrc<SourceMap>,
+    tests: Vec<ScrapedDoctest>,
+    cur_path: Vec<String>,
+    position: Span,
+}
+
+impl RustCollector {
+    fn get_filename(&self) -> FileName {
+        let filename = self.source_map.span_to_filename(self.position);
+        if let FileName::Real(ref filename) = filename {
+            let path = filename.remapped_path_if_available();
+            // Strip the cwd prefix from the path. This will likely exist if
+            // the path was not remapped.
+            let path = env::current_dir()
+                .map(|cur_dir| path.strip_prefix(&cur_dir).unwrap_or(path))
+                .unwrap_or(path);
+            return path.to_owned().into();
+        }
+        filename
+    }
+
+    fn get_base_line(&self) -> usize {
+        let sp_lo = self.position.lo().to_usize();
+        let loc = self.source_map.lookup_char_pos(BytePos(sp_lo as u32));
+        loc.line
+    }
+}
+
+impl DoctestVisitor for RustCollector {
+    fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine) {
+        let line = self.get_base_line() + rel_line.offset();
+        self.tests.push(ScrapedDoctest {
+            filename: self.get_filename(),
+            line,
+            logical_path: self.cur_path.clone(),
+            langstr: config,
+            text: test,
+        });
+    }
+
+    fn visit_header(&mut self, _name: &str, _level: u32) {}
+}
+
+pub(super) struct HirCollector<'a, 'tcx> {
+    sess: &'a Session,
+    map: Map<'tcx>,
+    codes: ErrorCodes,
+    tcx: TyCtxt<'tcx>,
+    enable_per_target_ignores: bool,
+    collector: RustCollector,
+}
+
+impl<'a, 'tcx> HirCollector<'a, 'tcx> {
+    pub fn new(
+        sess: &'a Session,
+        map: Map<'tcx>,
+        codes: ErrorCodes,
+        enable_per_target_ignores: bool,
+        tcx: TyCtxt<'tcx>,
+    ) -> Self {
+        let collector = RustCollector {
+            source_map: sess.psess.clone_source_map(),
+            cur_path: vec![],
+            position: DUMMY_SP,
+            tests: vec![],
+        };
+        Self { sess, map, codes, enable_per_target_ignores, tcx, collector }
+    }
+
+    pub fn collect_crate(mut self) -> Vec<ScrapedDoctest> {
+        let tcx = self.tcx;
+        self.visit_testable("".to_string(), CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| {
+            tcx.hir().walk_toplevel_module(this)
+        });
+        self.collector.tests
+    }
+}
+
+impl<'a, 'tcx> HirCollector<'a, 'tcx> {
+    fn visit_testable<F: FnOnce(&mut Self)>(
+        &mut self,
+        name: String,
+        def_id: LocalDefId,
+        sp: Span,
+        nested: F,
+    ) {
+        let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
+        if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
+            if !cfg.matches(&self.sess.psess, Some(self.tcx.features())) {
+                return;
+            }
+        }
+
+        let has_name = !name.is_empty();
+        if has_name {
+            self.collector.cur_path.push(name);
+        }
+
+        // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
+        // anything else, this will combine them for us.
+        let attrs = Attributes::from_ast(ast_attrs);
+        if let Some(doc) = attrs.opt_doc_value() {
+            // Use the outermost invocation, so that doctest names come from where the docs were written.
+            let span = ast_attrs
+                .iter()
+                .find(|attr| attr.doc_str().is_some())
+                .map(|attr| attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span))
+                .unwrap_or(DUMMY_SP);
+            self.collector.position = span;
+            markdown::find_testable_code(
+                &doc,
+                &mut self.collector,
+                self.codes,
+                self.enable_per_target_ignores,
+                Some(&crate::html::markdown::ExtraInfo::new(
+                    self.tcx,
+                    def_id.to_def_id(),
+                    span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
+                )),
+            );
+        }
+
+        nested(self);
+
+        if has_name {
+            self.collector.cur_path.pop();
+        }
+    }
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for HirCollector<'a, 'tcx> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.map
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item<'_>) {
+        let name = match &item.kind {
+            hir::ItemKind::Impl(impl_) => {
+                rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
+            }
+            _ => item.ident.to_string(),
+        };
+
+        self.visit_testable(name, item.owner_id.def_id, item.span, |this| {
+            intravisit::walk_item(this, item);
+        });
+    }
+
+    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'_>) {
+        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
+            intravisit::walk_trait_item(this, item);
+        });
+    }
+
+    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'_>) {
+        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
+            intravisit::walk_impl_item(this, item);
+        });
+    }
+
+    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'_>) {
+        self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
+            intravisit::walk_foreign_item(this, item);
+        });
+    }
+
+    fn visit_variant(&mut self, v: &'tcx hir::Variant<'_>) {
+        self.visit_testable(v.ident.to_string(), v.def_id, v.span, |this| {
+            intravisit::walk_variant(this, v);
+        });
+    }
+
+    fn visit_field_def(&mut self, f: &'tcx hir::FieldDef<'_>) {
+        self.visit_testable(f.ident.to_string(), f.def_id, f.span, |this| {
+            intravisit::walk_field_def(this, f);
+        });
+    }
+}
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 9629acb31eb..9124ec63267 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -1,10 +1,23 @@
+use std::path::PathBuf;
+
 use super::{make_test, GlobalTestOptions};
 use rustc_span::edition::DEFAULT_EDITION;
 
+/// Default [`GlobalTestOptions`] for these unit tests.
+fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions {
+    GlobalTestOptions {
+        crate_name: crate_name.into(),
+        no_crate_inject: false,
+        insert_indent_space: false,
+        attrs: vec![],
+        args_file: PathBuf::new(),
+    }
+}
+
 #[test]
 fn make_test_basic() {
     //basic use: wraps with `fn main`, adds `#![allow(unused)]`
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() {
@@ -19,7 +32,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_name_no_use() {
     // If you give a crate name but *don't* use it within the test, it won't bother inserting
     // the `extern crate` statement.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("asdf");
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() {
@@ -34,7 +47,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_name() {
     // If you give a crate name and use it within the test, it will insert an `extern crate`
     // statement before `fn main`.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("asdf");
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -53,8 +66,7 @@ assert_eq!(2+2, 4);
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts =
-        GlobalTestOptions { no_crate_inject: true, attrs: vec![], insert_indent_space: false };
+    let opts = GlobalTestOptions { no_crate_inject: true, ..default_global_opts("asdf") };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -72,7 +84,7 @@ fn make_test_ignore_std() {
     // Even if you include a crate name, and use it in the doctest, we still won't include an
     // `extern crate` statement if the crate is "std" -- that's included already by the
     // compiler!
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("std");
     let input = "use std::*;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -89,7 +101,7 @@ assert_eq!(2+2, 4);
 fn make_test_manual_extern_crate() {
     // When you manually include an `extern crate` statement in your doctest, `make_test`
     // assumes you've included one for your own crate too.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("asdf");
     let input = "extern crate asdf;
 use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -106,7 +118,7 @@ assert_eq!(2+2, 4);
 
 #[test]
 fn make_test_manual_extern_crate_with_macro_use() {
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("asdf");
     let input = "#[macro_use] extern crate asdf;
 use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -125,7 +137,7 @@ assert_eq!(2+2, 4);
 fn make_test_opts_attrs() {
     // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
     // those instead of the stock `#![allow(unused)]`.
-    let mut opts = GlobalTestOptions::default();
+    let mut opts = default_global_opts("asdf");
     opts.attrs.push("feature(sick_rad)".to_string());
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -159,7 +171,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_attrs() {
     // Including inner attributes in your doctest will apply them to the whole "crate", pasting
     // them outside the generated main function.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "#![feature(sick_rad)]
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -175,7 +187,7 @@ assert_eq!(2+2, 4);
 #[test]
 fn make_test_with_main() {
     // Including your own `fn main` wrapper lets the test use it verbatim.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "fn main() {
     assert_eq!(2+2, 4);
 }";
@@ -191,7 +203,7 @@ fn main() {
 #[test]
 fn make_test_fake_main() {
     // ... but putting it in a comment will still provide a wrapper.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -207,7 +219,7 @@ assert_eq!(2+2, 4);
 #[test]
 fn make_test_dont_insert_main() {
     // Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper.
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -219,8 +231,8 @@ assert_eq!(2+2, 4);"
 }
 
 #[test]
-fn make_test_issues_21299_33731() {
-    let opts = GlobalTestOptions::default();
+fn make_test_issues_21299() {
+    let opts = default_global_opts("");
 
     let input = "// fn main
 assert_eq!(2+2, 4);";
@@ -234,6 +246,11 @@ assert_eq!(2+2, 4);
 
     let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None);
     assert_eq!((output, len), (expected, 2));
+}
+
+#[test]
+fn make_test_issues_33731() {
+    let opts = default_global_opts("asdf");
 
     let input = "extern crate hella_qwop;
 assert_eq!(asdf::foo, 4);";
@@ -253,7 +270,7 @@ assert_eq!(asdf::foo, 4);
 
 #[test]
 fn make_test_main_in_macro() {
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("my_crate");
     let input = "#[macro_use] extern crate my_crate;
 test_wrapper! {
     fn main() {}
@@ -272,7 +289,7 @@ test_wrapper! {
 #[test]
 fn make_test_returns_result() {
     // creates an inner function and unwraps it
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "use std::io;
 let mut input = String::new();
 io::stdin().read_line(&mut input)?;
@@ -292,7 +309,7 @@ Ok::<(), io:Error>(())
 #[test]
 fn make_test_named_wrapper() {
     // creates an inner function with a specific name
-    let opts = GlobalTestOptions::default();
+    let opts = default_global_opts("");
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {
@@ -307,8 +324,7 @@ assert_eq!(2+2, 4);
 #[test]
 fn make_test_insert_extra_space() {
     // will insert indent spaces in the code block if `insert_indent_space` is true
-    let opts =
-        GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true };
+    let opts = GlobalTestOptions { insert_indent_space: true, ..default_global_opts("") };
     let input = "use std::*;
 assert_eq!(2+2, 4);
 eprintln!(\"hello anan\");
@@ -327,8 +343,7 @@ fn main() {
 #[test]
 fn make_test_insert_extra_space_fn_main() {
     // if input already has a fn main, it should insert a space before it
-    let opts =
-        GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true };
+    let opts = GlobalTestOptions { insert_indent_space: true, ..default_global_opts("") };
     let input = "use std::*;
 fn main() {
     assert_eq!(2+2, 4);
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index cf11e2d7899..c85b955d4c5 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -79,7 +79,7 @@ pub(crate) trait DocFolder: Sized {
             | FunctionItem(_)
             | OpaqueTyItem(_)
             | StaticItem(_)
-            | ConstantItem(_)
+            | ConstantItem(_, _, _)
             | TraitAliasItem(_)
             | TyMethodItem(_)
             | MethodItem(_, _)
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 28ddf76a3a6..a3b88a880f2 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -155,7 +155,7 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &crate_num in tcx.crates_including_speculative(()) {
+        for &crate_num in tcx.crates(()) {
             let e = ExternalCrate { crate_num };
 
             let name = e.name(tcx);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d20cef745ab..4268fadd6c5 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1438,13 +1438,9 @@ impl clean::FnDecl {
         {
             write!(f, "\n{}", Indent(n + 4))?;
         }
+
+        let last_input_index = self.inputs.values.len().checked_sub(1);
         for (i, input) in self.inputs.values.iter().enumerate() {
-            if i > 0 {
-                match line_wrapping_indent {
-                    None => write!(f, ", ")?,
-                    Some(n) => write!(f, ",\n{}", Indent(n + 4))?,
-                };
-            }
             if let Some(selfty) = input.to_self() {
                 match selfty {
                     clean::SelfValue => {
@@ -1477,18 +1473,25 @@ impl clean::FnDecl {
                 write!(f, "{}: ", input.name)?;
                 input.type_.print(cx).fmt(f)?;
             }
+            match (line_wrapping_indent, last_input_index) {
+                (_, None) => (),
+                (None, Some(last_i)) if i != last_i => write!(f, ", ")?,
+                (None, Some(_)) => (),
+                (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?,
+                (Some(_), Some(_)) => write!(f, ",\n")?,
+            }
         }
 
         if self.c_variadic {
             match line_wrapping_indent {
                 None => write!(f, ", ...")?,
-                Some(n) => write!(f, "\n{}...", Indent(n + 4))?,
+                Some(n) => write!(f, "{}...\n", Indent(n + 4))?,
             };
         }
 
         match line_wrapping_indent {
             None => write!(f, ")")?,
-            Some(n) => write!(f, "\n{})", Indent(n))?,
+            Some(n) => write!(f, "{})", Indent(n))?,
         };
 
         self.print_output(cx).fmt(f)
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 11cc81700ff..bae929c64ea 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -39,6 +39,7 @@ use std::collections::VecDeque;
 use std::fmt::Write;
 use std::iter::Peekable;
 use std::ops::{ControlFlow, Range};
+use std::path::PathBuf;
 use std::str::{self, CharIndices};
 use std::sync::OnceLock;
 
@@ -287,8 +288,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                 .collect::<String>();
             let krate = krate.as_ref().map(|s| s.as_str());
 
-            let mut opts: GlobalTestOptions = Default::default();
-            opts.insert_indent_space = true;
+            // FIXME: separate out the code to make a code block into runnable code
+            //        from the complicated doctest logic
+            let opts = GlobalTestOptions {
+                crate_name: krate.map(String::from).unwrap_or_default(),
+                no_crate_inject: false,
+                insert_indent_space: true,
+                attrs: vec![],
+                args_file: PathBuf::new(),
+            };
             let (test, _, _) = doctest::make_test(&test, krate, false, &opts, edition, None);
             let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };
 
@@ -710,7 +718,29 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
     }
 }
 
-pub(crate) fn find_testable_code<T: doctest::Tester>(
+/// A newtype that represents a relative line number in Markdown.
+///
+/// In other words, this represents an offset from the first line of Markdown
+/// in a doc comment or other source. If the first Markdown line appears on line 32,
+/// and the `MdRelLine` is 3, then the absolute line for this one is 35. I.e., it's
+/// a zero-based offset.
+pub(crate) struct MdRelLine {
+    offset: usize,
+}
+
+impl MdRelLine {
+    /// See struct docs.
+    pub(crate) const fn new(offset: usize) -> Self {
+        Self { offset }
+    }
+
+    /// See struct docs.
+    pub(crate) const fn offset(self) -> usize {
+        self.offset
+    }
+}
+
+pub(crate) fn find_testable_code<T: doctest::DoctestVisitor>(
     doc: &str,
     tests: &mut T,
     error_codes: ErrorCodes,
@@ -720,7 +750,7 @@ pub(crate) fn find_testable_code<T: doctest::Tester>(
     find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false)
 }
 
-pub(crate) fn find_codes<T: doctest::Tester>(
+pub(crate) fn find_codes<T: doctest::DoctestVisitor>(
     doc: &str,
     tests: &mut T,
     error_codes: ErrorCodes,
@@ -772,8 +802,8 @@ pub(crate) fn find_codes<T: doctest::Tester>(
                 if nb_lines != 0 && !&doc[prev_offset..offset.start].ends_with('\n') {
                     nb_lines -= 1;
                 }
-                let line = tests.get_line() + nb_lines + 1;
-                tests.add_test(text, block_info, line);
+                let line = MdRelLine::new(nb_lines);
+                tests.visit_test(text, block_info, line);
                 prev_offset = offset.start;
             }
             Event::Start(Tag::Heading(level, _, _)) => {
@@ -781,7 +811,7 @@ pub(crate) fn find_codes<T: doctest::Tester>(
             }
             Event::Text(ref s) if register_header.is_some() => {
                 let level = register_header.unwrap();
-                tests.register_header(s, level);
+                tests.visit_header(s, level);
                 register_header = None;
             }
             _ => {}
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index c5b88c7a951..e1f79254b24 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -266,7 +266,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
         clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
         clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
         clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i),
-        clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
+        clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c),
         clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
         clean::KeywordItem => item_keyword(buf, cx, item),
         clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e),
@@ -1844,7 +1844,14 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
     }
 }
 
-fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
+fn item_constant(
+    w: &mut Buffer,
+    cx: &mut Context<'_>,
+    it: &clean::Item,
+    generics: &clean::Generics,
+    ty: &clean::Type,
+    c: &clean::Constant,
+) {
     wrap_item(w, |w| {
         let tcx = cx.tcx();
         render_attributes_in_code(w, it, cx);
@@ -1854,9 +1861,9 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
             "{vis}const {name}{generics}: {typ}{where_clause}",
             vis = visibility_print_with_space(it, cx),
             name = it.name.unwrap(),
-            generics = c.generics.print(cx),
-            typ = c.type_.print(cx),
-            where_clause = print_where_clause(&c.generics, cx, 0, Ending::NoNewline),
+            generics = generics.print(cx),
+            typ = ty.print(cx),
+            where_clause = print_where_clause(&generics, cx, 0, Ending::NoNewline),
         );
 
         // FIXME: The code below now prints
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index a1e9cc6dfa1..fbb096fe9c7 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -5,7 +5,7 @@ module.exports = {
     },
     "extends": "eslint:recommended",
     "parserOptions": {
-        "ecmaVersion": 8,
+        "ecmaVersion": 2019,
         "sourceType": "module"
     },
     "rules": {
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 8cebce7ae86..6fd60d6cc34 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -41,8 +41,9 @@ let ParserState;
  *     foundElems: number,
  *     totalElems: number,
  *     literalSearch: boolean,
- *     corrections: Array<{from: string, to: integer}>,
+ *     corrections: Array<{from: string, to: integer}> | null,
  *     typeFingerprint: Uint32Array,
+ *     error: Array<string> | null,
  * }}
  */
 let ParsedQuery;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 76a6fc9008e..a0ab262bf0b 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -89,6 +89,10 @@ const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
 // of permutations we need to check.
 const UNBOXING_LIMIT = 5;
 
+// used for search query verification
+const REGEX_IDENT = /\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;
+const REGEX_INVALID_TYPE_FILTER = /[^a-z]/ui;
+
 // In the search display, allows to switch between tabs.
 function printTab(nb) {
     let iter = 0;
@@ -410,18 +414,21 @@ function initSearch(rawSearchIndex) {
     }
 
     /**
-     * Returns `true` if the given `c` character is valid for an ident.
+     * If the current parser position is at the beginning of an identifier,
+     * move the position to the end of it and return `true`. Otherwise, return `false`.
      *
-     * @param {string} c
+     * @param {ParserState} parserState
      *
      * @return {boolean}
      */
-    function isIdentCharacter(c) {
-        return (
-            c === "_" ||
-            (c >= "0" && c <= "9") ||
-            (c >= "a" && c <= "z") ||
-            (c >= "A" && c <= "Z"));
+    function consumeIdent(parserState) {
+        REGEX_IDENT.lastIndex = parserState.pos;
+        const match = parserState.userQuery.match(REGEX_IDENT);
+        if (match) {
+            parserState.pos += match[0].length;
+            return true;
+        }
+        return false;
     }
 
     /**
@@ -618,70 +625,62 @@ function initSearch(rawSearchIndex) {
      * @return {integer}
      */
     function getIdentEndPosition(parserState) {
-        const start = parserState.pos;
+        let afterIdent = consumeIdent(parserState);
         let end = parserState.pos;
-        let foundExclamation = -1;
+        let macroExclamation = -1;
         while (parserState.pos < parserState.length) {
             const c = parserState.userQuery[parserState.pos];
-            if (!isIdentCharacter(c)) {
-                if (c === "!") {
-                    if (foundExclamation !== -1) {
-                        throw ["Cannot have more than one ", "!", " in an ident"];
-                    } else if (parserState.pos + 1 < parserState.length &&
-                        isIdentCharacter(parserState.userQuery[parserState.pos + 1])
-                    ) {
+            if (c === "!") {
+                if (macroExclamation !== -1) {
+                    throw ["Cannot have more than one ", "!", " in an ident"];
+                } else if (parserState.pos + 1 < parserState.length) {
+                    const pos = parserState.pos;
+                    parserState.pos++;
+                    const beforeIdent = consumeIdent(parserState);
+                    parserState.pos = pos;
+                    if (beforeIdent) {
                         throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
                     }
-                    foundExclamation = parserState.pos;
-                } else if (isPathSeparator(c)) {
-                    if (c === ":") {
-                        if (!isPathStart(parserState)) {
+                }
+                if (afterIdent) macroExclamation = parserState.pos;
+            } else if (isPathSeparator(c)) {
+                if (c === ":") {
+                    if (!isPathStart(parserState)) {
+                        break;
+                    }
+                    // Skip current ":".
+                    parserState.pos += 1;
+                } else {
+                    while (parserState.pos + 1 < parserState.length) {
+                        const next_c = parserState.userQuery[parserState.pos + 1];
+                        if (next_c !== " ") {
                             break;
                         }
-                        // Skip current ":".
                         parserState.pos += 1;
-                    } else {
-                        while (parserState.pos + 1 < parserState.length) {
-                            const next_c = parserState.userQuery[parserState.pos + 1];
-                            if (next_c !== " ") {
-                                break;
-                            }
-                            parserState.pos += 1;
-                        }
                     }
-                    if (foundExclamation !== -1) {
-                        if (foundExclamation !== start &&
-                            isIdentCharacter(parserState.userQuery[foundExclamation - 1])
-                        ) {
-                            throw ["Cannot have associated items in macros"];
-                        } else {
-                            // while the never type has no associated macros, we still
-                            // can parse a path like that
-                            foundExclamation = -1;
-                        }
-                    }
-                } else if (
-                    c === "[" ||
-                    c === "(" ||
-                    isEndCharacter(c) ||
-                    isSpecialStartCharacter(c) ||
-                    isSeparatorCharacter(c)
-                ) {
-                    break;
-                } else if (parserState.pos > 0) {
-                    throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]];
-                } else {
-                    throw ["Unexpected ", c];
                 }
+                if (macroExclamation !== -1) {
+                    throw ["Cannot have associated items in macros"];
+                }
+            } else if (
+                c === "[" ||
+                c === "(" ||
+                isEndCharacter(c) ||
+                isSpecialStartCharacter(c) ||
+                isSeparatorCharacter(c)
+            ) {
+                break;
+            } else if (parserState.pos > 0) {
+                throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1],
+                    " (not a valid identifier)"];
+            } else {
+                throw ["Unexpected ", c, " (not a valid identifier)"];
             }
             parserState.pos += 1;
+            afterIdent = consumeIdent(parserState);
             end = parserState.pos;
         }
-        // if start == end - 1, we got the never type
-        if (foundExclamation !== -1 &&
-            foundExclamation !== start &&
-            isIdentCharacter(parserState.userQuery[foundExclamation - 1])
-        ) {
+        if (macroExclamation !== -1) {
             if (parserState.typeFilter === null) {
                 parserState.typeFilter = "macro";
             } else if (parserState.typeFilter !== "macro") {
@@ -693,7 +692,7 @@ function initSearch(rawSearchIndex) {
                     " both specified",
                 ];
             }
-            end = foundExclamation;
+            end = macroExclamation;
         }
         return end;
     }
@@ -1071,16 +1070,15 @@ function initSearch(rawSearchIndex) {
     function checkExtraTypeFilterCharacters(start, parserState) {
         const query = parserState.userQuery.slice(start, parserState.pos).trim();
 
-        for (const c in query) {
-            if (!isIdentCharacter(query[c])) {
-                throw [
-                    "Unexpected ",
-                    query[c],
-                    " in type filter (before ",
-                    ":",
-                    ")",
-                ];
-            }
+        const match = query.match(REGEX_INVALID_TYPE_FILTER);
+        if (match) {
+            throw [
+                "Unexpected ",
+                match[0],
+                " in type filter (before ",
+                ":",
+                ")",
+            ];
         }
     }
 
@@ -2127,7 +2125,7 @@ function initSearch(rawSearchIndex) {
             };
         }
 
-        function handleAliases(ret, query, filterCrates, currentCrate) {
+        async function handleAliases(ret, query, filterCrates, currentCrate) {
             const lowerQuery = query.toLowerCase();
             // We separate aliases and crate aliases because we want to have current crate
             // aliases to be before the others in the displayed results.
@@ -2163,6 +2161,15 @@ function initSearch(rawSearchIndex) {
             crateAliases.sort(sortFunc);
             aliases.sort(sortFunc);
 
+            const fetchDesc = alias => {
+                return searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
+                    "" : searchState.loadDesc(alias);
+            };
+            const [crateDescs, descs] = await Promise.all([
+                Promise.all(crateAliases.map(fetchDesc)),
+                Promise.all(aliases.map(fetchDesc)),
+            ]);
+
             const pushFunc = alias => {
                 alias.alias = query;
                 const res = buildHrefAndPath(alias);
@@ -2176,7 +2183,13 @@ function initSearch(rawSearchIndex) {
                 }
             };
 
+            aliases.forEach((alias, i) => {
+                alias.desc = descs[i];
+            });
             aliases.forEach(pushFunc);
+            crateAliases.forEach((alias, i) => {
+                alias.desc = crateDescs[i];
+            });
             crateAliases.forEach(pushFunc);
         }
 
@@ -2386,15 +2399,19 @@ function initSearch(rawSearchIndex) {
              * @param {boolean} isAssocType
              */
             function convertNameToId(elem, isAssocType) {
-                if (typeNameIdMap.has(elem.normalizedPathLast) &&
-                    (isAssocType || !typeNameIdMap.get(elem.normalizedPathLast).assocOnly)) {
-                    elem.id = typeNameIdMap.get(elem.normalizedPathLast).id;
+                const loweredName = elem.pathLast.toLowerCase();
+                if (typeNameIdMap.has(loweredName) &&
+                    (isAssocType || !typeNameIdMap.get(loweredName).assocOnly)) {
+                    elem.id = typeNameIdMap.get(loweredName).id;
                 } else if (!parsedQuery.literalSearch) {
                     let match = null;
                     let matchDist = maxEditDistance + 1;
                     let matchName = "";
                     for (const [name, {id, assocOnly}] of typeNameIdMap) {
-                        const dist = editDistance(name, elem.normalizedPathLast, maxEditDistance);
+                        const dist = Math.min(
+                            editDistance(name, loweredName, maxEditDistance),
+                            editDistance(name, elem.normalizedPathLast, maxEditDistance),
+                        );
                         if (dist <= matchDist && dist <= maxEditDistance &&
                             (isAssocType || !assocOnly)) {
                             if (dist === matchDist && matchName > name) {
@@ -2538,7 +2555,8 @@ function initSearch(rawSearchIndex) {
             sorted_returned,
             sorted_others,
             parsedQuery);
-        handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates, currentCrate);
+        await handleAliases(ret, parsedQuery.original.replace(/"/g, ""),
+            filterCrates, currentCrate);
         await Promise.all([ret.others, ret.returned, ret.in_args].map(async list => {
             const descs = await Promise.all(list.map(result => {
                 return searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ?
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 7e6a19aa52e..afafb4fbe4b 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -183,7 +183,7 @@ impl FromWithTcx<clean::Constant> for Constant {
         let expr = constant.expr(tcx);
         let value = constant.value(tcx);
         let is_literal = constant.is_literal(tcx);
-        Constant { type_: (*constant.type_).into_tcx(tcx), expr, value, is_literal }
+        Constant { expr, value, is_literal }
     }
 }
 
@@ -321,7 +321,10 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         ForeignTypeItem => ItemEnum::ForeignType,
         TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)),
         OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
-        ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
+        // FIXME(generic_const_items): Add support for generic free consts
+        ConstantItem(_generics, t, c) => {
+            ItemEnum::Constant { type_: (*t).into_tcx(tcx), const_: c.into_tcx(tcx) }
+        }
         MacroItem(m) => ItemEnum::Macro(m.source),
         ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
         PrimitiveItem(p) => {
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index c1d90020e87..0ef24818515 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -186,7 +186,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 | types::ItemEnum::Impl(_)
                 | types::ItemEnum::TypeAlias(_)
                 | types::ItemEnum::OpaqueTy(_)
-                | types::ItemEnum::Constant(_)
+                | types::ItemEnum::Constant { .. }
                 | types::ItemEnum::Static(_)
                 | types::ItemEnum::ForeignType
                 | types::ItemEnum::Macro(_)
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index c0d2f9cfaf9..d6e715d48ea 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -555,6 +555,14 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("no-run", |o| {
             o.optflagmulti("", "no-run", "Compile doctests without running them")
         }),
+        unstable("remap-path-prefix", |o| {
+            o.optmulti(
+                "",
+                "remap-path-prefix",
+                "Remap source names in compiler messages",
+                "FROM=TO",
+            )
+        }),
         unstable("show-type-layout", |o| {
             o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs")
         }),
@@ -728,7 +736,7 @@ fn main_args(
         core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts);
 
     match (options.should_test, options.markdown_input()) {
-        (true, Some(_)) => return wrap_return(&diag, markdown::test(options)),
+        (true, Some(_)) => return wrap_return(&diag, doctest::test_markdown(options)),
         (true, None) => return doctest::run(&diag, options),
         (false, Some(input)) => {
             let input = input.to_owned();
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index bcc5a37618a..a98f81d011e 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -3,18 +3,12 @@ use std::fs::{create_dir_all, read_to_string, File};
 use std::io::prelude::*;
 use std::path::Path;
 
-use tempfile::tempdir;
-
 use rustc_span::edition::Edition;
-use rustc_span::DUMMY_SP;
 
-use crate::config::{Options, RenderOptions};
-use crate::doctest::{generate_args_file, Collector, GlobalTestOptions};
+use crate::config::RenderOptions;
 use crate::html::escape::Escape;
 use crate::html::markdown;
-use crate::html::markdown::{
-    find_testable_code, ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc,
-};
+use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc};
 
 /// Separate any lines at the start of the file that begin with `# ` or `%`.
 fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
@@ -137,41 +131,3 @@ pub(crate) fn render<P: AsRef<Path>>(
         Ok(_) => Ok(()),
     }
 }
-
-/// Runs any tests/code examples in the markdown file `input`.
-pub(crate) fn test(options: Options) -> Result<(), String> {
-    use rustc_session::config::Input;
-    let input_str = match &options.input {
-        Input::File(path) => {
-            read_to_string(&path).map_err(|err| format!("{}: {err}", path.display()))?
-        }
-        Input::Str { name: _, input } => input.clone(),
-    };
-
-    let mut opts = GlobalTestOptions::default();
-    opts.no_crate_inject = true;
-
-    let temp_dir =
-        tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
-    let file_path = temp_dir.path().join("rustdoc-cfgs");
-    generate_args_file(&file_path, &options)?;
-
-    let mut collector = Collector::new(
-        options.input.filestem().to_string(),
-        options.clone(),
-        true,
-        opts,
-        None,
-        options.input.opt_path().map(ToOwned::to_owned),
-        options.enable_per_target_ignores,
-        file_path,
-    );
-    collector.set_position(DUMMY_SP);
-    let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
-
-    // For markdown files, custom code classes will be disabled until the feature is enabled by default.
-    find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
-
-    crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests);
-    Ok(())
-}
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 02589a137b4..0437f5e5fd8 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -10,7 +10,7 @@ use crate::clean;
 use crate::clean::utils::inherits_doc_hidden;
 use crate::clean::*;
 use crate::core::DocContext;
-use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
+use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString, MdRelLine};
 use crate::visit::DocVisitor;
 use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
@@ -44,8 +44,8 @@ pub(crate) struct Tests {
     pub(crate) found_tests: usize,
 }
 
-impl crate::doctest::Tester for Tests {
-    fn add_test(&mut self, _: String, config: LangString, _: usize) {
+impl crate::doctest::DoctestVisitor for Tests {
+    fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine) {
         if config.rust && config.ignore == Ignore::None {
             self.found_tests += 1;
         }
@@ -62,7 +62,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
                 | clean::AssocTypeItem(..)
                 | clean::TypeAliasItem(_)
                 | clean::StaticItem(_)
-                | clean::ConstantItem(_)
+                | clean::ConstantItem(_, _, _)
                 | clean::ExternCrateItem { .. }
                 | clean::ImportItem(_)
                 | clean::PrimitiveItem(_)
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 8ab24a8c12e..440b02a1fa7 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -12,7 +12,7 @@ use rustc_errors::{Applicability, Diag, DiagMessage};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
-use rustc_hir::Mutability;
+use rustc_hir::{Mutability, Safety};
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
@@ -1517,7 +1517,11 @@ impl Disambiguator {
                 "union" => Kind(DefKind::Union),
                 "module" | "mod" => Kind(DefKind::Mod),
                 "const" | "constant" => Kind(DefKind::Const),
-                "static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }),
+                "static" => Kind(DefKind::Static {
+                    mutability: Mutability::Not,
+                    nested: false,
+                    safety: Safety::Safe,
+                }),
                 "function" | "fn" | "method" => Kind(DefKind::Fn),
                 "derive" => Kind(DefKind::Macro(MacroKind::Derive)),
                 "type" => NS(Namespace::TypeNS),
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 22daac9efb1..c92cf9d3e80 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
     // External trait impls.
     {
         let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls");
-        for &cnum in tcx.crates_including_speculative(()) {
+        for &cnum in tcx.crates(()) {
             for &impl_def_id in tcx.trait_impls_in_crate(cnum) {
                 cx.with_param_env(impl_def_id, |cx| {
                     inline::build_impl(cx, impl_def_id, None, &mut new_items_external);
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 39350f4cbbb..c185442fd55 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -5,7 +5,7 @@ use rustc_errors::{
     translation::{to_fluent_args, Translate},
     Applicability, DiagCtxt, DiagInner, LazyFallbackBundle,
 };
-use rustc_parse::parse_stream_from_source_str;
+use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
 use rustc_resolve::rustdoc::source_span_for_markdown_range;
 use rustc_session::parse::ParseSess;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, Transparency};
@@ -51,12 +51,12 @@ fn check_rust_syntax(
     let span = DUMMY_SP.apply_mark(expn_id.to_expn_id(), Transparency::Transparent);
 
     let is_empty = rustc_driver::catch_fatal_errors(|| {
-        parse_stream_from_source_str(
+        unwrap_or_emit_fatal(source_str_to_stream(
+            &psess,
             FileName::Custom(String::from("doctest")),
             source,
-            &psess,
             Some(span),
-        )
+        ))
         .is_empty()
     })
     .unwrap_or(false);
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 64753a58a2b..e9b380fdeac 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -283,7 +283,7 @@ pub(crate) fn run(
         // Collect CrateIds corresponding to provided target crates
         // If two different versions of the crate in the dependency tree, then examples will be collected from both.
         let all_crates = tcx
-            .crates_including_speculative(())
+            .crates(())
             .iter()
             .chain([&LOCAL_CRATE])
             .map(|crate_num| (crate_num, tcx.crate_name(*crate_num)))
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index 01e6cb4b93b..0660037e4d8 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -28,7 +28,7 @@ pub(crate) trait DocVisitor: Sized {
             | TypeAliasItem(_)
             | OpaqueTyItem(_)
             | StaticItem(_)
-            | ConstantItem(_)
+            | ConstantItem(_, _, _)
             | TraitAliasItem(_)
             | TyMethodItem(_)
             | MethodItem(_, _)
diff --git a/src/llvm-project b/src/llvm-project
-Subproject b31c30a9bb4dbbd13c359d0e2bea7f65d20adf3
+Subproject 5a5152f653959d14d68613a3a8a033fb65eec02
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 1c5a6dcfb1f..68030493e9c 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
 use std::path::PathBuf;
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 29;
+pub const FORMAT_VERSION: u32 = 30;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -167,8 +167,6 @@ pub enum GenericArg {
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Constant {
-    #[serde(rename = "type")]
-    pub type_: Type,
     pub expr: String,
     pub value: Option<String>,
     pub is_literal: bool,
@@ -256,7 +254,12 @@ pub enum ItemEnum {
 
     TypeAlias(TypeAlias),
     OpaqueTy(OpaqueTy),
-    Constant(Constant),
+    Constant {
+        #[serde(rename = "type")]
+        type_: Type,
+        #[serde(rename = "const")]
+        const_: Constant,
+    },
 
     Static(Static),
 
diff --git a/src/tools/build_helper/README.md b/src/tools/build_helper/README.md
new file mode 100644
index 00000000000..f81b631c3fd
--- /dev/null
+++ b/src/tools/build_helper/README.md
@@ -0,0 +1 @@
+Types and functions shared across tools in this workspace.
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
index 2abda5d3ebf..15807d1c0d8 100644
--- a/src/tools/build_helper/src/lib.rs
+++ b/src/tools/build_helper/src/lib.rs
@@ -1,5 +1,30 @@
+//! Types and functions shared across tools in this workspace.
+
 pub mod ci;
 pub mod git;
 pub mod metrics;
 pub mod stage0_parser;
 pub mod util;
+
+/// The default set of crates for opt-dist to collect LLVM profiles.
+pub const LLVM_PGO_CRATES: &[&str] = &[
+    "syn-1.0.89",
+    "cargo-0.60.0",
+    "serde-1.0.136",
+    "ripgrep-13.0.0",
+    "regex-1.5.5",
+    "clap-3.1.6",
+    "hyper-0.14.18",
+];
+
+/// The default set of crates for opt-dist to collect rustc profiles.
+pub const RUSTC_PGO_CRATES: &[&str] = &[
+    "externs",
+    "ctfe-stress-5",
+    "cargo-0.60.0",
+    "token-stream-stress",
+    "match-stress",
+    "tuple-stress",
+    "diesel-1.4.8",
+    "bitmaps-3.1.0",
+];
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7a6fad0984d28c8330974636972aa296b67c451
+Subproject b1feb75d062444e2cee8b3d2aaa95309d65e9cc
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index 651f2ebaee6..c3e3c0431e6 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::HumanEmitter;
 use rustc_errors::{Diag, DiagCtxt};
 use rustc_lint::LateContext;
-use rustc_parse::maybe_new_parser_from_source_str;
+use rustc_parse::new_parser_from_source_str;
 use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
@@ -50,7 +50,7 @@ pub fn check(
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
                 let psess = ParseSess::with_dcx(dcx, sm);
 
-                let mut parser = match maybe_new_parser_from_source_str(&psess, filename, code) {
+                let mut parser = match new_parser_from_source_str(&psess, filename, code) {
                     Ok(p) => p,
                     Err(errs) => {
                         errs.into_iter().for_each(Diag::cancel);
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 192fb611c2d..cb1d0de1edf 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
                 let infcx = cx.tcx.infer_ctxt().build();
-                let ocx = ObligationCtxt::new(&infcx);
+                let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
                 let cause = traits::ObligationCause::misc(span, fn_def_id);
                 ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
                 let send_errors = ocx.select_all_or_error();
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index b561054b582..7f8197c0cc0 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -54,8 +54,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
             && generics.params.is_empty() && !generics.has_where_clause_predicates
             && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
             && let ty::Array(element_type, cst) = ty.kind()
-            && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
-            && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
+            && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
+            && let element_count = element_count.to_target_usize(cx.tcx)
             && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
             && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
         {
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 208d1bb6e68..c9bfc9c85d9 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -64,8 +64,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
         if let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind
             && !self.is_from_vec_macro(cx, expr.span)
             && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
-            && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
-            && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
+            && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
+            && let element_count = element_count.to_target_usize(cx.tcx)
             && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
             && !cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| {
                 matches!(
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 8199366d175..45b375dbe3d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
-                            mir_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
                         },
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
-                            mir_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index f4397212cf6..7f6b666e434 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -42,7 +42,7 @@ fn is_arg_ty_unified_in_fn<'tcx>(
     cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| {
         clause
             .as_projection_clause()
-            .and_then(|p| p.map_bound(|p| p.term.ty()).transpose())
+            .and_then(|p| p.map_bound(|p| p.term.as_type()).transpose())
             .is_some_and(|ty| ty.skip_binder() == arg_ty_in_args)
     }) || fn_sig
         .inputs()
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 5b5e1c23424..4f99eaa40c2 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
@@ -311,7 +311,7 @@ fn is_mixed_projection_predicate<'tcx>(
 ) -> bool {
     let generics = cx.tcx.generics_of(callee_def_id);
     // The predicate requires the projected type to equal a type parameter from the parent context.
-    if let Some(term_ty) = projection_predicate.term.ty()
+    if let Some(term_ty) = projection_predicate.term.as_type()
         && let ty::Param(term_param_ty) = term_ty.kind()
         && (term_param_ty.index as usize) < generics.parent_count
     {
@@ -370,7 +370,7 @@ fn replace_types<'tcx>(
         if replaced.insert(param_ty.index) {
             for projection_predicate in projection_predicates {
                 if projection_predicate.projection_term.self_ty() == param_ty.to_ty(cx.tcx)
-                    && let Some(term_ty) = projection_predicate.term.ty()
+                    && let Some(term_ty) = projection_predicate.term.as_type()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
                     let projection = projection_predicate
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 76d9cee18aa..20a97645af9 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -199,7 +199,7 @@ impl<'tcx> NonCopyConst<'tcx> {
                 .any(|field| Self::is_value_unfrozen_raw_inner(cx, *field, ty)),
             ty::Adt(def, args) if def.is_enum() => {
                 let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap();
-                let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
+                let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().to_u32());
                 fields
                     .iter()
                     .copied()
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index f0d1458a59b..a8cc2f97963 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -100,12 +100,12 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
                     {
                         if ord_preds
                             .iter()
-                            .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty())
+                            .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.as_type())
                         {
                             args_to_check.push((i, "Ord".to_string()));
                         } else if partial_ord_preds
                             .iter()
-                            .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap())
+                            .any(|pord| pord.self_ty() == return_ty_pred.term.expect_type())
                         {
                             args_to_check.push((i, "PartialOrd".to_string()));
                         }
diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
index 143fecdd237..8796b8f61d1 100644
--- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
@@ -55,9 +55,8 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
             inner_check(cx, expr, inner_expr, true);
         } else if let ExprKind::Repeat(inner_expr, _) = expr.kind
             && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind()
-            && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
-            && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
-            && element_count == 0
+            && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
+            && element_count.to_target_usize(cx.tcx) == 0
         {
             inner_check(cx, expr, inner_expr, false);
         }
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index bbdde3049db..c70f5c2df84 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -308,13 +308,15 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 ty: lt,
                 mutability: lm,
                 expr: le,
+                safety: ls,
             }),
             Static(box StaticItem {
                 ty: rt,
                 mutability: rm,
                 expr: re,
+                safety: rs,
             }),
-        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
+        ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (
             Const(box ConstItem {
                 defaultness: ld,
@@ -451,13 +453,15 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 ty: lt,
                 mutability: lm,
                 expr: le,
+                safety: ls,
             }),
             Static(box StaticForeignItem {
                 ty: rt,
                 mutability: rm,
                 expr: re,
+                safety: rs,
             }),
-        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
+        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re) && ls == rs,
         (
             Fn(box ast::Fn {
                 defaultness: ld,
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index cd88ccd87cf..e9e1aa7e445 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -6,7 +6,7 @@ use crate::{clip, is_direct_expn_of, sext, unsext};
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{alloc_range, Scalar};
@@ -412,7 +412,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
-            ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr(e),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e),
             ExprKind::Path(ref qpath) => {
                 self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
                     let result = mir_to_const(this.lcx, result)?;
@@ -490,7 +490,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// leaves the local crate.
     pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
         match e.kind {
-            ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr_is_empty(e),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr_is_empty(e),
             ExprKind::Path(ref qpath) => {
                 if !self
                     .typeck_results
@@ -810,14 +810,14 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
         (ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
             ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
-            ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
+            ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
             ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
                 int.try_into().expect("invalid f32 bit representation"),
             ))),
             ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
                 int.try_into().expect("invalid f64 bit representation"),
             ))),
-            ty::RawPtr(_, _) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
+            ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
             _ => None,
         },
         (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index c649c179468..36634817fc9 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -295,7 +295,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
             },
             (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false,
-            (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_expr(lb, rb),
+            (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
             (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
                 both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
             },
@@ -769,8 +769,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 // closures inherit TypeckResults
                 self.hash_expr(self.cx.tcx.hir().body(body).value);
             },
-            ExprKind::ConstBlock(l_id) => {
-                self.hash_expr(l_id);
+            ExprKind::ConstBlock(ref l_id) => {
+                self.hash_body(l_id.body);
             },
             ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
                 self.hash_expr(e);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index b10830b24e1..2f6bf920967 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
 /// This function is expensive and should be used sparingly.
 pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
     fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
-        tcx.crates_including_speculative(())
+        tcx.crates(())
             .iter()
             .copied()
             .filter(move |&num| tcx.crate_name(num) == name)
@@ -1534,7 +1534,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
             if let rustc_ty::Adt(_, subst) = ty.kind()
                 && let bnd_ty = subst.type_at(0)
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
-                && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, cx.tcx))
+                && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, bnd_ty, cx.tcx))
                 && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
@@ -1547,7 +1547,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 if let rustc_ty::Adt(_, subst) = ty.kind()
                     && let bnd_ty = subst.type_at(0)
                     && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
-                    && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, cx.tcx))
+                    && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, bnd_ty, cx.tcx))
                     && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                 {
                     end_const == max_const
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 3414b5ef680..6e5626297c9 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -23,7 +23,7 @@ use rustc_middle::ty::{
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
-use rustc_target::abi::{Size, VariantIdx};
+use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
@@ -750,7 +750,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
                     let output = bounds
                         .projection_bounds()
                         .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id()))
-                        .map(|p| p.map_bound(|p| p.term.ty().unwrap()));
+                        .map(|p| p.map_bound(|p| p.term.expect_type()));
                     Some(ExprFnSig::Trait(bound.map_bound(|b| b.args.type_at(0)), output, None))
                 },
                 _ => None,
@@ -798,7 +798,7 @@ fn sig_from_bounds<'tcx>(
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
-                output = Some(pred.kind().rebind(p.term.ty().unwrap()));
+                output = Some(pred.kind().rebind(p.term.expect_type()));
             },
             _ => (),
         }
@@ -836,7 +836,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
                 }
-                output = pred.kind().rebind(p.term.ty()).transpose();
+                output = pred.kind().rebind(p.term.as_type()).transpose();
             },
             _ => (),
         }
@@ -865,22 +865,8 @@ impl core::ops::Add<u32> for EnumValue {
 pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
     if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
         match tcx.type_of(id).instantiate_identity().kind() {
-            ty::Int(_) => Some(EnumValue::Signed(match value.size().bytes() {
-                1 => i128::from(value.assert_bits(Size::from_bytes(1)) as u8 as i8),
-                2 => i128::from(value.assert_bits(Size::from_bytes(2)) as u16 as i16),
-                4 => i128::from(value.assert_bits(Size::from_bytes(4)) as u32 as i32),
-                8 => i128::from(value.assert_bits(Size::from_bytes(8)) as u64 as i64),
-                16 => value.assert_bits(Size::from_bytes(16)) as i128,
-                _ => return None,
-            })),
-            ty::Uint(_) => Some(EnumValue::Unsigned(match value.size().bytes() {
-                1 => value.assert_bits(Size::from_bytes(1)),
-                2 => value.assert_bits(Size::from_bytes(2)),
-                4 => value.assert_bits(Size::from_bytes(4)),
-                8 => value.assert_bits(Size::from_bytes(8)),
-                16 => value.assert_bits(Size::from_bytes(16)),
-                _ => return None,
-            })),
+            ty::Int(_) => Some(EnumValue::Signed(value.to_int(value.size()))),
+            ty::Uint(_) => Some(EnumValue::Unsigned(value.to_uint(value.size()))),
             _ => None,
         }
     } else {
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index df14ff396f6..8039c0bfa24 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,35 +1,11 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:188:36
-   |
-LL |     let _ = const { let mut n = 1; n += 1; n };
-   |                                    ^^^^^^
-   |
-   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
-
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:191:40
-   |
-LL |     let _ = const { let mut n = 1; n = n + 1; n };
-   |                                        ^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:194:40
-   |
-LL |     let _ = const { let mut n = 1; n = 1 + n; n };
-   |                                        ^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:200:59
-   |
-LL |     let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
-   |                                                           ^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
   --> tests/ui/arithmetic_side_effects.rs:304:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
+   |
+   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
   --> tests/ui/arithmetic_side_effects.rs:305:5
@@ -751,5 +727,5 @@ error: arithmetic operation that can potentially result in unexpected side-effec
 LL |     one.sub_assign(1);
    |     ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 125 previous errors
+error: aborting due to 121 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
index 84dac431169..05d5b3d10ea 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
@@ -16,7 +16,7 @@ fn foo(
 
 fn skip_on_statements() {
     #[rustfmt::skip]
-    { 5+3; }
+    5+3;
 }
 
 #[rustfmt::skip]
@@ -33,11 +33,11 @@ mod foo {
 #[clippy::msrv = "1.29"]
 fn msrv_1_29() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    { 1+29; }
+    1+29;
 }
 
 #[clippy::msrv = "1.30"]
 fn msrv_1_30() {
     #[rustfmt::skip]
-    { 1+30; }
+    1+30;
 }
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
index 4ab5c70e13b..bc29e20210e 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
@@ -16,7 +16,7 @@ fn foo(
 
 fn skip_on_statements() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    { 5+3; }
+    5+3;
 }
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
@@ -33,11 +33,11 @@ mod foo {
 #[clippy::msrv = "1.29"]
 fn msrv_1_29() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    { 1+29; }
+    1+29;
 }
 
 #[clippy::msrv = "1.30"]
 fn msrv_1_30() {
     #[cfg_attr(rustfmt, rustfmt::skip)]
-    { 1+30; }
+    1+30;
 }
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
index ec4ae2ea13c..6ede7bfcd9f 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
@@ -45,8 +45,8 @@ fn std_instead_of_core() {
 
     let _ = std::env!("PATH");
 
-    // do not lint until `error_in_core` is stable
-    use std::error::Error;
+    use core::error::Error;
+    //~^ ERROR: used import from `std` instead of `core`
 
     // lint items re-exported from private modules, `core::iter::traits::iterator::Iterator`
     use core::iter::Iterator;
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs
index c12c459c7eb..e22b4f61f3e 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.rs
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs
@@ -45,8 +45,8 @@ fn std_instead_of_core() {
 
     let _ = std::env!("PATH");
 
-    // do not lint until `error_in_core` is stable
     use std::error::Error;
+    //~^ ERROR: used import from `std` instead of `core`
 
     // lint items re-exported from private modules, `core::iter::traits::iterator::Iterator`
     use std::iter::Iterator;
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index 8f920511cc5..22cb9db7050 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -50,6 +50,12 @@ LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
    |                           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
+  --> tests/ui/std_instead_of_core.rs:48:9
+   |
+LL |     use std::error::Error;
+   |         ^^^ help: consider importing the item from `core`: `core`
+
+error: used import from `std` instead of `core`
   --> tests/ui/std_instead_of_core.rs:52:9
    |
 LL |     use std::iter::Iterator;
@@ -79,5 +85,5 @@ LL |     use alloc::slice::from_ref;
    = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unicode.stderr b/src/tools/clippy/tests/ui/unicode.stderr
index 9c365e1097d..b004493300e 100644
--- a/src/tools/clippy/tests/ui/unicode.stderr
+++ b/src/tools/clippy/tests/ui/unicode.stderr
@@ -11,7 +11,7 @@ error: invisible character detected
   --> tests/ui/unicode.rs:7:12
    |
 LL |     print!("Here >­< is a SHY, and ­another");
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{AD}< is a SHY, and \u{AD}another"`
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{AD}< is a SHY, and \u{AD}another"`
 
 error: invisible character detected
   --> tests/ui/unicode.rs:9:12
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index a2cdf800a97..a5475a158de 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -94,7 +94,7 @@ pub struct TestProps {
     // Extra flags to pass to the compiler
     pub compile_flags: Vec<String>,
     // Extra flags to pass when the compiled code is run (such as --bench)
-    pub run_flags: Option<String>,
+    pub run_flags: Vec<String>,
     // If present, the name of a file that this test should match when
     // pretty-printed
     pub pp_exact: Option<PathBuf>,
@@ -107,6 +107,9 @@ pub struct TestProps {
     // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies
     // to build and pass with the `--extern` flag.
     pub aux_crates: Vec<(String, String)>,
+    /// Similar to `aux_builds`, but also passes the resulting dylib path to
+    /// `-Zcodegen-backend`.
+    pub aux_codegen_backend: Option<String>,
     // Environment settings to use for compiling
     pub rustc_env: Vec<(String, String)>,
     // Environment variables to unset prior to compiling.
@@ -231,6 +234,7 @@ mod directives {
     pub const AUX_BIN: &'static str = "aux-bin";
     pub const AUX_BUILD: &'static str = "aux-build";
     pub const AUX_CRATE: &'static str = "aux-crate";
+    pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend";
     pub const EXEC_ENV: &'static str = "exec-env";
     pub const RUSTC_ENV: &'static str = "rustc-env";
     pub const UNSET_EXEC_ENV: &'static str = "unset-exec-env";
@@ -262,11 +266,12 @@ impl TestProps {
             error_patterns: vec![],
             regex_error_patterns: vec![],
             compile_flags: vec![],
-            run_flags: None,
+            run_flags: vec![],
             pp_exact: None,
             aux_builds: vec![],
             aux_bins: vec![],
             aux_crates: vec![],
+            aux_codegen_backend: None,
             revisions: vec![],
             rustc_env: vec![
                 ("RUSTC_ICE".to_string(), "0".to_string()),
@@ -399,7 +404,9 @@ impl TestProps {
 
                     config.parse_and_update_revisions(ln, &mut self.revisions);
 
-                    config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r);
+                    if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) {
+                        self.run_flags.extend(split_flags(&flags));
+                    }
 
                     if self.pp_exact.is_none() {
                         self.pp_exact = config.parse_pp_exact(ln, testfile);
@@ -444,6 +451,9 @@ impl TestProps {
                         &mut self.aux_crates,
                         Config::parse_aux_crate,
                     );
+                    if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) {
+                        self.aux_codegen_backend = Some(r.trim().to_owned());
+                    }
                     config.push_name_value_directive(
                         ln,
                         EXEC_ENV,
@@ -720,6 +730,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "assembly-output",
     "aux-bin",
     "aux-build",
+    "aux-codegen-backend",
     "aux-crate",
     "build-aux-docs",
     "build-fail",
@@ -799,6 +810,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-none",
     "ignore-nto",
     "ignore-nvptx64",
+    "ignore-nvptx64-nvidia-cuda",
     "ignore-openbsd",
     "ignore-pass",
     "ignore-remote",
@@ -842,9 +854,9 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-asm-support",
     "needs-dlltool",
     "needs-dynamic-linking",
+    "needs-force-clang-based-tests",
     "needs-git-hash",
     "needs-llvm-components",
-    "needs-matching-clang",
     "needs-profiler-support",
     "needs-relocation-model-pic",
     "needs-run-enabled",
@@ -1267,6 +1279,8 @@ fn expand_variables(mut value: String, config: &Config) -> String {
     const CWD: &str = "{{cwd}}";
     const SRC_BASE: &str = "{{src-base}}";
     const BUILD_BASE: &str = "{{build-base}}";
+    const SYSROOT_BASE: &str = "{{sysroot-base}}";
+    const TARGET_LINKER: &str = "{{target-linker}}";
 
     if value.contains(CWD) {
         let cwd = env::current_dir().unwrap();
@@ -1281,6 +1295,14 @@ fn expand_variables(mut value: String, config: &Config) -> String {
         value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy());
     }
 
+    if value.contains(SYSROOT_BASE) {
+        value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_string_lossy());
+    }
+
+    if value.contains(TARGET_LINKER) {
+        value = value.replace(TARGET_LINKER, config.target_linker.as_deref().unwrap_or(""));
+    }
+
     value
 }
 
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 7bc7e4b8680..b96832db67b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -100,9 +100,9 @@ pub(super) fn handle_needs(
             ignore_reason: "ignored when profiler support is disabled",
         },
         Need {
-            name: "needs-matching-clang",
+            name: "needs-force-clang-based-tests",
             condition: config.run_clang_based_tests_with.is_some(),
-            ignore_reason: "ignored when the used clang does not match the built LLVM",
+            ignore_reason: "ignored when RUSTBUILD_FORCE_CLANG_BASED_TESTS is not set",
         },
         Need {
             name: "needs-xray",
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 9bd0002a3d9..dbe016b8305 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -15,7 +15,7 @@ use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
 use crate::json;
 use crate::read2::{read2_abbreviated, Truncated};
-use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt};
+use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, PathBufExt};
 use crate::ColorConfig;
 use colored::Colorize;
 use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
@@ -1833,6 +1833,16 @@ impl<'test> TestCx<'test> {
                 ));
             }
         }
+
+        // Build any `//@ aux-codegen-backend`, and pass the resulting library
+        // to `-Zcodegen-backend` when compiling the test file.
+        if let Some(aux_file) = &self.props.aux_codegen_backend {
+            let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false);
+            if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
+                let lib_path = aux_dir.join(&lib_name);
+                rustc.arg(format!("-Zcodegen-backend={}", lib_path.display()));
+            }
+        }
     }
 
     fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
@@ -2254,6 +2264,9 @@ impl<'test> TestCx<'test> {
         }
 
         match output_file {
+            // If the test's compile flags specify an output path with `-o`,
+            // avoid a compiler warning about `--out-dir` being ignored.
+            _ if self.props.compile_flags.iter().any(|flag| flag == "-o") => {}
             TargetLocation::ThisFile(path) => {
                 rustc.arg("-o").arg(path);
             }
@@ -2355,7 +2368,7 @@ impl<'test> TestCx<'test> {
         args.push(exe_file.into_os_string());
 
         // Add the arguments in the run_flags directive
-        args.extend(self.split_maybe_args(&self.props.run_flags));
+        args.extend(self.props.run_flags.iter().map(OsString::from));
 
         let prog = args.remove(0);
         ProcArgs { prog, args }
@@ -2469,6 +2482,7 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    #[track_caller]
     fn fatal(&self, err: &str) -> ! {
         self.error(err);
         error!("fatal error, panic: {:?}", err);
@@ -3457,6 +3471,21 @@ impl<'test> TestCx<'test> {
         let rmake_out_dir = base_dir.join("rmake_out");
         create_dir_all(&rmake_out_dir).unwrap();
 
+        // Copy all input files (apart from rmake.rs) to the temporary directory,
+        // so that the input directory structure from `tests/run-make/<test>` is mirrored
+        // to the `rmake_out` directory.
+        for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
+            let path = path.unwrap().path().to_path_buf();
+            if path.file_name().is_some_and(|s| s != "rmake.rs") {
+                let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap());
+                if path.is_dir() {
+                    copy_dir_all(&path, target).unwrap();
+                } else {
+                    fs::copy(&path, target).unwrap();
+                }
+            }
+        }
+
         // HACK: assume stageN-target, we only want stageN.
         let stage = self.config.stage_id.split('-').next().unwrap();
 
@@ -3514,21 +3543,13 @@ impl<'test> TestCx<'test> {
             .arg(&self.testpaths.file.join("rmake.rs"))
             .env("TARGET", &self.config.target)
             .env("PYTHON", &self.config.python)
-            .env("S", &src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &rmake_out_dir)
             .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
             .env(dylib_env_var(), &host_dylib_env_paths)
             .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
             .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-            .env("LLVM_COMPONENTS", &self.config.llvm_components)
-            // We for sure don't want these tests to run in parallel, so make
-            // sure they don't have access to these vars if we run via `make`
-            // at the top level
-            .env_remove("MAKEFLAGS")
-            .env_remove("MFLAGS")
-            .env_remove("CARGO_MAKEFLAGS");
+            .env("LLVM_COMPONENTS", &self.config.llvm_components);
 
         if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
             let mut stage0_sysroot = build_root.clone();
@@ -3558,7 +3579,7 @@ impl<'test> TestCx<'test> {
         let target_rpath_env_path = env::join_paths(target_rpath_env_path).unwrap();
 
         let mut cmd = Command::new(&recipe_bin);
-        cmd.current_dir(&self.testpaths.file)
+        cmd.current_dir(&rmake_out_dir)
             .stdout(Stdio::piped())
             .stderr(Stdio::piped())
             .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
@@ -3566,19 +3587,12 @@ impl<'test> TestCx<'test> {
             .env(dylib_env_var(), &dylib_env_paths)
             .env("TARGET", &self.config.target)
             .env("PYTHON", &self.config.python)
-            .env("S", &src_root)
+            .env("SOURCE_ROOT", &src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &rmake_out_dir)
             .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
             .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-            .env("LLVM_COMPONENTS", &self.config.llvm_components)
-            // We for sure don't want these tests to run in parallel, so make
-            // sure they don't have access to these vars if we run via `make`
-            // at the top level
-            .env_remove("MAKEFLAGS")
-            .env_remove("MFLAGS")
-            .env_remove("CARGO_MAKEFLAGS");
+            .env("LLVM_COMPONENTS", &self.config.llvm_components);
 
         if let Some(ref rustdoc) = self.config.rustdoc_path {
             cmd.env("RUSTDOC", cwd.join(rustdoc));
@@ -4173,10 +4187,12 @@ impl<'test> TestCx<'test> {
     }
 
     fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
-        let rflags = self.props.run_flags.as_ref();
+        // Crude heuristic to detect when the output should have JSON-specific
+        // normalization steps applied.
+        let rflags = self.props.run_flags.join(" ");
         let cflags = self.props.compile_flags.join(" ");
-        let json = rflags
-            .map_or(false, |s| s.contains("--format json") || s.contains("--format=json"))
+        let json = rflags.contains("--format json")
+            || rflags.contains("--format=json")
             || cflags.contains("--error-format json")
             || cflags.contains("--error-format pretty-json")
             || cflags.contains("--error-format=json")
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 09a7f0395cf..ec20bda8c18 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -1,7 +1,7 @@
 use crate::common::Config;
 use std::env;
 use std::ffi::OsStr;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 
 use tracing::*;
@@ -76,3 +76,17 @@ pub fn add_dylib_path(cmd: &mut Command, paths: impl Iterator<Item = impl Into<P
     let new_paths = paths.map(Into::into).chain(old_paths.into_iter().flatten());
     cmd.env(dylib_env_var(), env::join_paths(new_paths).unwrap());
 }
+
+pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Result<()> {
+    std::fs::create_dir_all(&dst)?;
+    for entry in std::fs::read_dir(src)? {
+        let entry = entry?;
+        let ty = entry.file_type()?;
+        if ty.is_dir() {
+            copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
+        } else {
+            std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
+        }
+    }
+    Ok(())
+}
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index 9bd04e11cb3..525de03bbce 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -150,7 +150,7 @@ impl Kind {
             ItemEnum::Impl(_) => Impl,
             ItemEnum::TypeAlias(_) => TypeAlias,
             ItemEnum::OpaqueTy(_) => OpaqueTy,
-            ItemEnum::Constant(_) => Constant,
+            ItemEnum::Constant { .. } => Constant,
             ItemEnum::Static(_) => Static,
             ItemEnum::Macro(_) => Macro,
             ItemEnum::ProcMacro(_) => ProcMacro,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 904c2b614f3..5e35ce242fe 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -101,7 +101,10 @@ impl<'a> Validator<'a> {
                 ItemEnum::Impl(x) => self.check_impl(x, id),
                 ItemEnum::TypeAlias(x) => self.check_type_alias(x),
                 ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
-                ItemEnum::Constant(x) => self.check_constant(x),
+                ItemEnum::Constant { type_, const_ } => {
+                    self.check_type(type_);
+                    self.check_constant(const_);
+                }
                 ItemEnum::Static(x) => self.check_static(x),
                 ItemEnum::ForeignType => {} // nop
                 ItemEnum::Macro(x) => self.check_macro(x),
@@ -231,8 +234,8 @@ impl<'a> Validator<'a> {
         self.check_generics(&x.generics);
     }
 
-    fn check_constant(&mut self, x: &'a Constant) {
-        self.check_type(&x.type_);
+    fn check_constant(&mut self, _x: &'a Constant) {
+        // nop
     }
 
     fn check_static(&mut self, x: &'a Static) {
diff --git a/src/tools/libcxx-version/main.cpp b/src/tools/libcxx-version/main.cpp
new file mode 100644
index 00000000000..79df7ef457c
--- /dev/null
+++ b/src/tools/libcxx-version/main.cpp
@@ -0,0 +1,26 @@
+// Detecting the standard library version manually using a bunch of shell commands is very
+// complicated and fragile across different platforms. This program provides the major version
+// of the standard library on any target platform without requiring any messy work.
+//
+// It's nothing more than specifying the name of the standard library implementation (either libstdc++ or libc++)
+// and its major version.
+
+#include <iostream>
+
+int main() {
+    #ifdef _GLIBCXX_RELEASE
+        std::cout << "libstdc++ version: " << _GLIBCXX_RELEASE << std::endl;
+    #elif defined(_LIBCPP_VERSION)
+        // _LIBCPP_VERSION follows "XXYYZZ" format (e.g., 170001 for 17.0.1).
+        // ref: https://github.com/llvm/llvm-project/blob/f64732195c1030ee2627ff4e4142038e01df1d26/libcxx/include/__config#L51-L54
+        //
+        // Since we use the major version from _GLIBCXX_RELEASE, we need to extract only the first 2 characters of _LIBCPP_VERSION
+        // to provide the major version for consistency.
+        std::cout << "libc++ version: " << std::to_string(_LIBCPP_VERSION).substr(0, 2) << std::endl;
+    #else
+        std::cerr << "Coudln't recognize the standard library version." << std::endl;
+        return 1;
+    #endif
+
+    return 0;
+}
diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index 092ad46a7ca..9067cbc6032 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -223,7 +223,7 @@ will eventually sync those changes back into this repository.
 When working on Miri in the rustc tree, here's how you can run tests:
 
 ```
-./x.py test miri --stage 0
+./x.py test miri
 ```
 
 `--bless` will work, too.
@@ -231,7 +231,7 @@ When working on Miri in the rustc tree, here's how you can run tests:
 You can also directly run Miri on a Rust source file:
 
 ```
-./x.py run miri --stage 0 --args src/tools/miri/tests/pass/hello.rs
+./x.py run miri --stage 1 --args src/tools/miri/tests/pass/hello.rs
 ```
 
 ## Advanced topic: Syncing with the rustc repo
@@ -287,7 +287,22 @@ https. Add the following to your `.gitconfig`:
     pushInsteadOf = https://github.com/
 ```
 
-## Internal environment variables
+## Further environment variables
+
+The following environment variables are relevant to `./miri`:
+
+* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup
+  (as controlled by the `./auto-*` files) should be skipped. If it is set to `no`, they are skipped.
+  This is used to allow automated IDE actions to avoid the auto ops.
+* `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during Miri executions.
+* `MIRI_TEST_THREADS` (recognized by `./miri test`) sets the number of threads to use for running
+  tests. By default, the number of cores is used.
+* `MIRI_SKIP_UI_CHECKS` (recognized by `./miri test`) disables checking that the `stderr` or
+  `stdout` files match the actual output.
+
+Furthermore, the usual environment variables recognized by `cargo miri` also work for `./miri`, e.g.
+`MIRI_LIB_SRC`. Note that `MIRIFLAGS` is ignored by `./miri test` as each test controls the flags it
+is run with.
 
 The following environment variables are *internal* and must not be used by
 anyone but Miri itself. They are used to communicate between different Miri
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 208a8b9ee61..c437619a76e 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -448,28 +448,19 @@ Some native rustc `-Z` flags are also very relevant for Miri:
 * `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
   enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows].
 
-Moreover, Miri recognizes some environment variables (unless noted otherwise, these are supported
-by all intended entry points, i.e. `cargo miri` and `./miri {test,run}`):
-
-* `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup
-  should be skipped. If it is set to `no`, they are skipped. This is used to allow automated IDE
-  actions to avoid the auto ops.
-* `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during
-  Miri executions, also [see "Testing the Miri driver" in `CONTRIBUTING.md`][testing-miri].
+Moreover, Miri recognizes some environment variables:
+
 * `MIRIFLAGS` defines extra flags to be passed to Miri.
 * `MIRI_LIB_SRC` defines the directory where Miri expects the sources of the standard library that
   it will build and use for interpretation. This directory must point to the `library` subdirectory
   of a `rust-lang/rust` repository checkout.
-* `MIRI_SYSROOT` indicates the sysroot to use. When using `cargo miri`, this skips the automatic
+* `MIRI_SYSROOT` indicates the sysroot to use. When using `cargo miri test`/`cargo miri run`, this skips the automatic
   setup -- only set this if you do not want to use the automatically created sysroot. When invoking
   `cargo miri setup`, this indicates where the sysroot will be put.
-* `MIRI_TEST_THREADS` (recognized by `./miri test`): set the number of threads to use for running tests.
-  By default, the number of cores is used.
 * `MIRI_NO_STD` makes sure that the target's sysroot is built without libstd. This allows testing
-  and running no_std programs. (Miri has a heuristic to detect no-std targets based on the target
-  name; this environment variable is only needed when that heuristic fails.)
-* `MIRI_SKIP_UI_CHECKS` (recognized by `./miri test`): don't check whether the
-  `stderr` or `stdout` files match the actual output.
+  and running no_std programs. This should *not usually be used*; Miri has a heuristic to detect
+  no-std targets based on the target name. Setting this on a target that does support libstd can
+  lead to confusing results.
 
 [testing-miri]: CONTRIBUTING.md#testing-the-miri-driver
 
diff --git a/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.lock b/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.lock
new file mode 100644
index 00000000000..da0db7f47ea
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "big-allocs"
+version = "0.1.0"
diff --git a/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.toml b/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.toml
new file mode 100644
index 00000000000..7234c9371cf
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/big-allocs/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "big-allocs"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs b/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs
new file mode 100644
index 00000000000..a1c1708cf3b
--- /dev/null
+++ b/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs
@@ -0,0 +1,13 @@
+//! This is a regression test for https://github.com/rust-lang/miri/issues/3637.
+//! `Allocation`s are backed by a `Box<[u8]>`, which we create using `alloc_zeroed`, which should
+//! make very large allocations cheap. But then we also need to not clone those `Allocation`s, or
+//! we end up slow anyway.
+
+fn main() {
+    // We can't use too big of an allocation or this code will encounter an allocation failure in
+    // CI. Since the allocation can't be huge, we need to do a few iterations so that the effect
+    // we're trying to measure is clearly visible above the interpreter's startup time.
+    for _ in 0..10 {
+        drop(Vec::<u8>::with_capacity(512 * 1024 * 1024));
+    }
+}
diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs
index 9fdd4c3e470..7d9f77f3752 100644
--- a/src/tools/miri/cargo-miri/src/main.rs
+++ b/src/tools/miri/cargo-miri/src/main.rs
@@ -1,15 +1,14 @@
 #![allow(clippy::useless_format, clippy::derive_partial_eq_without_eq, rustc::internal)]
 
-#[macro_use]
-mod util;
-
 mod arg;
 mod phases;
 mod setup;
+mod util;
 
 use std::{env, iter};
 
 use crate::phases::*;
+use crate::util::show_error;
 
 /// Returns `true` if our flags look like they may be for rustdoc, i.e., this is cargo calling us to
 /// be rustdoc. It's hard to be sure as cargo does not have a RUSTDOC_WRAPPER or an env var that
diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs
index 28a824e54f6..f36cff1f798 100644
--- a/src/tools/miri/cargo-miri/src/util.rs
+++ b/src/tools/miri/cargo-miri/src/util.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
 use std::env;
 use std::ffi::OsString;
 use std::fs::File;
@@ -11,14 +12,15 @@ use serde::{Deserialize, Serialize};
 
 pub use crate::arg::*;
 
-pub fn show_error(msg: &impl std::fmt::Display) -> ! {
+pub fn show_error_(msg: &impl std::fmt::Display) -> ! {
     eprintln!("fatal error: {msg}");
     std::process::exit(1)
 }
 
 macro_rules! show_error {
-    ($($tt:tt)*) => { crate::util::show_error(&format_args!($($tt)*)) };
+    ($($tt:tt)*) => { crate::util::show_error_(&format_args!($($tt)*)) };
 }
+pub(crate) use show_error;
 
 /// The information to run a crate with the given environment.
 #[derive(Clone, Serialize, Deserialize)]
@@ -232,21 +234,18 @@ pub fn get_cargo_metadata() -> Metadata {
 }
 
 /// Pulls all the crates in this workspace from the cargo metadata.
-/// Workspace members are emitted like "miri 0.1.0 (path+file:///path/to/miri)"
 /// Additionally, somewhere between cargo metadata and TyCtxt, '-' gets replaced with '_' so we
 /// make that same transformation here.
 pub fn local_crates(metadata: &Metadata) -> String {
     assert!(!metadata.workspace_members.is_empty());
-    let mut local_crates = String::new();
-    for member in &metadata.workspace_members {
-        let name = member.repr.split(' ').next().unwrap();
-        let name = name.replace('-', "_");
-        local_crates.push_str(&name);
-        local_crates.push(',');
-    }
-    local_crates.pop(); // Remove the trailing ','
-
-    local_crates
+    let package_name_by_id: HashMap<_, _> =
+        metadata.packages.iter().map(|package| (&package.id, package.name.as_str())).collect();
+    metadata
+        .workspace_members
+        .iter()
+        .map(|id| package_name_by_id[id].replace('-', "_"))
+        .collect::<Vec<_>>()
+        .join(",")
 }
 
 /// Debug-print a command that is going to be run.
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index f97a611b364..67985f9b7d6 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -148,8 +148,8 @@ case $HOST_TARGET in
     UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
     TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
     TEST_TARGET=i686-unknown-freebsd   run_tests_minimal $BASIC $UNIX threadname libc-time fs
-    TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX threadname pthread-sync libc-time
-    TEST_TARGET=x86_64-pc-solaris      run_tests_minimal $BASIC $UNIX threadname pthread-sync libc-time
+    TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time
+    TEST_TARGET=x86_64-pc-solaris      run_tests_minimal $BASIC $UNIX threadname pthread-sync available-parallelism libc-time
     TEST_TARGET=aarch64-linux-android  run_tests_minimal $BASIC $UNIX
     TEST_TARGET=wasm32-wasip2          run_tests_minimal empty_main wasm heap_alloc libc-mem
     TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index aa06a0dbcdc..0f738653b14 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-21e6de7eb64c09102de3f100420a09edc1a2a8d7
+565cadb514d35e7b851540edbc172af0f606014f
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 002e1062061..ae95d28d3eb 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -257,7 +257,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn ptr_from_addr_cast(&self, addr: u64) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn ptr_from_addr_cast(&self, addr: u64) -> InterpResult<'tcx, Pointer> {
         trace!("Casting {:#x} to a pointer", addr);
 
         let ecx = self.eval_context_ref();
@@ -297,10 +297,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Convert a relative (tcx) pointer to a Miri pointer.
     fn adjust_alloc_root_pointer(
         &self,
-        ptr: Pointer<CtfeProvenance>,
+        ptr: interpret::Pointer<CtfeProvenance>,
         tag: BorTag,
         kind: MemoryKind,
-    ) -> InterpResult<'tcx, Pointer<Provenance>> {
+    ) -> InterpResult<'tcx, interpret::Pointer<Provenance>> {
         let ecx = self.eval_context_ref();
 
         let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
@@ -310,12 +310,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // Add offset with the right kind of pointer-overflowing arithmetic.
         let dl = ecx.data_layout();
         let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0;
-        Ok(Pointer::new(Provenance::Concrete { alloc_id, tag }, Size::from_bytes(absolute_addr)))
+        Ok(interpret::Pointer::new(
+            Provenance::Concrete { alloc_id, tag },
+            Size::from_bytes(absolute_addr),
+        ))
     }
 
     /// When a pointer is used for a memory access, this computes where in which allocation the
     /// access is going.
-    fn ptr_get_alloc(&self, ptr: Pointer<Provenance>) -> Option<(AllocId, Size)> {
+    fn ptr_get_alloc(&self, ptr: interpret::Pointer<Provenance>) -> Option<(AllocId, Size)> {
         let ecx = self.eval_context_ref();
 
         let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index d748febeed4..829bfa7cd70 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -8,7 +8,6 @@
 )]
 
 // Some "regular" crates we want to share with rustc
-#[macro_use]
 extern crate tracing;
 
 // The rustc crates we need
@@ -26,6 +25,8 @@ use std::num::NonZero;
 use std::path::PathBuf;
 use std::str::FromStr;
 
+use tracing::debug;
+
 use rustc_data_structures::sync::Lrc;
 use rustc_driver::Compilation;
 use rustc_hir::{self as hir, Node};
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index a55ec427d5f..c9e7e300593 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -281,8 +281,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn retag_ptr_value(
         &mut self,
         kind: RetagKind,
-        val: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        val: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
@@ -294,7 +294,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn retag_place_contents(
         &mut self,
         kind: RetagKind,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
@@ -304,10 +304,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn protect_place(
-        &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    fn protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
@@ -327,7 +324,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn give_pointer_debug_name(
         &mut self,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         nth_parent: u8,
         name: &str,
     ) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 8270a8c321c..87d9057cb89 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -149,11 +149,7 @@ impl<'ecx, 'tcx> DiagnosticCxBuilder<'ecx, 'tcx> {
         DiagnosticCxBuilder { machine, operation }
     }
 
-    pub fn read(
-        machine: &'ecx MiriMachine<'tcx>,
-        tag: ProvenanceExtra,
-        range: AllocRange,
-    ) -> Self {
+    pub fn read(machine: &'ecx MiriMachine<'tcx>, tag: ProvenanceExtra, range: AllocRange) -> Self {
         let operation = Operation::Access(AccessOp { kind: AccessKind::Read, tag, range });
         DiagnosticCxBuilder { machine, operation }
     }
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 2786668695e..603733f9dc0 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -531,7 +531,7 @@ impl Stacks {
         trace!(
             "read access with tag {:?}: {:?}, size {}",
             tag,
-            Pointer::new(alloc_id, range.start),
+            interpret::Pointer::new(alloc_id, range.start),
             range.size.bytes()
         );
         let dcx = DiagnosticCxBuilder::read(machine, tag, range);
@@ -552,7 +552,7 @@ impl Stacks {
         trace!(
             "write access with tag {:?}: {:?}, size {}",
             tag,
-            Pointer::new(alloc_id, range.start),
+            interpret::Pointer::new(alloc_id, range.start),
             range.size.bytes()
         );
         let dcx = DiagnosticCxBuilder::write(machine, tag, range);
@@ -587,7 +587,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns the provenance that should be used henceforth.
     fn sb_reborrow(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         size: Size,
         new_perm: NewPermission,
         new_tag: BorTag,
@@ -692,7 +692,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
             new_tag,
             orig_tag,
             place.layout.ty,
-            Pointer::new(alloc_id, base_offset),
+            interpret::Pointer::new(alloc_id, base_offset),
             size.bytes()
         );
 
@@ -809,10 +809,10 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
 
     fn sb_retag_place(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         new_perm: NewPermission,
         info: RetagInfo, // diagnostics info about this retag
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
         let size = this.size_and_align_of_mplace(place)?.map(|(size, _)| size);
         // FIXME: If we cannot determine the size (because the unsized tail is an `extern type`),
@@ -839,10 +839,10 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
     /// `kind` indicates what kind of reference is being created.
     fn sb_retag_reference(
         &mut self,
-        val: &ImmTy<'tcx, Provenance>,
+        val: &ImmTy<'tcx>,
         new_perm: NewPermission,
         info: RetagInfo, // diagnostics info about this retag
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         let place = this.ref_to_mplace(val)?;
         let new_place = this.sb_retag_place(&place, new_perm, info)?;
@@ -855,8 +855,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn sb_retag_ptr_value(
         &mut self,
         kind: RetagKind,
-        val: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        val: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
         let cause = match kind {
@@ -870,7 +870,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn sb_retag_place_contents(
         &mut self,
         kind: RetagKind,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
@@ -895,7 +895,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
             fn retag_ptr_inplace(
                 &mut self,
-                place: &PlaceTy<'tcx, Provenance>,
+                place: &PlaceTy<'tcx>,
                 new_perm: NewPermission,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
@@ -909,18 +909,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
         }
         impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> {
-            type V = PlaceTy<'tcx, Provenance>;
+            type V = PlaceTy<'tcx>;
 
             #[inline(always)]
             fn ecx(&self) -> &MiriInterpCx<'tcx> {
                 self.ecx
             }
 
-            fn visit_box(
-                &mut self,
-                box_ty: Ty<'tcx>,
-                place: &PlaceTy<'tcx, Provenance>,
-            ) -> InterpResult<'tcx> {
+            fn visit_box(&mut self, box_ty: Ty<'tcx>, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> {
                 // Only boxes for the global allocator get any special treatment.
                 if box_ty.is_box_global(*self.ecx.tcx) {
                     // Boxes get a weak protectors, since they may be deallocated.
@@ -930,7 +926,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 Ok(())
             }
 
-            fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+            fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> {
                 // If this place is smaller than a pointer, we know that it can't contain any
                 // pointers we need to retag, so we can stop recursion early.
                 // This optimization is crucial for ZSTs, because they can contain way more fields
@@ -984,10 +980,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// call.
     ///
     /// This is used to ensure soundness of in-place function argument/return passing.
-    fn sb_protect_place(
-        &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
 
         // Retag it. With protection! That is the entire point.
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
index 3b6c29b5eb1..f65f49a75dd 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
@@ -2,6 +2,7 @@
 use std::ops::Range;
 
 use rustc_data_structures::fx::FxHashSet;
+use tracing::trace;
 
 use crate::borrow_tracker::{
     stacked_borrows::{Item, Permission},
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 e1c06b2bd98..77e003ab8a7 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -56,7 +56,7 @@ impl<'tcx> Tree {
             "{} with tag {:?}: {:?}, size {}",
             access_kind,
             prov,
-            Pointer::new(alloc_id, range.start),
+            interpret::Pointer::new(alloc_id, range.start),
             range.size.bytes(),
         );
         // TODO: for now we bail out on wildcard pointers. Eventually we should
@@ -195,7 +195,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns the provenance that should be used henceforth.
     fn tb_reborrow(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here
+        place: &MPlaceTy<'tcx>, // parent tag extracted from here
         ptr_size: Size,
         new_perm: NewPermission,
         new_tag: BorTag,
@@ -258,7 +258,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             new_tag,
             orig_tag,
             place.layout.ty,
-            Pointer::new(alloc_id, base_offset),
+            interpret::Pointer::new(alloc_id, base_offset),
             ptr_size.bytes()
         );
 
@@ -327,9 +327,9 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn tb_retag_place(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         new_perm: NewPermission,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
 
         // Determine the size of the reborrow.
@@ -366,9 +366,9 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Retags an individual pointer, returning the retagged version.
     fn tb_retag_reference(
         &mut self,
-        val: &ImmTy<'tcx, Provenance>,
+        val: &ImmTy<'tcx>,
         new_perm: NewPermission,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         let place = this.ref_to_mplace(val)?;
         let new_place = this.tb_retag_place(&place, new_perm)?;
@@ -383,8 +383,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn tb_retag_ptr_value(
         &mut self,
         kind: RetagKind,
-        val: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        val: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         let new_perm = match val.layout.ty.kind() {
             &ty::Ref(_, pointee, mutability) =>
@@ -402,7 +402,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn tb_retag_place_contents(
         &mut self,
         kind: RetagKind,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let options = this.machine.borrow_tracker.as_mut().unwrap().get_mut();
@@ -423,7 +423,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
             fn retag_ptr_inplace(
                 &mut self,
-                place: &PlaceTy<'tcx, Provenance>,
+                place: &PlaceTy<'tcx>,
                 new_perm: Option<NewPermission>,
             ) -> InterpResult<'tcx> {
                 if let Some(new_perm) = new_perm {
@@ -435,7 +435,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
         }
         impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> {
-            type V = PlaceTy<'tcx, Provenance>;
+            type V = PlaceTy<'tcx>;
 
             #[inline(always)]
             fn ecx(&self) -> &MiriInterpCx<'tcx> {
@@ -445,11 +445,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             /// Regardless of how `Unique` is handled, Boxes are always reborrowed.
             /// When `Unique` is also reborrowed, then it behaves exactly like `Box`
             /// except for the fact that `Box` has a non-zero-sized reborrow.
-            fn visit_box(
-                &mut self,
-                box_ty: Ty<'tcx>,
-                place: &PlaceTy<'tcx, Provenance>,
-            ) -> InterpResult<'tcx> {
+            fn visit_box(&mut self, box_ty: Ty<'tcx>, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> {
                 // Only boxes for the global allocator get any special treatment.
                 if box_ty.is_box_global(*self.ecx.tcx) {
                     let new_perm = NewPermission::from_unique_ty(
@@ -463,7 +459,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 Ok(())
             }
 
-            fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+            fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> {
                 // If this place is smaller than a pointer, we know that it can't contain any
                 // pointers we need to retag, so we can stop recursion early.
                 // This optimization is crucial for ZSTs, because they can contain way more fields
@@ -526,10 +522,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// call.
     ///
     /// This is used to ensure soundness of in-place function argument/return passing.
-    fn tb_protect_place(
-        &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
 
         // Retag it. With protection! That is the entire point.
@@ -581,7 +574,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// of `ptr` (with 0 representing `ptr` itself)
     fn tb_give_pointer_debug_name(
         &mut self,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         nth_parent: u8,
         name: &str,
     ) -> InterpResult<'tcx> {
@@ -604,8 +597,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 /// and output can be used by `retag_ptr_inplace`.
 fn inner_ptr_of_unique<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
-    place: &PlaceTy<'tcx, Provenance>,
-) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> {
+    place: &PlaceTy<'tcx>,
+) -> InterpResult<'tcx, PlaceTy<'tcx>> {
     // Follows the same layout as `interpret/visitor.rs:walk_value` for `Box` in
     // `rustc_const_eval`, just with one fewer layer.
     // Here we have a `Unique(NonNull(*mut), PhantomData)`
diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs
index fd0c121626b..c9bffc449f7 100644
--- a/src/tools/miri/src/clock.rs
+++ b/src/tools/miri/src/clock.rs
@@ -6,7 +6,7 @@ use std::time::{Duration, Instant as StdInstant};
 /// This number is pretty random, but it has been shown to approximately cause
 /// some sample programs to run within an order of magnitude of real time on desktop CPUs.
 /// (See `tests/pass/shims/time-with-isolation*.rs`.)
-const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000;
+const NANOSECONDS_PER_BASIC_BLOCK: u128 = 5000;
 
 #[derive(Debug)]
 pub struct Instant {
@@ -16,19 +16,24 @@ pub struct Instant {
 #[derive(Debug)]
 enum InstantKind {
     Host(StdInstant),
-    Virtual { nanoseconds: u64 },
+    Virtual { nanoseconds: u128 },
 }
 
 impl Instant {
-    pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
+    /// Will try to add `duration`, but if that overflows it may add less.
+    pub fn add_lossy(&self, duration: Duration) -> Instant {
         match self.kind {
-            InstantKind::Host(instant) =>
-                instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }),
-            InstantKind::Virtual { nanoseconds } =>
-                u128::from(nanoseconds)
-                    .checked_add(duration.as_nanos())
-                    .and_then(|n| u64::try_from(n).ok())
-                    .map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }),
+            InstantKind::Host(instant) => {
+                // If this overflows, try adding just 1h and assume that will not overflow.
+                let i = instant
+                    .checked_add(duration)
+                    .unwrap_or_else(|| instant.checked_add(Duration::from_secs(3600)).unwrap());
+                Instant { kind: InstantKind::Host(i) }
+            }
+            InstantKind::Virtual { nanoseconds } => {
+                let n = nanoseconds.saturating_add(duration.as_nanos());
+                Instant { kind: InstantKind::Virtual { nanoseconds: n } }
+            }
         }
     }
 
@@ -39,7 +44,17 @@ impl Instant {
             (
                 InstantKind::Virtual { nanoseconds },
                 InstantKind::Virtual { nanoseconds: earlier },
-            ) => Duration::from_nanos(nanoseconds.saturating_sub(earlier)),
+            ) => {
+                let duration = nanoseconds.saturating_sub(earlier);
+                // `Duration` does not provide a nice constructor from a `u128` of nanoseconds,
+                // so we have to implement this ourselves.
+                // It is possible for second to overflow because u64::MAX < (u128::MAX / 1e9).
+                // It will be saturated to u64::MAX seconds if the value after division exceeds u64::MAX.
+                let seconds = u64::try_from(duration / 1_000_000_000).unwrap_or(u64::MAX);
+                // It is impossible for nanosecond to overflow because u32::MAX > 1e9.
+                let nanosecond = u32::try_from(duration.wrapping_rem(1_000_000_000)).unwrap();
+                Duration::new(seconds, nanosecond)
+            }
             _ => panic!("all `Instant` must be of the same kind"),
         }
     }
@@ -54,12 +69,13 @@ pub struct Clock {
 #[derive(Debug)]
 enum ClockKind {
     Host {
-        /// The "time anchor" for this machine's monotone clock.
-        time_anchor: StdInstant,
+        /// The "epoch" for this machine's monotone clock:
+        /// the moment we consider to be time = 0.
+        epoch: StdInstant,
     },
     Virtual {
         /// The "current virtual time".
-        nanoseconds: Cell<u64>,
+        nanoseconds: Cell<u128>,
     },
 }
 
@@ -67,7 +83,7 @@ impl Clock {
     /// Create a new clock based on the availability of communication with the host.
     pub fn new(communicate: bool) -> Self {
         let kind = if communicate {
-            ClockKind::Host { time_anchor: StdInstant::now() }
+            ClockKind::Host { epoch: StdInstant::now() }
         } else {
             ClockKind::Virtual { nanoseconds: 0.into() }
         };
@@ -93,16 +109,19 @@ impl Clock {
             ClockKind::Host { .. } => std::thread::sleep(duration),
             ClockKind::Virtual { nanoseconds } => {
                 // Just pretend that we have slept for some time.
-                let nanos: u64 = duration.as_nanos().try_into().unwrap();
-                nanoseconds.update(|x| x + nanos);
+                let nanos: u128 = duration.as_nanos();
+                nanoseconds.update(|x| {
+                    x.checked_add(nanos)
+                        .expect("Miri's virtual clock cannot represent an execution this long")
+                });
             }
         }
     }
 
-    /// Return the `anchor` instant, to convert between monotone instants and durations relative to the anchor.
-    pub fn anchor(&self) -> Instant {
+    /// Return the `epoch` instant (time = 0), to convert between monotone instants and absolute durations.
+    pub fn epoch(&self) -> Instant {
         match &self.kind {
-            ClockKind::Host { time_anchor } => Instant { kind: InstantKind::Host(*time_anchor) },
+            ClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) },
             ClockKind::Virtual { .. } => Instant { kind: InstantKind::Virtual { nanoseconds: 0 } },
         }
     }
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 719c262290e..2baa09bec16 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -606,9 +606,9 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Perform an atomic read operation at the memory location.
     fn read_scalar_atomic(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicReadOrd,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
         this.atomic_access_check(place, AtomicAccessType::Load(atomic))?;
         // This will read from the last store in the modification order of this location. In case
@@ -625,8 +625,8 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Perform an atomic write operation at the memory location.
     fn write_scalar_atomic(
         &mut self,
-        val: Scalar<Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        val: Scalar,
+        dest: &MPlaceTy<'tcx>,
         atomic: AtomicWriteOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -645,12 +645,12 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Perform an atomic RMW operation on a memory location.
     fn atomic_rmw_op_immediate(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-        rhs: &ImmTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
+        rhs: &ImmTy<'tcx>,
         op: mir::BinOp,
         not: bool,
         atomic: AtomicRwOrd,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
@@ -670,10 +670,10 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// scalar value, the old value is returned.
     fn atomic_exchange_scalar(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-        new: Scalar<Provenance>,
+        place: &MPlaceTy<'tcx>,
+        new: Scalar,
         atomic: AtomicRwOrd,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
@@ -690,11 +690,11 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// scalar value, the old value is returned.
     fn atomic_min_max_scalar(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-        rhs: ImmTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
+        rhs: ImmTy<'tcx>,
         min: bool,
         atomic: AtomicRwOrd,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
         this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
@@ -726,9 +726,9 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// identical.
     fn atomic_compare_exchange_scalar(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
-        expect_old: &ImmTy<'tcx, Provenance>,
-        new: Scalar<Provenance>,
+        place: &MPlaceTy<'tcx>,
+        expect_old: &ImmTy<'tcx>,
+        new: Scalar,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
         can_fail_spuriously: bool,
@@ -948,7 +948,7 @@ impl VClockAlloc {
         mem_clocks: &MemoryCellClocks,
         access: AccessType,
         access_size: Size,
-        ptr_dbg: Pointer<AllocId>,
+        ptr_dbg: interpret::Pointer<AllocId>,
         ty: Option<Ty<'_>>,
     ) -> InterpResult<'tcx> {
         let (active_index, active_clocks) = global.active_thread_state(thread_mgr);
@@ -1063,7 +1063,7 @@ impl VClockAlloc {
                         mem_clocks,
                         AccessType::NaRead(read_type),
                         access_range.size,
-                        Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
+                        interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                         ty,
                     );
                 }
@@ -1108,7 +1108,7 @@ impl VClockAlloc {
                         mem_clocks,
                         AccessType::NaWrite(write_type),
                         access_range.size,
-                        Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
+                        interpret::Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
                         ty,
                     );
                 }
@@ -1163,7 +1163,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Checks that an atomic access is legal at the given place.
     fn atomic_access_check(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         access_type: AtomicAccessType,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
@@ -1219,7 +1219,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// associated memory-place and on the current thread.
     fn validate_atomic_load(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
@@ -1241,7 +1241,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// associated memory-place and on the current thread.
     fn validate_atomic_store(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicWriteOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -1263,7 +1263,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// at the associated memory place and on the current thread.
     fn validate_atomic_rmw(
         &mut self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx> {
         use AtomicRwOrd::*;
@@ -1292,7 +1292,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Generic atomic operation implementation
     fn validate_atomic_op<A: Debug + Copy>(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: A,
         access: AccessType,
         mut op: impl FnMut(
@@ -1337,7 +1337,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
                                     mem_clocks,
                                     access,
                                     place.layout.size,
-                                    Pointer::new(
+                                    interpret::Pointer::new(
                                         alloc_id,
                                         Size::from_bytes(mem_clocks_range.start),
                                     ),
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index ed10c128026..9145ef32c52 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -7,7 +7,7 @@ use super::sync::EvalContextExtPriv as _;
 use super::vector_clock::VClock;
 use crate::*;
 
-declare_id!(InitOnceId);
+super::sync::declare_id!(InitOnceId);
 
 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
 /// The current status of a one time initialization.
@@ -33,10 +33,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[inline]
     fn init_once_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, InitOnceId>
     where
-        F: FnOnce(
-            &mut MiriInterpCx<'tcx>,
-            InitOnceId,
-        ) -> InterpResult<'tcx, Option<InitOnceId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, InitOnceId) -> InterpResult<'tcx, Option<InitOnceId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.init_onces.next_index();
@@ -54,7 +51,7 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn init_once_get_or_create_id(
         &mut self,
-        lock_op: &OpTy<'tcx, Provenance>,
+        lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
     ) -> InterpResult<'tcx, InitOnceId> {
diff --git a/src/tools/miri/src/concurrency/mod.rs b/src/tools/miri/src/concurrency/mod.rs
index 15e1a94d6db..822d173ac06 100644
--- a/src/tools/miri/src/concurrency/mod.rs
+++ b/src/tools/miri/src/concurrency/mod.rs
@@ -1,8 +1,7 @@
 pub mod data_race;
+pub mod init_once;
 mod range_object_map;
-#[macro_use]
 pub mod sync;
-pub mod init_once;
 pub mod thread;
 mod vector_clock;
 pub mod weak_memory;
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 52036f4ed2c..76a045c4dc1 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -1,5 +1,6 @@
 use std::collections::{hash_map::Entry, VecDeque};
 use std::ops::Not;
+use std::time::Duration;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::{Idx, IndexVec};
@@ -55,12 +56,13 @@ macro_rules! declare_id {
         }
 
         impl $name {
-            pub fn to_u32_scalar(&self) -> Scalar<Provenance> {
+            pub fn to_u32_scalar(&self) -> Scalar {
                 Scalar::from_u32(self.0.get())
             }
         }
     };
 }
+pub(super) use declare_id;
 
 declare_id!(MutexId);
 
@@ -160,16 +162,14 @@ pub struct SynchronizationObjects {
 
 // Private extension trait for local helper methods
 impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExtPriv<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Lazily initialize the ID of this Miri sync structure.
     /// ('0' indicates uninit.)
     #[inline]
     fn get_or_create_id<Id: SyncId>(
         &mut self,
         next_id: Id,
-        lock_op: &OpTy<'tcx, Provenance>,
+        lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
     ) -> InterpResult<'tcx, Option<Id>> {
@@ -244,10 +244,7 @@ pub(super) trait EvalContextExtPriv<'tcx>:
     #[inline]
     fn condvar_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, CondvarId>
     where
-        F: FnOnce(
-            &mut MiriInterpCx<'tcx>,
-            CondvarId,
-        ) -> InterpResult<'tcx, Option<CondvarId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, CondvarId) -> InterpResult<'tcx, Option<CondvarId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.condvars.next_index();
@@ -266,8 +263,8 @@ pub(super) trait EvalContextExtPriv<'tcx>:
     fn condvar_reacquire_mutex(
         &mut self,
         mutex: MutexId,
-        retval: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
+        retval: Scalar,
+        dest: MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         if this.mutex_is_locked(mutex) {
@@ -291,7 +288,7 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mutex_get_or_create_id(
         &mut self,
-        lock_op: &OpTy<'tcx, Provenance>,
+        lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
     ) -> InterpResult<'tcx, MutexId> {
@@ -303,7 +300,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn rwlock_get_or_create_id(
         &mut self,
-        lock_op: &OpTy<'tcx, Provenance>,
+        lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
     ) -> InterpResult<'tcx, RwLockId> {
@@ -315,7 +312,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn condvar_get_or_create_id(
         &mut self,
-        lock_op: &OpTy<'tcx, Provenance>,
+        lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
     ) -> InterpResult<'tcx, CondvarId> {
@@ -397,12 +394,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Put the thread into the queue waiting for the mutex.
     /// Once the Mutex becomes available, `retval` will be written to `dest`.
     #[inline]
-    fn mutex_enqueue_and_block(
-        &mut self,
-        id: MutexId,
-        retval: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
-    ) {
+    fn mutex_enqueue_and_block(&mut self, id: MutexId, retval: Scalar, dest: MPlaceTy<'tcx>) {
         let this = self.eval_context_mut();
         assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
         let thread = this.active_thread();
@@ -413,8 +405,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             callback!(
                 @capture<'tcx> {
                     id: MutexId,
-                    retval: Scalar<Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
+                    retval: Scalar,
+                    dest: MPlaceTy<'tcx>,
                 }
                 @unblock = |this| {
                     assert!(!this.mutex_is_locked(id));
@@ -510,8 +502,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn rwlock_enqueue_and_block_reader(
         &mut self,
         id: RwLockId,
-        retval: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
+        retval: Scalar,
+        dest: MPlaceTy<'tcx>,
     ) {
         let this = self.eval_context_mut();
         let thread = this.active_thread();
@@ -523,8 +515,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             callback!(
                 @capture<'tcx> {
                     id: RwLockId,
-                    retval: Scalar<Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
+                    retval: Scalar,
+                    dest: MPlaceTy<'tcx>,
                 }
                 @unblock = |this| {
                     this.rwlock_reader_lock(id);
@@ -593,8 +585,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn rwlock_enqueue_and_block_writer(
         &mut self,
         id: RwLockId,
-        retval: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
+        retval: Scalar,
+        dest: MPlaceTy<'tcx>,
     ) {
         let this = self.eval_context_mut();
         assert!(this.rwlock_is_locked(id), "write-queueing on unlocked rwlock");
@@ -606,8 +598,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             callback!(
                 @capture<'tcx> {
                     id: RwLockId,
-                    retval: Scalar<Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
+                    retval: Scalar,
+                    dest: MPlaceTy<'tcx>,
                 }
                 @unblock = |this| {
                     this.rwlock_writer_lock(id);
@@ -632,10 +624,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         condvar: CondvarId,
         mutex: MutexId,
-        timeout: Option<Timeout>,
-        retval_succ: Scalar<Provenance>,
-        retval_timeout: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
+        timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>,
+        retval_succ: Scalar,
+        retval_timeout: Scalar,
+        dest: MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         if let Some(old_locked_count) = this.mutex_unlock(mutex)? {
@@ -659,9 +651,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 @capture<'tcx> {
                     condvar: CondvarId,
                     mutex: MutexId,
-                    retval_succ: Scalar<Provenance>,
-                    retval_timeout: Scalar<Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
+                    retval_succ: Scalar,
+                    retval_timeout: Scalar,
+                    dest: MPlaceTy<'tcx>,
                 }
                 @unblock = |this| {
                     // The condvar was signaled. Make sure we get the clock for that.
@@ -713,11 +705,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         addr: u64,
         bitset: u32,
-        timeout: Option<Timeout>,
-        retval_succ: Scalar<Provenance>,
-        retval_timeout: Scalar<Provenance>,
-        dest: MPlaceTy<'tcx, Provenance>,
-        errno_timeout: Scalar<Provenance>,
+        timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>,
+        retval_succ: Scalar,
+        retval_timeout: Scalar,
+        dest: MPlaceTy<'tcx>,
+        errno_timeout: Scalar,
     ) {
         let this = self.eval_context_mut();
         let thread = this.active_thread();
@@ -731,10 +723,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             callback!(
                 @capture<'tcx> {
                     addr: u64,
-                    retval_succ: Scalar<Provenance>,
-                    retval_timeout: Scalar<Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
-                    errno_timeout: Scalar<Provenance>,
+                    retval_succ: Scalar,
+                    retval_timeout: Scalar,
+                    dest: MPlaceTy<'tcx>,
+                    errno_timeout: Scalar,
                 }
                 @unblock = |this| {
                     let futex = this.machine.sync.futexes.get(&addr).unwrap();
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 06af72dadbd..6a2b99825ad 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -256,10 +256,10 @@ pub struct Thread<'tcx> {
     /// which then forwards it to 'Resume'. However this argument is implicit in MIR,
     /// so we have to store it out-of-band. When there are multiple active unwinds,
     /// the innermost one is always caught first, so we can store them as a stack.
-    pub(crate) panic_payloads: Vec<Scalar<Provenance>>,
+    pub(crate) panic_payloads: Vec<Scalar>,
 
     /// Last OS error location in memory. It is a 32-bit integer.
-    pub(crate) last_error: Option<MPlaceTy<'tcx, Provenance>>,
+    pub(crate) last_error: Option<MPlaceTy<'tcx>>,
 }
 
 pub type StackEmptyCallback<'tcx> =
@@ -407,7 +407,7 @@ impl VisitProvenance for Frame<'_, Provenance, FrameExtra<'_>> {
 
 /// The moment in time when a blocked thread should be woken up.
 #[derive(Debug)]
-pub enum Timeout {
+enum Timeout {
     Monotonic(Instant),
     RealTime(SystemTime),
 }
@@ -421,6 +421,34 @@ impl Timeout {
                 time.duration_since(SystemTime::now()).unwrap_or(Duration::ZERO),
         }
     }
+
+    /// Will try to add `duration`, but if that overflows it may add less.
+    fn add_lossy(&self, duration: Duration) -> Self {
+        match self {
+            Timeout::Monotonic(i) => Timeout::Monotonic(i.add_lossy(duration)),
+            Timeout::RealTime(s) => {
+                // If this overflows, try adding just 1h and assume that will not overflow.
+                Timeout::RealTime(
+                    s.checked_add(duration)
+                        .unwrap_or_else(|| s.checked_add(Duration::from_secs(3600)).unwrap()),
+                )
+            }
+        }
+    }
+}
+
+/// The clock to use for the timeout you are asking for.
+#[derive(Debug, Copy, Clone)]
+pub enum TimeoutClock {
+    Monotonic,
+    RealTime,
+}
+
+/// Whether the timeout is relative or absolute.
+#[derive(Debug, Copy, Clone)]
+pub enum TimeoutAnchor {
+    Relative,
+    Absolute,
 }
 
 /// A set of threads.
@@ -432,9 +460,8 @@ pub struct ThreadManager<'tcx> {
     ///
     /// Note that this vector also contains terminated threads.
     threads: IndexVec<ThreadId, Thread<'tcx>>,
-    /// A mapping from a thread-local static to an allocation id of a thread
-    /// specific allocation.
-    thread_local_alloc_ids: FxHashMap<(DefId, ThreadId), Pointer<Provenance>>,
+    /// A mapping from a thread-local static to the thread specific allocation.
+    thread_local_allocs: FxHashMap<(DefId, ThreadId), StrictPointer>,
     /// A flag that indicates that we should change the active thread.
     yield_active_thread: bool,
 }
@@ -443,7 +470,7 @@ impl VisitProvenance for ThreadManager<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let ThreadManager {
             threads,
-            thread_local_alloc_ids,
+            thread_local_allocs,
             active_thread: _,
             yield_active_thread: _,
         } = self;
@@ -451,7 +478,7 @@ impl VisitProvenance for ThreadManager<'_> {
         for thread in threads {
             thread.visit_provenance(visit);
         }
-        for ptr in thread_local_alloc_ids.values() {
+        for ptr in thread_local_allocs.values() {
             ptr.visit_provenance(visit);
         }
     }
@@ -465,7 +492,7 @@ impl<'tcx> Default for ThreadManager<'tcx> {
         Self {
             active_thread: ThreadId::MAIN_THREAD,
             threads,
-            thread_local_alloc_ids: Default::default(),
+            thread_local_allocs: Default::default(),
             yield_active_thread: false,
         }
     }
@@ -487,16 +514,16 @@ impl<'tcx> ThreadManager<'tcx> {
 
     /// Check if we have an allocation for the given thread local static for the
     /// active thread.
-    fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Provenance>> {
-        self.thread_local_alloc_ids.get(&(def_id, self.active_thread)).cloned()
+    fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<StrictPointer> {
+        self.thread_local_allocs.get(&(def_id, self.active_thread)).cloned()
     }
 
     /// Set the pointer for the allocation of the given thread local
     /// static for the active thread.
     ///
     /// Panics if a thread local is initialized twice for the same thread.
-    fn set_thread_local_alloc(&mut self, def_id: DefId, ptr: Pointer<Provenance>) {
-        self.thread_local_alloc_ids.try_insert((def_id, self.active_thread), ptr).unwrap();
+    fn set_thread_local_alloc(&mut self, def_id: DefId, ptr: StrictPointer) {
+        self.thread_local_allocs.try_insert((def_id, self.active_thread), ptr).unwrap();
     }
 
     /// Borrow the stack of the active thread.
@@ -848,7 +875,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn get_or_create_thread_local_alloc(
         &mut self,
         def_id: DefId,
-    ) -> InterpResult<'tcx, Pointer<Provenance>> {
+    ) -> InterpResult<'tcx, StrictPointer> {
         let this = self.eval_context_mut();
         let tcx = this.tcx;
         if let Some(old_alloc) = this.machine.threads.get_thread_local_alloc_id(def_id) {
@@ -864,7 +891,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
             let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
             // We make a full copy of this allocation.
-            let mut alloc = alloc.inner().adjust_from_tcx(&this.tcx, |ptr| this.global_root_pointer(ptr))?;
+            let mut alloc =
+                alloc.inner().adjust_from_tcx(&this.tcx, |ptr| this.global_root_pointer(ptr))?;
             // This allocation will be deallocated when the thread dies, so it is not in read-only memory.
             alloc.mutability = Mutability::Mut;
             // Create a fresh allocation with this content.
@@ -878,10 +906,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[inline]
     fn start_regular_thread(
         &mut self,
-        thread: Option<MPlaceTy<'tcx, Provenance>>,
-        start_routine: Pointer<Option<Provenance>>,
+        thread: Option<MPlaceTy<'tcx>>,
+        start_routine: Pointer,
         start_abi: Abi,
-        func_arg: ImmTy<'tcx, Provenance>,
+        func_arg: ImmTy<'tcx>,
         ret_layout: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx, ThreadId> {
         let this = self.eval_context_mut();
@@ -948,18 +976,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let gone_thread = this.active_thread();
         {
             let mut free_tls_statics = Vec::new();
-            this.machine.threads.thread_local_alloc_ids.retain(
-                |&(_def_id, thread), &mut alloc_id| {
-                    if thread != gone_thread {
-                        // A different thread, keep this static around.
-                        return true;
-                    }
-                    // Delete this static from the map and from memory.
-                    // We cannot free directly here as we cannot use `?` in this context.
-                    free_tls_statics.push(alloc_id);
-                    false
-                },
-            );
+            this.machine.threads.thread_local_allocs.retain(|&(_def_id, thread), &mut alloc_id| {
+                if thread != gone_thread {
+                    // A different thread, keep this static around.
+                    return true;
+                }
+                // Delete this static from the map and from memory.
+                // We cannot free directly here as we cannot use `?` in this context.
+                free_tls_statics.push(alloc_id);
+                false
+            });
             // Now free the TLS statics.
             for ptr in free_tls_statics {
                 match tls_alloc_action {
@@ -997,13 +1023,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn block_thread(
         &mut self,
         reason: BlockReason,
-        timeout: Option<Timeout>,
+        timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>,
         callback: impl UnblockCallback<'tcx> + 'tcx,
     ) {
         let this = self.eval_context_mut();
-        if !this.machine.communicate() && matches!(timeout, Some(Timeout::RealTime(..))) {
-            panic!("cannot have `RealTime` callback with isolation enabled!")
-        }
+        let timeout = timeout.map(|(clock, anchor, duration)| {
+            let anchor = match clock {
+                TimeoutClock::RealTime => {
+                    assert!(
+                        this.machine.communicate(),
+                        "cannot have `RealTime` timeout with isolation enabled!"
+                    );
+                    Timeout::RealTime(match anchor {
+                        TimeoutAnchor::Absolute => SystemTime::UNIX_EPOCH,
+                        TimeoutAnchor::Relative => SystemTime::now(),
+                    })
+                }
+                TimeoutClock::Monotonic =>
+                    Timeout::Monotonic(match anchor {
+                        TimeoutAnchor::Absolute => this.machine.clock.epoch(),
+                        TimeoutAnchor::Relative => this.machine.clock.now(),
+                    }),
+            };
+            anchor.add_lossy(duration)
+        });
         this.machine.threads.block_thread(reason, timeout, callback);
     }
 
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index 7a49f6d3470..e92eaa8f91f 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -148,7 +148,7 @@ struct StoreElement {
     // FIXME: this means the store must be fully initialized;
     // we will have to change this if we want to support atomics on
     // (partially) uninitialized data.
-    val: Scalar<Provenance>,
+    val: Scalar,
 
     /// Metadata about loads from this store element,
     /// behind a RefCell to keep load op take &self
@@ -197,7 +197,7 @@ impl StoreBufferAlloc {
     fn get_or_create_store_buffer<'tcx>(
         &self,
         range: AllocRange,
-        init: Scalar<Provenance>,
+        init: Scalar,
     ) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> {
         let access_type = self.store_buffers.borrow().access_type(range);
         let pos = match access_type {
@@ -222,7 +222,7 @@ impl StoreBufferAlloc {
     fn get_or_create_store_buffer_mut<'tcx>(
         &mut self,
         range: AllocRange,
-        init: Scalar<Provenance>,
+        init: Scalar,
     ) -> InterpResult<'tcx, &mut StoreBuffer> {
         let buffers = self.store_buffers.get_mut();
         let access_type = buffers.access_type(range);
@@ -244,7 +244,7 @@ impl StoreBufferAlloc {
 }
 
 impl<'tcx> StoreBuffer {
-    fn new(init: Scalar<Provenance>) -> Self {
+    fn new(init: Scalar) -> Self {
         let mut buffer = VecDeque::new();
         buffer.reserve(STORE_BUFFER_LIMIT);
         let mut ret = Self { buffer };
@@ -282,7 +282,7 @@ impl<'tcx> StoreBuffer {
         is_seqcst: bool,
         rng: &mut (impl rand::Rng + ?Sized),
         validate: impl FnOnce() -> InterpResult<'tcx>,
-    ) -> InterpResult<'tcx, (Scalar<Provenance>, LoadRecency)> {
+    ) -> InterpResult<'tcx, (Scalar, LoadRecency)> {
         // Having a live borrow to store_buffer while calling validate_atomic_load is fine
         // because the race detector doesn't touch store_buffer
 
@@ -307,7 +307,7 @@ impl<'tcx> StoreBuffer {
 
     fn buffered_write(
         &mut self,
-        val: Scalar<Provenance>,
+        val: Scalar,
         global: &DataRaceState,
         thread_mgr: &ThreadManager<'_>,
         is_seqcst: bool,
@@ -408,7 +408,7 @@ impl<'tcx> StoreBuffer {
     /// ATOMIC STORE IMPL in the paper (except we don't need the location's vector clock)
     fn store_impl(
         &mut self,
-        val: Scalar<Provenance>,
+        val: Scalar,
         index: VectorIdx,
         thread_clock: &VClock,
         is_seqcst: bool,
@@ -450,12 +450,7 @@ impl StoreElement {
     /// buffer regardless of subsequent loads by the same thread; if the earliest load of another
     /// thread doesn't happen before the current one, then no subsequent load by the other thread
     /// can happen before the current one.
-    fn load_impl(
-        &self,
-        index: VectorIdx,
-        clocks: &ThreadClockSet,
-        is_seqcst: bool,
-    ) -> Scalar<Provenance> {
+    fn load_impl(&self, index: VectorIdx, clocks: &ThreadClockSet, is_seqcst: bool) -> Scalar {
         let mut load_info = self.load_info.borrow_mut();
         load_info.sc_loaded |= is_seqcst;
         let _ = load_info.timestamps.try_insert(index, clocks.clock[index]);
@@ -467,10 +462,10 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn buffered_atomic_rmw(
         &mut self,
-        new_val: Scalar<Provenance>,
-        place: &MPlaceTy<'tcx, Provenance>,
+        new_val: Scalar,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicRwOrd,
-        init: Scalar<Provenance>,
+        init: Scalar,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
@@ -493,11 +488,11 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn buffered_atomic_read(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicReadOrd,
-        latest_in_mo: Scalar<Provenance>,
+        latest_in_mo: Scalar,
         validate: impl FnOnce() -> InterpResult<'tcx>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
         if let Some(global) = &this.machine.data_race {
             let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
@@ -534,10 +529,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn buffered_atomic_write(
         &mut self,
-        val: Scalar<Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        val: Scalar,
+        dest: &MPlaceTy<'tcx>,
         atomic: AtomicWriteOrd,
-        init: Scalar<Provenance>,
+        init: Scalar,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr())?;
@@ -579,9 +574,9 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// to perform load_impl on the latest store element
     fn perform_read_on_buffered_latest(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         atomic: AtomicReadOrd,
-        init: Scalar<Provenance>,
+        init: Scalar,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
 
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index d55f21d74ef..14e29aa423d 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -42,7 +42,7 @@ pub enum TerminationInfo {
     },
     DataRace {
         involves_non_atomic: bool,
-        ptr: Pointer<AllocId>,
+        ptr: interpret::Pointer<AllocId>,
         op1: RacingOp,
         op2: RacingOp,
         extra: Option<&'static str>,
@@ -128,7 +128,7 @@ pub enum NonHaltingDiagnostic {
         details: bool,
     },
     WeakMemoryOutdatedLoad {
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
     },
 }
 
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 5c3b8f2d2a0..87b53d87ac8 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -126,7 +126,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
     // the one in the sysroot and the one locally built by `cargo test`.)
     // FIXME: can we prefer the one from the sysroot?
     'crates: for krate in
-        tcx.used_crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name)
+        tcx.crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name)
     {
         let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX };
         // Go over the modules.
@@ -255,7 +255,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Evaluates the scalar at the specified path.
-    fn eval_path(&self, path: &[&str]) -> OpTy<'tcx, Provenance> {
+    fn eval_path(&self, path: &[&str]) -> OpTy<'tcx> {
         let this = self.eval_context_ref();
         let instance = this.resolve_path(path, Namespace::ValueNS);
         // We don't give a span -- this isn't actually used directly by the program anyway.
@@ -264,7 +264,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         });
         const_val.into()
     }
-    fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
+    fn eval_path_scalar(&self, path: &[&str]) -> Scalar {
         let this = self.eval_context_ref();
         let val = this.eval_path(path);
         this.read_scalar(&val)
@@ -272,7 +272,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Helper function to get a `libc` constant as a `Scalar`.
-    fn eval_libc(&self, name: &str) -> Scalar<Provenance> {
+    fn eval_libc(&self, name: &str) -> Scalar {
         self.eval_path_scalar(&["libc", name])
     }
 
@@ -293,7 +293,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Helper function to get a `windows` constant as a `Scalar`.
-    fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
+    fn eval_windows(&self, module: &str, name: &str) -> Scalar {
         self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal", "windows", module, name])
     }
 
@@ -374,7 +374,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let val = if dest.layout().abi.is_signed() {
             Scalar::from_int(i, dest.layout().size)
         } else {
-            Scalar::from_uint(u64::try_from(i.into()).unwrap(), dest.layout().size)
+            // `unwrap` can only fail here if `i` is negative
+            Scalar::from_uint(u128::try_from(i.into()).unwrap(), dest.layout().size)
         };
         self.eval_context_mut().write_scalar(val, dest)
     }
@@ -413,12 +414,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Test if this pointer equals 0.
-    fn ptr_is_null(&self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, bool> {
+    fn ptr_is_null(&self, ptr: Pointer) -> InterpResult<'tcx, bool> {
         Ok(ptr.addr().bytes() == 0)
     }
 
     /// Generate some random bytes, and write them to `dest`.
-    fn gen_random(&mut self, ptr: Pointer<Option<Provenance>>, len: u64) -> InterpResult<'tcx> {
+    fn gen_random(&mut self, ptr: Pointer, len: u64) -> InterpResult<'tcx> {
         // Some programs pass in a null pointer and a length of 0
         // to their platform's random-generation function (e.g. getrandom())
         // on Linux. For compatibility with these programs, we don't perform
@@ -453,7 +454,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         f: ty::Instance<'tcx>,
         caller_abi: Abi,
         args: &[Immediate<Provenance>],
-        dest: Option<&MPlaceTy<'tcx, Provenance>>,
+        dest: Option<&MPlaceTy<'tcx>>,
         stack_pop: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -501,7 +502,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// The range is relative to `place`.
     fn visit_freeze_sensitive(
         &self,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
         size: Size,
         mut action: impl FnMut(AllocRange, bool) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx> {
@@ -520,8 +521,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let mut cur_addr = start_addr;
         // Called when we detected an `UnsafeCell` at the given offset and size.
         // Calls `action` and advances `cur_ptr`.
-        let mut unsafe_cell_action = |unsafe_cell_ptr: &Pointer<Option<Provenance>>,
-                                      unsafe_cell_size: Size| {
+        let mut unsafe_cell_action = |unsafe_cell_ptr: &Pointer, unsafe_cell_size: Size| {
             // We assume that we are given the fields in increasing offset order,
             // and nothing else changes.
             let unsafe_cell_addr = unsafe_cell_ptr.addr();
@@ -575,7 +575,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         /// whether we are inside an `UnsafeCell` or not.
         struct UnsafeCellVisitor<'ecx, 'tcx, F>
         where
-            F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
+            F: FnMut(&MPlaceTy<'tcx>) -> InterpResult<'tcx>,
         {
             ecx: &'ecx MiriInterpCx<'tcx>,
             unsafe_cell_action: F,
@@ -583,9 +583,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         impl<'ecx, 'tcx, F> ValueVisitor<'tcx, MiriMachine<'tcx>> for UnsafeCellVisitor<'ecx, 'tcx, F>
         where
-            F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
+            F: FnMut(&MPlaceTy<'tcx>) -> InterpResult<'tcx>,
         {
-            type V = MPlaceTy<'tcx, Provenance>;
+            type V = MPlaceTy<'tcx>;
 
             #[inline(always)]
             fn ecx(&self) -> &MiriInterpCx<'tcx> {
@@ -603,7 +603,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             // Hook to detect `UnsafeCell`.
-            fn visit_value(&mut self, v: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+            fn visit_value(&mut self, v: &MPlaceTy<'tcx>) -> InterpResult<'tcx> {
                 trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                 let is_unsafe_cell = match v.layout.ty.kind() {
                     ty::Adt(adt, _) =>
@@ -649,7 +649,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
             fn visit_union(
                 &mut self,
-                _v: &MPlaceTy<'tcx, Provenance>,
+                _v: &MPlaceTy<'tcx>,
                 _fields: NonZero<usize>,
             ) -> InterpResult<'tcx> {
                 bug!("we should have already handled unions in `visit_value`")
@@ -720,7 +720,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     /// Get last error variable as a place, lazily allocating thread-local storage for it if
     /// necessary.
-    fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
         if let Some(errno_place) = this.active_thread_ref().last_error.as_ref() {
             Ok(errno_place.clone())
@@ -735,14 +735,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Sets the last error variable.
-    fn set_last_error(&mut self, scalar: Scalar<Provenance>) -> InterpResult<'tcx> {
+    fn set_last_error(&mut self, scalar: Scalar) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let errno_place = this.last_error_place()?;
         this.write_scalar(scalar, &errno_place)
     }
 
     /// Gets the last error variable.
-    fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         let errno_place = this.last_error_place()?;
         this.read_scalar(&errno_place)
@@ -750,7 +750,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     /// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
     /// as a platform-specific errnum.
-    fn io_error_to_errnum(&self, err: std::io::Error) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn io_error_to_errnum(&self, err: std::io::Error) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
         let target = &this.tcx.sess.target;
         if target.families.iter().any(|f| f == "unix") {
@@ -779,7 +779,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(clippy::needless_return)]
     fn try_errnum_to_io_error(
         &self,
-        errnum: Scalar<Provenance>,
+        errnum: Scalar,
     ) -> InterpResult<'tcx, Option<std::io::ErrorKind>> {
         let this = self.eval_context_ref();
         let target = &this.tcx.sess.target;
@@ -836,7 +836,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &self,
         op: &impl Readable<'tcx, Provenance>,
         layout: TyAndLayout<'tcx>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_ref();
         let ptr = this.read_pointer(op)?;
         Ok(this.ptr_to_mplace(ptr, layout))
@@ -849,7 +849,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         offset: u64,
         base_layout: TyAndLayout<'tcx>,
         value_layout: TyAndLayout<'tcx>,
-    ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_ref();
         let op_place = this.deref_pointer_as(op, base_layout)?;
         let offset = Size::from_bytes(offset);
@@ -866,7 +866,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         offset: u64,
         base_layout: TyAndLayout<'tcx>,
         value_layout: TyAndLayout<'tcx>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
         let value_place = this.deref_pointer_and_offset(op, offset, base_layout, value_layout)?;
         this.read_scalar(&value_place)
@@ -876,7 +876,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         op: &impl Readable<'tcx, Provenance>,
         offset: u64,
-        value: impl Into<Scalar<Provenance>>,
+        value: impl Into<Scalar>,
         base_layout: TyAndLayout<'tcx>,
         value_layout: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx, ()> {
@@ -888,10 +888,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Parse a `timespec` struct and return it as a `std::time::Duration`. It returns `None`
     /// if the value in the `timespec` struct is invalid. Some libc functions will return
     /// `EINVAL` in this case.
-    fn read_timespec(
-        &mut self,
-        tp: &MPlaceTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Option<Duration>> {
+    fn read_timespec(&mut self, tp: &MPlaceTy<'tcx>) -> InterpResult<'tcx, Option<Duration>> {
         let this = self.eval_context_mut();
         let seconds_place = this.project_field(tp, 0)?;
         let seconds_scalar = this.read_scalar(&seconds_place)?;
@@ -914,10 +911,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Read bytes from a byte slice.
-    fn read_byte_slice<'a>(
-        &'a self,
-        slice: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, &'a [u8]>
+    fn read_byte_slice<'a>(&'a self, slice: &ImmTy<'tcx>) -> InterpResult<'tcx, &'a [u8]>
     where
         'tcx: 'a,
     {
@@ -930,7 +924,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Read a sequence of bytes until the first null terminator.
-    fn read_c_str<'a>(&'a self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, &'a [u8]>
+    fn read_c_str<'a>(&'a self, ptr: Pointer) -> InterpResult<'tcx, &'a [u8]>
     where
         'tcx: 'a,
     {
@@ -963,7 +957,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_c_str(
         &mut self,
         c_str: &[u8],
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
@@ -982,7 +976,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// until the first null terminator.
     fn read_c_str_with_char_size<T>(
         &self,
-        mut ptr: Pointer<Option<Provenance>>,
+        mut ptr: Pointer,
         size: Size,
         align: Align,
     ) -> InterpResult<'tcx, Vec<T>>
@@ -1014,7 +1008,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Read a sequence of u16 until the first null terminator.
-    fn read_wide_str(&self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, Vec<u16>> {
+    fn read_wide_str(&self, ptr: Pointer) -> InterpResult<'tcx, Vec<u16>> {
         self.read_c_str_with_char_size(ptr, Size::from_bytes(2), Align::from_bytes(2).unwrap())
     }
 
@@ -1027,7 +1021,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_wide_str(
         &mut self,
         wide_str: &[u16],
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
@@ -1052,7 +1046,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     /// Read a sequence of wchar_t until the first null terminator.
     /// Always returns a `Vec<u32>` no matter the size of `wchar_t`.
-    fn read_wchar_t_str(&self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, Vec<u32>> {
+    fn read_wchar_t_str(&self, ptr: Pointer) -> InterpResult<'tcx, Vec<u32>> {
         let this = self.eval_context_ref();
         let wchar_t = this.libc_ty_layout("wchar_t");
         self.read_c_str_with_char_size(ptr, wchar_t.size, wchar_t.align.abi)
@@ -1138,17 +1132,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         abi: Abi,
         exp_abi: Abi,
         link_name: Symbol,
-        args: &'a [OpTy<'tcx, Provenance>],
-    ) -> InterpResult<'tcx, &'a [OpTy<'tcx, Provenance>; N]>
+        args: &'a [OpTy<'tcx>],
+    ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>
     where
-        &'a [OpTy<'tcx, Provenance>; N]: TryFrom<&'a [OpTy<'tcx, Provenance>]>,
+        &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
     {
         self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
         check_arg_count(args)
     }
 
     /// Mark a machine allocation that was just created as immutable.
-    fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx, Provenance>) {
+    fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx>) {
         let this = self.eval_context_mut();
         // This got just allocated, so there definitely is a pointer here.
         let provenance = mplace.ptr().into_pointer_or_addr().unwrap().provenance;
@@ -1168,10 +1162,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns `None` if `f` is NaN or out of range.
     fn float_to_int_checked(
         &self,
-        src: &ImmTy<'tcx, Provenance>,
+        src: &ImmTy<'tcx>,
         cast_to: TyAndLayout<'tcx>,
         round: rustc_apfloat::Round,
-    ) -> InterpResult<'tcx, Option<ImmTy<'tcx, Provenance>>> {
+    ) -> InterpResult<'tcx, Option<ImmTy<'tcx>>> {
         let this = self.eval_context_ref();
 
         fn float_to_int_inner<'tcx, F: rustc_apfloat::Float>(
@@ -1179,7 +1173,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             src: F,
             cast_to: TyAndLayout<'tcx>,
             round: rustc_apfloat::Round,
-        ) -> (Scalar<Provenance>, rustc_apfloat::Status) {
+        ) -> (Scalar, rustc_apfloat::Status) {
             let int_size = cast_to.layout.size;
             match cast_to.ty.kind() {
                 // Unsigned
@@ -1267,10 +1261,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Lookup an array of immediates stored as a linker section of name `name`.
-    fn lookup_link_section(
-        &mut self,
-        name: &str,
-    ) -> InterpResult<'tcx, Vec<ImmTy<'tcx, Provenance>>> {
+    fn lookup_link_section(&mut self, name: &str) -> InterpResult<'tcx, Vec<ImmTy<'tcx>>> {
         let this = self.eval_context_mut();
         let tcx = this.tcx.tcx;
 
@@ -1338,10 +1329,10 @@ impl<'tcx> MiriMachine<'tcx> {
 
 /// Check that the number of args is what we expect.
 pub fn check_arg_count<'a, 'tcx, const N: usize>(
-    args: &'a [OpTy<'tcx, Provenance>],
-) -> InterpResult<'tcx, &'a [OpTy<'tcx, Provenance>; N]>
+    args: &'a [OpTy<'tcx>],
+) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>
 where
-    &'a [OpTy<'tcx, Provenance>; N]: TryFrom<&'a [OpTy<'tcx, Provenance>]>,
+    &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
 {
     if let Ok(ops) = args.try_into() {
         return Ok(ops);
@@ -1364,7 +1355,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
         .map(|crates| crates.split(',').map(|krate| krate.to_string()).collect::<Vec<_>>())
         .unwrap_or_default();
     let mut local_crates = Vec::new();
-    for &crate_num in tcx.crates_including_speculative(()) {
+    for &crate_num in tcx.crates(()) {
         let name = tcx.crate_name(crate_num);
         let name = name.as_str();
         if local_crate_names.iter().any(|local_name| local_name == name) {
@@ -1374,7 +1365,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
     local_crates
 }
 
-pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Provenance> {
+pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar {
     // SIMD uses all-1 as pattern for "true". In two's complement,
     // -1 has all its bits set to one and `from_int` will truncate or
     // sign-extend it to `size` as required.
@@ -1382,7 +1373,7 @@ pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Provenance> {
     Scalar::from_int(val, size)
 }
 
-pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<'_, bool> {
+pub(crate) fn simd_element_to_bool(elem: ImmTy<'_>) -> InterpResult<'_, bool> {
     let val = elem.to_scalar().to_int(elem.layout.size)?;
     Ok(match val {
         0 => false,
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 17f95df9aa1..d76f622e84b 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -18,8 +18,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_atomic_intrinsic(
         &mut self,
         intrinsic_name: &str,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
@@ -124,8 +124,8 @@ impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {}
 trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     fn atomic_load(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         atomic: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -140,11 +140,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn atomic_store(
-        &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        atomic: AtomicWriteOrd,
-    ) -> InterpResult<'tcx> {
+    fn atomic_store(&mut self, args: &[OpTy<'tcx>], atomic: AtomicWriteOrd) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         let [place, val] = check_arg_count(args)?;
@@ -159,7 +155,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn compiler_fence_intrinsic(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[OpTy<'tcx>],
         atomic: AtomicFenceOrd,
     ) -> InterpResult<'tcx> {
         let [] = check_arg_count(args)?;
@@ -170,7 +166,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_fence_intrinsic(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[OpTy<'tcx>],
         atomic: AtomicFenceOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -181,8 +177,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_rmw_op(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         atomic_op: AtomicOp,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx> {
@@ -223,8 +219,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_exchange(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -240,8 +236,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_compare_exchange_impl(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
         can_fail_spuriously: bool,
@@ -269,8 +265,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_compare_exchange(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
@@ -279,8 +275,8 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
 
     fn atomic_compare_exchange_weak(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index e39b78d3816..74e39ffd933 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -1,3 +1,5 @@
+#![warn(clippy::arithmetic_side_effects)]
+
 mod atomic;
 mod simd;
 
@@ -23,8 +25,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn call_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -79,8 +81,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         intrinsic_name: &str,
         generic_args: ty::GenericArgsRef<'tcx>,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
@@ -385,7 +387,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     "frem_fast" => mir::BinOp::Rem,
                     _ => bug!(),
                 };
-                let float_finite = |x: &ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
+                let float_finite = |x: &ImmTy<'tcx>| -> InterpResult<'tcx, bool> {
                     let ty::Float(fty) = x.layout.ty.kind() else {
                         bug!("float_finite: non-float input type {}", x.layout.ty)
                     };
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index ed0c30e2a11..c3b34f0c0c6 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -23,8 +23,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         intrinsic_name: &str,
         generic_args: ty::GenericArgsRef<'tcx>,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match intrinsic_name {
@@ -452,28 +452,54 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let (no, no_len) = this.operand_to_simd(no)?;
                 let (dest, dest_len) = this.mplace_to_simd(dest)?;
                 let bitmask_len = dest_len.next_multiple_of(8);
+                if bitmask_len > 64 {
+                    throw_unsup_format!(
+                        "simd_select_bitmask: vectors larger than 64 elements are currently not supported"
+                    );
+                }
 
-                // The mask must be an integer or an array.
-                assert!(
-                    mask.layout.ty.is_integral()
-                        || matches!(mask.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
-                );
-                assert!(bitmask_len <= 64);
-                assert_eq!(bitmask_len, mask.layout.size.bits());
                 assert_eq!(dest_len, yes_len);
                 assert_eq!(dest_len, no_len);
-                let dest_len = u32::try_from(dest_len).unwrap();
-                let bitmask_len = u32::try_from(bitmask_len).unwrap();
 
-                // To read the mask, we transmute it to an integer.
-                // That does the right thing wrt endianness.
-                let mask_ty = this.machine.layouts.uint(mask.layout.size).unwrap();
-                let mask = mask.transmute(mask_ty, this)?;
-                let mask: u64 = this.read_scalar(&mask)?.to_bits(mask_ty.size)?.try_into().unwrap();
+                // Read the mask, either as an integer or as an array.
+                let mask: u64 = match mask.layout.ty.kind() {
+                    ty::Uint(_) => {
+                        // Any larger integer type is fine.
+                        assert!(mask.layout.size.bits() >= bitmask_len);
+                        this.read_scalar(mask)?.to_bits(mask.layout.size)?.try_into().unwrap()
+                    }
+                    ty::Array(elem, _len) if elem == &this.tcx.types.u8 => {
+                        // The array must have exactly the right size.
+                        assert_eq!(mask.layout.size.bits(), bitmask_len);
+                        // Read the raw bytes.
+                        let mask = mask.assert_mem_place(); // arrays cannot be immediate
+                        let mask_bytes =
+                            this.read_bytes_ptr_strip_provenance(mask.ptr(), mask.layout.size)?;
+                        // Turn them into a `u64` in the right way.
+                        let mask_size = mask.layout.size.bytes_usize();
+                        let mut mask_arr = [0u8; 8];
+                        match this.data_layout().endian {
+                            Endian::Little => {
+                                // Fill the first N bytes.
+                                mask_arr[..mask_size].copy_from_slice(mask_bytes);
+                                u64::from_le_bytes(mask_arr)
+                            }
+                            Endian::Big => {
+                                // Fill the last N bytes.
+                                let i = mask_arr.len().strict_sub(mask_size);
+                                mask_arr[i..].copy_from_slice(mask_bytes);
+                                u64::from_be_bytes(mask_arr)
+                            }
+                        }
+                    }
+                    _ => bug!("simd_select_bitmask: invalid mask type {}", mask.layout.ty),
+                };
 
+                let dest_len = u32::try_from(dest_len).unwrap();
+                let bitmask_len = u32::try_from(bitmask_len).unwrap();
                 for i in 0..dest_len {
                     let bit_i = simd_bitmask_index(i, dest_len, this.data_layout().endian);
-                    let mask = mask & 1u64.checked_shl(bit_i).unwrap();
+                    let mask = mask & 1u64.strict_shl(bit_i);
                     let yes = this.read_immediate(&this.project_index(&yes, i.into())?)?;
                     let no = this.read_immediate(&this.project_index(&no, i.into())?)?;
                     let dest = this.project_index(&dest, i.into())?;
@@ -485,7 +511,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     // If the mask is "padded", ensure that padding is all-zero.
                     // This deliberately does not use `simd_bitmask_index`; these bits are outside
                     // the bitmask. It does not matter in which order we check them.
-                    let mask = mask & 1u64.checked_shl(i).unwrap();
+                    let mask = mask & 1u64.strict_shl(i);
                     if mask != 0 {
                         throw_ub_format!(
                             "a SIMD bitmask less than 8 bits long must be filled with 0s for the remaining bits"
@@ -498,30 +524,49 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let bitmask_len = op_len.next_multiple_of(8);
+                if bitmask_len > 64 {
+                    throw_unsup_format!(
+                        "simd_bitmask: vectors larger than 64 elements are currently not supported"
+                    );
+                }
 
-                // Returns either an unsigned integer or array of `u8`.
-                assert!(
-                    dest.layout.ty.is_integral()
-                        || matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
-                );
-                assert!(bitmask_len <= 64);
-                assert_eq!(bitmask_len, dest.layout.size.bits());
                 let op_len = u32::try_from(op_len).unwrap();
-
                 let mut res = 0u64;
                 for i in 0..op_len {
                     let op = this.read_immediate(&this.project_index(&op, i.into())?)?;
                     if simd_element_to_bool(op)? {
-                        res |= 1u64
-                            .checked_shl(simd_bitmask_index(i, op_len, this.data_layout().endian))
-                            .unwrap();
+                        let bit_i = simd_bitmask_index(i, op_len, this.data_layout().endian);
+                        res |= 1u64.strict_shl(bit_i);
+                    }
+                }
+                // Write the result, depending on the `dest` type.
+                // Returns either an unsigned integer or array of `u8`.
+                match dest.layout.ty.kind() {
+                    ty::Uint(_) => {
+                        // Any larger integer type is fine, it will be zero-extended.
+                        assert!(dest.layout.size.bits() >= bitmask_len);
+                        this.write_int(res, dest)?;
+                    }
+                    ty::Array(elem, _len) if elem == &this.tcx.types.u8 => {
+                        // The array must have exactly the right size.
+                        assert_eq!(dest.layout.size.bits(), bitmask_len);
+                        // We have to write the result byte-for-byte.
+                        let res_size = dest.layout.size.bytes_usize();
+                        let res_bytes;
+                        let res_bytes_slice = match this.data_layout().endian {
+                            Endian::Little => {
+                                res_bytes = res.to_le_bytes();
+                                &res_bytes[..res_size] // take the first N bytes
+                            }
+                            Endian::Big => {
+                                res_bytes = res.to_be_bytes();
+                                &res_bytes[res_bytes.len().strict_sub(res_size)..] // take the last N bytes
+                            }
+                        };
+                        this.write_bytes_ptr(dest.ptr(), res_bytes_slice.iter().cloned())?;
                     }
+                    _ => bug!("simd_bitmask: invalid return type {}", dest.layout.ty),
                 }
-                // We have to change the type of the place to be able to write `res` into it. This
-                // transmutes the integer to an array, which does the right thing wrt endianness.
-                let dest =
-                    dest.transmute(this.machine.layouts.uint(dest.layout.size).unwrap(), this)?;
-                this.write_int(res, &dest)?;
             }
             "cast" | "as" | "cast_ptr" | "expose_provenance" | "with_exposed_provenance" => {
                 let [op] = check_arg_count(args)?;
@@ -590,6 +635,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     .expect_const()
                     .eval(*this.tcx, this.param_env(), this.tcx.span)
                     .unwrap()
+                    .1
                     .unwrap_branch();
                 let index_len = index.len();
 
@@ -599,15 +645,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 for i in 0..dest_len {
                     let src_index: u64 = index[usize::try_from(i).unwrap()]
                         .unwrap_leaf()
-                        .try_to_u32()
-                        .unwrap()
+                        .to_u32()
                         .into();
                     let dest = this.project_index(&dest, i)?;
 
                     let val = if src_index < left_len {
                         this.read_immediate(&this.project_index(&left, src_index)?)?
-                    } else if src_index < left_len.checked_add(right_len).unwrap() {
-                        let right_idx = src_index.checked_sub(left_len).unwrap();
+                    } else if src_index < left_len.strict_add(right_len) {
+                        let right_idx = src_index.strict_sub(left_len);
                         this.read_immediate(&this.project_index(&right, right_idx)?)?
                     } else {
                         throw_ub_format!(
@@ -646,8 +691,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
                     let val = if src_index < left_len {
                         this.read_immediate(&this.project_index(&left, src_index)?)?
-                    } else if src_index < left_len.checked_add(right_len).unwrap() {
-                        let right_idx = src_index.checked_sub(left_len).unwrap();
+                    } else if src_index < left_len.strict_add(right_len) {
+                        let right_idx = src_index.strict_sub(left_len);
                         this.read_immediate(&this.project_index(&right, right_idx)?)?
                     } else {
                         throw_ub_format!(
@@ -760,9 +805,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn fminmax_op(
         &self,
         op: MinMax,
-        left: &ImmTy<'tcx, Provenance>,
-        right: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        left: &ImmTy<'tcx>,
+        right: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
         assert_eq!(left.layout.ty, right.layout.ty);
         let ty::Float(float_ty) = left.layout.ty.kind() else {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 2fa88b6a246..11cbbde06aa 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -53,7 +53,6 @@
 
 // Some "regular" crates we want to share with rustc
 extern crate either;
-#[macro_use]
 extern crate tracing;
 
 // The rustc crates we need
@@ -64,7 +63,6 @@ extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_index;
-#[macro_use]
 extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
@@ -91,13 +89,24 @@ mod range_map;
 mod shims;
 
 // Establish a "crate-wide prelude": we often import `crate::*`.
+use rustc_middle::{bug, span_bug};
+use tracing::{info, trace};
 
 // Make all those symbols available in the same place as our own.
 #[doc(no_inline)]
 pub use rustc_const_eval::interpret::*;
 // Resolve ambiguity.
 #[doc(no_inline)]
-pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};
+pub use rustc_const_eval::interpret::{self, AllocMap, Provenance as _};
+
+// Type aliases that set the provenance parameter.
+pub type Pointer = interpret::Pointer<Option<machine::Provenance>>;
+pub type StrictPointer = interpret::Pointer<machine::Provenance>;
+pub type Scalar = interpret::Scalar<machine::Provenance>;
+pub type ImmTy<'tcx> = interpret::ImmTy<'tcx, machine::Provenance>;
+pub type OpTy<'tcx> = interpret::OpTy<'tcx, machine::Provenance>;
+pub type PlaceTy<'tcx> = interpret::PlaceTy<'tcx, machine::Provenance>;
+pub type MPlaceTy<'tcx> = interpret::MPlaceTy<'tcx, machine::Provenance>;
 
 pub use crate::intrinsics::EvalContextExt as _;
 pub use crate::shims::env::{EnvVars, EvalContextExt as _};
@@ -123,8 +132,8 @@ pub use crate::concurrency::{
     init_once::{EvalContextExt as _, InitOnceId},
     sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects},
     thread::{
-        BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, Timeout,
-        UnblockCallback,
+        BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager,
+        TimeoutAnchor, TimeoutClock, UnblockCallback,
     },
 };
 pub use crate::diagnostics::{
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index c9b390eb67e..0d91279f9f4 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -240,12 +240,12 @@ pub enum ProvenanceExtra {
 }
 
 #[cfg(target_pointer_width = "64")]
-static_assert_size!(Pointer<Provenance>, 24);
+static_assert_size!(StrictPointer, 24);
 // FIXME: this would with in 24bytes but layout optimizations are not smart enough
 // #[cfg(target_pointer_width = "64")]
-//static_assert_size!(Pointer<Option<Provenance>>, 24);
+//static_assert_size!(Pointer, 24);
 #[cfg(target_pointer_width = "64")]
-static_assert_size!(Scalar<Provenance>, 32);
+static_assert_size!(Scalar, 32);
 
 impl fmt::Debug for Provenance {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -269,7 +269,7 @@ impl fmt::Debug for Provenance {
 }
 
 impl interpret::Provenance for Provenance {
-    /// We use absolute addresses in the `offset` of a `Pointer<Provenance>`.
+    /// We use absolute addresses in the `offset` of a `StrictPointer`.
     const OFFSET_IS_ADDR: bool = true;
 
     fn get_alloc_id(self) -> Option<AllocId> {
@@ -279,7 +279,7 @@ impl interpret::Provenance for Provenance {
         }
     }
 
-    fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    fn fmt(ptr: &interpret::Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let (prov, addr) = ptr.into_parts(); // address is absolute
         write!(f, "{:#x}", addr.bytes())?;
         if f.alternate() {
@@ -441,14 +441,14 @@ pub struct MiriMachine<'tcx> {
     pub(crate) env_vars: EnvVars<'tcx>,
 
     /// Return place of the main function.
-    pub(crate) main_fn_ret_place: Option<MPlaceTy<'tcx, Provenance>>,
+    pub(crate) main_fn_ret_place: Option<MPlaceTy<'tcx>>,
 
     /// Program arguments (`Option` because we can only initialize them after creating the ecx).
     /// These are *pointers* to argc/argv because macOS.
     /// We also need the full command line as one string because of Windows.
-    pub(crate) argc: Option<Pointer<Option<Provenance>>>,
-    pub(crate) argv: Option<Pointer<Option<Provenance>>>,
-    pub(crate) cmd_line: Option<Pointer<Option<Provenance>>>,
+    pub(crate) argc: Option<Pointer>,
+    pub(crate) argv: Option<Pointer>,
+    pub(crate) cmd_line: Option<Pointer>,
 
     /// TLS state.
     pub(crate) tls: TlsData<'tcx>,
@@ -503,7 +503,7 @@ pub struct MiriMachine<'tcx> {
     pub(crate) local_crates: Vec<CrateNum>,
 
     /// Mapping extern static names to their pointer.
-    extern_statics: FxHashMap<Symbol, Pointer<Provenance>>,
+    extern_statics: FxHashMap<Symbol, StrictPointer>,
 
     /// The random number generator used for resolving non-determinism.
     /// Needs to be queried by ptr_to_int, hence needs interior mutability.
@@ -564,7 +564,7 @@ pub struct MiriMachine<'tcx> {
     /// Maps MIR consts to their evaluated result. We combine the const with a "salt" (`usize`)
     /// that is fixed per stack frame; this lets us have sometimes different results for the
     /// same const while ensuring consistent results within a single call.
-    const_cache: RefCell<FxHashMap<(mir::Const<'tcx>, usize), OpTy<'tcx, Provenance>>>,
+    const_cache: RefCell<FxHashMap<(mir::Const<'tcx>, usize), OpTy<'tcx>>>,
 
     /// For each allocation, an offset inside that allocation that was deemed aligned even for
     /// symbolic alignment checks. This cannot be stored in `AllocExtra` since it needs to be
@@ -715,11 +715,7 @@ impl<'tcx> MiriMachine<'tcx> {
         Ok(())
     }
 
-    pub(crate) fn add_extern_static(
-        this: &mut MiriInterpCx<'tcx>,
-        name: &str,
-        ptr: Pointer<Option<Provenance>>,
-    ) {
+    pub(crate) fn add_extern_static(this: &mut MiriInterpCx<'tcx>, name: &str, ptr: Pointer) {
         // This got just allocated, so there definitely is a pointer here.
         let ptr = ptr.into_pointer_or_addr().unwrap();
         this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
@@ -945,7 +941,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         instance: ty::Instance<'tcx>,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -972,7 +968,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         fn_val: DynSym,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -984,8 +980,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn call_intrinsic(
         ecx: &mut MiriInterpCx<'tcx>,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -1026,9 +1022,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn binary_ptr_op(
         ecx: &MiriInterpCx<'tcx>,
         bin_op: mir::BinOp,
-        left: &ImmTy<'tcx, Provenance>,
-        right: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        left: &ImmTy<'tcx>,
+        right: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         ecx.binary_ptr_op(bin_op, left, right)
     }
 
@@ -1046,14 +1042,14 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn thread_local_static_pointer(
         ecx: &mut MiriInterpCx<'tcx>,
         def_id: DefId,
-    ) -> InterpResult<'tcx, Pointer<Provenance>> {
+    ) -> InterpResult<'tcx, StrictPointer> {
         ecx.get_or_create_thread_local_alloc(def_id)
     }
 
     fn extern_static_pointer(
         ecx: &MiriInterpCx<'tcx>,
         def_id: DefId,
-    ) -> InterpResult<'tcx, Pointer<Provenance>> {
+    ) -> InterpResult<'tcx, StrictPointer> {
         let link_name = ecx.item_link_name(def_id);
         if let Some(&ptr) = ecx.machine.extern_statics.get(&link_name) {
             // Various parts of the engine rely on `get_alloc_info` for size and alignment
@@ -1134,9 +1130,9 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
 
     fn adjust_alloc_root_pointer(
         ecx: &MiriInterpCx<'tcx>,
-        ptr: Pointer<CtfeProvenance>,
+        ptr: interpret::Pointer<CtfeProvenance>,
         kind: Option<MemoryKind>,
-    ) -> InterpResult<'tcx, Pointer<Provenance>> {
+    ) -> InterpResult<'tcx, interpret::Pointer<Provenance>> {
         let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None");
         let alloc_id = ptr.provenance.alloc_id();
         if cfg!(debug_assertions) {
@@ -1163,20 +1159,14 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
 
     /// Called on `usize as ptr` casts.
     #[inline(always)]
-    fn ptr_from_addr_cast(
-        ecx: &MiriInterpCx<'tcx>,
-        addr: u64,
-    ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>> {
+    fn ptr_from_addr_cast(ecx: &MiriInterpCx<'tcx>, addr: u64) -> InterpResult<'tcx, Pointer> {
         ecx.ptr_from_addr_cast(addr)
     }
 
     /// Called on `ptr as usize` casts.
     /// (Actually computing the resulting `usize` doesn't need machine help,
     /// that's just `Scalar::try_to_int`.)
-    fn expose_ptr(
-        ecx: &mut InterpCx<'tcx, Self>,
-        ptr: Pointer<Self::Provenance>,
-    ) -> InterpResult<'tcx> {
+    fn expose_ptr(ecx: &mut InterpCx<'tcx, Self>, ptr: StrictPointer) -> InterpResult<'tcx> {
         match ptr.provenance {
             Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
             Provenance::Wildcard => {
@@ -1197,7 +1187,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     /// stored in machine state).
     fn ptr_get_alloc(
         ecx: &MiriInterpCx<'tcx>,
-        ptr: Pointer<Self::Provenance>,
+        ptr: StrictPointer,
     ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
         let rel = ecx.ptr_get_alloc(ptr);
 
@@ -1295,8 +1285,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn retag_ptr_value(
         ecx: &mut InterpCx<'tcx, Self>,
         kind: mir::RetagKind,
-        val: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        val: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         if ecx.machine.borrow_tracker.is_some() {
             ecx.retag_ptr_value(kind, val)
         } else {
@@ -1308,7 +1298,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn retag_place_contents(
         ecx: &mut InterpCx<'tcx, Self>,
         kind: mir::RetagKind,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         if ecx.machine.borrow_tracker.is_some() {
             ecx.retag_place_contents(kind, place)?;
@@ -1318,7 +1308,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
 
     fn protect_in_place_function_argument(
         ecx: &mut InterpCx<'tcx, Self>,
-        place: &MPlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         // If we have a borrow tracker, we also have it set up protection so that all reads *and
         // writes* during this call are insta-UB.
@@ -1473,7 +1463,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     fn after_local_allocated(
         ecx: &mut InterpCx<'tcx, Self>,
         local: mir::Local,
-        mplace: &MPlaceTy<'tcx, Provenance>,
+        mplace: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr().provenance else {
             panic!("after_local_allocated should only be called on fresh allocations");
@@ -1490,14 +1480,14 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         span: Span,
         layout: Option<TyAndLayout<'tcx>>,
         eval: F,
-    ) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>
+    ) -> InterpResult<'tcx, OpTy<'tcx>>
     where
         F: Fn(
             &InterpCx<'tcx, Self>,
             mir::Const<'tcx>,
             Span,
             Option<TyAndLayout<'tcx>>,
-        ) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>,
+        ) -> InterpResult<'tcx, OpTy<'tcx>>,
     {
         let frame = ecx.active_thread_stack().last().unwrap();
         let mut cache = ecx.machine.const_cache.borrow_mut();
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index c04f12c339e..bc44e672bd8 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -12,9 +12,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn binary_ptr_op(
         &self,
         bin_op: mir::BinOp,
-        left: &ImmTy<'tcx, Provenance>,
-        right: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        left: &ImmTy<'tcx>,
+        right: &ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         use rustc_middle::mir::BinOp::*;
 
         let this = self.eval_context_ref();
diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs
index 03b6cfdce7b..af980ca4819 100644
--- a/src/tools/miri/src/provenance_gc.rs
+++ b/src/tools/miri/src/provenance_gc.rs
@@ -56,21 +56,21 @@ impl VisitProvenance for Provenance {
     }
 }
 
-impl VisitProvenance for Pointer<Provenance> {
+impl VisitProvenance for StrictPointer {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let (prov, _offset) = self.into_parts();
         prov.visit_provenance(visit);
     }
 }
 
-impl VisitProvenance for Pointer<Option<Provenance>> {
+impl VisitProvenance for Pointer {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let (prov, _offset) = self.into_parts();
         prov.visit_provenance(visit);
     }
 }
 
-impl VisitProvenance for Scalar<Provenance> {
+impl VisitProvenance for Scalar {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         match self {
             Scalar::Ptr(ptr, _) => ptr.visit_provenance(visit),
@@ -103,20 +103,20 @@ impl VisitProvenance for MemPlaceMeta<Provenance> {
     }
 }
 
-impl VisitProvenance for ImmTy<'_, Provenance> {
+impl VisitProvenance for ImmTy<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         (**self).visit_provenance(visit)
     }
 }
 
-impl VisitProvenance for MPlaceTy<'_, Provenance> {
+impl VisitProvenance for MPlaceTy<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         self.ptr().visit_provenance(visit);
         self.meta().visit_provenance(visit);
     }
 }
 
-impl VisitProvenance for PlaceTy<'_, Provenance> {
+impl VisitProvenance for PlaceTy<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         match self.as_mplace_or_local() {
             Either::Left(mplace) => mplace.visit_provenance(visit),
@@ -125,7 +125,7 @@ impl VisitProvenance for PlaceTy<'_, Provenance> {
     }
 }
 
-impl VisitProvenance for OpTy<'_, Provenance> {
+impl VisitProvenance for OpTy<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         match self.as_mplace_or_imm() {
             Either::Left(mplace) => mplace.visit_provenance(visit),
diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs
index bbe4bdd8450..7b0c54d763e 100644
--- a/src/tools/miri/src/shims/alloc.rs
+++ b/src/tools/miri/src/shims/alloc.rs
@@ -92,11 +92,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn malloc(
-        &mut self,
-        size: u64,
-        zero_init: bool,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn malloc(&mut self, size: u64, zero_init: bool) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         let align = this.malloc_align(size);
         let ptr = this.allocate_ptr(Size::from_bytes(size), align, MiriMemoryKind::C.into())?;
@@ -113,10 +109,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn posix_memalign(
         &mut self,
-        memptr: &OpTy<'tcx, Provenance>,
-        align: &OpTy<'tcx, Provenance>,
-        size: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        memptr: &OpTy<'tcx>,
+        align: &OpTy<'tcx>,
+        size: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         let memptr = this.deref_pointer(memptr)?;
         let align = this.read_target_usize(align)?;
@@ -137,7 +133,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn free(&mut self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx> {
+    fn free(&mut self, ptr: Pointer) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         if !this.ptr_is_null(ptr)? {
             this.deallocate_ptr(ptr, None, MiriMemoryKind::C.into())?;
@@ -145,11 +141,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn realloc(
-        &mut self,
-        old_ptr: Pointer<Option<Provenance>>,
-        new_size: u64,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn realloc(&mut self, old_ptr: Pointer, new_size: u64) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         let new_align = this.malloc_align(new_size);
         if this.ptr_is_null(old_ptr)? {
@@ -175,9 +167,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn aligned_alloc(
         &mut self,
-        align: &OpTy<'tcx, Provenance>,
-        size: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+        align: &OpTy<'tcx>,
+        size: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         let align = this.read_target_usize(align)?;
         let size = this.read_target_usize(size)?;
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 6ec65a16b8a..06be9c1e63e 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -11,8 +11,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         abi: Abi,
         link_name: Symbol,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let [flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -31,8 +31,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         abi: Abi,
         link_name: Symbol,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let tcx = this.tcx;
@@ -110,7 +110,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn resolve_frame_pointer(
         &mut self,
-        ptr: &OpTy<'tcx, Provenance>,
+        ptr: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, (Instance<'tcx>, Loc, String, String)> {
         let this = self.eval_context_mut();
 
@@ -140,8 +140,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         abi: Abi,
         link_name: Symbol,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let [ptr, flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -218,7 +218,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         abi: Abi,
         link_name: Symbol,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[OpTy<'tcx>],
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index 9330ac0b4dd..17ac2638a69 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -6,7 +6,7 @@ impl<'tcx> MiriMachine<'tcx> {
     fn alloc_extern_static(
         this: &mut MiriInterpCx<'tcx>,
         name: &str,
-        val: ImmTy<'tcx, Provenance>,
+        val: ImmTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
         this.write_immediate(*val, &place)?;
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 6dfd9866cae..898fc111fd4 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -40,8 +40,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -123,8 +123,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         sym: DynSym,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -208,8 +208,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
@@ -238,11 +238,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // ```
         // fn shim_name(
         //     &mut self,
-        //     arg1: &OpTy<'tcx, Provenance>,
-        //     arg2: &OpTy<'tcx, Provenance>,
-        //     arg3: &OpTy<'tcx, Provenance>,
-        //     arg4: &OpTy<'tcx, Provenance>)
-        // -> InterpResult<'tcx, Scalar<Provenance>> {
+        //     arg1: &OpTy<'tcx>,
+        //     arg2: &OpTy<'tcx>,
+        //     arg3: &OpTy<'tcx>,
+        //     arg4: &OpTy<'tcx>)
+        // -> InterpResult<'tcx, Scalar> {
         //     let this = self.eval_context_mut();
         //
         //     // First thing: load all the arguments. Details depend on the shim.
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index cc5cc75332a..40697e17ba1 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -14,10 +14,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn call_native_with_args<'a>(
         &mut self,
         link_name: Symbol,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx>,
         ptr: CodePtr,
         libffi_args: Vec<libffi::high::Arg<'a>>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         let this = self.eval_context_mut();
 
         // Call the function (`ptr`) with arguments `libffi_args`, and obtain the return value
@@ -132,8 +132,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn call_native_fn(
         &mut self,
         link_name: Symbol,
-        dest: &MPlaceTy<'tcx, Provenance>,
-        args: &[OpTy<'tcx, Provenance>],
+        dest: &MPlaceTy<'tcx>,
+        args: &[OpTy<'tcx>],
     ) -> InterpResult<'tcx, bool> {
         let this = self.eval_context_mut();
         // Get the pointer to the function in the shared object file if it exists.
@@ -216,10 +216,7 @@ impl<'a> CArg {
 
 /// Extract the scalar value from the result of reading a scalar from the machine,
 /// and convert it to a `CArg`.
-fn imm_to_carg<'tcx>(
-    v: ImmTy<'tcx, Provenance>,
-    cx: &impl HasDataLayout,
-) -> InterpResult<'tcx, CArg> {
+fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> {
     Ok(match v.layout.ty.kind() {
         // If the primitive provided can be converted to a type matching the type pattern
         // then create a `CArg` of this primitive value with the corresponding `CArg` constructor.
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index c00e4384bab..68eca5a3a0f 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -34,10 +34,7 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
     /// the Unix APIs usually handle.
-    fn read_os_str_from_c_str<'a>(
-        &'a self,
-        ptr: Pointer<Option<Provenance>>,
-    ) -> InterpResult<'tcx, &'a OsStr>
+    fn read_os_str_from_c_str<'a>(&'a self, ptr: Pointer) -> InterpResult<'tcx, &'a OsStr>
     where
         'tcx: 'a,
     {
@@ -48,10 +45,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
     /// which is what the Windows APIs usually handle.
-    fn read_os_str_from_wide_str<'a>(
-        &'a self,
-        ptr: Pointer<Option<Provenance>>,
-    ) -> InterpResult<'tcx, OsString>
+    fn read_os_str_from_wide_str<'a>(&'a self, ptr: Pointer) -> InterpResult<'tcx, OsString>
     where
         'tcx: 'a,
     {
@@ -76,7 +70,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_os_str_to_c_str(
         &mut self,
         os_str: &OsStr,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let bytes = os_str.as_encoded_bytes();
@@ -88,7 +82,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_os_str_to_wide_str_helper(
         &mut self,
         os_str: &OsStr,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
         truncate: bool,
     ) -> InterpResult<'tcx, (bool, u64)> {
@@ -125,7 +119,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_os_str_to_wide_str(
         &mut self,
         os_str: &OsStr,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         self.write_os_str_to_wide_str_helper(os_str, ptr, size, /*truncate*/ false)
@@ -136,7 +130,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_os_str_to_wide_str_truncated(
         &mut self,
         os_str: &OsStr,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         self.write_os_str_to_wide_str_helper(os_str, ptr, size, /*truncate*/ true)
@@ -147,7 +141,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         os_str: &OsStr,
         memkind: MemoryKind,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    ) -> InterpResult<'tcx, Pointer> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
         let this = self.eval_context_mut();
 
@@ -163,7 +157,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         os_str: &OsStr,
         memkind: MemoryKind,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    ) -> InterpResult<'tcx, Pointer> {
         let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
         let this = self.eval_context_mut();
 
@@ -175,10 +169,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
-    fn read_path_from_c_str<'a>(
-        &'a self,
-        ptr: Pointer<Option<Provenance>>,
-    ) -> InterpResult<'tcx, Cow<'a, Path>>
+    fn read_path_from_c_str<'a>(&'a self, ptr: Pointer) -> InterpResult<'tcx, Cow<'a, Path>>
     where
         'tcx: 'a,
     {
@@ -192,10 +183,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
-    fn read_path_from_wide_str(
-        &self,
-        ptr: Pointer<Option<Provenance>>,
-    ) -> InterpResult<'tcx, PathBuf> {
+    fn read_path_from_wide_str(&self, ptr: Pointer) -> InterpResult<'tcx, PathBuf> {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_wide_str(ptr)?;
 
@@ -207,7 +195,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_path_to_c_str(
         &mut self,
         path: &Path,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
@@ -221,7 +209,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_path_to_wide_str(
         &mut self,
         path: &Path,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
@@ -235,7 +223,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn write_path_to_wide_str_truncated(
         &mut self,
         path: &Path,
-        ptr: Pointer<Option<Provenance>>,
+        ptr: Pointer,
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
@@ -250,7 +238,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         path: &Path,
         memkind: MemoryKind,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    ) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         let os_str =
             this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
@@ -263,7 +251,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         path: &Path,
         memkind: MemoryKind,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    ) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         let os_str =
             this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 8aed6d4f463..ef832f5bbbd 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -23,11 +23,11 @@ use helpers::check_arg_count;
 #[derive(Debug)]
 pub struct CatchUnwindData<'tcx> {
     /// The `catch_fn` callback to call in case of a panic.
-    catch_fn: Pointer<Option<Provenance>>,
+    catch_fn: Pointer,
     /// The `data` argument for that callback.
-    data: Scalar<Provenance>,
+    data: Scalar,
     /// The return place from the original call to `try`.
-    dest: MPlaceTy<'tcx, Provenance>,
+    dest: MPlaceTy<'tcx>,
     /// The return block from the original call to `try`.
     ret: Option<mir::BasicBlock>,
 }
@@ -45,7 +45,7 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Handles the special `miri_start_unwind` intrinsic, which is called
     /// by libpanic_unwind to delegate the actual unwinding process to Miri.
-    fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         trace!("miri_start_unwind: {:?}", this.frame().instance);
@@ -60,8 +60,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
     fn handle_catch_unwind(
         &mut self,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 9fb7a735c30..ae17196f0b7 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -18,9 +18,9 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn clock_gettime(
         &mut self,
-        clk_id_op: &OpTy<'tcx, Provenance>,
-        tp_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        clk_id_op: &OpTy<'tcx>,
+        tp_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         // This clock support is deliberately minimal because a lot of clock types have fiddly
         // properties (is it possible for Miri to be suspended independently of the host?). If you
         // have a use for another clock type, please open an issue.
@@ -78,7 +78,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?;
             system_time_to_duration(&SystemTime::now())?
         } else if relative_clocks.contains(&clk_id) {
-            this.machine.clock.now().duration_since(this.machine.clock.anchor())
+            this.machine.clock.now().duration_since(this.machine.clock.epoch())
         } else {
             let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
@@ -93,11 +93,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Scalar::from_i32(0))
     }
 
-    fn gettimeofday(
-        &mut self,
-        tv_op: &OpTy<'tcx, Provenance>,
-        tz_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         this.assert_target_os_is_unix("gettimeofday");
@@ -127,9 +123,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     // https://linux.die.net/man/3/localtime_r
     fn localtime_r(
         &mut self,
-        timep: &OpTy<'tcx, Provenance>,
-        result_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+        timep: &OpTy<'tcx>,
+        result_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
 
         this.assert_target_os_is_unix("localtime_r");
@@ -212,7 +208,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn GetSystemTimeAsFileTime(
         &mut self,
         shim_name: &str,
-        LPFILETIME_op: &OpTy<'tcx, Provenance>,
+        LPFILETIME_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -242,15 +238,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn QueryPerformanceCounter(
         &mut self,
-        lpPerformanceCount_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        lpPerformanceCount_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("windows", "QueryPerformanceCounter");
 
         // QueryPerformanceCounter uses a hardware counter as its basis.
         // Miri will emulate a counter with a resolution of 1 nanosecond.
-        let duration = this.machine.clock.now().duration_since(this.machine.clock.anchor());
+        let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch());
         let qpc = i64::try_from(duration.as_nanos()).map_err(|_| {
             err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported")
         })?;
@@ -261,8 +257,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn QueryPerformanceFrequency(
         &mut self,
-        lpFrequency_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        lpFrequency_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("windows", "QueryPerformanceFrequency");
@@ -279,24 +275,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Scalar::from_i32(-1)) // Return non-zero on success
     }
 
-    fn mach_absolute_time(&self) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn mach_absolute_time(&self) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_ref();
 
         this.assert_target_os("macos", "mach_absolute_time");
 
         // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
         // We return plain nanoseconds.
-        let duration = this.machine.clock.now().duration_since(this.machine.clock.anchor());
+        let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch());
         let res = u64::try_from(duration.as_nanos()).map_err(|_| {
             err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported")
         })?;
         Ok(Scalar::from_u64(res))
     }
 
-    fn mach_timebase_info(
-        &mut self,
-        info_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn mach_timebase_info(&mut self, info_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("macos", "mach_timebase_info");
@@ -313,8 +306,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn nanosleep(
         &mut self,
-        req_op: &OpTy<'tcx, Provenance>,
-        _rem: &OpTy<'tcx, Provenance>, // Signal handlers are not supported, so rem will never be written to.
+        req_op: &OpTy<'tcx>,
+        _rem: &OpTy<'tcx>, // Signal handlers are not supported, so rem will never be written to.
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -330,16 +323,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 return Ok(-1);
             }
         };
-        // If adding the duration overflows, let's just sleep for an hour. Waking up early is always acceptable.
-        let now = this.machine.clock.now();
-        let timeout_time = now
-            .checked_add(duration)
-            .unwrap_or_else(|| now.checked_add(Duration::from_secs(3600)).unwrap());
-        let timeout_time = Timeout::Monotonic(timeout_time);
 
         this.block_thread(
             BlockReason::Sleep,
-            Some(timeout_time),
+            Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration)),
             callback!(
                 @capture<'tcx> {}
                 @unblock = |_this| { panic!("sleeping thread unblocked before time is up") }
@@ -350,7 +337,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     #[allow(non_snake_case)]
-    fn Sleep(&mut self, timeout: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn Sleep(&mut self, timeout: &OpTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("windows", "Sleep");
@@ -358,12 +345,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let timeout_ms = this.read_scalar(timeout)?.to_u32()?;
 
         let duration = Duration::from_millis(timeout_ms.into());
-        let timeout_time = this.machine.clock.now().checked_add(duration).unwrap();
-        let timeout_time = Timeout::Monotonic(timeout_time);
 
         this.block_thread(
             BlockReason::Sleep,
-            Some(timeout_time),
+            Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration)),
             callback!(
                 @capture<'tcx> {}
                 @unblock = |_this| { panic!("sleeping thread unblocked before time is up") }
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index fa52b036ce9..c91386fa877 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -16,7 +16,7 @@ pub type TlsKey = u128;
 pub struct TlsEntry<'tcx> {
     /// The data for this key. None is used to represent NULL.
     /// (We normalize this early to avoid having to do a NULL-ptr-test each time we access the data.)
-    data: BTreeMap<ThreadId, Scalar<Provenance>>,
+    data: BTreeMap<ThreadId, Scalar>,
     dtor: Option<ty::Instance<'tcx>>,
 }
 
@@ -38,7 +38,7 @@ pub struct TlsData<'tcx> {
 
     /// A single per thread destructor of the thread local storage (that's how
     /// things work on macOS) with a data argument.
-    macos_thread_dtors: BTreeMap<ThreadId, (ty::Instance<'tcx>, Scalar<Provenance>)>,
+    macos_thread_dtors: BTreeMap<ThreadId, (ty::Instance<'tcx>, Scalar)>,
 }
 
 impl<'tcx> Default for TlsData<'tcx> {
@@ -86,7 +86,7 @@ impl<'tcx> TlsData<'tcx> {
         key: TlsKey,
         thread_id: ThreadId,
         cx: &impl HasDataLayout,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         match self.keys.get(&key) {
             Some(TlsEntry { data, .. }) => {
                 let value = data.get(&thread_id).copied();
@@ -101,7 +101,7 @@ impl<'tcx> TlsData<'tcx> {
         &mut self,
         key: TlsKey,
         thread_id: ThreadId,
-        new_data: Scalar<Provenance>,
+        new_data: Scalar,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx> {
         match self.keys.get_mut(&key) {
@@ -132,7 +132,7 @@ impl<'tcx> TlsData<'tcx> {
         &mut self,
         thread: ThreadId,
         dtor: ty::Instance<'tcx>,
-        data: Scalar<Provenance>,
+        data: Scalar,
     ) -> InterpResult<'tcx> {
         if self.macos_thread_dtors.insert(thread, (dtor, data)).is_some() {
             throw_unsup_format!(
@@ -165,7 +165,7 @@ impl<'tcx> TlsData<'tcx> {
         &mut self,
         key: Option<TlsKey>,
         thread_id: ThreadId,
-    ) -> Option<(ty::Instance<'tcx>, Scalar<Provenance>, TlsKey)> {
+    ) -> Option<(ty::Instance<'tcx>, Scalar, TlsKey)> {
         use std::ops::Bound::*;
 
         let thread_local = &mut self.keys;
@@ -228,7 +228,7 @@ enum TlsDtorsStatePriv<'tcx> {
     PthreadDtors(RunningDtorState),
     /// For Windows Dtors, we store the list of functions that we still have to call.
     /// These are functions from the magic `.CRT$XLB` linker section.
-    WindowsDtors(Vec<ImmTy<'tcx, Provenance>>),
+    WindowsDtors(Vec<ImmTy<'tcx>>),
     Done,
 }
 
@@ -297,7 +297,7 @@ impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Schedule TLS destructors for Windows.
     /// On windows, TLS destructors are managed by std.
-    fn lookup_windows_tls_dtors(&mut self) -> InterpResult<'tcx, Vec<ImmTy<'tcx, Provenance>>> {
+    fn lookup_windows_tls_dtors(&mut self) -> InterpResult<'tcx, Vec<ImmTy<'tcx>>> {
         let this = self.eval_context_mut();
 
         // Windows has a special magic linker section that is run on certain events.
@@ -305,7 +305,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(this.lookup_link_section(".CRT$XLB")?)
     }
 
-    fn schedule_windows_tls_dtor(&mut self, dtor: ImmTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn schedule_windows_tls_dtor(&mut self, dtor: ImmTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         let dtor = dtor.to_scalar().to_pointer(this)?;
diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs
index 8a6e025ee18..42552a51eda 100644
--- a/src/tools/miri/src/shims/unix/android/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs
@@ -13,8 +13,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 26096910aa1..2f78d0f4296 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -13,10 +13,10 @@ use crate::*;
 pub struct UnixEnvVars<'tcx> {
     /// Stores pointers to the environment variables. These variables must be stored as
     /// null-terminated target strings (c_str or wide_str) with the `"{name}={value}"` format.
-    map: FxHashMap<OsString, Pointer<Option<Provenance>>>,
+    map: FxHashMap<OsString, Pointer>,
 
     /// Place where the `environ` static is stored. Lazily initialized, but then never changes.
-    environ: MPlaceTy<'tcx, Provenance>,
+    environ: MPlaceTy<'tcx>,
 }
 
 impl VisitProvenance for UnixEnvVars<'_> {
@@ -65,7 +65,7 @@ impl<'tcx> UnixEnvVars<'tcx> {
         Ok(())
     }
 
-    pub(crate) fn environ(&self) -> Pointer<Option<Provenance>> {
+    pub(crate) fn environ(&self) -> Pointer {
         self.environ.ptr()
     }
 
@@ -73,7 +73,7 @@ impl<'tcx> UnixEnvVars<'tcx> {
         &self,
         ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
         name: &OsStr,
-    ) -> InterpResult<'tcx, Option<Pointer<Option<Provenance>>>> {
+    ) -> InterpResult<'tcx, Option<Pointer>> {
         // We don't care about the value as we have the `map` to keep track of everything,
         // but we do want to do this read so it shows up as a data race.
         let _vars_ptr = ecx.read_pointer(&self.environ)?;
@@ -109,7 +109,7 @@ fn alloc_env_var<'tcx>(
     ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
     name: &OsStr,
     value: &OsStr,
-) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+) -> InterpResult<'tcx, Pointer> {
     let mut name_osstring = name.to_os_string();
     name_osstring.push("=");
     name_osstring.push(value);
@@ -119,8 +119,8 @@ fn alloc_env_var<'tcx>(
 /// Allocates an `environ` block with the given list of pointers.
 fn alloc_environ_block<'tcx>(
     ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
-    mut vars: Vec<Pointer<Option<Provenance>>>,
-) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    mut vars: Vec<Pointer>,
+) -> InterpResult<'tcx, Pointer> {
     // Add trailing null.
     vars.push(Pointer::null());
     // Make an array with all these pointers inside Miri.
@@ -139,10 +139,7 @@ fn alloc_environ_block<'tcx>(
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn getenv(
-        &mut self,
-        name_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn getenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("getenv");
 
@@ -153,11 +150,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(var_ptr.unwrap_or_else(Pointer::null))
     }
 
-    fn setenv(
-        &mut self,
-        name_op: &OpTy<'tcx, Provenance>,
-        value_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("setenv");
 
@@ -187,7 +180,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn unsetenv(&mut self, name_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("unsetenv");
 
@@ -213,11 +206,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn getcwd(
-        &mut self,
-        buf_op: &OpTy<'tcx, Provenance>,
-        size_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn getcwd(&mut self, buf_op: &OpTy<'tcx>, size_op: &OpTy<'tcx>) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("getcwd");
 
@@ -245,7 +234,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Pointer::null())
     }
 
-    fn chdir(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("chdir");
 
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 5fdd77a0cbd..b6ac841dc9f 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -273,7 +273,7 @@ impl FdTable {
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn fcntl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
+    fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         if args.len() < 2 {
@@ -329,7 +329,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn close(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn close(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -355,12 +355,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok((-1).into())
     }
 
-    fn read(
-        &mut self,
-        fd: i32,
-        buf: Pointer<Option<Provenance>>,
-        count: u64,
-    ) -> InterpResult<'tcx, i64> {
+    fn read(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescriptor` trait.
@@ -409,12 +404,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn write(
-        &mut self,
-        fd: i32,
-        buf: Pointer<Option<Provenance>>,
-        count: u64,
-    ) -> InterpResult<'tcx, i64> {
+    fn write(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescriptor` trait.
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 052715e239f..2282099fa0d 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -43,8 +43,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
@@ -326,7 +326,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let name = this.read_scalar(name)?.to_i32()?;
                 // FIXME: Which of these are POSIX, and which are GNU/Linux?
                 // At least the names seem to all also exist on macOS.
-                let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar<Provenance>)] = &[
+                let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[
                     ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
                     ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 30eb88151e4..36f25767a8e 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -14,8 +14,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 8e3d547b075..c8805f054ec 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -91,7 +91,7 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn macos_stat_write_buf(
         &mut self,
         metadata: FileMetadata,
-        buf_op: &OpTy<'tcx, Provenance>,
+        buf_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -180,7 +180,7 @@ struct OpenDir {
     read_dir: ReadDir,
     /// The most recent entry returned by readdir().
     /// Will be freed by the next call.
-    entry: Option<Pointer<Option<Provenance>>>,
+    entry: Option<Pointer>,
 }
 
 impl OpenDir {
@@ -256,7 +256,7 @@ fn maybe_sync_file(
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
+    fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
         if args.len() < 2 {
             throw_ub_format!(
                 "incorrect number of arguments for `open`: got {}, expected at least 2",
@@ -389,12 +389,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(fd)
     }
 
-    fn lseek64(
-        &mut self,
-        fd: i32,
-        offset: i128,
-        whence: i32,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescriptor` trait.
@@ -425,7 +420,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Scalar::from_i64(result))
     }
 
-    fn unlink(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
@@ -443,8 +438,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn symlink(
         &mut self,
-        target_op: &OpTy<'tcx, Provenance>,
-        linkpath_op: &OpTy<'tcx, Provenance>,
+        target_op: &OpTy<'tcx>,
+        linkpath_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         #[cfg(unix)]
         fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
@@ -474,9 +469,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn macos_fbsd_stat(
         &mut self,
-        path_op: &OpTy<'tcx, Provenance>,
-        buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        path_op: &OpTy<'tcx>,
+        buf_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
@@ -506,9 +501,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     // `lstat` is used to get symlink metadata.
     fn macos_fbsd_lstat(
         &mut self,
-        path_op: &OpTy<'tcx, Provenance>,
-        buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        path_op: &OpTy<'tcx>,
+        buf_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
@@ -536,9 +531,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn macos_fbsd_fstat(
         &mut self,
-        fd_op: &OpTy<'tcx, Provenance>,
-        buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        fd_op: &OpTy<'tcx>,
+        buf_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
@@ -563,11 +558,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn linux_statx(
         &mut self,
-        dirfd_op: &OpTy<'tcx, Provenance>,    // Should be an `int`
-        pathname_op: &OpTy<'tcx, Provenance>, // Should be a `const char *`
-        flags_op: &OpTy<'tcx, Provenance>,    // Should be an `int`
-        mask_op: &OpTy<'tcx, Provenance>,     // Should be an `unsigned int`
-        statxbuf_op: &OpTy<'tcx, Provenance>, // Should be a `struct statx *`
+        dirfd_op: &OpTy<'tcx>,    // Should be an `int`
+        pathname_op: &OpTy<'tcx>, // Should be a `const char *`
+        flags_op: &OpTy<'tcx>,    // Should be an `int`
+        mask_op: &OpTy<'tcx>,     // Should be an `unsigned int`
+        statxbuf_op: &OpTy<'tcx>, // Should be a `struct statx *`
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -745,8 +740,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn rename(
         &mut self,
-        oldpath_op: &OpTy<'tcx, Provenance>,
-        newpath_op: &OpTy<'tcx, Provenance>,
+        oldpath_op: &OpTy<'tcx>,
+        newpath_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -774,11 +769,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(result)
     }
 
-    fn mkdir(
-        &mut self,
-        path_op: &OpTy<'tcx, Provenance>,
-        mode_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         #[cfg_attr(not(unix), allow(unused_variables))]
@@ -813,7 +804,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(result)
     }
 
-    fn rmdir(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
@@ -830,10 +821,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(result)
     }
 
-    fn opendir(
-        &mut self,
-        name_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn opendir(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let name = this.read_path_from_c_str(this.read_pointer(name_op)?)?;
@@ -864,10 +852,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn linux_readdir64(
-        &mut self,
-        dirp_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn linux_readdir64(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("linux", "readdir64");
@@ -915,7 +900,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     dirent64_layout.align.abi,
                     MiriMemoryKind::Runtime.into(),
                 )?;
-                let entry: Pointer<Option<Provenance>> = entry.into();
+                let entry: Pointer = entry.into();
 
                 // If the host is a Unix system, fill in the inode number with its real value.
                 // If not, use 0 as a fallback value.
@@ -962,10 +947,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn macos_fbsd_readdir_r(
         &mut self,
-        dirp_op: &OpTy<'tcx, Provenance>,
-        entry_op: &OpTy<'tcx, Provenance>,
-        result_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        dirp_op: &OpTy<'tcx>,
+        entry_op: &OpTy<'tcx>,
+        result_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
@@ -1083,7 +1068,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }))
     }
 
-    fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let dirp = this.read_target_usize(dirp_op)?;
@@ -1106,7 +1091,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         // Reject if isolation is enabled.
@@ -1147,7 +1132,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn fsync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         // On macOS, `fsync` (unlike `fcntl(F_FULLFSYNC)`) does not wait for the
         // underlying disk to finish writing. In the interest of host compatibility,
         // we conservatively implement this with `sync_all`, which
@@ -1182,7 +1167,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(io_result)
     }
 
-    fn fdatasync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -1209,11 +1194,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn sync_file_range(
         &mut self,
-        fd_op: &OpTy<'tcx, Provenance>,
-        offset_op: &OpTy<'tcx, Provenance>,
-        nbytes_op: &OpTy<'tcx, Provenance>,
-        flags_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        fd_op: &OpTy<'tcx>,
+        offset_op: &OpTy<'tcx>,
+        nbytes_op: &OpTy<'tcx>,
+        flags_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -1259,9 +1244,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn readlink(
         &mut self,
-        pathname_op: &OpTy<'tcx, Provenance>,
-        buf_op: &OpTy<'tcx, Provenance>,
-        bufsize_op: &OpTy<'tcx, Provenance>,
+        pathname_op: &OpTy<'tcx>,
+        buf_op: &OpTy<'tcx>,
+        bufsize_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i64> {
         let this = self.eval_context_mut();
 
@@ -1302,10 +1287,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn isatty(
-        &mut self,
-        miri_fd: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn isatty(&mut self, miri_fd: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         // "returns 1 if fd is an open file descriptor referring to a terminal;
         // otherwise 0 is returned, and errno is set to indicate the error"
@@ -1326,9 +1308,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn realpath(
         &mut self,
-        path_op: &OpTy<'tcx, Provenance>,
-        processed_path_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        path_op: &OpTy<'tcx>,
+        processed_path_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("realpath");
 
@@ -1384,7 +1366,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
         }
     }
-    fn mkstemp(&mut self, template_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         use rand::seq::SliceRandom;
 
         // POSIX defines the template string.
@@ -1531,7 +1513,7 @@ fn extract_sec_and_nsec<'tcx>(
 /// Stores a file's metadata in order to avoid code duplication in the different metadata related
 /// shims.
 struct FileMetadata {
-    mode: Scalar<Provenance>,
+    mode: Scalar,
     size: u64,
     created: Option<(u64, u32)>,
     accessed: Option<(u64, u32)>,
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index 50868e60e95..aa4dc982870 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -25,10 +25,10 @@ struct Epoll {
 struct EpollEvent {
     #[allow(dead_code)]
     events: u32,
-    /// `Scalar<Provenance>` is used to represent the
+    /// `Scalar` is used to represent the
     /// `epoll_data` type union.
     #[allow(dead_code)]
-    data: Scalar<Provenance>,
+    data: Scalar,
 }
 
 impl FileDescription for Epoll {
@@ -51,10 +51,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// is 0, then this function is the same as `epoll_create()`.
     ///
     /// <https://linux.die.net/man/2/epoll_create1>
-    fn epoll_create1(
-        &mut self,
-        flags: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn epoll_create1(&mut self, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let flags = this.read_scalar(flags)?.to_i32()?;
@@ -85,11 +82,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// <https://linux.die.net/man/2/epoll_ctl>
     fn epoll_ctl(
         &mut self,
-        epfd: &OpTy<'tcx, Provenance>,
-        op: &OpTy<'tcx, Provenance>,
-        fd: &OpTy<'tcx, Provenance>,
-        event: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        epfd: &OpTy<'tcx>,
+        op: &OpTy<'tcx>,
+        fd: &OpTy<'tcx>,
+        event: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let epfd = this.read_scalar(epfd)?.to_i32()?;
@@ -167,11 +164,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>
     fn epoll_wait(
         &mut self,
-        epfd: &OpTy<'tcx, Provenance>,
-        events: &OpTy<'tcx, Provenance>,
-        maxevents: &OpTy<'tcx, Provenance>,
-        timeout: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        epfd: &OpTy<'tcx>,
+        events: &OpTy<'tcx>,
+        maxevents: &OpTy<'tcx>,
+        timeout: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let epfd = this.read_scalar(epfd)?.to_i32()?;
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs
index 1447e498fd7..cae5abca3bd 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs
@@ -1,14 +1,21 @@
 //! Linux `eventfd` implementation.
-//! Currently just a stub.
 use std::io;
+use std::io::{Error, ErrorKind};
+use std::mem;
 
 use rustc_target::abi::Endian;
 
 use crate::shims::unix::*;
-use crate::*;
+use crate::{concurrency::VClock, *};
 
 use self::shims::unix::fd::FileDescriptor;
 
+// We'll only do reads and writes in chunks of size u64.
+const U64_ARRAY_SIZE: usize = mem::size_of::<u64>();
+
+/// Maximum value that the eventfd counter can hold.
+const MAX_COUNTER: u64 = u64::MAX - 1;
+
 /// A kind of file descriptor created by `eventfd`.
 /// The `Event` type isn't currently written to by `eventfd`.
 /// The interface is meant to keep track of objects associated
@@ -20,7 +27,9 @@ use self::shims::unix::fd::FileDescriptor;
 struct Event {
     /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the
     /// kernel. This counter is initialized with the value specified in the argument initval.
-    val: u64,
+    counter: u64,
+    is_nonblock: bool,
+    clock: VClock,
 }
 
 impl FileDescription for Event {
@@ -35,6 +44,38 @@ impl FileDescription for Event {
         Ok(Ok(()))
     }
 
+    /// Read the counter in the buffer and return the counter if succeeded.
+    fn read<'tcx>(
+        &mut self,
+        _communicate_allowed: bool,
+        bytes: &mut [u8],
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<usize>> {
+        // Check the size of slice, and return error only if the size of the slice < 8.
+        let Some(bytes) = bytes.first_chunk_mut::<U64_ARRAY_SIZE>() else {
+            return Ok(Err(Error::from(ErrorKind::InvalidInput)));
+        };
+        // Block when counter == 0.
+        if self.counter == 0 {
+            if self.is_nonblock {
+                return Ok(Err(Error::from(ErrorKind::WouldBlock)));
+            } else {
+                //FIXME: blocking is not supported
+                throw_unsup_format!("eventfd: blocking is unsupported");
+            }
+        } else {
+            // Synchronize with all prior `write` calls to this FD.
+            ecx.acquire_clock(&self.clock);
+            // Return the counter in the host endianness using the buffer provided by caller.
+            *bytes = match ecx.tcx.sess.target.endian {
+                Endian::Little => self.counter.to_le_bytes(),
+                Endian::Big => self.counter.to_be_bytes(),
+            };
+            self.counter = 0;
+            return Ok(Ok(U64_ARRAY_SIZE));
+        }
+    }
+
     /// A write call adds the 8-byte integer value supplied in
     /// its buffer (in native endianness) to the counter.  The maximum value that may be
     /// stored in the counter is the largest unsigned 64-bit value
@@ -53,16 +94,39 @@ impl FileDescription for Event {
         bytes: &[u8],
         ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
-        let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size
-        // Convert from target endianness to host endianness.
+        // Check the size of slice, and return error only if the size of the slice < 8.
+        let Some(bytes) = bytes.first_chunk::<U64_ARRAY_SIZE>() else {
+            return Ok(Err(Error::from(ErrorKind::InvalidInput)));
+        };
+        // Convert from bytes to int according to host endianness.
         let num = match ecx.tcx.sess.target.endian {
-            Endian::Little => u64::from_le_bytes(bytes),
-            Endian::Big => u64::from_be_bytes(bytes),
+            Endian::Little => u64::from_le_bytes(*bytes),
+            Endian::Big => u64::from_be_bytes(*bytes),
+        };
+        // u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1.
+        if num == u64::MAX {
+            return Ok(Err(Error::from(ErrorKind::InvalidInput)));
+        }
+        // If the addition does not let the counter to exceed the maximum value, update the counter.
+        // Else, block.
+        match self.counter.checked_add(num) {
+            Some(new_count @ 0..=MAX_COUNTER) => {
+                // Future `read` calls will synchronize with this write, so update the FD clock.
+                if let Some(clock) = &ecx.release_clock() {
+                    self.clock.join(clock);
+                }
+                self.counter = new_count;
+            }
+            None | Some(u64::MAX) => {
+                if self.is_nonblock {
+                    return Ok(Err(Error::from(ErrorKind::WouldBlock)));
+                } else {
+                    //FIXME: blocking is not supported
+                    throw_unsup_format!("eventfd: blocking is unsupported");
+                }
+            }
         };
-        // FIXME handle blocking when addition results in exceeding the max u64 value
-        // or fail with EAGAIN if the file descriptor is nonblocking.
-        self.val = self.val.checked_add(num).unwrap();
-        Ok(Ok(8))
+        Ok(Ok(U64_ARRAY_SIZE))
     }
 }
 
@@ -84,34 +148,43 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
     ///
     /// <https://linux.die.net/man/2/eventfd>
-    fn eventfd(
-        &mut self,
-        val: &OpTy<'tcx, Provenance>,
-        flags: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
+        // eventfd is Linux specific.
+        this.assert_target_os("linux", "eventfd");
+
         let val = this.read_scalar(val)?.to_u32()?;
-        let flags = this.read_scalar(flags)?.to_i32()?;
+        let mut flags = this.read_scalar(flags)?.to_i32()?;
 
         let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC");
         let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK");
         let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE");
 
-        if flags & (efd_cloexec | efd_nonblock | efd_semaphore) != flags {
-            throw_unsup_format!("eventfd: flag {flags:#x} is unsupported");
+        if flags & efd_semaphore == efd_semaphore {
+            throw_unsup_format!("eventfd: EFD_SEMAPHORE is unsupported");
         }
+
+        let mut is_nonblock = false;
+        // Unset the flag that we support.
+        // After unloading, flags != 0 means other flags are used.
         if flags & efd_cloexec == efd_cloexec {
-            // cloexec does nothing as we don't support `exec`
+            // cloexec is ignored because Miri does not support exec.
+            flags &= !efd_cloexec;
         }
         if flags & efd_nonblock == efd_nonblock {
-            // FIXME remember the nonblock flag
+            flags &= !efd_nonblock;
+            is_nonblock = true;
         }
-        if flags & efd_semaphore == efd_semaphore {
-            throw_unsup_format!("eventfd: EFD_SEMAPHORE is unsupported");
+        if flags != 0 {
+            throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags);
         }
 
-        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Event { val: val.into() }));
+        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Event {
+            counter: val.into(),
+            is_nonblock,
+            clock: VClock::default(),
+        }));
         Ok(Scalar::from_i32(fd))
     }
 }
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 7d0c8be1eaa..e31d43d9190 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -20,8 +20,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs
index 5f5d2b0c739..c430eff0180 100644
--- a/src/tools/miri/src/shims/unix/linux/mem.rs
+++ b/src/tools/miri/src/shims/unix/linux/mem.rs
@@ -8,11 +8,11 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mremap(
         &mut self,
-        old_address: &OpTy<'tcx, Provenance>,
-        old_size: &OpTy<'tcx, Provenance>,
-        new_size: &OpTy<'tcx, Provenance>,
-        flags: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        old_address: &OpTy<'tcx>,
+        old_size: &OpTy<'tcx>,
+        new_size: &OpTy<'tcx>,
+        flags: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let old_address = this.read_pointer(old_address)?;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index de83a358db9..bd212039074 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -1,13 +1,11 @@
-use std::time::SystemTime;
-
 use crate::*;
 
 /// Implementation of the SYS_futex syscall.
 /// `args` is the arguments *after* the syscall number.
 pub fn futex<'tcx>(
     this: &mut MiriInterpCx<'tcx>,
-    args: &[OpTy<'tcx, Provenance>],
-    dest: &MPlaceTy<'tcx, Provenance>,
+    args: &[OpTy<'tcx>],
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx> {
     // The amount of arguments used depends on the type of futex operation.
     // The full futex syscall takes six arguments (excluding the syscall
@@ -84,15 +82,9 @@ pub fn futex<'tcx>(
             }
 
             let timeout = this.deref_pointer_as(&args[3], this.libc_ty_layout("timespec"))?;
-            let timeout_time = if this.ptr_is_null(timeout.ptr())? {
+            let timeout = if this.ptr_is_null(timeout.ptr())? {
                 None
             } else {
-                let realtime = op & futex_realtime == futex_realtime;
-                if realtime {
-                    this.check_no_isolation(
-                        "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`",
-                    )?;
-                }
                 let duration = match this.read_timespec(&timeout)? {
                     Some(duration) => duration,
                     None => {
@@ -102,23 +94,22 @@ pub fn futex<'tcx>(
                         return Ok(());
                     }
                 };
-                Some(if wait_bitset {
+                let timeout_clock = if op & futex_realtime == futex_realtime {
+                    this.check_no_isolation(
+                        "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`",
+                    )?;
+                    TimeoutClock::RealTime
+                } else {
+                    TimeoutClock::Monotonic
+                };
+                let timeout_anchor = if wait_bitset {
                     // FUTEX_WAIT_BITSET uses an absolute timestamp.
-                    if realtime {
-                        Timeout::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
-                    } else {
-                        Timeout::Monotonic(
-                            this.machine.clock.anchor().checked_add(duration).unwrap(),
-                        )
-                    }
+                    TimeoutAnchor::Absolute
                 } else {
                     // FUTEX_WAIT uses a relative timestamp.
-                    if realtime {
-                        Timeout::RealTime(SystemTime::now().checked_add(duration).unwrap())
-                    } else {
-                        Timeout::Monotonic(this.machine.clock.now().checked_add(duration).unwrap())
-                    }
-                })
+                    TimeoutAnchor::Relative
+                };
+                Some((timeout_clock, timeout_anchor, duration))
             };
             // There may be a concurrent thread changing the value of addr
             // and then invoking the FUTEX_WAKE syscall. It is critical that the
@@ -172,7 +163,7 @@ pub fn futex<'tcx>(
                 this.futex_wait(
                     addr_usize,
                     bitset,
-                    timeout_time,
+                    timeout,
                     Scalar::from_target_isize(0, this), // retval_succ
                     Scalar::from_target_isize(-1, this), // retval_timeout
                     dest.clone(),
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index a1e9ccec676..25002f0a611 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -14,8 +14,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 4d727c0b180..de5a5d0759c 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -21,13 +21,13 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mmap(
         &mut self,
-        addr: &OpTy<'tcx, Provenance>,
-        length: &OpTy<'tcx, Provenance>,
-        prot: &OpTy<'tcx, Provenance>,
-        flags: &OpTy<'tcx, Provenance>,
-        fd: &OpTy<'tcx, Provenance>,
+        addr: &OpTy<'tcx>,
+        length: &OpTy<'tcx>,
+        prot: &OpTy<'tcx>,
+        flags: &OpTy<'tcx>,
+        fd: &OpTy<'tcx>,
         offset: i128,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         // We do not support MAP_FIXED, so the addr argument is always ignored (except for the MacOS hack)
@@ -123,11 +123,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Scalar::from_pointer(ptr, this))
     }
 
-    fn munmap(
-        &mut self,
-        addr: &OpTy<'tcx, Provenance>,
-        length: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn munmap(&mut self, addr: &OpTy<'tcx>, length: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let addr = this.read_pointer(addr)?;
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index a0fa3bcee34..97bf6348f0b 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -35,11 +35,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// <https://linux.die.net/man/2/socketpair>
     fn socketpair(
         &mut self,
-        domain: &OpTy<'tcx, Provenance>,
-        type_: &OpTy<'tcx, Provenance>,
-        protocol: &OpTy<'tcx, Provenance>,
-        sv: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        domain: &OpTy<'tcx>,
+        type_: &OpTy<'tcx>,
+        protocol: &OpTy<'tcx>,
+        sv: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let _domain = this.read_scalar(domain)?.to_i32()?;
@@ -51,9 +51,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         let fds = &mut this.machine.fds;
         let sv0 = fds.insert_fd(FileDescriptor::new(SocketPair));
-        let sv0 = Scalar::try_from_int(sv0, sv.layout.size).unwrap();
+        let sv0 = Scalar::from_int(sv0, sv.layout.size);
         let sv1 = fds.insert_fd(FileDescriptor::new(SocketPair));
-        let sv1 = Scalar::try_from_int(sv1, sv.layout.size).unwrap();
+        let sv1 = Scalar::from_int(sv1, sv.layout.size);
 
         this.write_scalar(sv0, &sv)?;
         this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?)?;
diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
index 38cd83edd24..a0cc4a62bfd 100644
--- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
@@ -14,8 +14,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
@@ -69,6 +69,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_null(dest)?;
             }
 
+            "pset_info" => {
+                let [pset, tpe, cpus, list] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                // We do not need to handle the current process cpu mask, available_parallelism
+                // implementation pass null anyway. We only care for the number of
+                // cpus.
+                // https://docs.oracle.com/cd/E88353_01/html/E37841/pset-info-2.html
+
+                let pset = this.read_scalar(pset)?.to_i32()?;
+                let tpe = this.read_pointer(tpe)?;
+                let list = this.read_pointer(list)?;
+
+                let ps_myid = this.eval_libc_i32("PS_MYID");
+                if ps_myid != pset {
+                    throw_unsup_format!("pset_info is only supported with pset==PS_MYID");
+                }
+
+                if !this.ptr_is_null(tpe)? {
+                    throw_unsup_format!("pset_info is only supported with type==NULL");
+                }
+
+                if !this.ptr_is_null(list)? {
+                    throw_unsup_format!("pset_info is only supported with list==NULL");
+                }
+
+                let cpus = this.deref_pointer(cpus)?;
+                this.write_scalar(Scalar::from_u32(this.machine.num_cpus), &cpus)?;
+                this.write_null(dest)?;
+            }
+
             _ => return Ok(EmulateItemResult::NotSupported),
         }
         Ok(EmulateItemResult::NeedsReturn)
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 0743ad14495..be6732b1b67 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -1,5 +1,4 @@
 use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::SystemTime;
 
 use rustc_target::abi::Size;
 
@@ -10,9 +9,7 @@ use crate::*;
 // - kind: i32
 
 #[inline]
-fn mutexattr_kind_offset<'tcx>(
-    ecx: &MiriInterpCx<'tcx>,
-) -> InterpResult<'tcx, u64> {
+fn mutexattr_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     Ok(match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" | "macos" => 0,
         os => throw_unsup_format!("`pthread_mutexattr` is not supported on {os}"),
@@ -21,7 +18,7 @@ fn mutexattr_kind_offset<'tcx>(
 
 fn mutexattr_get_kind<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
-    attr_op: &OpTy<'tcx, Provenance>,
+    attr_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         attr_op,
@@ -34,7 +31,7 @@ fn mutexattr_get_kind<'tcx>(
 
 fn mutexattr_set_kind<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    attr_op: &OpTy<'tcx, Provenance>,
+    attr_op: &OpTy<'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -53,17 +50,11 @@ fn mutexattr_set_kind<'tcx>(
 /// in `pthread_mutexattr_settype` function.
 const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
 
-fn is_mutex_kind_default<'tcx>(
-    ecx: &MiriInterpCx<'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
+fn is_mutex_kind_default<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, bool> {
     Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
 }
 
-fn is_mutex_kind_normal<'tcx>(
-    ecx: &MiriInterpCx<'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
+fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, bool> {
     let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
     Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
 }
@@ -125,7 +116,7 @@ fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
 
 fn mutex_get_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx, Provenance>,
+    mutex_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, MutexId> {
     ecx.mutex_get_or_create_id(
         mutex_op,
@@ -136,7 +127,7 @@ fn mutex_get_id<'tcx>(
 
 fn mutex_reset_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx, Provenance>,
+    mutex_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         mutex_op,
@@ -149,7 +140,7 @@ fn mutex_reset_id<'tcx>(
 
 fn mutex_get_kind<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx, Provenance>,
+    mutex_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         mutex_op,
@@ -162,7 +153,7 @@ fn mutex_get_kind<'tcx>(
 
 fn mutex_set_kind<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx, Provenance>,
+    mutex_op: &OpTy<'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -206,7 +197,7 @@ fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
 
 fn rwlock_get_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    rwlock_op: &OpTy<'tcx, Provenance>,
+    rwlock_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, RwLockId> {
     ecx.rwlock_get_or_create_id(
         rwlock_op,
@@ -220,9 +211,7 @@ fn rwlock_get_id<'tcx>(
 // - clock: i32
 
 #[inline]
-fn condattr_clock_offset<'tcx>(
-    ecx: &MiriInterpCx<'tcx>,
-) -> InterpResult<'tcx, u64> {
+fn condattr_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     Ok(match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" => 0,
         // macOS does not have a clock attribute.
@@ -232,7 +221,7 @@ fn condattr_clock_offset<'tcx>(
 
 fn condattr_get_clock_id<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
-    attr_op: &OpTy<'tcx, Provenance>,
+    attr_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         attr_op,
@@ -245,7 +234,7 @@ fn condattr_get_clock_id<'tcx>(
 
 fn condattr_set_clock_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    attr_op: &OpTy<'tcx, Provenance>,
+    attr_op: &OpTy<'tcx>,
     clock_id: i32,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -323,7 +312,7 @@ fn cond_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
 
 fn cond_get_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    cond_op: &OpTy<'tcx, Provenance>,
+    cond_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, CondvarId> {
     ecx.condvar_get_or_create_id(
         cond_op,
@@ -334,7 +323,7 @@ fn cond_get_id<'tcx>(
 
 fn cond_reset_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    cond_op: &OpTy<'tcx, Provenance>,
+    cond_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
         cond_op,
@@ -347,7 +336,7 @@ fn cond_reset_id<'tcx>(
 
 fn cond_get_clock_id<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
-    cond_op: &OpTy<'tcx, Provenance>,
+    cond_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
         cond_op,
@@ -360,7 +349,7 @@ fn cond_get_clock_id<'tcx>(
 
 fn cond_set_clock_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
-    cond_op: &OpTy<'tcx, Provenance>,
+    cond_op: &OpTy<'tcx>,
     clock_id: i32,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -374,10 +363,7 @@ fn cond_set_clock_id<'tcx>(
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    fn pthread_mutexattr_init(
-        &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT");
@@ -388,8 +374,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_mutexattr_settype(
         &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-        kind_op: &OpTy<'tcx, Provenance>,
+        attr_op: &OpTy<'tcx>,
+        kind_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -427,10 +413,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(0)
     }
 
-    fn pthread_mutexattr_destroy(
-        &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         // Destroying an uninit pthread_mutexattr is UB, so check to make sure it's not uninit.
@@ -457,8 +440,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_mutex_init(
         &mut self,
-        mutex_op: &OpTy<'tcx, Provenance>,
-        attr_op: &OpTy<'tcx, Provenance>,
+        mutex_op: &OpTy<'tcx>,
+        attr_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -479,8 +462,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_mutex_lock(
         &mut self,
-        mutex_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        mutex_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -518,10 +501,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn pthread_mutex_trylock(
-        &mut self,
-        mutex_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let kind = mutex_get_kind(this, mutex_op)?;
@@ -553,10 +533,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn pthread_mutex_unlock(
-        &mut self,
-        mutex_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let kind = mutex_get_kind(this, mutex_op)?;
@@ -587,10 +564,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn pthread_mutex_destroy(
-        &mut self,
-        mutex_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = mutex_get_id(this, mutex_op)?;
@@ -614,8 +588,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_rwlock_rdlock(
         &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        rwlock_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -631,10 +605,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn pthread_rwlock_tryrdlock(
-        &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = rwlock_get_id(this, rwlock_op)?;
@@ -649,8 +620,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_rwlock_wrlock(
         &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        rwlock_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -678,10 +649,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn pthread_rwlock_trywrlock(
-        &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = rwlock_get_id(this, rwlock_op)?;
@@ -694,10 +662,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn pthread_rwlock_unlock(
-        &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = rwlock_get_id(this, rwlock_op)?;
@@ -712,10 +677,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
     }
 
-    fn pthread_rwlock_destroy(
-        &mut self,
-        rwlock_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = rwlock_get_id(this, rwlock_op)?;
@@ -736,10 +698,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(0)
     }
 
-    fn pthread_condattr_init(
-        &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         // no clock attribute on macOS
@@ -756,9 +715,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_condattr_setclock(
         &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-        clock_id_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        attr_op: &OpTy<'tcx>,
+        clock_id_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let clock_id = this.read_scalar(clock_id_op)?.to_i32()?;
@@ -776,9 +735,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_condattr_getclock(
         &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-        clk_id_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        attr_op: &OpTy<'tcx>,
+        clk_id_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let clock_id = condattr_get_clock_id(this, attr_op)?;
@@ -787,10 +746,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(Scalar::from_i32(0))
     }
 
-    fn pthread_condattr_destroy(
-        &mut self,
-        attr_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         // Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit.
@@ -810,8 +766,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_cond_init(
         &mut self,
-        cond_op: &OpTy<'tcx, Provenance>,
-        attr_op: &OpTy<'tcx, Provenance>,
+        cond_op: &OpTy<'tcx>,
+        attr_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -831,17 +787,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(0)
     }
 
-    fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
         let id = cond_get_id(this, cond_op)?;
         this.condvar_signal(id)?;
         Ok(0)
     }
 
-    fn pthread_cond_broadcast(
-        &mut self,
-        cond_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
         let id = cond_get_id(this, cond_op)?;
         while this.condvar_signal(id)? {}
@@ -850,9 +803,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_cond_wait(
         &mut self,
-        cond_op: &OpTy<'tcx, Provenance>,
-        mutex_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        cond_op: &OpTy<'tcx>,
+        mutex_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -873,10 +826,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_cond_timedwait(
         &mut self,
-        cond_op: &OpTy<'tcx, Provenance>,
-        mutex_op: &OpTy<'tcx, Provenance>,
-        abstime_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        cond_op: &OpTy<'tcx>,
+        mutex_op: &OpTy<'tcx>,
+        abstime_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -895,11 +848,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 return Ok(());
             }
         };
-        let timeout_time = if is_cond_clock_realtime(this, clock_id) {
+        let timeout_clock = if is_cond_clock_realtime(this, clock_id) {
             this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
-            Timeout::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
+            TimeoutClock::RealTime
         } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") {
-            Timeout::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
+            TimeoutClock::Monotonic
         } else {
             throw_unsup_format!("unsupported clock id: {}", clock_id);
         };
@@ -907,7 +860,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.condvar_wait(
             id,
             mutex_id,
-            Some(timeout_time),
+            Some((timeout_clock, TimeoutAnchor::Absolute, duration)),
             Scalar::from_i32(0),
             this.eval_libc("ETIMEDOUT"), // retval_timeout
             dest.clone(),
@@ -916,10 +869,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn pthread_cond_destroy(
-        &mut self,
-        cond_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let id = cond_get_id(this, cond_op)?;
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index 323b5c1992e..6fe331ba623 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -6,10 +6,10 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn pthread_create(
         &mut self,
-        thread: &OpTy<'tcx, Provenance>,
-        _attr: &OpTy<'tcx, Provenance>,
-        start_routine: &OpTy<'tcx, Provenance>,
-        arg: &OpTy<'tcx, Provenance>,
+        thread: &OpTy<'tcx>,
+        _attr: &OpTy<'tcx>,
+        start_routine: &OpTy<'tcx>,
+        arg: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -32,8 +32,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_join(
         &mut self,
-        thread: &OpTy<'tcx, Provenance>,
-        retval: &OpTy<'tcx, Provenance>,
+        thread: &OpTy<'tcx>,
+        retval: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -48,7 +48,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(0)
     }
 
-    fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
         let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
@@ -60,7 +60,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(0)
     }
 
-    fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let thread_id = this.active_thread();
@@ -71,10 +71,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// including the null terminator.
     fn pthread_setname_np(
         &mut self,
-        thread: Scalar<Provenance>,
-        name: Scalar<Provenance>,
+        thread: Scalar,
+        name: Scalar,
         max_name_len: usize,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?;
@@ -95,10 +95,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn pthread_getname_np(
         &mut self,
-        thread: Scalar<Provenance>,
-        name_out: Scalar<Provenance>,
-        len: Scalar<Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        thread: Scalar,
+        name_out: Scalar,
+        len: Scalar,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let thread = thread.to_int(this.libc_ty_layout("pthread_t").size)?;
diff --git a/src/tools/miri/src/shims/wasi/foreign_items.rs b/src/tools/miri/src/shims/wasi/foreign_items.rs
index b81b35bd963..e9fe90081d0 100644
--- a/src/tools/miri/src/shims/wasi/foreign_items.rs
+++ b/src/tools/miri/src/shims/wasi/foreign_items.rs
@@ -14,8 +14,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index 488a05366d2..ed3eb697986 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -38,10 +38,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn GetEnvironmentVariableW(
         &mut self,
-        name_op: &OpTy<'tcx, Provenance>, // LPCWSTR
-        buf_op: &OpTy<'tcx, Provenance>,  // LPWSTR
-        size_op: &OpTy<'tcx, Provenance>, // DWORD
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        name_op: &OpTy<'tcx>, // LPCWSTR
+        buf_op: &OpTy<'tcx>,  // LPWSTR
+        size_op: &OpTy<'tcx>, // DWORD
+    ) -> InterpResult<'tcx, Scalar> {
         // ^ Returns DWORD (u32 on Windows)
 
         let this = self.eval_context_mut();
@@ -71,7 +71,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     #[allow(non_snake_case)]
-    fn GetEnvironmentStringsW(&mut self) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    fn GetEnvironmentStringsW(&mut self) -> InterpResult<'tcx, Pointer> {
         let this = self.eval_context_mut();
         this.assert_target_os("windows", "GetEnvironmentStringsW");
 
@@ -93,10 +93,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     #[allow(non_snake_case)]
-    fn FreeEnvironmentStringsW(
-        &mut self,
-        env_block_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn FreeEnvironmentStringsW(&mut self, env_block_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         this.assert_target_os("windows", "FreeEnvironmentStringsW");
 
@@ -109,9 +106,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn SetEnvironmentVariableW(
         &mut self,
-        name_op: &OpTy<'tcx, Provenance>,  // LPCWSTR
-        value_op: &OpTy<'tcx, Provenance>, // LPCWSTR
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        name_op: &OpTy<'tcx>,  // LPCWSTR
+        value_op: &OpTy<'tcx>, // LPCWSTR
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         this.assert_target_os("windows", "SetEnvironmentVariableW");
 
@@ -142,9 +139,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn GetCurrentDirectoryW(
         &mut self,
-        size_op: &OpTy<'tcx, Provenance>, // DWORD
-        buf_op: &OpTy<'tcx, Provenance>,  // LPTSTR
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        size_op: &OpTy<'tcx>, // DWORD
+        buf_op: &OpTy<'tcx>,  // LPTSTR
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
         this.assert_target_os("windows", "GetCurrentDirectoryW");
 
@@ -174,8 +171,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn SetCurrentDirectoryW(
         &mut self,
-        path_op: &OpTy<'tcx, Provenance>, // LPCTSTR
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        path_op: &OpTy<'tcx>, // LPCTSTR
+    ) -> InterpResult<'tcx, Scalar> {
         // ^ Returns BOOL (i32 on Windows)
 
         let this = self.eval_context_mut();
@@ -211,10 +208,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn GetUserProfileDirectoryW(
         &mut self,
-        token: &OpTy<'tcx, Provenance>, // HANDLE
-        buf: &OpTy<'tcx, Provenance>,   // LPWSTR
-        size: &OpTy<'tcx, Provenance>,  // LPDWORD
-    ) -> InterpResult<'tcx, Scalar<Provenance>> // returns BOOL
+        token: &OpTy<'tcx>, // HANDLE
+        buf: &OpTy<'tcx>,   // LPWSTR
+        size: &OpTy<'tcx>,  // LPDWORD
+    ) -> InterpResult<'tcx, Scalar> // returns BOOL
     {
         let this = self.eval_context_mut();
         this.assert_target_os("windows", "GetUserProfileDirectoryW");
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index a60c2a337cf..bfa14bcb5fa 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -82,8 +82,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs
index 3e274a5b802..58c8683ff27 100644
--- a/src/tools/miri/src/shims/windows/handle.rs
+++ b/src/tools/miri/src/shims/windows/handle.rs
@@ -119,7 +119,7 @@ impl Handle {
         Self::new(discriminant, data)
     }
 
-    pub fn to_scalar(self, cx: &impl HasDataLayout) -> Scalar<Provenance> {
+    pub fn to_scalar(self, cx: &impl HasDataLayout) -> Scalar {
         // 64-bit handles are sign extended 32-bit handles
         // see https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
         #[allow(clippy::cast_possible_wrap)] // we want it to wrap
@@ -128,7 +128,7 @@ impl Handle {
     }
 
     pub fn from_scalar<'tcx>(
-        handle: Scalar<Provenance>,
+        handle: Scalar,
         cx: &impl HasDataLayout,
     ) -> InterpResult<'tcx, Option<Self>> {
         let sign_extended_handle = handle.to_target_isize(cx)?;
@@ -155,7 +155,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         )))
     }
 
-    fn CloseHandle(&mut self, handle_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn CloseHandle(&mut self, handle_op: &OpTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         let handle = this.read_scalar(handle_op)?;
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index d5fe15b401b..e1fbb77037c 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -10,10 +10,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     // Windows sync primitives are pointer sized.
     // We only use the first 4 bytes for the id.
 
-    fn init_once_get_id(
-        &mut self,
-        init_once_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, InitOnceId> {
+    fn init_once_get_id(&mut self, init_once_op: &OpTy<'tcx>) -> InterpResult<'tcx, InitOnceId> {
         let this = self.eval_context_mut();
         this.init_once_get_or_create_id(init_once_op, this.windows_ty_layout("INIT_ONCE"), 0)
     }
@@ -22,8 +19,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn init_once_try_begin(
         &mut self,
         id: InitOnceId,
-        pending_place: &MPlaceTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        pending_place: &MPlaceTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, bool> {
         let this = self.eval_context_mut();
         Ok(match this.init_once_status(id) {
@@ -49,11 +46,11 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn InitOnceBeginInitialize(
         &mut self,
-        init_once_op: &OpTy<'tcx, Provenance>,
-        flags_op: &OpTy<'tcx, Provenance>,
-        pending_op: &OpTy<'tcx, Provenance>,
-        context_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        init_once_op: &OpTy<'tcx>,
+        flags_op: &OpTy<'tcx>,
+        pending_op: &OpTy<'tcx>,
+        context_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -82,8 +79,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             callback!(
                 @capture<'tcx> {
                     id: InitOnceId,
-                    pending_place: MPlaceTy<'tcx, Provenance>,
-                    dest: MPlaceTy<'tcx, Provenance>,
+                    pending_place: MPlaceTy<'tcx>,
+                    dest: MPlaceTy<'tcx>,
                 }
                 @unblock = |this| {
                     let ret = this.init_once_try_begin(id, &pending_place, &dest)?;
@@ -97,10 +94,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn InitOnceComplete(
         &mut self,
-        init_once_op: &OpTy<'tcx, Provenance>,
-        flags_op: &OpTy<'tcx, Provenance>,
-        context_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        init_once_op: &OpTy<'tcx>,
+        flags_op: &OpTy<'tcx>,
+        context_op: &OpTy<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
         let id = this.init_once_get_id(init_once_op)?;
@@ -137,11 +134,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn WaitOnAddress(
         &mut self,
-        ptr_op: &OpTy<'tcx, Provenance>,
-        compare_op: &OpTy<'tcx, Provenance>,
-        size_op: &OpTy<'tcx, Provenance>,
-        timeout_op: &OpTy<'tcx, Provenance>,
-        dest: &MPlaceTy<'tcx, Provenance>,
+        ptr_op: &OpTy<'tcx>,
+        compare_op: &OpTy<'tcx>,
+        size_op: &OpTy<'tcx>,
+        timeout_op: &OpTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -160,11 +157,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         };
         let size = Size::from_bytes(size);
 
-        let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
+        let timeout = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
             None
         } else {
             let duration = Duration::from_millis(timeout_ms.into());
-            Some(Timeout::Monotonic(this.machine.clock.now().checked_add(duration).unwrap()))
+            Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration))
         };
 
         // See the Linux futex implementation for why this fence exists.
@@ -180,7 +177,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             this.futex_wait(
                 addr,
                 u32::MAX, // bitset
-                timeout_time,
+                timeout,
                 Scalar::from_i32(1), // retval_succ
                 Scalar::from_i32(0), // retval_timeout
                 dest.clone(),
@@ -193,7 +190,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(())
     }
 
-    fn WakeByAddressSingle(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn WakeByAddressSingle(&mut self, ptr_op: &OpTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         let ptr = this.read_pointer(ptr_op)?;
@@ -206,7 +203,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         Ok(())
     }
-    fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         let ptr = this.read_pointer(ptr_op)?;
diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs
index a9ef03d14ae..f3ddf6072af 100644
--- a/src/tools/miri/src/shims/windows/thread.rs
+++ b/src/tools/miri/src/shims/windows/thread.rs
@@ -10,12 +10,12 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn CreateThread(
         &mut self,
-        security_op: &OpTy<'tcx, Provenance>,
-        stacksize_op: &OpTy<'tcx, Provenance>,
-        start_op: &OpTy<'tcx, Provenance>,
-        arg_op: &OpTy<'tcx, Provenance>,
-        flags_op: &OpTy<'tcx, Provenance>,
-        thread_op: &OpTy<'tcx, Provenance>,
+        security_op: &OpTy<'tcx>,
+        stacksize_op: &OpTy<'tcx>,
+        start_op: &OpTy<'tcx>,
+        arg_op: &OpTy<'tcx>,
+        flags_op: &OpTy<'tcx>,
+        thread_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, ThreadId> {
         let this = self.eval_context_mut();
 
@@ -57,8 +57,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn WaitForSingleObject(
         &mut self,
-        handle_op: &OpTy<'tcx, Provenance>,
-        timeout_op: &OpTy<'tcx, Provenance>,
+        handle_op: &OpTy<'tcx>,
+        timeout_op: &OpTy<'tcx>,
     ) -> InterpResult<'tcx, u32> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs
index c1be1d4582a..e4e1531157a 100644
--- a/src/tools/miri/src/shims/x86/aesni.rs
+++ b/src/tools/miri/src/shims/x86/aesni.rs
@@ -6,15 +6,13 @@ use rustc_target::spec::abi::Abi;
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_aesni_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "aes")?;
@@ -135,9 +133,9 @@ pub(super) trait EvalContextExt<'tcx>:
 // `state` with the corresponding 128-bit key of `key`.
 fn aes_round<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    state: &OpTy<'tcx, Provenance>,
-    key: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    state: &OpTy<'tcx>,
+    key: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
     f: impl Fn(u128, u128) -> u128,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(dest.layout.size, state.layout.size);
diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs
index f782fbfff4e..07d737e0663 100644
--- a/src/tools/miri/src/shims/x86/avx.rs
+++ b/src/tools/miri/src/shims/x86/avx.rs
@@ -13,15 +13,13 @@ use super::{
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_avx_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "avx")?;
diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs
index 91764a20572..016c525e57b 100644
--- a/src/tools/miri/src/shims/x86/avx2.rs
+++ b/src/tools/miri/src/shims/x86/avx2.rs
@@ -11,15 +11,13 @@ use super::{
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_avx2_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "avx2")?;
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index b5951e9e895..f2d120df21c 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -26,8 +26,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         // Prefix should have already been checked.
@@ -105,6 +105,13 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
 
+            "pclmulqdq" => {
+                let [left, right, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                pclmulqdq(this, left, right, imm, dest)?;
+            }
+
             name if name.starts_with("sse.") => {
                 return sse::EvalContextExt::emulate_x86_sse_intrinsic(
                     this, link_name, abi, args, dest,
@@ -244,9 +251,9 @@ impl FloatBinOp {
 fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
     this: &crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
-    left: &ImmTy<'tcx, Provenance>,
-    right: &ImmTy<'tcx, Provenance>,
-) -> InterpResult<'tcx, Scalar<Provenance>> {
+    left: &ImmTy<'tcx>,
+    right: &ImmTy<'tcx>,
+) -> InterpResult<'tcx, Scalar> {
     match which {
         FloatBinOp::Arith(which) => {
             let res = this.binary_op(which, left, right)?;
@@ -306,9 +313,9 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
 fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
@@ -337,9 +344,9 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>(
 fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
@@ -384,8 +391,8 @@ enum FloatUnaryOp {
 fn unary_op_f32<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
-    op: &ImmTy<'tcx, Provenance>,
-) -> InterpResult<'tcx, Scalar<Provenance>> {
+    op: &ImmTy<'tcx>,
+) -> InterpResult<'tcx, Scalar> {
     match which {
         FloatUnaryOp::Sqrt => {
             let op = op.to_scalar();
@@ -435,8 +442,8 @@ fn apply_random_float_error<F: rustc_apfloat::Float>(
 fn unary_op_ss<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
-    op: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -458,8 +465,8 @@ fn unary_op_ss<'tcx>(
 fn unary_op_ps<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
-    op: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -494,10 +501,10 @@ enum ShiftOp {
 /// bit is copied to all bits.
 fn shift_simd_by_scalar<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
     which: ShiftOp,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -550,10 +557,10 @@ fn shift_simd_by_scalar<'tcx>(
 /// bit is copied to all bits.
 fn shift_simd_by_simd<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
     which: ShiftOp,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
@@ -602,7 +609,7 @@ fn shift_simd_by_simd<'tcx>(
 /// the first value.
 fn extract_first_u64<'tcx>(
     this: &crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, u64> {
     // Transmute vector to `[u64; 2]`
     let array_layout = this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u64, 2))?;
@@ -616,10 +623,10 @@ fn extract_first_u64<'tcx>(
 // and copies the remaining elements from `left`.
 fn round_first<'tcx, F: rustc_apfloat::Float>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    rounding: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    rounding: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
@@ -647,9 +654,9 @@ fn round_first<'tcx, F: rustc_apfloat::Float>(
 // Rounds all elements of `op` according to `rounding`.
 fn round_all<'tcx, F: rustc_apfloat::Float>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
-    rounding: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    rounding: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -699,9 +706,9 @@ fn rounding_from_imm<'tcx>(rounding: i32) -> InterpResult<'tcx, rustc_apfloat::R
 /// has less elements than `dest`, the rest is filled with zeros.
 fn convert_float_to_int<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
     rnd: rustc_apfloat::Round,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -734,8 +741,8 @@ fn convert_float_to_int<'tcx>(
 /// will wrap around.
 fn int_abs<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -802,9 +809,9 @@ fn horizontal_bin_op<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
     which: mir::BinOp,
     saturating: bool,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(left.layout, dest.layout);
     assert_eq!(right.layout, dest.layout);
@@ -853,10 +860,10 @@ fn horizontal_bin_op<'tcx>(
 /// 128-bit blocks of `left` and `right`).
 fn conditional_dot_product<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    imm: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    imm: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(left.layout, dest.layout);
     assert_eq!(right.layout, dest.layout);
@@ -911,8 +918,8 @@ fn conditional_dot_product<'tcx>(
 /// The second is true when `(op & mask) == mask`
 fn test_bits_masked<'tcx>(
     this: &crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
-    mask: &OpTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    mask: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, (bool, bool)> {
     assert_eq!(op.layout, mask.layout);
 
@@ -942,8 +949,8 @@ fn test_bits_masked<'tcx>(
 /// The second is true when the highest bit of each element of `!op & mask` is zero.
 fn test_high_bits_masked<'tcx>(
     this: &crate::MiriInterpCx<'tcx>,
-    op: &OpTy<'tcx, Provenance>,
-    mask: &OpTy<'tcx, Provenance>,
+    op: &OpTy<'tcx>,
+    mask: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, (bool, bool)> {
     assert_eq!(op.layout, mask.layout);
 
@@ -973,9 +980,9 @@ fn test_high_bits_masked<'tcx>(
 /// element of `mask`. `ptr` does not need to be aligned.
 fn mask_load<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    ptr: &OpTy<'tcx, Provenance>,
-    mask: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    ptr: &OpTy<'tcx>,
+    mask: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (mask, mask_len) = this.operand_to_simd(mask)?;
     let (dest, dest_len) = this.mplace_to_simd(dest)?;
@@ -1006,9 +1013,9 @@ fn mask_load<'tcx>(
 /// element of `mask`. `ptr` does not need to be aligned.
 fn mask_store<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    ptr: &OpTy<'tcx, Provenance>,
-    mask: &OpTy<'tcx, Provenance>,
-    value: &OpTy<'tcx, Provenance>,
+    ptr: &OpTy<'tcx>,
+    mask: &OpTy<'tcx>,
+    value: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (mask, mask_len) = this.operand_to_simd(mask)?;
     let (value, value_len) = this.operand_to_simd(value)?;
@@ -1046,10 +1053,10 @@ fn mask_store<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn mpsadbw<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    imm: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    imm: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(left.layout, right.layout);
     assert_eq!(left.layout.size, dest.layout.size);
@@ -1103,9 +1110,9 @@ fn mpsadbw<'tcx>(
 /// <https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16>
 fn pmulhrsw<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
@@ -1133,6 +1140,68 @@ fn pmulhrsw<'tcx>(
     Ok(())
 }
 
+/// Perform a carry-less multiplication of two 64-bit integers, selected from `left` and `right` according to `imm8`,
+/// and store the results in `dst`.
+///
+/// `left` and `right` are both vectors of type 2 x i64. Only bits 0 and 4 of `imm8` matter;
+/// they select the element of `left` and `right`, respectively.
+///
+/// <https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clmulepi64_si128>
+fn pclmulqdq<'tcx>(
+    this: &mut MiriInterpCx<'tcx>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    imm8: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
+) -> InterpResult<'tcx, ()> {
+    assert_eq!(left.layout, right.layout);
+    assert_eq!(left.layout.size, dest.layout.size);
+
+    // Transmute to `[u64; 2]`
+
+    let array_layout = this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u64, 2))?;
+    let left = left.transmute(array_layout, this)?;
+    let right = right.transmute(array_layout, this)?;
+    let dest = dest.transmute(array_layout, this)?;
+
+    let imm8 = this.read_scalar(imm8)?.to_u8()?;
+
+    // select the 64-bit integer from left that the user specified (low or high)
+    let index = if (imm8 & 0x01) == 0 { 0 } else { 1 };
+    let left = this.read_scalar(&this.project_index(&left, index)?)?.to_u64()?;
+
+    // select the 64-bit integer from right that the user specified (low or high)
+    let index = if (imm8 & 0x10) == 0 { 0 } else { 1 };
+    let right = this.read_scalar(&this.project_index(&right, index)?)?.to_u64()?;
+
+    // Perform carry-less multiplication
+    //
+    // This operation is like long multiplication, but ignores all carries.
+    // That idea corresponds to the xor operator, which is used in the implementation.
+    //
+    // Wikipedia has an example https://en.wikipedia.org/wiki/Carry-less_product#Example
+    let mut result: u128 = 0;
+
+    for i in 0..64 {
+        // if the i-th bit in right is set
+        if (right & (1 << i)) != 0 {
+            // xor result with `left` shifted to the left by i positions
+            result ^= (left as u128) << i;
+        }
+    }
+
+    let result_low = (result & 0xFFFF_FFFF_FFFF_FFFF) as u64;
+    let result_high = (result >> 64) as u64;
+
+    let dest_low = this.project_index(&dest, 0)?;
+    this.write_scalar(Scalar::from_u64(result_low), &dest_low)?;
+
+    let dest_high = this.project_index(&dest, 1)?;
+    this.write_scalar(Scalar::from_u64(result_high), &dest_high)?;
+
+    Ok(())
+}
+
 /// Packs two N-bit integer vectors to a single N/2-bit integers.
 ///
 /// The conversion from N-bit to N/2-bit should be provided by `f`.
@@ -1142,10 +1211,10 @@ fn pmulhrsw<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn pack_generic<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
-    f: impl Fn(Scalar<Provenance>) -> InterpResult<'tcx, Scalar<Provenance>>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
+    f: impl Fn(Scalar) -> InterpResult<'tcx, Scalar>,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(left.layout, right.layout);
     assert_eq!(left.layout.size, dest.layout.size);
@@ -1187,9 +1256,9 @@ fn pack_generic<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn packsswb<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     pack_generic(this, left, right, dest, |op| {
         let op = op.to_i16()?;
@@ -1206,9 +1275,9 @@ fn packsswb<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn packuswb<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     pack_generic(this, left, right, dest, |op| {
         let op = op.to_i16()?;
@@ -1225,9 +1294,9 @@ fn packuswb<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn packssdw<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     pack_generic(this, left, right, dest, |op| {
         let op = op.to_i32()?;
@@ -1244,9 +1313,9 @@ fn packssdw<'tcx>(
 /// 128-bit chunks of `left` and `right`).
 fn packusdw<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     pack_generic(this, left, right, dest, |op| {
         let op = op.to_i32()?;
@@ -1261,9 +1330,9 @@ fn packusdw<'tcx>(
 /// In other words, multiplies `left` with `right.signum()`.
 fn psign<'tcx>(
     this: &mut crate::MiriInterpCx<'tcx>,
-    left: &OpTy<'tcx, Provenance>,
-    right: &OpTy<'tcx, Provenance>,
-    dest: &MPlaceTy<'tcx, Provenance>,
+    left: &OpTy<'tcx>,
+    right: &OpTy<'tcx>,
+    dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index 0afb2090cad..32e8e8a66c1 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -10,15 +10,13 @@ use super::{
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse")?;
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index bdff22cfa95..e10047fefe6 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -9,15 +9,13 @@ use super::{
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse2_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse2")?;
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
index 7dbe5163199..ef5a55d6eb2 100644
--- a/src/tools/miri/src/shims/x86/sse3.rs
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -6,15 +6,13 @@ use super::horizontal_bin_op;
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse3_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse3")?;
diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs
index b3880fec3e0..9e048fb9eb8 100644
--- a/src/tools/miri/src/shims/x86/sse41.rs
+++ b/src/tools/miri/src/shims/x86/sse41.rs
@@ -5,15 +5,13 @@ use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first,
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse41_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?;
diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs
index 1f7870f8ca0..6a815e4cea3 100644
--- a/src/tools/miri/src/shims/x86/ssse3.rs
+++ b/src/tools/miri/src/shims/x86/ssse3.rs
@@ -6,15 +6,13 @@ use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
-pub(super) trait EvalContextExt<'tcx>:
-    crate::MiriInterpCxExt<'tcx>
-{
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_ssse3_intrinsic(
         &mut self,
         link_name: Symbol,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx, Provenance>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "ssse3")?;
diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock
index 4783f79ea8f..8f618e7ffb3 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.lock
+++ b/src/tools/miri/test-cargo-miri/Cargo.lock
@@ -124,6 +124,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "test-local-crate-detection"
+version = "0.1.0"
+
+[[package]]
 name = "unicode-ident"
 version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml
index bfef388669d..574f1d05a6f 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.toml
+++ b/src/tools/miri/test-cargo-miri/Cargo.toml
@@ -1,5 +1,5 @@
 [workspace]
-members = ["subcrate", "issue-1567", "exported-symbol-dep"]
+members = ["subcrate", "issue-1567", "exported-symbol-dep", "test-local-crate-detection"]
 exclude = ["no-std-smoke"] # it wants to be panic="abort"
 
 [package]
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index 83f3e4c919b..d855c333a75 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -131,6 +131,10 @@ def test_cargo_miri_run():
         cargo_miri("run") + ["--target-dir=custom-run", "--", "--target-dir=target/custom-run"],
         "run.args.stdout.ref", "run.custom-target-dir.stderr.ref",
     )
+    test("`cargo miri run --package=test-local-crate-detection` (test local crate detection)",
+         cargo_miri("run") + ["--package=test-local-crate-detection"],
+         "run.local_crate.stdout.ref", "run.local_crate.stderr.ref",
+    )
 
 def test_cargo_miri_test():
     # rustdoc is not run on foreign targets
diff --git a/src/tools/miri/test-cargo-miri/run.local_crate.stderr.ref b/src/tools/miri/test-cargo-miri/run.local_crate.stderr.ref
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/tools/miri/test-cargo-miri/run.local_crate.stderr.ref
diff --git a/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref b/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref
new file mode 100644
index 00000000000..1587de9ff3f
--- /dev/null
+++ b/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref
@@ -0,0 +1 @@
+subcrate,issue_1567,exported_symbol_dep,test_local_crate_detection,cargo_miri_test,cdylib,exported_symbol,issue_1691,issue_1705,issue_rust_86261,proc_macro_crate
diff --git a/src/tools/miri/test-cargo-miri/test-local-crate-detection/Cargo.toml b/src/tools/miri/test-cargo-miri/test-local-crate-detection/Cargo.toml
new file mode 100644
index 00000000000..2d41b210d4c
--- /dev/null
+++ b/src/tools/miri/test-cargo-miri/test-local-crate-detection/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "test-local-crate-detection"
+version = "0.1.0"
+edition = "2021"
diff --git a/src/tools/miri/test-cargo-miri/test-local-crate-detection/src/main.rs b/src/tools/miri/test-cargo-miri/test-local-crate-detection/src/main.rs
new file mode 100644
index 00000000000..0991aa38460
--- /dev/null
+++ b/src/tools/miri/test-cargo-miri/test-local-crate-detection/src/main.rs
@@ -0,0 +1,5 @@
+fn main() {
+    // Make sure we detect all crates from this workspace as "local".
+    // The env var is set during the "build" so we can use `env!` to access it directly.
+    println!("{}", env!("MIRI_LOCAL_CRATES"));
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.rs b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.rs
new file mode 100644
index 00000000000..fb9a23206c6
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.rs
@@ -0,0 +1,11 @@
+//@only-target-linux
+fn main() {
+    // eventfd read will block when EFD_NONBLOCK flag is clear and counter = 0.
+    // This will pass when blocking is implemented.
+    let flags = libc::EFD_CLOEXEC;
+    let fd = unsafe { libc::eventfd(0, flags) };
+    let mut buf: [u8; 8] = [0; 8];
+    let _res: i32 = unsafe {
+        libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() //~ERROR: blocking is unsupported
+    };
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.stderr b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.stderr
new file mode 100644
index 00000000000..fdd0b4272ca
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_read_block.stderr
@@ -0,0 +1,14 @@
+error: unsupported operation: eventfd: blocking is unsupported
+  --> $DIR/libc_eventfd_read_block.rs:LL:CC
+   |
+LL |         libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ eventfd: blocking is unsupported
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/libc_eventfd_read_block.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-dep/libc/libc_eventfd_write_block.rs b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.rs
new file mode 100644
index 00000000000..2037a516dea
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.rs
@@ -0,0 +1,21 @@
+//@only-target-linux
+fn main() {
+    // eventfd write will block when EFD_NONBLOCK flag is clear
+    // and the addition caused counter to exceed u64::MAX - 1.
+    // This will pass when blocking is implemented.
+    let flags = libc::EFD_CLOEXEC;
+    let fd = unsafe { libc::eventfd(0, flags) };
+    // Write u64 - 1.
+    let mut sized_8_data: [u8; 8] = (u64::MAX - 1).to_ne_bytes();
+    let res: i64 = unsafe {
+        libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
+    };
+    assert_eq!(res, 8);
+
+    // Write 1.
+    sized_8_data = 1_u64.to_ne_bytes();
+    // Write 1 to the counter.
+    let _res: i64 = unsafe {
+        libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() //~ERROR: blocking is unsupported
+    };
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.stderr b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.stderr
new file mode 100644
index 00000000000..f12c0ddfb17
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/libc_eventfd_write_block.stderr
@@ -0,0 +1,14 @@
+error: unsupported operation: eventfd: blocking is unsupported
+  --> $DIR/libc_eventfd_write_block.rs:LL:CC
+   |
+LL |         libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ eventfd: blocking is unsupported
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/libc_eventfd_write_block.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/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
index ff23f1e729e..0c305eed6e1 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs
@@ -7,10 +7,12 @@ use std::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime")]
 pub unsafe fn deref_meta(p: *const *const [i32]) -> usize {
-    mir!({
-        RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
-        Return()
-    })
+    mir! {
+        {
+            RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
index 61e1541d1ee..6478dcc2507 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
   --> $DIR/ptr_metadata_uninit_slice_data.rs:LL:CC
    |
-LL |         RET = PtrMetadata(*p);
-   |         ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+LL |             RET = PtrMetadata(*p);
+   |             ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
    |
    = 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_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
index 65f74c0acdd..a2ffdc92c4e 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs
@@ -7,10 +7,12 @@ use std::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime")]
 pub unsafe fn deref_meta(p: *const *const [i32]) -> usize {
-    mir!({
-        RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
-        Return()
-    })
+    mir! {
+        {
+            RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
index de559263a32..4e2e7218432 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
@@ -16,8 +16,8 @@ LL |         (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32;
 error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
   --> $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC
    |
-LL |         RET = PtrMetadata(*p);
-   |         ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+LL |             RET = PtrMetadata(*p);
+   |             ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
    |
    = 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_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
index ad2e9fc800e..e5a51289a8a 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs
@@ -7,10 +7,12 @@ use std::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime")]
 pub unsafe fn deref_meta(p: *const *const i32) -> () {
-    mir!({
-        RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
-        Return()
-    })
+    mir! {
+        {
+            RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
index 3ab2643afa7..0e218de0eeb 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
   --> $DIR/ptr_metadata_uninit_thin.rs:LL:CC
    |
-LL |         RET = PtrMetadata(*p);
-   |         ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+LL |             RET = PtrMetadata(*p);
+   |             ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
    |
    = 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/issue-miri-2432.rs b/src/tools/miri/tests/fail/issue-miri-2432.rs
deleted file mode 100644
index f822479c436..00000000000
--- a/src/tools/miri/tests/fail/issue-miri-2432.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#![allow(where_clauses_object_safety)]
-
-trait Trait {}
-
-trait X {
-    fn foo(&self)
-    where
-        Self: Trait;
-}
-
-impl X for () {
-    fn foo(&self) {}
-}
-
-impl Trait for dyn X {}
-
-pub fn main() {
-    <dyn X as X>::foo(&()); //~ERROR: trying to call something that is not a method
-}
diff --git a/src/tools/miri/tests/fail/issue-miri-2432.stderr b/src/tools/miri/tests/fail/issue-miri-2432.stderr
deleted file mode 100644
index 3befe31dc5a..00000000000
--- a/src/tools/miri/tests/fail/issue-miri-2432.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: Undefined Behavior: `dyn` call trying to call something that is not a method
-  --> $DIR/issue-miri-2432.rs:LL:CC
-   |
-LL |     <dyn X as X>::foo(&());
-   |     ^^^^^^^^^^^^^^^^^^^^^^ `dyn` call trying to call something that is not a method
-   |
-   = 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/issue-miri-2432.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/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
new file mode 100644
index 00000000000..a3567eeb7cb
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
@@ -0,0 +1,108 @@
+//@only-target-linux
+// test_race depends on a deterministic schedule.
+//@compile-flags: -Zmiri-preemption-rate=0
+
+use std::thread;
+
+fn main() {
+    test_read_write();
+    test_race();
+}
+
+fn read_bytes<const N: usize>(fd: i32, buf: &mut [u8; N]) -> i32 {
+    let res: i32 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), N).try_into().unwrap() };
+    return res;
+}
+
+fn write_bytes<const N: usize>(fd: i32, data: [u8; N]) -> i32 {
+    let res: i32 =
+        unsafe { libc::write(fd, data.as_ptr() as *const libc::c_void, N).try_into().unwrap() };
+    return res;
+}
+
+fn test_read_write() {
+    let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
+    let fd = unsafe { libc::eventfd(0, flags) };
+    let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes();
+    // Write 1 to the counter.
+    let res = write_bytes(fd, sized_8_data);
+    assert_eq!(res, 8);
+
+    // Read 1 from the counter.
+    let mut buf: [u8; 8] = [0; 8];
+    let res = read_bytes(fd, &mut buf);
+    // Read returns number of bytes has been read, which is always 8.
+    assert_eq!(res, 8);
+    // Check the value of counter read.
+    let counter = u64::from_ne_bytes(buf);
+    assert_eq!(counter, 1);
+
+    // After read, the counter is currently 0, read counter 0 should fail with return
+    // value -1.
+    let mut buf: [u8; 8] = [0; 8];
+    let res = read_bytes(fd, &mut buf);
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::EAGAIN));
+    assert_eq!(res, -1);
+
+    // Write with supplied buffer bigger than 8 bytes should be allowed.
+    let sized_9_data: [u8; 9];
+    if cfg!(target_endian = "big") {
+        // Adjust the data based on the endianness of host system.
+        sized_9_data = [0, 0, 0, 0, 0, 0, 0, 1, 0];
+    } else {
+        sized_9_data = [1, 0, 0, 0, 0, 0, 0, 0, 0];
+    }
+    let res = write_bytes(fd, sized_9_data);
+    assert_eq!(res, 8);
+
+    // Read with supplied buffer smaller than 8 bytes should fail with return
+    // value -1.
+    let mut buf: [u8; 7] = [1; 7];
+    let res = read_bytes(fd, &mut buf);
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
+    assert_eq!(res, -1);
+
+    // Write with supplied buffer smaller than 8 bytes should fail with return
+    // value -1.
+    let size_7_data: [u8; 7] = [1; 7];
+    let res = write_bytes(fd, size_7_data);
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
+    assert_eq!(res, -1);
+
+    // Read with supplied buffer bigger than 8 bytes should be allowed.
+    let mut buf: [u8; 9] = [1; 9];
+    let res = read_bytes(fd, &mut buf);
+    assert_eq!(res, 8);
+
+    // Write u64::MAX should fail.
+    let u64_max_bytes: [u8; 8] = [255; 8];
+    let res = write_bytes(fd, u64_max_bytes);
+    let e = std::io::Error::last_os_error();
+    assert_eq!(e.raw_os_error(), Some(libc::EINVAL));
+    assert_eq!(res, -1);
+}
+
+fn test_race() {
+    static mut VAL: u8 = 0;
+    let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
+    let fd = unsafe { libc::eventfd(0, flags) };
+    let thread1 = thread::spawn(move || {
+        let mut buf: [u8; 8] = [0; 8];
+        let res = read_bytes(fd, &mut buf);
+        // read returns number of bytes has been read, which is always 8.
+        assert_eq!(res, 8);
+        let counter = u64::from_ne_bytes(buf);
+        assert_eq!(counter, 1);
+        unsafe { assert_eq!(VAL, 1) };
+    });
+    unsafe { VAL = 1 };
+    let data: [u8; 8] = 1_u64.to_ne_bytes();
+    let res = write_bytes(fd, data);
+    // write returns number of bytes written, which is always 8.
+    assert_eq!(res, 8);
+    thread::yield_now();
+    thread1.join().unwrap();
+}
diff --git a/src/tools/miri/tests/pass/drop_in_place.rs b/src/tools/miri/tests/pass/drop_in_place.rs
index 0615a43c800..cac8d76dd9d 100644
--- a/src/tools/miri/tests/pass/drop_in_place.rs
+++ b/src/tools/miri/tests/pass/drop_in_place.rs
@@ -6,7 +6,5 @@ use std::ptr;
 
 fn main() {
     let mut not_a_bool = 13u8;
-    unsafe {
-        ptr::drop_in_place(&mut not_a_bool as *mut u8 as *mut bool)
-    };
+    unsafe { ptr::drop_in_place(&mut not_a_bool as *mut u8 as *mut bool) };
 }
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 136660a305a..0cfcd532ff4 100644
--- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs
+++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
@@ -83,12 +83,24 @@ fn main() {
     test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
     // - 1-ZST
     test_abi_compat((), [0u8; 0]);
-    // - Guaranteed null-pointer-optimizations (RFC 3391).
+    // - Guaranteed Option<X> 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::NonZero::new(1u32).unwrap()));
     test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
-    test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
+    test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap())));
+    // - Guaranteed Result<X, ZST1> does the same as Option<X> (RFC 3391)
+    test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32));
+    test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn()));
+    test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap()));
+    test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32)));
+    test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap())));
+    // - Guaranteed Result<ZST1, X> also does the same as Option<X> (RFC 3391)
+    test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32));
+    test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn()));
+    test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap()));
+    test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32)));
+    test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap())));
 
     // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
     // with the wrapped field.
diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
index 248a57d6850..03d9fc0a76f 100644
--- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
+++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-strict-provenance
-#![feature(portable_simd, adt_const_params, core_intrinsics)]
+#![feature(portable_simd, adt_const_params, core_intrinsics, repr_simd)]
 #![allow(incomplete_features, internal_features)]
 use std::intrinsics::simd as intrinsics;
 use std::ptr;
@@ -318,6 +318,83 @@ fn simd_mask() {
         assert_eq!(selected1, i32x4::from_array([0, 0, 0, 1]));
         assert_eq!(selected2, selected1);
     }
+
+    // Non-power-of-2 multi-byte mask.
+    #[repr(simd, packed)]
+    #[allow(non_camel_case_types)]
+    #[derive(Copy, Clone, Debug, PartialEq)]
+    struct i32x10([i32; 10]);
+    impl i32x10 {
+        fn splat(x: i32) -> Self {
+            Self([x; 10])
+        }
+    }
+    unsafe {
+        let mask = i32x10([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]);
+        let mask_bits = if cfg!(target_endian = "little") { 0b0101001011 } else { 0b1101001010 };
+        let mask_bytes =
+            if cfg!(target_endian = "little") { [0b01001011, 0b01] } else { [0b11, 0b01001010] };
+
+        let bitmask1: u16 = simd_bitmask(mask);
+        let bitmask2: [u8; 2] = simd_bitmask(mask);
+        assert_eq!(bitmask1, mask_bits);
+        assert_eq!(bitmask2, mask_bytes);
+
+        let selected1 = simd_select_bitmask::<u16, _>(
+            mask_bits,
+            i32x10::splat(!0), // yes
+            i32x10::splat(0),  // no
+        );
+        let selected2 = simd_select_bitmask::<[u8; 2], _>(
+            mask_bytes,
+            i32x10::splat(!0), // yes
+            i32x10::splat(0),  // no
+        );
+        assert_eq!(selected1, mask);
+        assert_eq!(selected2, mask);
+    }
+
+    // Test for a mask where the next multiple of 8 is not a power of two.
+    #[repr(simd, packed)]
+    #[allow(non_camel_case_types)]
+    #[derive(Copy, Clone, Debug, PartialEq)]
+    struct i32x20([i32; 20]);
+    impl i32x20 {
+        fn splat(x: i32) -> Self {
+            Self([x; 20])
+        }
+    }
+    unsafe {
+        let mask = i32x20([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0, 0, 0, 0, !0, !0, !0, !0, !0, !0, !0]);
+        let mask_bits = if cfg!(target_endian = "little") {
+            0b11111110000101001011
+        } else {
+            0b11010010100001111111
+        };
+        let mask_bytes = if cfg!(target_endian = "little") {
+            [0b01001011, 0b11100001, 0b1111]
+        } else {
+            [0b1101, 0b00101000, 0b01111111]
+        };
+
+        let bitmask1: u32 = simd_bitmask(mask);
+        let bitmask2: [u8; 3] = simd_bitmask(mask);
+        assert_eq!(bitmask1, mask_bits);
+        assert_eq!(bitmask2, mask_bytes);
+
+        let selected1 = simd_select_bitmask::<u32, _>(
+            mask_bits,
+            i32x20::splat(!0), // yes
+            i32x20::splat(0),  // no
+        );
+        let selected2 = simd_select_bitmask::<[u8; 3], _>(
+            mask_bytes,
+            i32x20::splat(!0), // yes
+            i32x20::splat(0),  // no
+        );
+        assert_eq!(selected1, mask);
+        assert_eq!(selected2, mask);
+    }
 }
 
 fn simd_cast() {
@@ -581,11 +658,32 @@ fn simd_masked_loadstore() {
     assert_eq!(buf, [2, 3, 4]);
 }
 
+fn simd_ops_non_pow2() {
+    // Just a little smoke test for operations on non-power-of-two vectors.
+    #[repr(simd, packed)]
+    #[derive(Copy, Clone)]
+    pub struct SimdPacked<T, const N: usize>([T; N]);
+    #[repr(simd)]
+    #[derive(Copy, Clone)]
+    pub struct SimdPadded<T, const N: usize>([T; N]);
+
+    let x = SimdPacked([1u32; 3]);
+    let y = SimdPacked([2u32; 3]);
+    let z = unsafe { intrinsics::simd_add(x, y) };
+    assert_eq!({ z.0 }, [3u32; 3]);
+
+    let x = SimdPadded([1u32; 3]);
+    let y = SimdPadded([2u32; 3]);
+    let z = unsafe { intrinsics::simd_add(x, y) };
+    assert_eq!(z.0, [3u32; 3]);
+}
+
 fn main() {
     simd_mask();
     simd_ops_f32();
     simd_ops_f64();
     simd_ops_i32();
+    simd_ops_non_pow2();
     simd_cast();
     simd_swizzle();
     simd_gather_scatter();
diff --git a/src/tools/miri/tests/pass/shims/env/var.rs b/src/tools/miri/tests/pass/shims/env/var.rs
index babaf00578a..a576c1fc8bb 100644
--- a/src/tools/miri/tests/pass/shims/env/var.rs
+++ b/src/tools/miri/tests/pass/shims/env/var.rs
@@ -1,3 +1,4 @@
+//@compile-flags: -Zmiri-preemption-rate=0
 use std::env;
 use std::thread;
 
@@ -26,6 +27,8 @@ fn main() {
     println!("{:#?}", env::vars().collect::<Vec<_>>());
 
     // Do things concurrently, to make sure there's no data race.
+    // We disable preemption to make sure the lock is not contended;
+    // that means we don't hit e.g. the futex codepath on Android (which we don't support).
     let t = thread::spawn(|| {
         env::set_var("MIRI_TEST", "42");
     });
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs
new file mode 100644
index 00000000000..2f242dd5379
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs
@@ -0,0 +1,48 @@
+// Ignore everything except x86 and x86_64
+// Any new targets that are added to CI should be ignored here.
+// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
+//@ignore-target-aarch64
+//@ignore-target-arm
+//@ignore-target-avr
+//@ignore-target-s390x
+//@ignore-target-thumbv7em
+//@ignore-target-wasm32
+//@compile-flags: -C target-feature=+pclmulqdq
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+fn main() {
+    assert!(is_x86_feature_detected!("pclmulqdq"));
+
+    let a = (0x7fffffffffffffff, 0x4317e40ab4ddcf05);
+    let b = (0xdd358416f52ecd34, 0x633d11cc638ca16b);
+
+    unsafe {
+        assert_eq!(clmulepi64_si128::<0x00>(a, b), (13036940098130298092, 2704901987789626761));
+        assert_eq!(clmulepi64_si128::<0x01>(a, b), (6707488474444649956, 3901733953304450635));
+        assert_eq!(clmulepi64_si128::<0x10>(a, b), (11607166829323378905, 1191897396234301548));
+        assert_eq!(clmulepi64_si128::<0x11>(a, b), (7731954893213347271, 1760130762532070957));
+    }
+}
+
+#[target_feature(enable = "pclmulqdq")]
+unsafe fn clmulepi64_si128<const IMM8: i32>(
+    (a1, a2): (u64, u64),
+    (b1, b2): (u64, u64),
+) -> (u64, u64) {
+    // SAFETY: There are no safety requirements for calling `_mm_clmulepi64_si128`.
+    // It's just unsafe for API consistency with other intrinsics.
+    unsafe {
+        let a = core::mem::transmute::<_, __m128i>([a1, a2]);
+        let b = core::mem::transmute::<_, __m128i>([b1, b2]);
+
+        let out = _mm_clmulepi64_si128::<IMM8>(a, b);
+
+        let [c1, c2] = core::mem::transmute::<_, [u64; 2]>(out);
+
+        (c1, c2)
+    }
+}
diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs
index ff782a1687e..bc01b7fb8a3 100644
--- a/src/tools/opt-dist/src/environment.rs
+++ b/src/tools/opt-dist/src/environment.rs
@@ -17,6 +17,9 @@ pub struct Environment {
     host_llvm_dir: Utf8PathBuf,
     /// List of test paths that should be skipped when testing the optimized artifacts.
     skipped_tests: Vec<String>,
+    /// Arguments passed to `rustc-perf --cargo-config <value>` when running benchmarks.
+    #[builder(default)]
+    benchmark_cargo_config: Vec<String>,
     /// Directory containing a pre-built rustc-perf checkout.
     #[builder(default)]
     prebuilt_rustc_perf: Option<Utf8PathBuf>,
@@ -94,6 +97,10 @@ impl Environment {
     pub fn skipped_tests(&self) -> &[String] {
         &self.skipped_tests
     }
+
+    pub fn benchmark_cargo_config(&self) -> &[String] {
+        &self.benchmark_cargo_config
+    }
 }
 
 /// What is the extension of binary executables on this platform?
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index a709076f245..e4271a6e2dd 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -90,6 +90,10 @@ enum EnvironmentCmd {
 
         #[clap(flatten)]
         shared: SharedArgs,
+
+        /// Arguments passed to `rustc-perf --cargo-config <value>` when running benchmarks.
+        #[arg(long)]
+        benchmark_cargo_config: Vec<String>,
     },
     /// Perform an optimized build on Linux CI, from inside Docker.
     LinuxCi {
@@ -119,6 +123,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
             llvm_shared,
             use_bolt,
             skipped_tests,
+            benchmark_cargo_config,
             shared,
         } => {
             let env = EnvironmentBuilder::default()
@@ -132,6 +137,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
                 .shared_llvm(llvm_shared)
                 .use_bolt(use_bolt)
                 .skipped_tests(skipped_tests)
+                .benchmark_cargo_config(benchmark_cargo_config)
                 .build()?;
 
             (env, shared.build_args)
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 46040e32a03..89f4d8957c8 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -3,30 +3,10 @@ use crate::exec::{cmd, CmdBuilder};
 use crate::utils::io::{count_files, delete_directory};
 use crate::utils::with_log_group;
 use anyhow::Context;
+use build_helper::{LLVM_PGO_CRATES, RUSTC_PGO_CRATES};
 use camino::{Utf8Path, Utf8PathBuf};
 use humansize::BINARY;
 
-const LLVM_PGO_CRATES: &[&str] = &[
-    "syn-1.0.89",
-    "cargo-0.60.0",
-    "serde-1.0.136",
-    "ripgrep-13.0.0",
-    "regex-1.5.5",
-    "clap-3.1.6",
-    "hyper-0.14.18",
-];
-
-const RUSTC_PGO_CRATES: &[&str] = &[
-    "externs",
-    "ctfe-stress-5",
-    "cargo-0.60.0",
-    "token-stream-stress",
-    "match-stress",
-    "tuple-stress",
-    "diesel-1.4.8",
-    "bitmaps-3.1.0",
-];
-
 fn init_compiler_benchmarks(
     env: &Environment,
     profiles: &[&str],
@@ -36,7 +16,7 @@ fn init_compiler_benchmarks(
     // Run rustc-perf benchmarks
     // Benchmark using profile_local with eprintln, which essentially just means
     // don't actually benchmark -- just make sure we run rustc a bunch of times.
-    cmd(&[
+    let mut cmd = cmd(&[
         env.cargo_stage_0().as_str(),
         "run",
         "-p",
@@ -61,7 +41,17 @@ fn init_compiler_benchmarks(
     .env("RUST_LOG", "collector=debug")
     .env("RUSTC", env.rustc_stage_0().as_str())
     .env("RUSTC_BOOTSTRAP", "1")
-    .workdir(&env.rustc_perf_dir())
+    .workdir(&env.rustc_perf_dir());
+
+    // This propagates cargo configs to `rustc-perf --cargo-config`,
+    // which is particularly useful when the environment is air-gapped,
+    // and you want to use the default set of training crates vendored
+    // in the rustc-src tarball.
+    for config in env.benchmark_cargo_config() {
+        cmd = cmd.arg("--cargo-config").arg(config);
+    }
+
+    cmd
 }
 
 /// Describes which `llvm-profdata` binary should be used for merging PGO profiles.
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index 0012e7b66af..5c0158d7547 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -1,8 +1,7 @@
-use std::env;
 use std::path::Path;
-use std::process::Command;
 
-use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname};
+use crate::command::Command;
+use crate::{bin_name, cygpath_windows, env_var, is_msvc, is_windows, uname};
 
 /// Construct a new platform-specific C compiler invocation.
 ///
@@ -27,11 +26,11 @@ impl Cc {
     /// WARNING: This means that what flags are accepted by the underlying C compile is
     /// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
     pub fn new() -> Self {
-        let compiler = env::var("CC").unwrap();
+        let compiler = env_var("CC");
 
         let mut cmd = Command::new(compiler);
 
-        let default_cflags = env::var("CC_DEFAULT_FLAGS").unwrap();
+        let default_cflags = env_var("CC_DEFAULT_FLAGS");
         for flag in default_cflags.split(char::is_whitespace) {
             cmd.arg(flag);
         }
@@ -53,8 +52,7 @@ impl Cc {
         self
     }
 
-    /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
-    /// is under `$TMPDIR`.
+    /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler.
     pub fn out_exe(&mut self, name: &str) -> &mut Self {
         // Ref: tools.mk (irrelevant lines omitted):
         //
@@ -68,13 +66,13 @@ impl Cc {
         // ```
 
         if is_msvc() {
-            let fe_path = cygpath_windows(tmp_dir().join(bin_name(name)));
-            let fo_path = cygpath_windows(tmp_dir().join(format!("{name}.obj")));
+            let fe_path = cygpath_windows(bin_name(name));
+            let fo_path = cygpath_windows(format!("{name}.obj"));
             self.cmd.arg(format!("-Fe:{fe_path}"));
             self.cmd.arg(format!("-Fo:{fo_path}"));
         } else {
             self.cmd.arg("-o");
-            self.cmd.arg(tmp_dir().join(name));
+            self.cmd.arg(name);
         }
 
         self
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs
index 6ccce67b250..d2ebed7ab06 100644
--- a/src/tools/run-make-support/src/clang.rs
+++ b/src/tools/run-make-support/src/clang.rs
@@ -1,8 +1,7 @@
-use std::env;
 use std::path::Path;
-use std::process::Command;
 
-use crate::{bin_name, handle_failed_output, tmp_dir};
+use crate::command::Command;
+use crate::{bin_name, env_var};
 
 /// Construct a new `clang` invocation. `clang` is not always available for all targets.
 pub fn clang() -> Clang {
@@ -20,8 +19,7 @@ crate::impl_common_helpers!(Clang);
 impl Clang {
     /// Construct a new `clang` invocation. `clang` is not always available for all targets.
     pub fn new() -> Self {
-        let clang =
-            env::var("CLANG").expect("`CLANG` not specified, but this is required to find `clang`");
+        let clang = env_var("CLANG");
         let cmd = Command::new(clang);
         Self { cmd }
     }
@@ -32,11 +30,11 @@ impl Clang {
         self
     }
 
-    /// Specify the name of the executable. The executable will be placed under `$TMPDIR`, and the
-    /// extension will be determined by [`bin_name`].
+    /// Specify the name of the executable. The executable will be placed under the current directory
+    /// and the extension will be determined by [`bin_name`].
     pub fn out_exe(&mut self, name: &str) -> &mut Self {
         self.cmd.arg("-o");
-        self.cmd.arg(tmp_dir().join(bin_name(name)));
+        self.cmd.arg(bin_name(name));
         self
     }
 
@@ -70,9 +68,4 @@ impl Clang {
         self.cmd.arg(format!("-fuse-ld={ld}"));
         self
     }
-
-    /// Get the [`Output`][::std::process::Output] of the finished process.
-    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/command.rs b/src/tools/run-make-support/src/command.rs
new file mode 100644
index 00000000000..cc395e491ee
--- /dev/null
+++ b/src/tools/run-make-support/src/command.rs
@@ -0,0 +1,151 @@
+use crate::{assert_not_contains, handle_failed_output};
+use std::ffi::OsStr;
+use std::io::Write;
+use std::ops::{Deref, DerefMut};
+use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
+
+/// This is a custom command wrapper that simplifies working with commands
+/// and makes it easier to ensure that we check the exit status of executed
+/// processes.
+#[derive(Debug)]
+pub struct Command {
+    cmd: StdCommand,
+    stdin: Option<Box<[u8]>>,
+}
+
+impl Command {
+    pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
+        Self { cmd: StdCommand::new(program), stdin: None }
+    }
+
+    pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
+        self.stdin = Some(stdin);
+    }
+
+    /// Run the constructed command and assert that it is successfully run.
+    #[track_caller]
+    pub fn run(&mut self) -> CompletedProcess {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.command_output();
+        if !output.status().success() {
+            handle_failed_output(&self, output, caller_line_number);
+        }
+        output
+    }
+
+    /// Run the constructed command and assert that it does not successfully run.
+    #[track_caller]
+    pub fn run_fail(&mut self) -> CompletedProcess {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.command_output();
+        if output.status().success() {
+            handle_failed_output(&self, output, caller_line_number);
+        }
+        output
+    }
+
+    #[track_caller]
+    pub(crate) fn command_output(&mut self) -> CompletedProcess {
+        // let's make sure we piped all the input and outputs
+        self.cmd.stdin(Stdio::piped());
+        self.cmd.stdout(Stdio::piped());
+        self.cmd.stderr(Stdio::piped());
+
+        let output = if let Some(input) = &self.stdin {
+            let mut child = self.cmd.spawn().unwrap();
+
+            {
+                let mut stdin = child.stdin.take().unwrap();
+                stdin.write_all(input.as_ref()).unwrap();
+            }
+
+            child.wait_with_output().expect("failed to get output of finished process")
+        } else {
+            self.cmd.output().expect("failed to get output of finished process")
+        };
+        output.into()
+    }
+}
+
+impl Deref for Command {
+    type Target = StdCommand;
+
+    fn deref(&self) -> &Self::Target {
+        &self.cmd
+    }
+}
+
+impl DerefMut for Command {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.cmd
+    }
+}
+
+/// Represents the result of an executed process.
+/// The various `assert_` helper methods should preferably be used for
+/// checking the contents of stdout/stderr.
+pub struct CompletedProcess {
+    output: Output,
+}
+
+impl CompletedProcess {
+    pub fn stdout_utf8(&self) -> String {
+        String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
+    }
+
+    pub fn stderr_utf8(&self) -> String {
+        String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
+    }
+
+    pub fn status(&self) -> ExitStatus {
+        self.output.status
+    }
+
+    /// Checks that trimmed `stdout` matches trimmed `content`.
+    #[track_caller]
+    pub fn assert_stdout_equals<S: AsRef<str>>(&self, content: S) -> &Self {
+        assert_eq!(self.stdout_utf8().trim(), content.as_ref().trim());
+        self
+    }
+
+    #[track_caller]
+    pub fn assert_stdout_not_contains<S: AsRef<str>>(&self, needle: S) -> &Self {
+        assert_not_contains(&self.stdout_utf8(), needle.as_ref());
+        self
+    }
+
+    /// Checks that trimmed `stderr` matches trimmed `content`.
+    #[track_caller]
+    pub fn assert_stderr_equals<S: AsRef<str>>(&self, content: S) -> &Self {
+        assert_eq!(self.stderr_utf8().trim(), content.as_ref().trim());
+        self
+    }
+
+    #[track_caller]
+    pub fn assert_stderr_contains<S: AsRef<str>>(&self, needle: S) -> &Self {
+        assert!(self.stderr_utf8().contains(needle.as_ref()));
+        self
+    }
+
+    #[track_caller]
+    pub fn assert_stderr_not_contains<S: AsRef<str>>(&self, needle: S) -> &Self {
+        assert_not_contains(&self.stdout_utf8(), needle.as_ref());
+        self
+    }
+
+    #[track_caller]
+    pub fn assert_exit_code(&self, code: i32) -> &Self {
+        assert!(self.output.status.code() == Some(code));
+        self
+    }
+}
+
+impl From<Output> for CompletedProcess {
+    fn from(output: Output) -> Self {
+        Self { output }
+    }
+}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 323fc40e648..960f4bcd254 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -5,6 +5,7 @@
 
 pub mod cc;
 pub mod clang;
+mod command;
 pub mod diff;
 pub mod llvm_readobj;
 pub mod run;
@@ -12,10 +13,10 @@ pub mod rustc;
 pub mod rustdoc;
 
 use std::env;
+use std::ffi::OsString;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output};
 
 pub use gimli;
 pub use object;
@@ -26,18 +27,27 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
 pub use diff::{diff, Diff};
 pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
-pub use run::{run, run_fail};
+pub use run::{cmd, run, run_fail};
 pub use rustc::{aux_build, rustc, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
 
-/// Path of `TMPDIR` (a temporary build directory, not under `/tmp`).
-pub fn tmp_dir() -> PathBuf {
-    env::var_os("TMPDIR").unwrap().into()
+pub fn env_var(name: &str) -> String {
+    match env::var(name) {
+        Ok(v) => v,
+        Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"),
+    }
+}
+
+pub fn env_var_os(name: &str) -> OsString {
+    match env::var_os(name) {
+        Some(v) => v,
+        None => panic!("failed to retrieve environment variable {name:?}"),
+    }
 }
 
 /// `TARGET`
 pub fn target() -> String {
-    env::var("TARGET").unwrap()
+    env_var("TARGET")
 }
 
 /// Check if target is windows-like.
@@ -55,25 +65,25 @@ pub fn is_darwin() -> bool {
     target().contains("darwin")
 }
 
-/// Construct a path to a static library under `$TMPDIR` given the library name. This will return a
-/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
-pub fn static_lib(name: &str) -> PathBuf {
-    tmp_dir().join(static_lib_name(name))
-}
-
 pub fn python_command() -> Command {
-    let python_path = std::env::var("PYTHON").expect("PYTHON environment variable does not exist");
+    let python_path = env_var("PYTHON");
     Command::new(python_path)
 }
 
 pub fn htmldocck() -> Command {
     let mut python = python_command();
-    python.arg(source_path().join("src/etc/htmldocck.py"));
+    python.arg(source_root().join("src/etc/htmldocck.py"));
     python
 }
 
-pub fn source_path() -> PathBuf {
-    std::env::var("S").expect("S variable does not exist").into()
+/// Returns the path for a local test file.
+pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
+    cwd().join(p.as_ref())
+}
+
+/// Path to the root rust-lang/rust source checkout.
+pub fn source_root() -> PathBuf {
+    env_var("SOURCE_ROOT").into()
 }
 
 /// Construct the static library name based on the platform.
@@ -100,12 +110,6 @@ pub fn static_lib_name(name: &str) -> String {
     if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
 }
 
-/// Construct a path to a dynamic library under `$TMPDIR` given the library name. This will return a
-/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
-pub fn dynamic_lib(name: &str) -> PathBuf {
-    tmp_dir().join(dynamic_lib_name(name))
-}
-
 /// Construct the dynamic library name based on the platform.
 pub fn dynamic_lib_name(name: &str) -> String {
     // See tools.mk (irrelevant lines omitted):
@@ -143,14 +147,7 @@ pub fn dynamic_lib_extension() -> &'static str {
     }
 }
 
-/// Construct a path to a rust library (rlib) under `$TMPDIR` given the library name. This will return a
-/// path with `$TMPDIR` joined with the library name.
-pub fn rust_lib(name: &str) -> PathBuf {
-    tmp_dir().join(rust_lib_name(name))
-}
-
-/// Generate the name a rust library (rlib) would have. If you want the complete path, use
-/// [`rust_lib`] instead.
+/// Construct a rust library (rlib) name.
 pub fn rust_lib_name(name: &str) -> String {
     format!("lib{name}.rlib")
 }
@@ -160,6 +157,11 @@ pub fn bin_name(name: &str) -> String {
     if is_windows() { format!("{name}.exe") } else { name.to_string() }
 }
 
+/// Return the current working directory.
+pub fn cwd() -> PathBuf {
+    env::current_dir().unwrap()
+}
+
 /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
 /// available on the platform!
 #[track_caller]
@@ -170,13 +172,12 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
     let mut cygpath = Command::new("cygpath");
     cygpath.arg("-w");
     cygpath.arg(path.as_ref());
-    let output = cygpath.output().unwrap();
-    if !output.status.success() {
+    let output = cygpath.command_output();
+    if !output.status().success() {
         handle_failed_output(&cygpath, output, caller_line_number);
     }
-    let s = String::from_utf8(output.stdout).unwrap();
     // cygpath -w can attach a newline
-    s.trim().to_string()
+    output.stdout_utf8().trim().to_string()
 }
 
 /// Run `uname`. This assumes that `uname` is available on the platform!
@@ -186,34 +187,34 @@ pub fn uname() -> String {
     let caller_line_number = caller_location.line();
 
     let mut uname = Command::new("uname");
-    let output = uname.output().unwrap();
-    if !output.status.success() {
+    let output = uname.command_output();
+    if !output.status().success() {
         handle_failed_output(&uname, output, caller_line_number);
     }
-    String::from_utf8(output.stdout).unwrap()
+    output.stdout_utf8()
 }
 
-fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) -> ! {
-    if output.status.success() {
+fn handle_failed_output(cmd: &Command, output: CompletedProcess, caller_line_number: u32) -> ! {
+    if output.status().success() {
         eprintln!("command unexpectedly succeeded at line {caller_line_number}");
     } else {
         eprintln!("command failed at line {caller_line_number}");
     }
     eprintln!("{cmd:?}");
-    eprintln!("output status: `{}`", output.status);
-    eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
-    eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
+    eprintln!("output status: `{}`", output.status());
+    eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
+    eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
     std::process::exit(1)
 }
 
 /// Set the runtime library path as needed for running the host rustc/rustdoc/etc.
 pub fn set_host_rpath(cmd: &mut Command) {
-    let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
+    let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
     cmd.env(&ld_lib_path_envvar, {
         let mut paths = vec![];
-        paths.push(PathBuf::from(env::var("TMPDIR").unwrap()));
-        paths.push(PathBuf::from(env::var("HOST_RPATH_DIR").unwrap()));
-        for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) {
+        paths.push(cwd());
+        paths.push(PathBuf::from(env_var("HOST_RPATH_DIR")));
+        for p in env::split_paths(&env_var(&ld_lib_path_envvar)) {
             paths.push(p.to_path_buf());
         }
         env::join_paths(paths.iter()).unwrap()
@@ -289,6 +290,7 @@ pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
 }
 
 /// Check that `haystack` does not contain `needle`. Panic otherwise.
+#[track_caller]
 pub fn assert_not_contains(haystack: &str, needle: &str) {
     if haystack.contains(needle) {
         eprintln!("=== HAYSTACK ===");
@@ -299,39 +301,52 @@ pub fn assert_not_contains(haystack: &str, needle: &str) {
     }
 }
 
+/// This function is designed for running commands in a temporary directory
+/// that is cleared after the function ends.
+///
+/// What this function does:
+/// 1) Creates a temporary directory (`tmpdir`)
+/// 2) Copies all files from the current directory to `tmpdir`
+/// 3) Changes the current working directory to `tmpdir`
+/// 4) Calls `callback`
+/// 5) Switches working directory back to the original one
+/// 6) Removes `tmpdir`
+pub fn run_in_tmpdir<F: FnOnce()>(callback: F) {
+    let original_dir = cwd();
+    let tmpdir = original_dir.join("../temporary-directory");
+    copy_dir_all(".", &tmpdir);
+
+    env::set_current_dir(&tmpdir).unwrap();
+    callback();
+    env::set_current_dir(original_dir).unwrap();
+    fs::remove_dir_all(tmpdir).unwrap();
+}
+
 /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
-/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
+/// containing a `cmd: Command` field. The provided helpers are:
 ///
 /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
 ///    to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
 ///    new specific helper methods over relying on these generic argument providers.
 /// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
 ///    methods of the same name on [`Command`].
-/// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
-///    command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
-///    higher-level convenience methods which waits for the command to finish running and assert
-///    that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
-///    possible.
+/// 3. Output and execution: `run` and `run_fail` are provided. These are
+///    higher-level convenience methods which wait for the command to finish running and assert
+///    that the command successfully ran or failed as expected. They return
+///    [`CompletedProcess`], which can be used to assert the stdout/stderr/exit code of the executed
+///    process.
 ///
 /// Example usage:
 ///
 /// ```ignore (illustrative)
 /// struct CommandWrapper { cmd: Command } // <- required `cmd` field
 ///
-/// impl CommandWrapper {
-///     /// Get the [`Output`][::std::process::Output] of the finished process.
-///     pub fn command_output(&mut self) -> Output { /* ... */ } // <- required `command_output()` method
-/// }
-///
 /// crate::impl_common_helpers!(CommandWrapper);
 ///
 /// impl CommandWrapper {
 ///     // ... additional specific helper methods
 /// }
 /// ```
-///
-/// [`Command`]: ::std::process::Command
-/// [`Output`]: ::std::process::Output
 macro_rules! impl_common_helpers {
     ($wrapper: ident) => {
         impl $wrapper {
@@ -394,28 +409,14 @@ macro_rules! impl_common_helpers {
 
             /// Run the constructed command and assert that it is successfully run.
             #[track_caller]
-            pub fn run(&mut self) -> ::std::process::Output {
-                let caller_location = ::std::panic::Location::caller();
-                let caller_line_number = caller_location.line();
-
-                let output = self.command_output();
-                if !output.status.success() {
-                    handle_failed_output(&self.cmd, output, caller_line_number);
-                }
-                output
+            pub fn run(&mut self) -> crate::command::CompletedProcess {
+                self.cmd.run()
             }
 
             /// Run the constructed command and assert that it does not successfully run.
             #[track_caller]
-            pub fn run_fail(&mut self) -> ::std::process::Output {
-                let caller_location = ::std::panic::Location::caller();
-                let caller_line_number = caller_location.line();
-
-                let output = self.command_output();
-                if output.status.success() {
-                    handle_failed_output(&self.cmd, output, caller_line_number);
-                }
-                output
+            pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
+                self.cmd.run_fail()
             }
 
             /// Set the path where the command will be run.
@@ -427,4 +428,5 @@ macro_rules! impl_common_helpers {
     };
 }
 
+use crate::command::{Command, CompletedProcess};
 pub(crate) use impl_common_helpers;
diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs
index f114aacfa3f..db2f9db6e41 100644
--- a/src/tools/run-make-support/src/llvm_readobj.rs
+++ b/src/tools/run-make-support/src/llvm_readobj.rs
@@ -1,8 +1,7 @@
-use std::env;
 use std::path::{Path, PathBuf};
-use std::process::Command;
 
-use crate::handle_failed_output;
+use crate::command::Command;
+use crate::env_var;
 
 /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
 /// at `$LLVM_BIN_DIR/llvm-readobj`.
@@ -22,8 +21,7 @@ impl LlvmReadobj {
     /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
     /// at `$LLVM_BIN_DIR/llvm-readobj`.
     pub fn new() -> Self {
-        let llvm_bin_dir = env::var("LLVM_BIN_DIR")
-            .expect("`LLVM_BIN_DIR` not specified, but this is required to find `llvm-readobj`");
+        let llvm_bin_dir = env_var("LLVM_BIN_DIR");
         let llvm_bin_dir = PathBuf::from(llvm_bin_dir);
         let llvm_readobj = llvm_bin_dir.join("llvm-readobj");
         let cmd = Command::new(llvm_readobj);
@@ -41,10 +39,4 @@ impl LlvmReadobj {
         self.cmd.arg("--file-header");
         self
     }
-
-    /// Get the [`Output`][::std::process::Output] of the finished process.
-    #[track_caller]
-    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/run.rs b/src/tools/run-make-support/src/run.rs
index 9aad91f1b46..4a6fd7c432e 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -1,24 +1,25 @@
 use std::env;
+use std::ffi::OsStr;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output};
 
-use crate::is_windows;
+use crate::command::{Command, CompletedProcess};
+use crate::{cwd, env_var, is_windows, set_host_rpath};
 
-use super::{bin_name, handle_failed_output};
+use super::handle_failed_output;
 
-fn run_common(name: &str) -> (Command, Output) {
+fn run_common(name: &str) -> (Command, CompletedProcess) {
     let mut bin_path = PathBuf::new();
-    bin_path.push(env::var("TMPDIR").unwrap());
-    bin_path.push(&bin_name(name));
-    let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
+    bin_path.push(cwd());
+    bin_path.push(name);
+    let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
     let mut cmd = Command::new(bin_path);
     cmd.env(&ld_lib_path_envvar, {
         let mut paths = vec![];
-        paths.push(PathBuf::from(env::var("TMPDIR").unwrap()));
-        for p in env::split_paths(&env::var("TARGET_RPATH_ENV").unwrap()) {
+        paths.push(cwd());
+        for p in env::split_paths(&env_var("TARGET_RPATH_ENV")) {
             paths.push(p.to_path_buf());
         }
-        for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) {
+        for p in env::split_paths(&env_var(&ld_lib_path_envvar)) {
             paths.push(p.to_path_buf());
         }
         env::join_paths(paths.iter()).unwrap()
@@ -29,22 +30,22 @@ fn run_common(name: &str) -> (Command, Output) {
         for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
             paths.push(p.to_path_buf());
         }
-        paths.push(Path::new(&std::env::var("TARGET_RPATH_DIR").unwrap()).to_path_buf());
+        paths.push(Path::new(&env_var("TARGET_RPATH_DIR")).to_path_buf());
         cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
     }
 
-    let output = cmd.output().unwrap();
+    let output = cmd.command_output();
     (cmd, output)
 }
 
 /// Run a built binary and make sure it succeeds.
 #[track_caller]
-pub fn run(name: &str) -> Output {
+pub fn run(name: &str) -> CompletedProcess {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
     let (cmd, output) = run_common(name);
-    if !output.status.success() {
+    if !output.status().success() {
         handle_failed_output(&cmd, output, caller_line_number);
     }
     output
@@ -52,13 +53,21 @@ pub fn run(name: &str) -> Output {
 
 /// Run a built binary and make sure it fails.
 #[track_caller]
-pub fn run_fail(name: &str) -> Output {
+pub fn run_fail(name: &str) -> CompletedProcess {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
     let (cmd, output) = run_common(name);
-    if output.status.success() {
+    if output.status().success() {
         handle_failed_output(&cmd, output, caller_line_number);
     }
     output
 }
+
+/// Create a new custom Command.
+/// This should be preferred to creating `std::process::Command` directly.
+pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
+    let mut command = Command::new(program);
+    set_host_rpath(&mut command);
+    command
+}
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index 8b0252b8f04..5ea231442bc 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -1,10 +1,8 @@
-use std::env;
+use command::Command;
 use std::ffi::{OsStr, OsString};
-use std::io::Write;
 use std::path::Path;
-use std::process::{Command, Output, Stdio};
 
-use crate::{handle_failed_output, set_host_rpath, tmp_dir};
+use crate::{command, cwd, env_var, set_host_rpath};
 
 /// Construct a new `rustc` invocation.
 pub fn rustc() -> Rustc {
@@ -20,16 +18,15 @@ pub fn aux_build() -> Rustc {
 #[derive(Debug)]
 pub struct Rustc {
     cmd: Command,
-    stdin: Option<Box<[u8]>>,
 }
 
 crate::impl_common_helpers!(Rustc);
 
 fn setup_common() -> Command {
-    let rustc = env::var("RUSTC").unwrap();
+    let rustc = env_var("RUSTC");
     let mut cmd = Command::new(rustc);
     set_host_rpath(&mut cmd);
-    cmd.arg("--out-dir").arg(tmp_dir()).arg("-L").arg(tmp_dir());
+    cmd.arg("-L").arg(cwd());
     cmd
 }
 
@@ -39,14 +36,14 @@ impl Rustc {
     /// Construct a new `rustc` invocation.
     pub fn new() -> Self {
         let cmd = setup_common();
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
     pub fn new_aux_build() -> Self {
         let mut cmd = setup_common();
         cmd.arg("--crate-type=lib");
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     // Argument provider methods
@@ -70,6 +67,12 @@ impl Rustc {
         self
     }
 
+    /// Add a suffix in each output filename.
+    pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
+        self.cmd.arg(format!("-Cextra-filename={suffix}"));
+        self
+    }
+
     /// Specify type(s) of output files to generate.
     pub fn emit(&mut self, kinds: &str) -> &mut Self {
         self.cmd.arg(format!("--emit={kinds}"));
@@ -104,6 +107,13 @@ impl Rustc {
         self
     }
 
+    /// Specify path to the output directory. Equivalent to `--out-dir`` in rustc.
+    pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("--out-dir");
+        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}"));
@@ -192,7 +202,7 @@ impl Rustc {
 
     /// Specify a stdin input
     pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+        self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
         self
     }
 
@@ -208,38 +218,4 @@ impl Rustc {
         self.cmd.arg(format!("-Clinker={linker}"));
         self
     }
-
-    /// Get the [`Output`] of the finished process.
-    #[track_caller]
-    pub fn command_output(&mut self) -> Output {
-        // let's make sure we piped all the input and outputs
-        self.cmd.stdin(Stdio::piped());
-        self.cmd.stdout(Stdio::piped());
-        self.cmd.stderr(Stdio::piped());
-
-        if let Some(input) = &self.stdin {
-            let mut child = self.cmd.spawn().unwrap();
-
-            {
-                let mut stdin = child.stdin.take().unwrap();
-                stdin.write_all(input.as_ref()).unwrap();
-            }
-
-            child.wait_with_output().expect("failed to get output of finished process")
-        } else {
-            self.cmd.output().expect("failed to get output of finished process")
-        }
-    }
-
-    #[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.command_output();
-        if output.status.code().unwrap() != code {
-            handle_failed_output(&self.cmd, output, caller_line_number);
-        }
-        output
-    }
 }
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index 61d7448a6bf..39a698a47b4 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -1,10 +1,8 @@
-use std::env;
 use std::ffi::OsStr;
-use std::io::Write;
 use std::path::Path;
-use std::process::{Command, Output, Stdio};
 
-use crate::{handle_failed_output, set_host_rpath};
+use crate::command::Command;
+use crate::{env_var, env_var_os, set_host_rpath};
 
 /// Construct a plain `rustdoc` invocation with no flags set.
 pub fn bare_rustdoc() -> Rustdoc {
@@ -19,13 +17,12 @@ pub fn rustdoc() -> Rustdoc {
 #[derive(Debug)]
 pub struct Rustdoc {
     cmd: Command,
-    stdin: Option<Box<[u8]>>,
 }
 
 crate::impl_common_helpers!(Rustdoc);
 
 fn setup_common() -> Command {
-    let rustdoc = env::var("RUSTDOC").unwrap();
+    let rustdoc = env_var("RUSTDOC");
     let mut cmd = Command::new(rustdoc);
     set_host_rpath(&mut cmd);
     cmd
@@ -35,15 +32,15 @@ impl Rustdoc {
     /// Construct a bare `rustdoc` invocation.
     pub fn bare() -> Self {
         let cmd = setup_common();
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
     pub fn new() -> Self {
         let mut cmd = setup_common();
-        let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
+        let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
         cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Specify where an external library is located.
@@ -89,33 +86,10 @@ impl Rustdoc {
 
     /// Specify a stdin input
     pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.cmd.stdin(Stdio::piped());
-        self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+        self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
         self
     }
 
-    /// Get the [`Output`] of the finished process.
-    #[track_caller]
-    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());
-        self.cmd.stderr(Stdio::piped());
-
-        if let Some(input) = &self.stdin {
-            let mut child = self.cmd.spawn().unwrap();
-
-            {
-                let mut stdin = child.stdin.take().unwrap();
-                stdin.write_all(input.as_ref()).unwrap();
-            }
-
-            child.wait_with_output().expect("failed to get output of finished process")
-        } else {
-            self.cmd.output().expect("failed to get output of finished process")
-        }
-    }
-
     /// Specify the edition year.
     pub fn edition(&mut self, edition: &str) -> &mut Self {
         self.cmd.arg("--edition");
@@ -157,16 +131,4 @@ impl Rustdoc {
         self.cmd.arg(format);
         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.command_output();
-        if output.status.code().unwrap() != code {
-            handle_failed_output(&self.cmd, output, caller_line_number);
-        }
-        output
-    }
 }
diff --git a/src/tools/rust-installer/src/compression.rs b/src/tools/rust-installer/src/compression.rs
index 4e840dbfbb4..40c7c597e9b 100644
--- a/src/tools/rust-installer/src/compression.rs
+++ b/src/tools/rust-installer/src/compression.rs
@@ -214,22 +214,16 @@ impl Write for CombinedEncoder {
     }
 
     fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
-        self.encoders
-            .par_iter_mut()
-            .map(|w| w.write_all(buf))
-            .collect::<std::io::Result<Vec<()>>>()?;
-        Ok(())
+        self.encoders.par_iter_mut().try_for_each(|w| w.write_all(buf))
     }
 
     fn flush(&mut self) -> std::io::Result<()> {
-        self.encoders.par_iter_mut().map(|w| w.flush()).collect::<std::io::Result<Vec<()>>>()?;
-        Ok(())
+        self.encoders.par_iter_mut().try_for_each(Write::flush)
     }
 }
 
 impl Encoder for CombinedEncoder {
     fn finish(self: Box<Self>) -> Result<(), Error> {
-        self.encoders.into_par_iter().map(|e| e.finish()).collect::<Result<Vec<()>, Error>>()?;
-        Ok(())
+        self.encoders.into_par_iter().try_for_each(Encoder::finish)
     }
 }
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 2b0dd0062b9..95f1a5d6e1d 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -9,6 +9,7 @@ clap = "4.0.32"
 env_logger = "0.11"
 mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" }
 mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" }
+mdbook-i18n-helpers = "0.3.3"
 
 [dependencies.mdbook]
 version = "0.4.37"
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index 9a06754e4a6..31bba56adde 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -7,6 +7,7 @@ use clap::{arg, ArgMatches, Command};
 
 use mdbook::errors::Result as Result3;
 use mdbook::MDBook;
+use mdbook_i18n_helpers::preprocessors::Gettext;
 
 use mdbook_trpl_listing::TrplListing;
 use mdbook_trpl_note::TrplNote;
@@ -19,6 +20,11 @@ fn main() {
     .required(false)
     .value_parser(clap::value_parser!(PathBuf));
 
+    let l_arg = arg!(-l --"lang" <LANGUAGE>
+"The output language")
+    .required(false)
+    .value_parser(clap::value_parser!(String));
+
     let dir_arg = arg!([dir] "Root directory for the book\n\
                               (Defaults to the current directory when omitted)")
     .value_parser(clap::value_parser!(PathBuf));
@@ -33,6 +39,7 @@ fn main() {
             Command::new("build")
                 .about("Build the book from the markdown files")
                 .arg(d_arg)
+                .arg(l_arg)
                 .arg(&dir_arg),
         )
         .subcommand(
@@ -63,6 +70,12 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
     let book_dir = get_book_dir(args);
     let mut book = load_book(&book_dir)?;
 
+    if let Some(lang) = args.get_one::<String>("lang") {
+        let gettext = Gettext;
+        book.with_preprocessor(gettext);
+        book.config.set("book.language", lang).unwrap();
+    }
+
     // Set this to allow us to catch bugs in advance.
     book.config.build.create_missing = false;
 
diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf
-Subproject cc81f9654dac3fe08de286907dba747538417af
+Subproject 72daa50ce2350f5a9b5ae6dc3ad6babccd14ec0
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index 0ddd2c66cf9..bf581279f2a 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -123,9 +123,7 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse
                     cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
                 }
 
-                if let Some(flags) = &test_props.run_flags {
-                    cargo.arg(flags);
-                }
+                cargo.args(&test_props.run_flags);
             }
 
             if try_run(&mut cargo, config.verbose).is_err() {
diff --git a/src/tools/rustdoc-gui/.eslintrc.js b/src/tools/rustdoc-gui/.eslintrc.js
index f4aadc07199..3eccbc74cb9 100644
--- a/src/tools/rustdoc-gui/.eslintrc.js
+++ b/src/tools/rustdoc-gui/.eslintrc.js
@@ -6,7 +6,7 @@ module.exports = {
     },
     "extends": "eslint:recommended",
     "parserOptions": {
-        "ecmaVersion": 2018,
+        "ecmaVersion": 2019,
         "sourceType": "module"
     },
     "rules": {
diff --git a/src/tools/rustdoc-js/.eslintrc.js b/src/tools/rustdoc-js/.eslintrc.js
index b9d0e251c24..3eccbc74cb9 100644
--- a/src/tools/rustdoc-js/.eslintrc.js
+++ b/src/tools/rustdoc-js/.eslintrc.js
@@ -6,7 +6,7 @@ module.exports = {
     },
     "extends": "eslint:recommended",
     "parserOptions": {
-        "ecmaVersion": 8,
+        "ecmaVersion": 2019,
         "sourceType": "module"
     },
     "rules": {
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index 3cf133c647c..cbcc0b2d636 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -2,7 +2,7 @@ use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ast, ptr};
 use rustc_parse::parser::{ForceCollect, Parser, Recovery};
-use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
+use rustc_parse::MACRO_ARGUMENTS;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{self, kw};
 use rustc_span::Symbol;
@@ -15,7 +15,7 @@ pub(crate) mod cfg_if;
 pub(crate) mod lazy_static;
 
 fn build_stream_parser<'a>(psess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
-    stream_to_parser(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
+    Parser::new(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
 }
 
 fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 5dcdca1d953..6051241309d 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -4,7 +4,8 @@ use std::path::{Path, PathBuf};
 use rustc_ast::token::TokenKind;
 use rustc_ast::{ast, attr, ptr};
 use rustc_errors::Diag;
-use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
+use rustc_parse::parser::Parser as RawParser;
+use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_span::{sym, Span};
 use thin_vec::ThinVec;
 
@@ -50,12 +51,9 @@ impl<'a> ParserBuilder<'a> {
 
         let parser = match Self::parser(psess.inner(), input) {
             Ok(p) => p,
-            Err(db) => {
-                if let Some(diagnostics) = db {
-                    psess.emit_diagnostics(diagnostics);
-                    return Err(ParserError::ParserCreationError);
-                }
-                return Err(ParserError::ParsePanicError);
+            Err(diagnostics) => {
+                psess.emit_diagnostics(diagnostics);
+                return Err(ParserError::ParserCreationError);
             }
         };
 
@@ -65,18 +63,14 @@ impl<'a> ParserBuilder<'a> {
     fn parser(
         psess: &'a rustc_session::parse::ParseSess,
         input: Input,
-    ) -> Result<rustc_parse::parser::Parser<'a>, Option<Vec<Diag<'a>>>> {
+    ) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
         match input {
-            Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || {
-                new_parser_from_file(psess, file, None)
-            }))
-            .map_err(|_| None),
-            Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str(
+            Input::File(ref file) => new_parser_from_file(psess, file, None),
+            Input::Text(text) => new_parser_from_source_str(
                 psess,
                 rustc_span::FileName::Custom("stdin".to_owned()),
                 text,
-            )
-            .map_err(Some),
+            ),
         }
     }
 }
@@ -111,7 +105,8 @@ impl<'a> Parser<'a> {
         span: Span,
     ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(psess.inner(), path, Some(span));
+            let mut parser =
+                unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span)));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
                 Err(e) => {
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 09e1dbde1d0..fd59aedadfe 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -111,6 +111,7 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str
 pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str {
     match unsafety {
         ast::Safety::Unsafe(..) => "unsafe ",
+        ast::Safety::Safe(..) => "safe ",
         ast::Safety::Default => "",
     }
 }
diff --git a/src/tools/rustfmt/tests/source/attrib.rs b/src/tools/rustfmt/tests/source/attrib.rs
index fc13cd02b03..d45fba55224 100644
--- a/src/tools/rustfmt/tests/source/attrib.rs
+++ b/src/tools/rustfmt/tests/source/attrib.rs
@@ -214,8 +214,8 @@ type Os = NoSource;
 // #3313
 fn stmt_expr_attributes() {
     let foo ;
-    (#[must_use]
-   foo) = false ;
+    #[must_use]
+   foo = false ;
 }
 
 // #3509
diff --git a/src/tools/rustfmt/tests/target/attrib.rs b/src/tools/rustfmt/tests/target/attrib.rs
index 7b3309676de..7e61f68d76a 100644
--- a/src/tools/rustfmt/tests/target/attrib.rs
+++ b/src/tools/rustfmt/tests/target/attrib.rs
@@ -248,8 +248,8 @@ type Os = NoSource;
 // #3313
 fn stmt_expr_attributes() {
     let foo;
-    (#[must_use]
-    foo) = false;
+    #[must_use]
+    foo = false;
 }
 
 // #3509
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 96a27610500..b07e012a1b8 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -2,7 +2,6 @@ run-make/allocator-shim-circular-deps/Makefile
 run-make/allow-non-lint-warnings-cmdline/Makefile
 run-make/archive-duplicate-names/Makefile
 run-make/atomic-lock-free/Makefile
-run-make/bare-outfile/Makefile
 run-make/branch-protection-check-IBT/Makefile
 run-make/c-dynamic-dylib/Makefile
 run-make/c-dynamic-rlib/Makefile
@@ -40,7 +39,6 @@ run-make/emit-path-unhashed/Makefile
 run-make/emit-shared-files/Makefile
 run-make/emit-stack-sizes/Makefile
 run-make/emit-to-stdout/Makefile
-run-make/emit/Makefile
 run-make/env-dep-info/Makefile
 run-make/error-found-staticlib-instead-crate/Makefile
 run-make/error-writing-dependencies/Makefile
@@ -72,7 +70,6 @@ run-make/inaccessible-temp-dir/Makefile
 run-make/include_bytes_deps/Makefile
 run-make/incr-add-rust-src-component/Makefile
 run-make/incr-foreign-head-span/Makefile
-run-make/incr-prev-body-beyond-eof/Makefile
 run-make/incremental-debugger-visualizer/Makefile
 run-make/incremental-session-fail/Makefile
 run-make/inline-always-many-cgu/Makefile
@@ -125,7 +122,6 @@ run-make/link-framework/Makefile
 run-make/link-path-order/Makefile
 run-make/linkage-attr-on-static/Makefile
 run-make/llvm-ident/Makefile
-run-make/llvm-outputs/Makefile
 run-make/long-linker-command-lines-cmd-exe/Makefile
 run-make/long-linker-command-lines/Makefile
 run-make/longjmp-across-rust/Makefile
@@ -138,7 +134,6 @@ run-make/lto-readonly-lib/Makefile
 run-make/lto-smoke-c/Makefile
 run-make/macos-deployment-target/Makefile
 run-make/macos-fat-archive/Makefile
-run-make/manual-crate-name/Makefile
 run-make/manual-link/Makefile
 run-make/many-crates-but-no-match/Makefile
 run-make/metadata-dep-info/Makefile
@@ -147,10 +142,8 @@ run-make/min-global-align/Makefile
 run-make/mingw-export-call-convention/Makefile
 run-make/mismatching-target-triples/Makefile
 run-make/missing-crate-dependency/Makefile
-run-make/mixing-formats/Makefile
 run-make/mixing-libs/Makefile
 run-make/msvc-opt-minsize/Makefile
-run-make/multiple-emits/Makefile
 run-make/native-link-modifier-bundle/Makefile
 run-make/native-link-modifier-verbatim-linker/Makefile
 run-make/native-link-modifier-verbatim-rustc/Makefile
@@ -205,7 +198,6 @@ run-make/remap-path-prefix-dwarf/Makefile
 run-make/remap-path-prefix/Makefile
 run-make/reproducible-build-2/Makefile
 run-make/reproducible-build/Makefile
-run-make/resolve-rename/Makefile
 run-make/return-non-c-like-enum-from-c/Makefile
 run-make/return-non-c-like-enum/Makefile
 run-make/rlib-chain/Makefile
@@ -235,7 +227,6 @@ run-make/static-pie/Makefile
 run-make/staticlib-blank-lib/Makefile
 run-make/staticlib-dylib-linkage/Makefile
 run-make/std-core-cycle/Makefile
-run-make/suspicious-library/Makefile
 run-make/symbol-mangling-hashed/Makefile
 run-make/symbol-visibility/Makefile
 run-make/symbols-include-type-name/Makefile
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index efcd2a181ff..2dd3d17f9e3 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -27,7 +27,8 @@ const LICENSES: &[&str] = &[
     "MIT OR Zlib OR Apache-2.0",                           // miniz_oxide
     "MIT",
     "MIT/Apache-2.0",
-    "Unicode-DFS-2016",                                    // tinystr and icu4x
+    "Unicode-3.0",                                         // icu4x
+    "Unicode-DFS-2016",                                    // tinystr
     "Unlicense OR MIT",
     "Unlicense/MIT",
     "Zlib OR Apache-2.0 OR MIT",                           // tinyvec
@@ -67,6 +68,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
     //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
     //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
     ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
+    ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None),
     ("src/tools/x", &[], None),
     // tidy-alphabetical-end
 ];
@@ -142,6 +144,22 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
     // tidy-alphabetical-end
 ];
 
+const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("alloc-no-stdlib", "BSD-3-Clause"),
+    ("alloc-stdlib", "BSD-3-Clause"),
+    ("brotli", "BSD-3-Clause/MIT"),
+    ("brotli-decompressor", "BSD-3-Clause/MIT"),
+    ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"),
+    ("inferno", "CDDL-1.0"),
+    ("instant", "BSD-3-Clause"),
+    ("ring", NON_STANDARD_LICENSE), // see EXCEPTIONS_NON_STANDARD_LICENSE_DEPS for more.
+    ("ryu", "Apache-2.0 OR BSL-1.0"),
+    ("snap", "BSD-3-Clause"),
+    ("subtle", "BSD-3-Clause"),
+    // tidy-alphabetical-end
+];
+
 const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-start
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
@@ -178,6 +196,20 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
     ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptible, but we use it under MIT OR Apache-2.0
 ];
 
+/// Placeholder for non-standard license file.
+const NON_STANDARD_LICENSE: &str = "NON_STANDARD_LICENSE";
+
+/// These dependencies have non-standard licenses but are genenrally permitted.
+const EXCEPTIONS_NON_STANDARD_LICENSE_DEPS: &[&str] = &[
+    // `ring` is included because it is an optional dependency of `hyper`,
+    // which is a training data in rustc-perf for optimized build.
+    // The license of it is generally `ISC AND MIT AND OpenSSL`,
+    // though the `package.license` field is not set.
+    //
+    // See https://github.com/briansmith/ring/issues/902
+    "ring",
+];
+
 /// These are the root crates that are part of the runtime. The licenses for
 /// these and all their dependencies *must not* be in the exception list.
 const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
@@ -411,32 +443,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-end
 ];
 
-// These crates come from ICU4X and are licensed under the unicode license.
-// It currently doesn't have an SPDX identifier, so they cannot put one there.
-// See https://github.com/unicode-org/icu4x/pull/3875
-// FIXME: This should be removed once ICU4X crates update.
-const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[
-    // tidy-alphabetical-start
-    "icu_list",
-    "icu_list_data",
-    "icu_locid",
-    "icu_locid_transform",
-    "icu_locid_transform_data",
-    "icu_provider",
-    "icu_provider_adapters",
-    "icu_provider_macros",
-    "litemap",
-    "tinystr",
-    "writeable",
-    "yoke",
-    "yoke-derive",
-    "zerofrom",
-    "zerofrom-derive",
-    "zerovec",
-    "zerovec-derive",
-    // tidy-alphabetical-end
-];
-
 const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "ahash",
@@ -610,6 +616,11 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
         for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
             match &pkg.license {
                 None => {
+                    if *license == NON_STANDARD_LICENSE
+                        && EXCEPTIONS_NON_STANDARD_LICENSE_DEPS.contains(&pkg.name.as_str())
+                    {
+                        continue;
+                    }
                     tidy_error!(
                         bad,
                         "dependency exception `{}` does not declare a license expression",
@@ -642,10 +653,6 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
         let license = match &pkg.license {
             Some(license) => license,
             None => {
-                if ICU4X_UNICODE_LICENSE_DEPENDENCIES.contains(&pkg.name.as_str()) {
-                    // See the comment on ICU4X_UNICODE_LICENSE_DEPENDENCIES.
-                    continue;
-                }
                 tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
                 continue;
             }
diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs
index 40e75d1d3fa..2c97a39f100 100644
--- a/src/tools/tidy/src/ext_tool_checks.rs
+++ b/src/tools/tidy/src/ext_tool_checks.rs
@@ -320,7 +320,7 @@ fn install_requirements(
     }
 
     let stat = Command::new(py_path)
-        .args(["-m", "pip", "install", "--require-hashes", "-r"])
+        .args(["-m", "pip", "install", "--quiet", "--require-hashes", "-r"])
         .arg(src_reqs_path)
         .status()?;
     if !stat.success() {
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index ff71ca53725..2118de5f204 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -4,7 +4,11 @@ use std::fs;
 use std::path::Path;
 
 /// List of allowed sources for packages.
-const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""];
+const ALLOWED_SOURCES: &[&str] = &[
+    r#""registry+https://github.com/rust-lang/crates.io-index""#,
+    // This is `rust_team_data` used by `site` in src/tools/rustc-perf,
+    r#""git+https://github.com/rust-lang/team#a5260e76d3aa894c64c56e6ddc8545b9a98043ec""#,
+];
 
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 398a6fd0fba..a6ba8959f0c 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2445,7 +2445,6 @@ ui/issues/issue-53300.rs
 ui/issues/issue-53333.rs
 ui/issues/issue-53348.rs
 ui/issues/issue-53419.rs
-ui/issues/issue-53498.rs
 ui/issues/issue-53568.rs
 ui/issues/issue-5358-1.rs
 ui/issues/issue-53728.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index cce0fb2c1a2..f2eeda339d8 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
 const ENTRY_LIMIT: u32 = 900;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: u32 = 1674;
+const ISSUES_ENTRY_LIMIT: u32 = 1672;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index f68b7675c76..63a03834166 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -16,6 +16,7 @@ pub fn filter_dirs(path: &Path) -> bool {
         "library/stdarch",
         "src/tools/cargo",
         "src/tools/clippy",
+        "src/tools/libcxx-version",
         "src/tools/miri",
         "src/tools/rust-analyzer",
         "src/tools/rustc-perf",
diff --git a/src/version b/src/version
index aaceec04e04..dbd41264aa9 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.80.0
+1.81.0
diff --git a/tests/assembly/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs
index 8f824563e8a..22cf4bdb15b 100644
--- a/tests/assembly/asm/global_asm.rs
+++ b/tests/assembly/asm/global_asm.rs
@@ -25,9 +25,9 @@ global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
 global_asm!("call {}", sym my_func);
 // CHECK: lea rax, [rip + MY_STATIC]
 global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
-// CHECK: call _RNvCsddMtV7nAi4C_10global_asm6foobar
+// CHECK: call _RNvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_10global_asm6foobar
 global_asm!("call {}", sym foobar);
-// CHECK: _RNvCsddMtV7nAi4C_10global_asm6foobar:
+// CHECK: _RNvC[[CRATE_IDENT]]_10global_asm6foobar:
 fn foobar() {
     loop {}
 }
diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs
index 23d09e0d8af..b4cd99272b1 100644
--- a/tests/codegen-units/item-collection/generic-impl.rs
+++ b/tests/codegen-units/item-collection/generic-impl.rs
@@ -22,16 +22,16 @@ impl<T> Struct<T> {
     }
 }
 
-pub struct LifeTimeOnly<'a> {
+pub struct _LifeTimeOnly<'a> {
     _a: &'a u32,
 }
 
-impl<'a> LifeTimeOnly<'a> {
-    //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo
+impl<'a> _LifeTimeOnly<'a> {
+    //~ MONO_ITEM fn _LifeTimeOnly::<'_>::foo
     pub fn foo(&self) {}
-    //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar
+    //~ MONO_ITEM fn _LifeTimeOnly::<'_>::bar
     pub fn bar(&'a self) {}
-    //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz
+    //~ MONO_ITEM fn _LifeTimeOnly::<'_>::baz
     pub fn baz<'b>(&'b self) {}
 
     pub fn non_instantiated<T>(&self) {}
diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs
index 69b55695d3d..e00e22dbab9 100644
--- a/tests/codegen-units/item-collection/overloaded-operators.rs
+++ b/tests/codegen-units/item-collection/overloaded-operators.rs
@@ -5,44 +5,44 @@
 
 use std::ops::{Add, Deref, Index, IndexMut};
 
-pub struct Indexable {
+pub struct _Indexable {
     data: [u8; 3],
 }
 
-impl Index<usize> for Indexable {
+impl Index<usize> for _Indexable {
     type Output = u8;
 
-    //~ MONO_ITEM fn <Indexable as std::ops::Index<usize>>::index
+    //~ MONO_ITEM fn <_Indexable as std::ops::Index<usize>>::index
     fn index(&self, index: usize) -> &Self::Output {
         if index >= 3 { &self.data[0] } else { &self.data[index] }
     }
 }
 
-impl IndexMut<usize> for Indexable {
-    //~ MONO_ITEM fn <Indexable as std::ops::IndexMut<usize>>::index_mut
+impl IndexMut<usize> for _Indexable {
+    //~ MONO_ITEM fn <_Indexable as std::ops::IndexMut<usize>>::index_mut
     fn index_mut(&mut self, index: usize) -> &mut Self::Output {
         if index >= 3 { &mut self.data[0] } else { &mut self.data[index] }
     }
 }
 
-//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::eq
-//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::ne
+//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::eq
+//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::ne
 #[derive(PartialEq)]
-pub struct Equatable(u32);
+pub struct _Equatable(u32);
 
-impl Add<u32> for Equatable {
+impl Add<u32> for _Equatable {
     type Output = u32;
 
-    //~ MONO_ITEM fn <Equatable as std::ops::Add<u32>>::add
+    //~ MONO_ITEM fn <_Equatable as std::ops::Add<u32>>::add
     fn add(self, rhs: u32) -> u32 {
         self.0 + rhs
     }
 }
 
-impl Deref for Equatable {
+impl Deref for _Equatable {
     type Target = u32;
 
-    //~ MONO_ITEM fn <Equatable as std::ops::Deref>::deref
+    //~ MONO_ITEM fn <_Equatable as std::ops::Deref>::deref
     fn deref(&self) -> &Self::Target {
         &self.0
     }
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index 93c58c37c28..42ce7679d1a 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -9,11 +9,11 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @alloc_af1f8e8e6f4b341431a1d405e652df2d = {{.*}}, align 2
+// CHECK: @alloc_[[INLINE_ENUM_HASH:[a-f0-9]{32}]] = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]{32}]] = {{.*}}, align 4
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
diff --git a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs
index eeeaebe52dd..df50b4af809 100644
--- a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs
+++ b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs
@@ -3,8 +3,25 @@
 
 //@compile-flags: --crate-type=lib -Copt-level=0
 
+#![feature(generic_const_items)]
+
 const fn foo() {}
 
 pub static FOO: () = foo();
 
 // CHECK-NOT: define{{.*}}foo{{.*}}
+
+const fn bar() {}
+
+pub const BAR: () = bar();
+
+// CHECK-NOT: define{{.*}}bar{{.*}}
+
+const fn baz() {}
+
+#[rustfmt::skip]
+pub const BAZ<const C: bool>: () = if C {
+    baz()
+};
+
+// CHECK: define{{.*}}baz{{.*}}
diff --git a/tests/codegen/pattern_type_symbols.rs b/tests/codegen/pattern_type_symbols.rs
index dfe83443348..a99b3efca41 100644
--- a/tests/codegen/pattern_type_symbols.rs
+++ b/tests/codegen/pattern_type_symbols.rs
@@ -15,9 +15,9 @@ fn foo<T>() {}
 
 pub fn bar() {
     // CHECK: call pattern_type_symbols::foo::<u32>
-    // CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3foomEB2_
+    // CHECK: call void @_RINvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_20pattern_type_symbols3foomEB2_
     foo::<u32>();
     // CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999], [(); true])>
-    // CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
+    // CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
     foo::<NanoU32>();
 }
diff --git a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs
index c3f795e8857..e72a649a530 100644
--- a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs
+++ b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs
@@ -23,7 +23,7 @@ pub fn do_call() {
 
     unsafe {
         // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
-        // CHECK: store float 4.000000e+00, float* %{{.}}, align 4
+        // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4
         // CHECK: call float @llvm.sqrt.f32(float %{{.}}
         sqrt(4.0);
     }
diff --git a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
index 060d91a2696..bcd9b0eae71 100644
--- a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
+++ b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs
@@ -1,10 +1,19 @@
-//
-//@ compile-flags: -C no-prepopulate-passes
-//@ only-riscv64
-//@ only-linux
+//@ compile-flags: -O -C no-prepopulate-passes --target riscv64gc-unknown-linux-gnu
+//@ needs-llvm-components: riscv
+
+#![feature(no_core, lang_items)]
 #![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "freeze"]
+trait Freeze {}
+#[lang = "copy"]
+trait Copy {}
 
-// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 zeroext %i)
+// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i)
 #[no_mangle]
 pub extern "C" fn f_fpr_tracking(
     a: f64,
@@ -144,7 +153,7 @@ pub extern "C" fn f_ret_double_int64_s() -> DoubleInt64 {
     DoubleInt64 { f: 1., i: 2 }
 }
 
-// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, [2 x i64] %0)
+// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, [2 x i64] %0)
 #[no_mangle]
 pub extern "C" fn f_double_int8_s_arg_insufficient_gprs(
     a: i32,
@@ -250,11 +259,11 @@ pub struct IntDoubleInt {
     c: i32,
 }
 
-// CHECK: define void @f_int_double_int_s_arg(%IntDoubleInt* {{.*}}%a)
+// CHECK: define void @f_int_double_int_s_arg(ptr {{.*}} %a)
 #[no_mangle]
 pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
 
-// CHECK: define void @f_ret_int_double_int_s(%IntDoubleInt* {{.*}}sret
+// CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 dereferenceable(24) %_0)
 #[no_mangle]
 pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
     IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs
index 3d0512817f7..27018d2e6d2 100644
--- a/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs
+++ b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs
@@ -1,10 +1,19 @@
-//
-//@ compile-flags: -C no-prepopulate-passes
-//@ only-riscv64
-//@ only-linux
+//@ compile-flags: -O -C no-prepopulate-passes --target riscv64gc-unknown-linux-gnu
+//@ needs-llvm-components: riscv
+
+#![feature(no_core, lang_items)]
 #![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "freeze"]
+trait Freeze {}
+#[lang = "copy"]
+trait Copy {}
 
-// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %i)
+// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 noundef zeroext %i)
 #[no_mangle]
 pub extern "C" fn f_fpr_tracking(
     a: f32,
@@ -128,7 +137,7 @@ pub extern "C" fn f_ret_float_int64_s() -> FloatInt64 {
     FloatInt64 { f: 1., i: 2 }
 }
 
-// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %0)
+// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, i64 %0)
 #[no_mangle]
 pub extern "C" fn f_float_int8_s_arg_insufficient_gprs(
     a: i32,
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
index 4e5ad8ad4a9..9870ecc69ba 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
@@ -82,9 +82,9 @@ pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {}
 // CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
 // CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
 // CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
-// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooEE"}
-// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_E"}
-// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooES0_S0_E"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
 // CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
 // CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
 // CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}
diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs
index f0911b6e360..1df09c96e6c 100644
--- a/tests/codegen/simd/packed-simd.rs
+++ b/tests/codegen/simd/packed-simd.rs
@@ -9,10 +9,11 @@ use core::intrinsics::simd as intrinsics;
 use core::{mem, ptr};
 
 // Test codegen for not only "packed" but also "fully aligned" SIMD types, and conversion between
-// A repr(packed,simd) type with 3 elements can't exceed its element alignment,
-// whereas the same type as repr(simd) will instead have padding.
+// them. A repr(packed,simd) type with 3 elements can't exceed its element alignment, whereas the
+// same type as repr(simd) will instead have padding.
 
 #[repr(simd, packed)]
+#[derive(Copy, Clone)]
 pub struct Simd<T, const N: usize>([T; N]);
 
 #[repr(simd)]
@@ -28,11 +29,11 @@ fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
     }
 }
 
-// CHECK-LABEL: square_packed
+// CHECK-LABEL: square_packed_full
 // CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
 // CHECK-SAME: ptr{{[a-z_ ]*}} align 4
 #[no_mangle]
-pub fn square_packed(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
+pub fn square_packed_full(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
     // CHECK-NEXT: start
     // noopt: alloca [[RET_TYPE]], [[RET_ALIGN]]
     // CHECK: load <3 x float>
@@ -42,3 +43,17 @@ pub fn square_packed(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
     // CHECK-NEXT: ret void
     unsafe { intrinsics::simd_mul(x, x) }
 }
+
+// CHECK-LABEL: square_packed
+// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align 4]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
+// CHECK-SAME: ptr{{[a-z_ ]*}} align 4
+#[no_mangle]
+pub fn square_packed(x: Simd<f32, 3>) -> Simd<f32, 3> {
+    // CHECK-NEXT: start
+    // CHECK-NEXT: load <3 x float>
+    // noopt-NEXT: load <3 x float>
+    // CHECK-NEXT: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
+    // CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]]
+    // CHECK-NEXT: ret void
+    unsafe { intrinsics::simd_mul(x, x) }
+}
diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs
index 6c391d9114b..23d7657baa9 100644
--- a/tests/codegen/virtual-function-elimination.rs
+++ b/tests/codegen/virtual-function-elimination.rs
@@ -81,7 +81,7 @@ fn taking_u(u: &dyn U) -> i32 {
 }
 
 pub fn taking_v(v: &dyn V) -> i32 {
-    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCs64ITQYi9761_28virtual_function_elimination1V")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_28virtual_function_elimination1V")
     v.public_function()
 }
 
@@ -96,5 +96,5 @@ pub fn main() {
 // CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"}
 // CHECK: ![[VCALL_VIS0]] = !{i64 2}
 // CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"}
-// CHECK: ![[TYPE2]] = !{i64 0, !"NtCs64ITQYi9761_28virtual_function_elimination1V"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"NtC[[CRATE_IDENT]]_28virtual_function_elimination1V"}
 // CHECK: ![[VCALL_VIS2]] = !{i64 1}
diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map
index fd8fbd9fa75..156947f4e21 100644
--- a/tests/coverage/closure_macro.cov-map
+++ b/tests/coverage/closure_macro.cov-map
@@ -7,16 +7,14 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2)
 
 Function name: closure_macro::main
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 12, 02, 00, 0f, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-Number of file 0 mappings: 6
+Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33)
-- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 18)
-    = (c0 - c1)
-- Code(Expression(0, Sub)) at (prev + 0, 15) to (start + 0, 84)
+- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index 43b52008f33..0f2b4e01748 100644
--- a/tests/coverage/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
@@ -15,16 +15,14 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43)
 
 Function name: closure_macro_async::test::{closure#0}
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 12, 02, 00, 0f, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-Number of file 0 mappings: 6
+Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33)
-- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 18)
-    = (c0 - c1)
-- Code(Expression(0, Sub)) at (prev + 0, 15) to (start + 0, 84)
+- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
diff --git a/tests/crashes/119830.rs b/tests/crashes/119830.rs
deleted file mode 100644
index 71becc04e16..00000000000
--- a/tests/crashes/119830.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #119830
-#![feature(effects)]
-#![feature(min_specialization)]
-
-trait Specialize {}
-
-trait Foo {}
-
-impl<T> const Foo for T {}
-
-impl<T> const Foo for T where T: const Specialize {}
diff --git a/tests/crashes/121134.rs b/tests/crashes/121134.rs
deleted file mode 100644
index 36397d4ec3c..00000000000
--- a/tests/crashes/121134.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: #121134
-trait Output<'a> {
-    type Type;
-}
-
-struct Wrapper;
-
-impl Wrapper {
-    fn do_something_wrapper<O, F>(&mut self, do_something_wrapper: F)
-    where
-        FnOnce:,
-        F: for<'a> FnOnce(<F as Output<i32, _>>::Type),
-    {
-    }
-}
-
-fn main() {
-    let mut wrapper = Wrapper;
-    wrapper.do_something_wrapper::<i32, _>(|value| ());
-}
diff --git a/tests/crashes/122908.rs b/tests/crashes/122908.rs
deleted file mode 100644
index c9da1bc1879..00000000000
--- a/tests/crashes/122908.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #122908
-trait Trait<const module_path: Trait = bar> {
-    async fn handle<F>(slf: &F) {}
-}
diff --git a/tests/crashes/123917.rs b/tests/crashes/123917.rs
deleted file mode 100644
index 66e75460662..00000000000
--- a/tests/crashes/123917.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-//@ known-bug: #123917
-//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on
-
-use std::marker::PhantomData;
-
-pub struct Id<'id>();
-
-pub struct Item<'life, T> {
-    data: T,
-}
-
-pub struct Token<'life, 'borrow, 'compact, 'reborrow, T>
-where
-    'life: 'reborrow,
-    T: Tokenize,
-{
-    ptr: *mut <T as Tokenize>::Tokenized,
-    ptr: core::ptr::NonNull<T::Tokenized>,
-    _phantom: PhantomData<Id<'life>>,
-}
-
-impl<'life> Arena<'life> {
-    pub fn tokenize<'before, 'compact, 'borrow, 'reborrow, T, U>(
-        item: Item<'life, &'before mut T>,
-    ) -> Token<'life, 'borrow, 'compact, 'reborrow, U>
-    where
-        T: Tokenize<'life, 'borrow, 'compact, 'reborrow, Untokenized = U>,
-        T::Untokenized: Tokenize<'life, 'borrow, 'compact, 'reborrow>,
-    {
-        let dst = item.data as *mut T as *mut T::Tokenized;
-        Token {
-            ptr: core::ptr::NonNull::new(dst as *mut _).unwrap(),
-            _phantom: PhantomData,
-        }
-    }
-}
-
-pub trait Tokenize {
-    type Tokenized;
-    type Untokenized;
-}
diff --git a/tests/crashes/124342.rs b/tests/crashes/124342.rs
deleted file mode 100644
index ae51b3db96f..00000000000
--- a/tests/crashes/124342.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ known-bug: #124342
-trait Trait2 : Trait {
-   reuse <() as Trait>::async {
-        (async || {}).await;
-    };
-}
diff --git a/tests/crashes/124347.rs b/tests/crashes/124347.rs
deleted file mode 100644
index d2bc555fe1c..00000000000
--- a/tests/crashes/124347.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #124347
-trait Trait: ToReuse {
-    reuse Trait::lolno { &self.0 };
-}
diff --git a/tests/crashes/124490.rs b/tests/crashes/124490.rs
deleted file mode 100644
index 9f605c32cf2..00000000000
--- a/tests/crashes/124490.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ 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
deleted file mode 100644
index 5320ce27843..00000000000
--- a/tests/crashes/124552.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ 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/125013-1.rs b/tests/crashes/125013-1.rs
deleted file mode 100644
index ae66d7a1466..00000000000
--- a/tests/crashes/125013-1.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ known-bug: rust-lang/rust#125013
-//@ edition:2021
-use io::{self as std};
-use std::ops::Deref::{self as io};
-pub fn main() {}
diff --git a/tests/crashes/125013-2.rs b/tests/crashes/125013-2.rs
deleted file mode 100644
index a14c8a76b63..00000000000
--- a/tests/crashes/125013-2.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ known-bug: rust-lang/rust#125013
-//@ edition:2021
-mod a {
-  pub mod b {
-    pub mod c {
-      pub trait D {}
-    }
-  }
-}
-
-use a::*;
-
-use e as b;
-use b::c::D as e;
-
-fn main() { }
diff --git a/tests/crashes/125556.rs b/tests/crashes/125556.rs
deleted file mode 100644
index f2e2a991b11..00000000000
--- a/tests/crashes/125556.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: rust-lang/rust#125556
-//@ compile-flags: -Znext-solver=coherence
-
-#![feature(generic_const_exprs)]
-
-pub struct A<const z: [usize; x]> {}
-
-impl A<2> {
-    pub const fn B() {}
-}
-
-impl A<2> {
-    pub const fn B() {}
-}
diff --git a/tests/crashes/125655.rs b/tests/crashes/125655.rs
new file mode 100644
index 00000000000..fbf92ca22be
--- /dev/null
+++ b/tests/crashes/125655.rs
@@ -0,0 +1,8 @@
+//@ known-bug: rust-lang/rust#125655
+
+fn main() {
+    static foo: dyn Fn() -> u32 = || -> u32 {
+        ...
+        0
+    };
+}
diff --git a/tests/crashes/125680.rs b/tests/crashes/125680.rs
new file mode 100644
index 00000000000..09f4f318bdd
--- /dev/null
+++ b/tests/crashes/125680.rs
@@ -0,0 +1,15 @@
+//@ known-bug: rust-lang/rust#125680
+//@ edition:2021
+
+#![feature(generic_const_exprs)]
+
+use core::fmt::Debug;
+
+struct Inline<T>
+where
+    [(); std::mem::offset_of!((T,), 0)]:,
+{}
+
+fn main() {
+    let dst = Inline::<dyn Debug>::new(0); // BANG!
+}
diff --git a/tests/crashes/125758.rs b/tests/crashes/125758.rs
new file mode 100644
index 00000000000..86c3b80abab
--- /dev/null
+++ b/tests/crashes/125758.rs
@@ -0,0 +1,26 @@
+//@ known-bug: rust-lang/rust#125758
+#![feature(impl_trait_in_assoc_type)]
+
+trait Trait: Sized {
+    type Assoc2;
+}
+
+impl Trait for Bar {
+    type Assoc2 = impl std::fmt::Debug;
+}
+
+struct Foo {
+    field: <Bar as Trait>::Assoc2,
+}
+
+enum Bar {
+    C = 42,
+    D = 99,
+}
+
+static BAR: u8 = 42;
+
+static FOO2: (&Foo, &<Bar as Trait>::Assoc2) =
+    unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) };
+
+fn main() {}
diff --git a/tests/crashes/125768.rs b/tests/crashes/125768.rs
new file mode 100644
index 00000000000..3c04431baa0
--- /dev/null
+++ b/tests/crashes/125768.rs
@@ -0,0 +1,15 @@
+//@ known-bug: rust-lang/rust#125768
+
+#![feature(generic_const_exprs)]
+
+struct Outer<const A: i64, const B: usize>();
+impl<const A: usize, const B: usize> Outer<A, B>
+where
+    [(); A + (B * 2)]:,
+{
+    fn o() -> Union {}
+}
+
+fn main() {
+    Outer::<1, 1>::o();
+}
diff --git a/tests/crashes/125769.rs b/tests/crashes/125769.rs
new file mode 100644
index 00000000000..da19458f7ca
--- /dev/null
+++ b/tests/crashes/125769.rs
@@ -0,0 +1,14 @@
+//@ known-bug: rust-lang/rust#125769
+
+#![feature(generic_const_exprs)]
+
+trait Trait {}
+
+struct HasCastInTraitImpl<const N: usize, const M: u128>;
+impl<const O: f64> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+
+pub fn use_trait_impl() {
+    fn assert_impl<T: Trait>() {}
+
+    assert_impl::<HasCastInTraitImpl<13, 13>>();
+}
diff --git a/tests/crashes/125772.rs b/tests/crashes/125772.rs
new file mode 100644
index 00000000000..2965cfc9e7c
--- /dev/null
+++ b/tests/crashes/125772.rs
@@ -0,0 +1,17 @@
+//@ known-bug: rust-lang/rust#125772
+//@ only-x86_64
+#![feature(generic_const_exprs)]
+
+struct Outer<const A: i64, const B: i64>();
+impl<const A: usize, const B: usize> Outer<A, B>
+where
+    [(); A + (B * 2)]:,
+{
+    fn i() -> Self {
+        Self
+    }
+}
+
+fn main() {
+    Outer::<1, 1>::o();
+}
diff --git a/tests/crashes/125799.rs b/tests/crashes/125799.rs
new file mode 100644
index 00000000000..62d5438b4e4
--- /dev/null
+++ b/tests/crashes/125799.rs
@@ -0,0 +1,22 @@
+//@ known-bug: rust-lang/rust#125799
+//@ only-x86_64
+
+trait Trait<T> {
+    type Assoc;
+}
+
+impl<T> Trait<T> for Vec<T> {
+    type Assoc = ();
+}
+
+impl Trait<u8> for Vec<u8> {}
+
+const BAR: <Vec<u8> as Trait<u8>>::Assoc = 3;
+
+pub fn main() {
+    let x: isize = 3;
+    let _ = match x {
+        BAR => 2,
+        _ => 3,
+    };
+}
diff --git a/tests/crashes/125801.rs b/tests/crashes/125801.rs
new file mode 100644
index 00000000000..aaa76bd0ba6
--- /dev/null
+++ b/tests/crashes/125801.rs
@@ -0,0 +1,20 @@
+//@ known-bug: rust-lang/rust#125801
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    type Output;
+}
+
+impl Foo for [u8; 3] {
+    type Output = [u8; 3];
+}
+
+static A: <[u8; N] as Foo>::Output = [1, 2, 3];
+
+fn main() {
+    || {
+        let _ = A[1];
+    };
+}
diff --git a/tests/crashes/125810.rs b/tests/crashes/125810.rs
new file mode 100644
index 00000000000..4a152da8ddf
--- /dev/null
+++ b/tests/crashes/125810.rs
@@ -0,0 +1,10 @@
+//@ known-bug: rust-lang/rust#125810
+#![feature(arbitrary_self_types, dispatch_from_dyn)]
+
+use std::ops::{Deref, DispatchFromDyn};
+
+trait Trait<T: Deref<Target = Self> + DispatchFromDyn<T>> {
+    fn MONO_BUF(self: T) -> dyn Trait<T>;
+}
+
+fn main() {}
diff --git a/tests/crashes/125811.rs b/tests/crashes/125811.rs
new file mode 100644
index 00000000000..eb764e8d152
--- /dev/null
+++ b/tests/crashes/125811.rs
@@ -0,0 +1,34 @@
+//@ known-bug: rust-lang/rust#125811
+mod assert {
+    use std::mem::{Assume, BikeshedIntrinsicFrom};
+
+    pub fn is_transmutable<Src, Dst>()
+    where
+        Dst: BikeshedIntrinsicFrom<Src>,
+    {
+    }
+}
+
+#[repr(C)]
+struct Zst;
+
+enum V0 {
+    B(!),
+}
+
+enum V2 {
+    V = 2,
+}
+
+enum Lopsided {
+    Smol(Zst),
+    Lorg(V0),
+}
+
+#[repr(C)]
+#[repr(C)]
+struct Dst(Lopsided, V2);
+
+fn should_pad_variants() {
+    assert::is_transmutable::<Src, Dst>();
+}
diff --git a/tests/crashes/125841.rs b/tests/crashes/125841.rs
new file mode 100644
index 00000000000..e2e61071f1d
--- /dev/null
+++ b/tests/crashes/125841.rs
@@ -0,0 +1,14 @@
+//@ known-bug: rust-lang/rust#125841
+#![feature(non_lifetime_binders)]
+fn take(id: impl for<T> Fn(T) -> T) {
+    id(0);
+    id("");
+}
+
+fn take2() -> impl for<T> Fn(T) -> T {
+    |x| x
+}
+
+fn main() {
+    take(|x| take2)
+}
diff --git a/tests/crashes/125843.rs b/tests/crashes/125843.rs
new file mode 100644
index 00000000000..8b9a3913c7e
--- /dev/null
+++ b/tests/crashes/125843.rs
@@ -0,0 +1,4 @@
+//@ known-bug: rust-lang/rust#125843
+#![feature(non_lifetime_binders)]
+trait v0<> {}
+fn kind  :(v3main impl for<v4> v0<'_, v2 = impl v0<v4> + '_>) {}
diff --git a/tests/crashes/125874.rs b/tests/crashes/125874.rs
new file mode 100644
index 00000000000..6a2713cd7c8
--- /dev/null
+++ b/tests/crashes/125874.rs
@@ -0,0 +1,22 @@
+//@ known-bug: rust-lang/rust#125874
+pub trait A {}
+
+pub trait Mirror {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for dyn A {
+    type Assoc = T;
+}
+
+struct Bar {
+    foo: <dyn A + 'static as Mirror>::Assoc,
+}
+
+pub fn main() {
+    let strct = Bar { foo: 3 };
+
+    match strct {
+        Bar { foo: 1, .. } => {}
+        _ => (),
+    };
+}
diff --git a/tests/crashes/125879.rs b/tests/crashes/125879.rs
new file mode 100644
index 00000000000..4318842e455
--- /dev/null
+++ b/tests/crashes/125879.rs
@@ -0,0 +1,18 @@
+//@ known-bug: rust-lang/rust#125879
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+pub type PubAlias0 = PubTy::PrivAssocTy;
+
+pub struct PubTy;
+impl PubTy {
+    type PrivAssocTy = ();
+}
+
+pub struct S(pub PubAlias0);
+
+pub unsafe fn foo(a: S) -> S {
+    a
+}
+
+fn main() {}
diff --git a/tests/crashes/125881.rs b/tests/crashes/125881.rs
new file mode 100644
index 00000000000..98331d3c974
--- /dev/null
+++ b/tests/crashes/125881.rs
@@ -0,0 +1,8 @@
+//@ known-bug: rust-lang/rust#125881
+#![crate_type = "lib"]
+#![feature(transmutability)]
+#![feature(unboxed_closures,effects)]
+
+const fn test() -> impl std::mem::BikeshedIntrinsicFrom() {
+    || {}
+}
diff --git a/tests/crashes/125888.rs b/tests/crashes/125888.rs
new file mode 100644
index 00000000000..ae8f2d6576b
--- /dev/null
+++ b/tests/crashes/125888.rs
@@ -0,0 +1,17 @@
+//@ known-bug: rust-lang/rust#125888
+enum NestedEnum {
+    First,
+    Second,
+}
+
+enum Enum {
+    Variant(*const &'a ()),
+}
+
+fn foo(x: Enum) {
+    match x {
+        Enum::Variant(NestedEnum::Second) => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/crashes/125914.rs b/tests/crashes/125914.rs
new file mode 100644
index 00000000000..77ccb9fb097
--- /dev/null
+++ b/tests/crashes/125914.rs
@@ -0,0 +1,20 @@
+//@ known-bug: rust-lang/rust#125914
+enum AstKind<'ast> {
+    ExprInt,
+}
+
+enum Foo {
+    Bar(isize),
+    Baz,
+}
+
+enum Other {
+    Other1(Foo),
+    Other2(AstKind),
+}
+
+fn main() {
+    match Other::Other1(Foo::Baz) {
+        ::Other::Other2(::Foo::Bar(..)) => {}
+    }
+}
diff --git a/tests/crashes/125957.rs b/tests/crashes/125957.rs
new file mode 100644
index 00000000000..e3abe5262eb
--- /dev/null
+++ b/tests/crashes/125957.rs
@@ -0,0 +1,20 @@
+//@ known-bug: rust-lang/rust#125957
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+#![feature(associated_const_equality)]
+
+pub struct Equal<const T: usize, const R: usize>();
+
+pub enum ParseMode {
+    Raw,
+}
+pub trait Parse {
+    const PARSE_MODE: ParseMode;
+}
+pub trait RenderRaw: Parse<PARSE_MODE = { ParseMode::Raw }> {}
+
+trait GenericVec<T> {
+    fn unwrap() -> dyn RenderRaw;
+}
+
+fn main() {}
diff --git a/tests/crashes/125992.rs b/tests/crashes/125992.rs
new file mode 100644
index 00000000000..d78f28ce6de
--- /dev/null
+++ b/tests/crashes/125992.rs
@@ -0,0 +1,19 @@
+//@ known-bug: rust-lang/rust#125992
+//@ compile-flags:  -Zpolonius=next
+
+#![feature(inherent_associated_types)]
+
+type Function = for<'a> fn(&'a i32) -> S<'a>::P;
+
+struct S<'a>(&'a ());
+
+impl<'a> S {
+    type P = &'a i32;
+}
+
+fn ret_ref_local<'e>() -> &'e i32 {
+    let f: Function = |x| x;
+
+    let local = 0;
+    f(&local)
+}
diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs
index 2b0c2593676..d9b61e73621 100644
--- a/tests/debuginfo/function-names.rs
+++ b/tests/debuginfo/function-names.rs
@@ -37,7 +37,7 @@
 // Const generic parameter
 // gdb-command:info functions -q function_names::const_generic_fn.*
 // gdb-check:[...]static fn function_names::const_generic_fn_bool<false>();
-// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#ad91263f6d2dd96e}>();
+// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#a70c39591cb5f53d}>();
 // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>();
 // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>();
 
@@ -76,9 +76,6 @@
 // Const generic parameter
 // cdb-command:x a!function_names::const_generic_fn*
 // cdb-check:[...] a!function_names::const_generic_fn_bool<false> (void)
-// cdb-check:[...] a!function_names::const_generic_fn_non_int<CONST$ad91263f6d2dd96e> (void)
-// cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void)
-// cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void)
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/tests/mir-opt/address_of.rs b/tests/mir-opt/address_of.rs
index 57a317a4a90..164ab38ebe7 100644
--- a/tests/mir-opt/address_of.rs
+++ b/tests/mir-opt/address_of.rs
@@ -9,7 +9,7 @@ fn address_of_reborrow() {
     y as *const [i32; 10];
     y as *const dyn Send;
     y as *const [i32];
-    y as *const i32;            // This is a cast, not a coercion
+    y as *const i32; // This is a cast, not a coercion
 
     let p: *const _ = y;
     let p: *const [i32; 10] = y;
diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs
index cd44c31d000..771fb3771b5 100644
--- a/tests/mir-opt/array_index_is_temporary.rs
+++ b/tests/mir-opt/array_index_is_temporary.rs
@@ -9,7 +9,6 @@ unsafe fn foo(z: *mut usize) -> u32 {
     99
 }
 
-
 // EMIT_MIR array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.mir
 fn main() {
     // CHECK-LABEL: fn main(
diff --git a/tests/mir-opt/building/custom/aggregate_exprs.rs b/tests/mir-opt/building/custom/aggregate_exprs.rs
index d581886247f..8985f106817 100644
--- a/tests/mir-opt/building/custom/aggregate_exprs.rs
+++ b/tests/mir-opt/building/custom/aggregate_exprs.rs
@@ -7,18 +7,18 @@ use core::intrinsics::mir::*;
 // EMIT_MIR aggregate_exprs.tuple.built.after.mir
 #[custom_mir(dialect = "built")]
 fn tuple() -> (i32, bool) {
-    mir!(
+    mir! {
         {
             RET = (1, true);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR aggregate_exprs.array.built.after.mir
 #[custom_mir(dialect = "built")]
 fn array() -> [i32; 2] {
-    mir!(
+    mir! {
         let x: [i32; 2];
         let one: i32;
         {
@@ -28,7 +28,7 @@ fn array() -> [i32; 2] {
             RET = Move(x);
             Return()
         }
-    )
+    }
 }
 
 struct Foo {
@@ -48,7 +48,7 @@ union Onion {
 // EMIT_MIR aggregate_exprs.adt.built.after.mir
 #[custom_mir(dialect = "built")]
 fn adt() -> Onion {
-    mir!(
+    mir! {
         let one: i32;
         let x: Foo;
         let y: Bar;
@@ -62,7 +62,7 @@ fn adt() -> Onion {
             RET = Onion { neon: Field(Variant(y, 0), 1) };
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/arbitrary_let.rs b/tests/mir-opt/building/custom/arbitrary_let.rs
index f8ee8504e32..3f251cd81bc 100644
--- a/tests/mir-opt/building/custom/arbitrary_let.rs
+++ b/tests/mir-opt/building/custom/arbitrary_let.rs
@@ -8,7 +8,7 @@ use core::ptr::{addr_of, addr_of_mut};
 // EMIT_MIR arbitrary_let.arbitrary_let.built.after.mir
 #[custom_mir(dialect = "built")]
 fn arbitrary_let(x: i32) -> i32 {
-    mir!(
+    mir! {
         {
             let y = x;
             Goto(second)
@@ -21,7 +21,7 @@ fn arbitrary_let(x: i32) -> i32 {
             let z = y;
             Goto(third)
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs
index e9a53b7aacb..4bd6f93e113 100644
--- a/tests/mir-opt/building/custom/arrays.rs
+++ b/tests/mir-opt/building/custom/arrays.rs
@@ -7,12 +7,14 @@ use core::intrinsics::mir::*;
 // EMIT_MIR arrays.arrays.built.after.mir
 #[custom_mir(dialect = "built")]
 fn arrays<const C: usize>() -> usize {
-    mir!({
-        let x = [5_i32; C];
-        let c = Len(x);
-        RET = c;
-        Return()
-    })
+    mir! {
+        {
+            let x = [5_i32; C];
+            let c = Len(x);
+            RET = c;
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/as_cast.rs b/tests/mir-opt/building/custom/as_cast.rs
index 92aea64db07..908d378771d 100644
--- a/tests/mir-opt/building/custom/as_cast.rs
+++ b/tests/mir-opt/building/custom/as_cast.rs
@@ -7,34 +7,34 @@ use core::intrinsics::mir::*;
 // EMIT_MIR as_cast.int_to_int.built.after.mir
 #[custom_mir(dialect = "built")]
 fn int_to_int(x: u32) -> i32 {
-    mir!(
+    mir! {
         {
             RET = x as i32;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR as_cast.float_to_int.built.after.mir
 #[custom_mir(dialect = "built")]
 fn float_to_int(x: f32) -> i32 {
-    mir!(
+    mir! {
         {
             RET = x as i32;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR as_cast.int_to_ptr.built.after.mir
 #[custom_mir(dialect = "built")]
 fn int_to_ptr(x: usize) -> *const i32 {
-    mir!(
+    mir! {
         {
             RET = x as *const i32;
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/assume.rs b/tests/mir-opt/building/custom/assume.rs
index a477e12f0e0..4a55617136a 100644
--- a/tests/mir-opt/building/custom/assume.rs
+++ b/tests/mir-opt/building/custom/assume.rs
@@ -7,34 +7,34 @@ use core::intrinsics::mir::*;
 // EMIT_MIR assume.assume_local.built.after.mir
 #[custom_mir(dialect = "built")]
 fn assume_local(x: bool) {
-    mir!(
+    mir! {
         {
             Assume(x);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR assume.assume_place.built.after.mir
 #[custom_mir(dialect = "built")]
 fn assume_place(p: (bool, u8)) {
-    mir!(
+    mir! {
         {
             Assume(p.0);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR assume.assume_constant.built.after.mir
 #[custom_mir(dialect = "built")]
 fn assume_constant() {
-    mir!(
+    mir! {
         {
             Assume(true);
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/composite_return.rs b/tests/mir-opt/building/custom/composite_return.rs
index 33c903fa0f8..0cf2cc8d189 100644
--- a/tests/mir-opt/building/custom/composite_return.rs
+++ b/tests/mir-opt/building/custom/composite_return.rs
@@ -7,14 +7,14 @@ use core::intrinsics::mir::*;
 // EMIT_MIR composite_return.tuple.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn tuple() -> (i32, bool) {
-    mir!(
+    mir! {
         type RET = (i32, bool);
         {
             RET.0 = 1;
             RET.1 = true;
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/consts.consts.built.after.mir b/tests/mir-opt/building/custom/consts.consts.built.after.mir
index 7b6964849d4..a011fadcef1 100644
--- a/tests/mir-opt/building/custom/consts.consts.built.after.mir
+++ b/tests/mir-opt/building/custom/consts.consts.built.after.mir
@@ -10,7 +10,7 @@ fn consts() -> () {
 
     bb0: {
         _1 = const 5_u8;
-        _2 = const consts::<C>::{constant#1};
+        _2 = const consts::<C>::{constant#0};
         _3 = const C;
         _4 = const D;
         _5 = consts::<10>;
diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs
index 1a410177fa5..c64709082dc 100644
--- a/tests/mir-opt/building/custom/consts.rs
+++ b/tests/mir-opt/building/custom/consts.rs
@@ -9,14 +9,16 @@ const D: i32 = 5;
 // EMIT_MIR consts.consts.built.after.mir
 #[custom_mir(dialect = "built")]
 fn consts<const C: u32>() {
-    mir!({
-        let _a = 5_u8;
-        let _b = const { 5_i8 };
-        let _c = C;
-        let _d = D;
-        let _e = consts::<10>;
-        Return()
-    })
+    mir! {
+        {
+            let _a = 5_u8;
+            let _b = const { 5_i8 };
+            let _c = C;
+            let _d = D;
+            let _e = consts::<10>;
+            Return()
+        }
+    }
 }
 
 static S: i32 = 0x05050505;
@@ -24,11 +26,13 @@ static mut T: i32 = 0x0a0a0a0a;
 // EMIT_MIR consts.statics.built.after.mir
 #[custom_mir(dialect = "built")]
 fn statics() {
-    mir!({
-        let _a: &i32 = Static(S);
-        let _b: *mut i32 = StaticMut(T);
-        Return()
-    })
+    mir! {
+        {
+            let _a: &i32 = Static(S);
+            let _b: *mut i32 = StaticMut(T);
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs
index 3671a1ef061..5ab83fd4214 100644
--- a/tests/mir-opt/building/custom/debuginfo.rs
+++ b/tests/mir-opt/building/custom/debuginfo.rs
@@ -7,60 +7,62 @@ use core::intrinsics::mir::*;
 // EMIT_MIR debuginfo.pointee.built.after.mir
 #[custom_mir(dialect = "built")]
 fn pointee(opt: &mut Option<i32>) {
-    mir!(
+    mir! {
         debug foo => Field::<i32>(Variant(*opt, 1), 0);
         {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR debuginfo.numbered.built.after.mir
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn numbered(i: (u32, i32)) {
-    mir!(
+    mir! {
         debug first => i.0;
         debug second => i.0;
         {
             Return()
         }
-    )
+    }
 }
 
-struct S { x: f32 }
+struct S {
+    x: f32,
+}
 
 // EMIT_MIR debuginfo.structured.built.after.mir
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn structured(i: S) {
-    mir!(
+    mir! {
         debug x => i.x;
         {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR debuginfo.variant.built.after.mir
 #[custom_mir(dialect = "built")]
 fn variant(opt: Option<i32>) {
-    mir!(
+    mir! {
         debug inner => Field::<i32>(Variant(opt, 1), 0);
         {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR debuginfo.variant_deref.built.after.mir
 #[custom_mir(dialect = "built")]
 fn variant_deref(opt: Option<&i32>) {
-    mir!(
+    mir! {
         debug pointer => Field::<&i32>(Variant(opt, 1), 0);
         debug deref => *Field::<&i32>(Variant(opt, 1), 0);
         {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/enums.rs b/tests/mir-opt/building/custom/enums.rs
index 6aab1503c0a..88ec228986a 100644
--- a/tests/mir-opt/building/custom/enums.rs
+++ b/tests/mir-opt/building/custom/enums.rs
@@ -7,7 +7,7 @@ use core::intrinsics::mir::*;
 // EMIT_MIR enums.switch_bool.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn switch_bool(b: bool) -> u32 {
-    mir!(
+    mir! {
         {
             match b {
                 true => t,
@@ -25,13 +25,13 @@ pub fn switch_bool(b: bool) -> u32 {
             RET = 10;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR enums.switch_option.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn switch_option(option: Option<()>) -> bool {
-    mir!(
+    mir! {
         {
             let discr = Discriminant(option);
             match discr {
@@ -50,7 +50,7 @@ pub fn switch_option(option: Option<()>) -> bool {
             RET = true;
             Return()
         }
-    )
+    }
 }
 
 #[repr(u8)]
@@ -62,7 +62,7 @@ enum Bool {
 // EMIT_MIR enums.switch_option_repr.built.after.mir
 #[custom_mir(dialect = "built")]
 fn switch_option_repr(option: Bool) -> bool {
-    mir!(
+    mir! {
         {
             let discr = Discriminant(option);
             match discr {
@@ -80,26 +80,30 @@ fn switch_option_repr(option: Bool) -> bool {
             RET = false;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR enums.set_discr.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "initial")]
 fn set_discr(option: &mut Option<()>) {
-    mir!({
-        Deinit(*option);
-        SetDiscriminant(*option, 0);
-        Return()
-    })
+    mir! {
+        {
+            Deinit(*option);
+            SetDiscriminant(*option, 0);
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR enums.set_discr_repr.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "initial")]
 fn set_discr_repr(b: &mut Bool) {
-    mir!({
-        SetDiscriminant(*b, 0);
-        Return()
-    })
+    mir! {
+        {
+            SetDiscriminant(*b, 0);
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs
index ff0e8dcbb41..07abf2d9651 100644
--- a/tests/mir-opt/building/custom/operators.rs
+++ b/tests/mir-opt/building/custom/operators.rs
@@ -6,37 +6,41 @@ use std::intrinsics::mir::*;
 // EMIT_MIR operators.f.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn f(a: i32, b: bool) -> i32 {
-    mir!({
-        a = -a;
-        b = !b;
-        a = a + a;
-        a = a - a;
-        a = a * a;
-        a = a / a;
-        a = a % a;
-        a = a ^ a;
-        a = a & a;
-        a = a << a;
-        a = a >> a;
-        b = a == a;
-        b = a < a;
-        b = a <= a;
-        b = a >= a;
-        b = a > a;
-        let res = Checked(a + a);
-        b = res.1;
-        a = res.0;
-        RET = a;
-        Return()
-    })
+    mir! {
+        {
+            a = -a;
+            b = !b;
+            a = a + a;
+            a = a - a;
+            a = a * a;
+            a = a / a;
+            a = a % a;
+            a = a ^ a;
+            a = a & a;
+            a = a << a;
+            a = a >> a;
+            b = a == a;
+            b = a < a;
+            b = a <= a;
+            b = a >= a;
+            b = a > a;
+            let res = Checked(a + a);
+            b = res.1;
+            a = res.0;
+            RET = a;
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR operators.g.runtime.after.mir
 #[custom_mir(dialect = "runtime")]
 pub fn g(p: *const i32, q: *const [i32]) {
-    mir!({
-        let a = PtrMetadata(p);
-        let b = PtrMetadata(q);
-        Return()
-    })
+    mir! {
+        {
+            let a = PtrMetadata(p);
+            let b = PtrMetadata(q);
+            Return()
+        }
+    }
 }
diff --git a/tests/mir-opt/building/custom/projections.rs b/tests/mir-opt/building/custom/projections.rs
index ac23fe59097..0250b9b84b6 100644
--- a/tests/mir-opt/building/custom/projections.rs
+++ b/tests/mir-opt/building/custom/projections.rs
@@ -12,74 +12,84 @@ union U {
 // EMIT_MIR projections.unions.built.after.mir
 #[custom_mir(dialect = "built")]
 fn unions(u: U) -> i32 {
-    mir!({
-        RET = u.a;
-        Return()
-    })
+    mir! {
+        {
+            RET = u.a;
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR projections.tuples.built.after.mir
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn tuples(i: (u32, i32)) -> (u32, i32) {
-    mir!(
+    mir! {
         type RET = (u32, i32);
         {
             RET.0 = i.0;
             RET.1 = i.1;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR projections.unwrap.built.after.mir
 #[custom_mir(dialect = "built")]
 fn unwrap(opt: Option<i32>) -> i32 {
-    mir!({
-        RET = Field(Variant(opt, 1), 0);
-        Return()
-    })
+    mir! {
+        {
+            RET = Field(Variant(opt, 1), 0);
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR projections.unwrap_deref.built.after.mir
 #[custom_mir(dialect = "built")]
 fn unwrap_deref(opt: Option<&i32>) -> i32 {
-    mir!({
-        RET = *Field::<&i32>(Variant(opt, 1), 0);
-        Return()
-    })
+    mir! {
+        {
+            RET = *Field::<&i32>(Variant(opt, 1), 0);
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR projections.set.built.after.mir
 #[custom_mir(dialect = "built")]
 fn set(opt: &mut Option<i32>) {
-    mir!({
-        place!(Field(Variant(*opt, 1), 0)) = 10;
-        Return()
-    })
+    mir! {
+        {
+            place!(Field(Variant(*opt, 1), 0)) = 10;
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR projections.simple_index.built.after.mir
 #[custom_mir(dialect = "built")]
 fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
-    mir!({
-        let temp = 3;
-        RET = a[temp];
-        RET = (*b)[temp];
-        Return()
-    })
+    mir! {
+        {
+            let temp = 3;
+            RET = a[temp];
+            RET = (*b)[temp];
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR projections.copy_for_deref.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "initial")]
 fn copy_for_deref(x: (&i32, i32)) -> i32 {
-    mir!(
+    mir! {
         let temp: &i32;
         {
             temp = CopyForDeref(x.0);
             RET = *temp;
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/references.rs b/tests/mir-opt/building/custom/references.rs
index 04afe6e6494..7ea8f8b4c15 100644
--- a/tests/mir-opt/building/custom/references.rs
+++ b/tests/mir-opt/building/custom/references.rs
@@ -8,31 +8,29 @@ use core::ptr::{addr_of, addr_of_mut};
 // EMIT_MIR references.mut_ref.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn mut_ref(x: &mut i32) -> &mut i32 {
-    mir!(
+    mir! {
         let t: *mut i32;
-
         {
             t = addr_of_mut!(*x);
             RET = &mut *t;
             Retag(RET);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR references.immut_ref.built.after.mir
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn immut_ref(x: &i32) -> &i32 {
-    mir!(
+    mir! {
         let t: *const i32;
-
         {
             t = addr_of!(*x);
             RET = & *t;
             Retag(RET);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR references.raw_pointer.built.after.mir
@@ -40,19 +38,23 @@ pub fn immut_ref(x: &i32) -> &i32 {
 pub fn raw_pointer(x: *const i32) -> *const i32 {
     // Regression test for a bug in which unsafetyck was not correctly turned off for
     // `dialect = "built"`
-    mir!({
-        RET = addr_of!(*x);
-        Return()
-    })
+    mir! {
+        {
+            RET = addr_of!(*x);
+            Return()
+        }
+    }
 }
 
 // EMIT_MIR references.raw_pointer_offset.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn raw_pointer_offset(x: *const i32) -> *const i32 {
-    mir!({
-        RET = Offset(x, 1_isize);
-        Return()
-    })
+    mir! {
+        {
+            RET = Offset(x, 1_isize);
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/simple_assign.rs b/tests/mir-opt/building/custom/simple_assign.rs
index 8442272291e..d6d054ab5a3 100644
--- a/tests/mir-opt/building/custom/simple_assign.rs
+++ b/tests/mir-opt/building/custom/simple_assign.rs
@@ -7,32 +7,32 @@ use core::intrinsics::mir::*;
 // EMIT_MIR simple_assign.simple.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn simple(x: i32) -> i32 {
-    mir!(
+    mir! {
         let temp1: i32;
         let temp2: _;
-
         {
             StorageLive(temp1);
             temp1 = x;
             Goto(exit)
         }
-
         exit = {
             temp2 = Move(temp1);
             StorageDead(temp1);
             RET = temp2;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR simple_assign.simple_ref.built.after.mir
 #[custom_mir(dialect = "built")]
 pub fn simple_ref(x: &mut i32) -> &mut i32 {
-    mir!({
-        RET = Move(x);
-        Return()
-    })
+    mir! {
+        {
+            RET = Move(x);
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs
index 01c132cf3e7..a8e0b4b35bf 100644
--- a/tests/mir-opt/building/custom/terminators.rs
+++ b/tests/mir-opt/building/custom/terminators.rs
@@ -11,7 +11,7 @@ fn ident<T>(t: T) -> T {
 // EMIT_MIR terminators.direct_call.built.after.mir
 #[custom_mir(dialect = "built")]
 fn direct_call(x: i32) -> i32 {
-    mir!(
+    mir! {
         {
             Call(RET = ident(x), ReturnTo(retblock), UnwindContinue())
         }
@@ -19,21 +19,20 @@ fn direct_call(x: i32) -> i32 {
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR terminators.indirect_call.built.after.mir
 #[custom_mir(dialect = "built")]
 fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
-    mir!(
+    mir! {
         {
             Call(RET = f(x), ReturnTo(retblock), UnwindContinue())
         }
-
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 struct WriteOnDrop<'a>(&'a mut i32, i32);
@@ -47,51 +46,47 @@ impl<'a> Drop for WriteOnDrop<'a> {
 // EMIT_MIR terminators.drop_first.built.after.mir
 #[custom_mir(dialect = "built")]
 fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
-    mir!(
+    mir! {
         {
             Drop(a, ReturnTo(retblock), UnwindContinue())
         }
-
         retblock = {
             a = Move(b);
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR terminators.drop_second.built.after.mir
 #[custom_mir(dialect = "built")]
 fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
-    mir!(
+    mir! {
         {
             Drop(b, ReturnTo(retblock), UnwindContinue())
         }
-
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR terminators.assert_nonzero.built.after.mir
 #[custom_mir(dialect = "built")]
 fn assert_nonzero(a: i32) {
-    mir!(
+    mir! {
         {
             match a {
                 0 => unreachable,
                 _ => retblock
             }
         }
-
         unreachable = {
             Unreachable()
         }
-
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs
index e3d54c72145..87aab1ea70c 100644
--- a/tests/mir-opt/building/custom/unwind_action.rs
+++ b/tests/mir-opt/building/custom/unwind_action.rs
@@ -9,14 +9,14 @@ use core::intrinsics::mir::*;
 // CHECK-NEXT:  a() -> [return: bb1, unwind unreachable];
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn a() {
-    mir!(
+    mir! {
         {
             Call(RET = a(), ReturnTo(bb1), UnwindUnreachable())
         }
         bb1 = {
             Return()
         }
-    )
+    }
 }
 
 // CHECK-LABEL: fn b()
@@ -24,14 +24,14 @@ pub fn a() {
 // CHECK-NEXT:  b() -> [return: bb1, unwind continue];
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn b() {
-    mir!(
+    mir! {
         {
             Call(RET = b(), ReturnTo(bb1), UnwindContinue())
         }
         bb1 = {
             Return()
         }
-    )
+    }
 }
 
 // CHECK-LABEL: fn c()
@@ -39,14 +39,14 @@ pub fn b() {
 // CHECK-NEXT:  c() -> [return: bb1, unwind terminate(abi)];
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn c() {
-    mir!(
+    mir! {
         {
             Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi))
         }
         bb1 = {
             Return()
         }
-    )
+    }
 }
 
 // CHECK-LABEL: fn d()
@@ -54,7 +54,7 @@ pub fn c() {
 // CHECK-NEXT:  d() -> [return: bb1, unwind: bb2];
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn d() {
-    mir!(
+    mir! {
         {
             Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2))
         }
@@ -64,5 +64,5 @@ pub fn d() {
         bb2 (cleanup) = {
             UnwindResume()
         }
-    )
+    }
 }
diff --git a/tests/mir-opt/building/custom/unwind_terminate.rs b/tests/mir-opt/building/custom/unwind_terminate.rs
index c5374fa7b69..9b495d52387 100644
--- a/tests/mir-opt/building/custom/unwind_terminate.rs
+++ b/tests/mir-opt/building/custom/unwind_terminate.rs
@@ -8,14 +8,14 @@ use core::intrinsics::mir::*;
 // CHECK-NEXT:  terminate(abi);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn f() {
-    mir!(
+    mir! {
         {
             Return()
         }
         bb1(cleanup) = {
             UnwindTerminate(ReasonAbi)
         }
-    )
+    }
 }
 
 // CHECK-LABEL: fn g()
@@ -23,12 +23,12 @@ pub fn f() {
 // CHECK-NEXT:  terminate(cleanup);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn g() {
-    mir!(
+    mir! {
         {
             Return()
         }
         bb1(cleanup) = {
             UnwindTerminate(ReasonInCleanup)
         }
-    )
+    }
 }
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index df8e397c8fe..7ff0cdbfe8d 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -5,21 +5,24 @@
 // EMIT_MIR enum_cast.far.built.after.mir
 
 enum Foo {
-    A
+    A,
 }
 
 enum Bar {
-    A, B
+    A,
+    B,
 }
 
 #[repr(u8)]
 enum Boo {
-    A, B
+    A,
+    B,
 }
 
 #[repr(i16)]
 enum Far {
-    A, B
+    A,
+    B,
 }
 
 fn foo(foo: Foo) -> usize {
@@ -40,7 +43,9 @@ fn far(far: Far) -> isize {
 
 // EMIT_MIR enum_cast.droppy.built.after.mir
 enum Droppy {
-    A, B, C
+    A,
+    B,
+    C,
 }
 
 impl Drop for Droppy {
@@ -82,12 +87,15 @@ fn unsigny(x: UnsignedAroundZero) -> u16 {
     x as u16
 }
 
-enum NotStartingAtZero { A = 4, B = 6, C = 8 }
+enum NotStartingAtZero {
+    A = 4,
+    B = 6,
+    C = 8,
+}
 
 // EMIT_MIR enum_cast.offsetty.built.after.mir
 fn offsetty(x: NotStartingAtZero) -> u32 {
     x as u32
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/mir-opt/building/logical_or_in_conditional.rs b/tests/mir-opt/building/logical_or_in_conditional.rs
index deb841f2b0d..e6872e6f2ec 100644
--- a/tests/mir-opt/building/logical_or_in_conditional.rs
+++ b/tests/mir-opt/building/logical_or_in_conditional.rs
@@ -30,9 +30,13 @@ fn test_or() {
 
 // EMIT_MIR logical_or_in_conditional.test_complex.built.after.mir
 fn test_complex() {
-    if let E::A(_) = E::f() && ((always_true() && Droppy(0).0 > 0) || Droppy(1).0 > 1) {}
+    if let E::A(_) = E::f()
+        && ((always_true() && Droppy(0).0 > 0) || Droppy(1).0 > 1)
+    {}
 
-    if !always_true() && let E::B = E::f() {}
+    if !always_true()
+        && let E::B = E::f()
+    {}
 }
 
 fn main() {
diff --git a/tests/mir-opt/building/match/simple_match.rs b/tests/mir-opt/building/match/simple_match.rs
index 4f0a3046a06..61c337822c8 100644
--- a/tests/mir-opt/building/match/simple_match.rs
+++ b/tests/mir-opt/building/match/simple_match.rs
@@ -1,7 +1,6 @@
 // skip-filecheck
 // Test that we don't generate unnecessarily large MIR for very simple matches
 
-
 // EMIT_MIR simple_match.match_bool.built.after.mir
 fn match_bool(x: bool) -> usize {
     match x {
diff --git a/tests/mir-opt/building/match/sort_candidates.rs b/tests/mir-opt/building/match/sort_candidates.rs
index f207f0b3234..593a975a7a4 100644
--- a/tests/mir-opt/building/match/sort_candidates.rs
+++ b/tests/mir-opt/building/match/sort_candidates.rs
@@ -5,9 +5,9 @@ fn constant_eq(s: &str, b: bool) -> u32 {
     // Check that we only test "a" once
 
     // CHECK-LABEL: fn constant_eq(
-    // CHECK: bb0: {
-    // CHECK: [[a:_.*]] = const "a";
-    // CHECK-NOT: {{_.*}} = const "a";
+    // CHECK-NOT: const "a"
+    // CHECK: {{_[0-9]+}} = const "a" as &[u8] (Transmute);
+    // CHECK-NOT: const "a"
     match (s, b) {
         ("a", _) if true => 1,
         ("b", true) => 2,
diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs
index 849d7b55f3a..d7747bb2f78 100644
--- a/tests/mir-opt/building/shifts.rs
+++ b/tests/mir-opt/building/shifts.rs
@@ -3,19 +3,12 @@
 
 // EMIT_MIR shifts.shift_signed.built.after.mir
 fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) {
-    (
-        [small >> a, small >> b, small >> c],
-        [big << a, big << b, big << c],
-    )
+    ([small >> a, small >> b, small >> c], [big << a, big << b, big << c])
 }
 
 // EMIT_MIR shifts.shift_unsigned.built.after.mir
 fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) {
-    (
-        [small >> a, small >> b, small >> c],
-        [big << a, big << b, big << c],
-    )
+    ([small >> a, small >> b, small >> c], [big << a, big << b, big << c])
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.rs b/tests/mir-opt/building/storage_live_dead_in_statics.rs
index 1f569211854..7cb74acbf06 100644
--- a/tests/mir-opt/building/storage_live_dead_in_statics.rs
+++ b/tests/mir-opt/building/storage_live_dead_in_statics.rs
@@ -3,6 +3,7 @@
 // generate `StorageStart` or `StorageEnd` statements.
 
 // EMIT_MIR storage_live_dead_in_statics.XXX.built.after.mir
+#[rustfmt::skip]
 static XXX: &'static Foo = &Foo {
     tup: "hi",
     data: &[
@@ -20,13 +21,13 @@ static XXX: &'static Foo = &Foo {
         (0, 1), (0, 2), (0, 3),
         (0, 1), (0, 2), (0, 3),
         (0, 1), (0, 2), (0, 3),
-    ]
+    ],
 };
 
 #[derive(Debug)]
 struct Foo {
     tup: &'static str,
-    data: &'static [(u32, u32)]
+    data: &'static [(u32, u32)],
 }
 
 fn main() {
diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff
index c1529dbee13..ac33f51984c 100644
--- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
+++ b/tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff
@@ -1,5 +1,5 @@
-- // MIR for `main` before ConstDebugInfo
-+ // MIR for `main` after ConstDebugInfo
+- // MIR for `main` before SingleUseConsts
++ // MIR for `main` after SingleUseConsts
   
   fn main() -> () {
       let mut _0: ();
@@ -56,39 +56,53 @@
   
       bb0: {
           nop;
-          _1 = const 1_u8;
+-         _1 = const 1_u8;
           nop;
-          _2 = const 2_u8;
+-         _2 = const 2_u8;
           nop;
-          _3 = const 3_u8;
+-         _3 = const 3_u8;
++         nop;
++         nop;
++         nop;
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
-          _6 = const 1_u8;
+-         _6 = const 1_u8;
++         nop;
           StorageLive(_7);
-          _7 = const 2_u8;
-          _5 = const 3_u8;
+-         _7 = const 2_u8;
+-         _5 = const 3_u8;
++         nop;
++         nop;
           StorageDead(_7);
           StorageDead(_6);
           StorageLive(_8);
-          _8 = const 3_u8;
-          _4 = const 6_u8;
+-         _8 = const 3_u8;
+-         _4 = const 6_u8;
++         nop;
++         nop;
           StorageDead(_8);
           StorageDead(_5);
           StorageLive(_9);
-          _9 = const "hello, world!";
+-         _9 = const "hello, world!";
++         nop;
           StorageLive(_10);
           _10 = (const true, const false, const 123_u32);
           StorageLive(_11);
-          _11 = const Option::<u16>::Some(99_u16);
+-         _11 = const Option::<u16>::Some(99_u16);
++         nop;
           StorageLive(_12);
-          _12 = const Point {{ x: 32_u32, y: 32_u32 }};
+-         _12 = const Point {{ x: 32_u32, y: 32_u32 }};
++         nop;
           StorageLive(_13);
           nop;
-          _14 = const 32_u32;
+-         _14 = const 32_u32;
++         nop;
           StorageLive(_15);
-          _15 = const 32_u32;
-          _13 = const 64_u32;
+-         _15 = const 32_u32;
+-         _13 = const 64_u32;
++         nop;
++         nop;
           StorageDead(_15);
           nop;
           _0 = const ();
diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs
index b880d7e07a6..907d7fef067 100644
--- a/tests/mir-opt/const_debuginfo.rs
+++ b/tests/mir-opt/const_debuginfo.rs
@@ -1,12 +1,14 @@
-//@ test-mir-pass: ConstDebugInfo
+//@ test-mir-pass: SingleUseConsts
 //@ compile-flags: -C overflow-checks=no -Zmir-enable-passes=+GVN
 
+#![allow(unused)]
+
 struct Point {
     x: u32,
     y: u32,
 }
 
-// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff
+// EMIT_MIR const_debuginfo.main.SingleUseConsts.diff
 fn main() {
     // CHECK-LABEL: fn main(
     // CHECK: debug x => const 1_u8;
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs
index 39b5f289830..64605ca11c2 100644
--- a/tests/mir-opt/const_prop/control_flow_simplification.rs
+++ b/tests/mir-opt/const_prop/control_flow_simplification.rs
@@ -11,7 +11,7 @@ impl<This> NeedsDrop for This {}
 
 // EMIT_MIR control_flow_simplification.hello.GVN.diff
 // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir
-fn hello<T>(){
+fn hello<T>() {
     if <bool>::NEEDS {
         panic!()
     }
diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs
index 2b7271f63ff..91ee36ae2c5 100644
--- a/tests/mir-opt/const_prop/invalid_constant.rs
+++ b/tests/mir-opt/const_prop/invalid_constant.rs
@@ -8,7 +8,11 @@
 
 #[derive(Copy, Clone)]
 #[repr(u32)]
-enum E { A, B, C }
+enum E {
+    A,
+    B,
+    C,
+}
 
 #[derive(Copy, Clone)]
 enum Empty {}
@@ -39,7 +43,5 @@ fn main() {
 
     // A non-UTF-8 string slice. Regression test for #75763 and #78520.
     struct Str<const S: &'static str>;
-    let _non_utf8_str: Str::<{
-        unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) }
-    }>;
+    let _non_utf8_str: Str<{ unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } }>;
 }
diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs
index 105cbfb53dd..264c8a3d21c 100644
--- a/tests/mir-opt/const_prop/offset_of.rs
+++ b/tests/mir-opt/const_prop/offset_of.rs
@@ -31,7 +31,7 @@ struct Delta<T> {
 enum Epsilon {
     A(u8, u16),
     B,
-    C { c: u32 }
+    C { c: u32 },
 }
 
 enum Zeta<T> {
diff --git a/tests/mir-opt/const_prop/pointer_expose_provenance.rs b/tests/mir-opt/const_prop/pointer_expose_provenance.rs
index f148a5b6542..a76fead9859 100644
--- a/tests/mir-opt/const_prop/pointer_expose_provenance.rs
+++ b/tests/mir-opt/const_prop/pointer_expose_provenance.rs
@@ -2,7 +2,7 @@
 //@ test-mir-pass: GVN
 
 #[inline(never)]
-fn read(_: usize) { }
+fn read(_: usize) {}
 
 // EMIT_MIR pointer_expose_provenance.main.GVN.diff
 fn main() {
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
index 9d02f24e76b..15e32490de4 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
@@ -10,4 +10,4 @@ fn main() {
 }
 
 #[inline(never)]
-fn consume(_: u32) { }
+fn consume(_: u32) {}
diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs
index 114380e316d..4ee4182caf6 100644
--- a/tests/mir-opt/const_prop/switch_int.rs
+++ b/tests/mir-opt/const_prop/switch_int.rs
@@ -3,7 +3,7 @@
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #[inline(never)]
-fn foo(_: i32) { }
+fn foo(_: i32) {}
 
 // EMIT_MIR switch_int.main.GVN.diff
 // EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff
diff --git a/tests/mir-opt/const_prop/transmute.rs b/tests/mir-opt/const_prop/transmute.rs
index 9cbf8928753..892b91a5414 100644
--- a/tests/mir-opt/const_prop/transmute.rs
+++ b/tests/mir-opt/const_prop/transmute.rs
@@ -45,7 +45,10 @@ pub unsafe fn undef_union_as_integer() -> u32 {
     // CHECK-LABEL: fn undef_union_as_integer(
     // CHECK: _1 = Union32 {
     // CHECK: _0 = move _1 as u32 (Transmute);
-    union Union32 { value: u32, unit: () }
+    union Union32 {
+        value: u32,
+        unit: (),
+    }
     unsafe { transmute(Union32 { unit: () }) }
 }
 
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
index 582411c7b59..e42a62cb6fd 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
@@ -10,4 +10,4 @@ fn main() {
 }
 
 #[inline(never)]
-fn consume(_: (u32, u32)) { }
+fn consume(_: (u32, u32)) {}
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index 512287dd176..dd1679513f6 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -4,10 +4,12 @@
 #![feature(custom_mir, core_intrinsics, freeze)]
 #![allow(unused_assignments)]
 extern crate core;
-use core::marker::Freeze;
 use core::intrinsics::mir::*;
+use core::marker::Freeze;
 
-fn opaque(_: impl Sized) -> bool { true }
+fn opaque(_: impl Sized) -> bool {
+    true
+}
 
 fn cmp_ref(a: &u8, b: &u8) -> bool {
     std::ptr::eq(a as *const u8, b as *const u8)
@@ -24,7 +26,7 @@ fn compare_address() -> bool {
     // CHECK-NEXT: _0 = cmp_ref(_2, _4)
     // CHECK: bb1: {
     // CHECK-NEXT: _0 = opaque::<u8>(_3)
-    mir!(
+    mir! {
         {
             let a = 5_u8;
             let r1 = &a;
@@ -40,7 +42,7 @@ fn compare_address() -> bool {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 /// Generic type `T` is `Freeze`, so shared borrows are immutable.
@@ -52,7 +54,7 @@ fn borrowed<T: Copy + Freeze>(x: T) -> bool {
     // CHECK-NEXT: _0 = opaque::<&T>(_3)
     // CHECK: bb1: {
     // CHECK-NEXT: _0 = opaque::<T>(_1)
-    mir!(
+    mir! {
         {
             let a = x;
             let r1 = &x;
@@ -64,7 +66,7 @@ fn borrowed<T: Copy + Freeze>(x: T) -> bool {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 /// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
@@ -77,7 +79,7 @@ fn non_freeze<T: Copy>(x: T) -> bool {
     // CHECK-NEXT: _0 = opaque::<&T>(_3)
     // CHECK: bb1: {
     // CHECK-NEXT: _0 = opaque::<T>(_2)
-    mir!(
+    mir! {
         {
             let a = x;
             let r1 = &x;
@@ -89,7 +91,7 @@ fn non_freeze<T: Copy>(x: T) -> bool {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
index a82d4618e68..3dce7807b34 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.rs
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -12,17 +12,19 @@ struct NotCopy(bool);
 // EMIT_MIR custom_move_arg.f.CopyProp.diff
 #[custom_mir(dialect = "runtime")]
 fn f(_1: NotCopy) {
-    mir!({
-        let _2 = _1;
-        Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable())
+    mir! {
+        {
+            let _2 = _1;
+            Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable())
+        }
+        bb1 = {
+            let _3 = Move(_2);
+            Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable())
+        }
+        bb2 = {
+            Return()
+        }
     }
-    bb1 = {
-        let _3 = Move(_2);
-        Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable())
-    }
-    bb2 = {
-        Return()
-    })
 }
 
 #[inline(never)]
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
index 231e4082e33..0ac1c4e0ba2 100644
--- a/tests/mir-opt/copy-prop/move_projection.rs
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -7,13 +7,15 @@
 extern crate core;
 use core::intrinsics::mir::*;
 
-fn opaque(_: impl Sized) -> bool { true }
+fn opaque(_: impl Sized) -> bool {
+    true
+}
 
 struct Foo(u8);
 
 #[custom_mir(dialect = "runtime")]
 fn f(a: Foo) -> bool {
-    mir!(
+    mir! {
         {
             let b = a;
             // This is a move out of a copy, so must become a copy of `a.0`.
@@ -26,7 +28,7 @@ fn f(a: Foo) -> bool {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.rs b/tests/mir-opt/copy-prop/mutate_through_pointer.rs
index 14ca513c692..53cca045248 100644
--- a/tests/mir-opt/copy-prop/mutate_through_pointer.rs
+++ b/tests/mir-opt/copy-prop/mutate_through_pointer.rs
@@ -18,14 +18,16 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn f(c: bool) -> bool {
-    mir!({
-        let a = c;
-        let p = core::ptr::addr_of!(a);
-        let p2 = core::ptr::addr_of_mut!(*p);
-        *p2 = false;
-        RET = c;
-        Return()
-    })
+    mir! {
+        {
+            let a = c;
+            let p = core::ptr::addr_of!(a);
+            let p2 = core::ptr::addr_of_mut!(*p);
+            *p2 = false;
+            RET = c;
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/copy-prop/non_dominate.rs b/tests/mir-opt/copy-prop/non_dominate.rs
index 34e7eabc81a..c01275370ea 100644
--- a/tests/mir-opt/copy-prop/non_dominate.rs
+++ b/tests/mir-opt/copy-prop/non_dominate.rs
@@ -8,16 +8,28 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn f(c: bool) -> bool {
-    mir!(
+    mir! {
         let a: bool;
         let b: bool;
-        { Goto(bb1) }
-        bb1 = { b = c; match b { false => bb3, _ => bb2 }}
+        {
+            Goto(bb1)
+        }
+        bb1 = {
+            b = c;
+            match b { false => bb3, _ => bb2 }
+        }
         // This assignment to `a` does not dominate the use in `bb3`.
         // It should not be replaced by `b`.
-        bb2 = { a = b; c = false; Goto(bb1) }
-        bb3 = { RET = a; Return() }
-    )
+        bb2 = {
+            a = b;
+            c = false;
+            Goto(bb1)
+        }
+        bb3 = {
+            RET = a;
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs
index 5c52f92cd8f..946cfa4c76c 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.rs
+++ b/tests/mir-opt/dataflow-const-prop/enum.rs
@@ -8,7 +8,7 @@ use std::intrinsics::mir::*;
 #[derive(Copy, Clone)]
 enum E {
     V1(i32),
-    V2(i32)
+    V2(i32),
 }
 
 // EMIT_MIR enum.simple.DataflowConstProp.diff
@@ -23,7 +23,10 @@ fn simple() {
     // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
     // CHECK: [[target_bb]]: {
     // CHECK:     [[x]] = const 0_i32;
-    let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 };
+    let x = match e {
+        E::V1(x1) => x1,
+        E::V2(x2) => x2,
+    };
 }
 
 // EMIT_MIR enum.constant.DataflowConstProp.diff
@@ -39,7 +42,10 @@ fn constant() {
     // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
     // CHECK: [[target_bb]]: {
     // CHECK:     [[x]] = const 0_i32;
-    let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 };
+    let x = match e {
+        E::V1(x1) => x1,
+        E::V2(x2) => x2,
+    };
 }
 
 // EMIT_MIR enum.statics.DataflowConstProp.diff
@@ -58,7 +64,10 @@ fn statics() {
     // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
     // CHECK: [[target_bb]]: {
     // CHECK:     [[x1]] = const 0_i32;
-    let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 };
+    let x1 = match e1 {
+        E::V1(x11) => x11,
+        E::V2(x12) => x12,
+    };
 
     static RC: &E = &E::V2(4);
 
@@ -72,7 +81,10 @@ fn statics() {
     // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can
     // get by printing MIR directly. It is better to check if there are any bugs in the
     // MIR passes around this stage.
-    let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 };
+    let x2 = match e2 {
+        E::V1(x21) => x21,
+        E::V2(x22) => x22,
+    };
 }
 
 #[rustc_layout_scalar_valid_range_start(1)]
@@ -84,7 +96,7 @@ struct NonZeroUsize(usize);
 // CHECK-LABEL: fn mutate_discriminant(
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn mutate_discriminant() -> u8 {
-    mir!(
+    mir! {
         let x: Option<NonZeroUsize>;
         {
             SetDiscriminant(x, 1);
@@ -109,7 +121,7 @@ fn mutate_discriminant() -> u8 {
             RET = 2;
             Unreachable()
         }
-    )
+    }
 }
 
 // EMIT_MIR enum.multiple.DataflowConstProp.diff
@@ -132,7 +144,10 @@ fn multiple(x: bool, i: u8) {
     // CHECK: [[x2]] = const 0_u8;
     // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8)
     // CHECK: [[x2]] = [[some]];
-    let x2 = match e { Some(i) => i, None => 0 };
+    let x2 = match e {
+        Some(i) => i,
+        None => 0,
+    };
 
     // Therefore, `x2` should be `Top` here, and no replacement shall happen.
 
diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs
index 3cd0b715a52..26f79c8c0e4 100644
--- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs
+++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs
@@ -2,9 +2,9 @@
 
 // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff
 // CHECK-LABEL: fn test(
-fn test(x : i32) -> i32 {
-  x * 0
-  // CHECK: _0 = const 0_i32;
+fn test(x: i32) -> i32 {
+    x * 0
+    // CHECK: _0 = const 0_i32;
 }
 
 fn main() {
diff --git a/tests/mir-opt/dataflow-const-prop/transmute.rs b/tests/mir-opt/dataflow-const-prop/transmute.rs
index e7f93f421cf..d0391f6974b 100644
--- a/tests/mir-opt/dataflow-const-prop/transmute.rs
+++ b/tests/mir-opt/dataflow-const-prop/transmute.rs
@@ -45,7 +45,10 @@ pub unsafe fn undef_union_as_integer() -> u32 {
     // CHECK-LABEL: fn undef_union_as_integer(
     // CHECK: _1 = Union32 {
     // CHECK: _0 = move _1 as u32 (Transmute);
-    union Union32 { value: u32, unit: () }
+    union Union32 {
+        value: u32,
+        unit: (),
+    }
     unsafe { transmute(Union32 { unit: () }) }
 }
 
diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs
index edb35061cc6..2556848ec46 100644
--- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs
+++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs
@@ -29,7 +29,7 @@ struct Packed {
 fn move_packed(packed: Packed) {
     // CHECK-LABEL: fn move_packed(
     // CHECK: = use_both(const 0_i32, (_1.1: i32))
-    mir!(
+    mir! {
         {
             // We have a packed struct, verify that the copy is not turned into a move.
             Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue())
@@ -37,7 +37,7 @@ fn move_packed(packed: Packed) {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs
index 795d57d36f5..c8f0c2644ab 100644
--- a/tests/mir-opt/dead-store-elimination/cycle.rs
+++ b/tests/mir-opt/dead-store-elimination/cycle.rs
@@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
     // CHECK-NOT: {{_.*}} = move {{_.*}};
 
     // We use custom MIR to avoid generating debuginfo, that would force to preserve writes.
-    mir!(
+    mir! {
         let condition: bool;
         {
             Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
@@ -38,7 +38,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/derefer_complex_case.rs b/tests/mir-opt/derefer_complex_case.rs
index b1fa2c8733e..96034522b9f 100644
--- a/tests/mir-opt/derefer_complex_case.rs
+++ b/tests/mir-opt/derefer_complex_case.rs
@@ -4,5 +4,7 @@
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 fn main() {
-    for &foo in &[42, 43] { drop(foo) }
+    for &foo in &[42, 43] {
+        drop(foo)
+    }
 }
diff --git a/tests/mir-opt/derefer_terminator_test.rs b/tests/mir-opt/derefer_terminator_test.rs
index 5de6a61eaf2..fd16c6c2045 100644
--- a/tests/mir-opt/derefer_terminator_test.rs
+++ b/tests/mir-opt/derefer_terminator_test.rs
@@ -7,7 +7,9 @@ fn main() {
     let b = foo();
     let d = foo();
     match ****(&&&&b) {
-        true => {let x = 5;},
+        true => {
+            let x = 5;
+        }
         false => {}
     }
     let y = 42;
diff --git a/tests/mir-opt/derefer_test.rs b/tests/mir-opt/derefer_test.rs
index 3ca2144e4fc..5676fa657fe 100644
--- a/tests/mir-opt/derefer_test.rs
+++ b/tests/mir-opt/derefer_test.rs
@@ -2,7 +2,7 @@
 //@ test-mir-pass: Derefer
 // EMIT_MIR derefer_test.main.Derefer.diff
 fn main() {
-    let mut a = (42,43);
+    let mut a = (42, 43);
     let mut b = (99, &mut a);
     let x = &mut (*b.1).0;
     let y = &mut (*b.1).1;
diff --git a/tests/mir-opt/derefer_test_multiple.rs b/tests/mir-opt/derefer_test_multiple.rs
index 145a19ee6a3..7c03af00e1e 100644
--- a/tests/mir-opt/derefer_test_multiple.rs
+++ b/tests/mir-opt/derefer_test_multiple.rs
@@ -1,7 +1,7 @@
 // skip-filecheck
 //@ test-mir-pass: Derefer
 // EMIT_MIR derefer_test_multiple.main.Derefer.diff
-fn main () {
+fn main() {
     let mut a = (42, 43);
     let mut b = (99, &mut a);
     let mut c = (11, &mut b);
diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff
index 570ec129f06..b596e25ddfd 100644
--- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff
+++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff
@@ -18,7 +18,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _2 = const 1_u32;
+          nop;
           _1 = Un { us: const 1_u32 };
           StorageDead(_2);
           StorageLive(_3);
diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff
index 570ec129f06..b596e25ddfd 100644
--- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff
+++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff
@@ -18,7 +18,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _2 = const 1_u32;
+          nop;
           _1 = Un { us: const 1_u32 };
           StorageDead(_2);
           StorageLive(_3);
diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs
index cacc7301f12..2cc5df84d6b 100644
--- a/tests/mir-opt/enum_opt.rs
+++ b/tests/mir-opt/enum_opt.rs
@@ -7,22 +7,22 @@
 
 // Tests that an enum with a variant with no data gets correctly transformed.
 pub enum NoData {
-  Large([u8; 8196]),
-  None,
+    Large([u8; 8196]),
+    None,
 }
 
 // Tests that an enum with a variant with data that is a valid candidate gets transformed.
 pub enum Candidate {
-  Small(u8),
-  Large([u8; 8196]),
+    Small(u8),
+    Large([u8; 8196]),
 }
 
 // Tests that an enum which has a discriminant much higher than the variant does not get
 // tformed.
 #[repr(u32)]
 pub enum InvalidIdxs {
-  A = 302,
-  Large([u64; 1024]),
+    A = 302,
+    Large([u64; 1024]),
 }
 
 // Tests that an enum with too high of a discriminant index (not in bounds of usize) does not
@@ -37,51 +37,51 @@ pub enum NotTrunctable {
 // Tests that an enum with discriminants in random order still gets tformed correctly.
 #[repr(u32)]
 pub enum RandOrderDiscr {
-  A = 13,
-  B([u8; 1024]) = 5,
-  C = 7,
+    A = 13,
+    B([u8; 1024]) = 5,
+    C = 7,
 }
 
 // EMIT_MIR enum_opt.unin.EnumSizeOpt.diff
 pub fn unin() -> NoData {
-  let mut a = NoData::None;
-  a = NoData::Large([1; 8196]);
-  a
+    let mut a = NoData::None;
+    a = NoData::Large([1; 8196]);
+    a
 }
 
 // EMIT_MIR enum_opt.cand.EnumSizeOpt.diff
 pub fn cand() -> Candidate {
-  let mut a = Candidate::Small(1);
-  a = Candidate::Large([1; 8196]);
-  a
+    let mut a = Candidate::Small(1);
+    a = Candidate::Large([1; 8196]);
+    a
 }
 
 // EMIT_MIR enum_opt.invalid.EnumSizeOpt.diff
 pub fn invalid() -> InvalidIdxs {
-  let mut a = InvalidIdxs::A;
-  a = InvalidIdxs::Large([0; 1024]);
-  a
+    let mut a = InvalidIdxs::A;
+    a = InvalidIdxs::Large([0; 1024]);
+    a
 }
 
 // EMIT_MIR enum_opt.trunc.EnumSizeOpt.diff
 pub fn trunc() -> NotTrunctable {
-  let mut a = NotTrunctable::A;
-  a = NotTrunctable::B([0; 1024]);
-  a = NotTrunctable::C([0; 4096]);
-  a
+    let mut a = NotTrunctable::A;
+    a = NotTrunctable::B([0; 1024]);
+    a = NotTrunctable::C([0; 4096]);
+    a
 }
 
 pub fn rand_order() -> RandOrderDiscr {
-  let mut a = RandOrderDiscr::A;
-  a = RandOrderDiscr::B([0; 1024]);
-  a = RandOrderDiscr::C;
-  a
+    let mut a = RandOrderDiscr::A;
+    a = RandOrderDiscr::B([0; 1024]);
+    a = RandOrderDiscr::C;
+    a
 }
 
 pub fn main() {
-  unin();
-  cand();
-  invalid();
-  trunc();
-  rand_order();
+    unin();
+    cand();
+    invalid();
+    trunc();
+    rand_order();
 }
diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff
new file mode 100644
index 00000000000..6e5bdb16595
--- /dev/null
+++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff
@@ -0,0 +1,60 @@
+- // MIR for `casts_before_aggregate_raw_ptr` before GVN
++ // MIR for `casts_before_aggregate_raw_ptr` after GVN
+  
+  fn casts_before_aggregate_raw_ptr(_1: *const u32) -> *const [u8] {
+      debug x => _1;
+      let mut _0: *const [u8];
+      let _2: *const [u8; 4];
+      let mut _3: *const u32;
+      let mut _5: *const [u8; 4];
+      let mut _7: *const u8;
+      let mut _8: *const ();
+      scope 1 {
+          debug x => _2;
+          let _4: *const u8;
+          scope 2 {
+              debug x => _4;
+              let _6: *const ();
+              scope 3 {
+                  debug x => _6;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = move _3 as *const [u8; 4] (PtrToPtr);
++         _2 = _1 as *const [u8; 4] (PtrToPtr);
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          StorageLive(_5);
+          _5 = _2;
+-         _4 = move _5 as *const u8 (PtrToPtr);
++         _4 = _1 as *const u8 (PtrToPtr);
+          StorageDead(_5);
+-         StorageLive(_6);
++         nop;
+          StorageLive(_7);
+          _7 = _4;
+-         _6 = move _7 as *const () (PtrToPtr);
++         _6 = _1 as *const () (PtrToPtr);
+          StorageDead(_7);
+          StorageLive(_8);
+          _8 = _6;
+-         _0 = *const [u8] from (move _8, const 4_usize);
++         _0 = *const [u8] from (_1, const 4_usize);
+          StorageDead(_8);
+-         StorageDead(_6);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..6e5bdb16595
--- /dev/null
+++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff
@@ -0,0 +1,60 @@
+- // MIR for `casts_before_aggregate_raw_ptr` before GVN
++ // MIR for `casts_before_aggregate_raw_ptr` after GVN
+  
+  fn casts_before_aggregate_raw_ptr(_1: *const u32) -> *const [u8] {
+      debug x => _1;
+      let mut _0: *const [u8];
+      let _2: *const [u8; 4];
+      let mut _3: *const u32;
+      let mut _5: *const [u8; 4];
+      let mut _7: *const u8;
+      let mut _8: *const ();
+      scope 1 {
+          debug x => _2;
+          let _4: *const u8;
+          scope 2 {
+              debug x => _4;
+              let _6: *const ();
+              scope 3 {
+                  debug x => _6;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = move _3 as *const [u8; 4] (PtrToPtr);
++         _2 = _1 as *const [u8; 4] (PtrToPtr);
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          StorageLive(_5);
+          _5 = _2;
+-         _4 = move _5 as *const u8 (PtrToPtr);
++         _4 = _1 as *const u8 (PtrToPtr);
+          StorageDead(_5);
+-         StorageLive(_6);
++         nop;
+          StorageLive(_7);
+          _7 = _4;
+-         _6 = move _7 as *const () (PtrToPtr);
++         _6 = _1 as *const () (PtrToPtr);
+          StorageDead(_7);
+          StorageLive(_8);
+          _8 = _6;
+-         _0 = *const [u8] from (move _8, const 4_usize);
++         _0 = *const [u8] from (_1, const 4_usize);
+          StorageDead(_8);
+-         StorageDead(_6);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff
new file mode 100644
index 00000000000..73dbabb56b3
--- /dev/null
+++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff
@@ -0,0 +1,32 @@
+- // MIR for `meta_of_ref_to_slice` before GVN
++ // MIR for `meta_of_ref_to_slice` after GVN
+  
+  fn meta_of_ref_to_slice(_1: *const i32) -> usize {
+      debug x => _1;
+      let mut _0: usize;
+      let _2: *const [i32];
+      let mut _3: *const i32;
+      let mut _4: *const [i32];
+      scope 1 {
+          debug ptr => _2;
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = *const [i32] from (move _3, const 1_usize);
++         _2 = *const [i32] from (_1, const 1_usize);
+          StorageDead(_3);
+          StorageLive(_4);
+          _4 = _2;
+-         _0 = PtrMetadata(move _4);
++         _0 = const 1_usize;
+          StorageDead(_4);
+-         StorageDead(_2);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..73dbabb56b3
--- /dev/null
+++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff
@@ -0,0 +1,32 @@
+- // MIR for `meta_of_ref_to_slice` before GVN
++ // MIR for `meta_of_ref_to_slice` after GVN
+  
+  fn meta_of_ref_to_slice(_1: *const i32) -> usize {
+      debug x => _1;
+      let mut _0: usize;
+      let _2: *const [i32];
+      let mut _3: *const i32;
+      let mut _4: *const [i32];
+      scope 1 {
+          debug ptr => _2;
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = *const [i32] from (move _3, const 1_usize);
++         _2 = *const [i32] from (_1, const 1_usize);
+          StorageDead(_3);
+          StorageLive(_4);
+          _4 = _2;
+-         _0 = PtrMetadata(move _4);
++         _0 = const 1_usize;
+          StorageDead(_4);
+-         StorageDead(_2);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 9be30515283..720018f112e 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -539,7 +539,7 @@ fn slices() {
 #[custom_mir(dialect = "analysis")]
 fn duplicate_slice() -> (bool, bool) {
     // CHECK-LABEL: fn duplicate_slice(
-    mir!(
+    mir! {
         let au: u128;
         let bu: u128;
         let cu: u128;
@@ -585,7 +585,7 @@ fn duplicate_slice() -> (bool, bool) {
             RET = (direct, indirect);
             Return()
         }
-    )
+    }
 }
 
 fn repeat() {
@@ -623,11 +623,13 @@ fn fn_pointers() {
 fn indirect_static() {
     static A: Option<u8> = None;
 
-    mir!({
-        let ptr = Static(A);
-        let out = Field::<u8>(Variant(*ptr, 1), 0);
-        Return()
-    })
+    mir! {
+        {
+            let ptr = Static(A);
+            let out = Field::<u8>(Variant(*ptr, 1), 0);
+            Return()
+        }
+    }
 }
 
 /// Verify that having constant index `u64::MAX` does not yield to an overflow in rustc.
@@ -733,7 +735,7 @@ fn borrowed<T: Copy + Freeze>(x: T) {
     // CHECK-NEXT: _0 = opaque::<T>(_1)
     // CHECK: bb2: {
     // CHECK-NEXT: _0 = opaque::<T>(_1)
-    mir!(
+    mir! {
         {
             let a = x;
             let r1 = &x;
@@ -748,7 +750,7 @@ fn borrowed<T: Copy + Freeze>(x: T) {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 /// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
@@ -763,7 +765,7 @@ fn non_freeze<T: Copy>(x: T) {
     // CHECK-NEXT: _0 = opaque::<T>(_2)
     // CHECK: bb2: {
     // CHECK-NEXT: _0 = opaque::<T>((*_3))
-    mir!(
+    mir! {
         {
             let a = x;
             let r1 = &x;
@@ -778,7 +780,40 @@ fn non_freeze<T: Copy>(x: T) {
         ret = {
             Return()
         }
-    )
+    }
+}
+
+// Check that we can const-prop into `from_raw_parts`
+fn slice_const_length(x: &[i32]) -> *const [i32] {
+    // CHECK-LABEL: fn slice_const_length(
+    // CHECK: _0 = *const [i32] from ({{_[0-9]+}}, const 123_usize);
+    let ptr = x.as_ptr();
+    let len = 123;
+    std::intrinsics::aggregate_raw_ptr(ptr, len)
+}
+
+fn meta_of_ref_to_slice(x: *const i32) -> usize {
+    // CHECK-LABEL: fn meta_of_ref_to_slice
+    // CHECK: _0 = const 1_usize
+    let ptr: *const [i32] = std::intrinsics::aggregate_raw_ptr(x, 1);
+    std::intrinsics::ptr_metadata(ptr)
+}
+
+fn slice_from_raw_parts_as_ptr(x: *const u16, n: usize) -> (*const u16, *const f32) {
+    // CHECK-LABEL: fn slice_from_raw_parts_as_ptr
+    // CHECK: _8 = _1 as *const f32 (PtrToPtr);
+    // CHECK: _0 = (_1, move _8);
+    let ptr: *const [u16] = std::intrinsics::aggregate_raw_ptr(x, n);
+    (ptr as *const u16, ptr as *const f32)
+}
+
+fn casts_before_aggregate_raw_ptr(x: *const u32) -> *const [u8] {
+    // CHECK-LABEL: fn casts_before_aggregate_raw_ptr
+    // CHECK: _0 = *const [u8] from (_1, const 4_usize);
+    let x = x as *const [u8; 4];
+    let x = x as *const u8;
+    let x = x as *const ();
+    std::intrinsics::aggregate_raw_ptr(x, 4)
 }
 
 fn main() {
@@ -805,6 +840,9 @@ fn main() {
     wide_ptr_integer();
     borrowed(5);
     non_freeze(5);
+    slice_const_length(&[1]);
+    meta_of_ref_to_slice(&42);
+    slice_from_raw_parts_as_ptr(&123, 456);
 }
 
 #[inline(never)]
@@ -838,3 +876,7 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.wide_ptr_integer.GVN.diff
 // EMIT_MIR gvn.borrowed.GVN.diff
 // EMIT_MIR gvn.non_freeze.GVN.diff
+// EMIT_MIR gvn.slice_const_length.GVN.diff
+// EMIT_MIR gvn.meta_of_ref_to_slice.GVN.diff
+// EMIT_MIR gvn.slice_from_raw_parts_as_ptr.GVN.diff
+// EMIT_MIR gvn.casts_before_aggregate_raw_ptr.GVN.diff
diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff
new file mode 100644
index 00000000000..fd5fa035d81
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `slice_const_length` before GVN
++ // MIR for `slice_const_length` after GVN
+  
+  fn slice_const_length(_1: &[i32]) -> *const [i32] {
+      debug x => _1;
+      let mut _0: *const [i32];
+      let _2: *const i32;
+      let mut _3: &[i32];
+      let mut _5: *const i32;
+      let mut _6: usize;
+      scope 1 {
+          debug ptr => _2;
+          let _4: usize;
+          scope 2 {
+              debug len => _4;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = &(*_1);
+          _2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          _4 = const 123_usize;
+          StorageLive(_5);
+          _5 = _2;
+          StorageLive(_6);
+-         _6 = _4;
+-         _0 = *const [i32] from (move _5, move _6);
++         _6 = const 123_usize;
++         _0 = *const [i32] from (_2, const 123_usize);
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..98945cf9724
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `slice_const_length` before GVN
++ // MIR for `slice_const_length` after GVN
+  
+  fn slice_const_length(_1: &[i32]) -> *const [i32] {
+      debug x => _1;
+      let mut _0: *const [i32];
+      let _2: *const i32;
+      let mut _3: &[i32];
+      let mut _5: *const i32;
+      let mut _6: usize;
+      scope 1 {
+          debug ptr => _2;
+          let _4: usize;
+          scope 2 {
+              debug len => _4;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = &(*_1);
+          _2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          _4 = const 123_usize;
+          StorageLive(_5);
+          _5 = _2;
+          StorageLive(_6);
+-         _6 = _4;
+-         _0 = *const [i32] from (move _5, move _6);
++         _6 = const 123_usize;
++         _0 = *const [i32] from (_2, const 123_usize);
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff
new file mode 100644
index 00000000000..75bcd2a8d72
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff
@@ -0,0 +1,51 @@
+- // MIR for `slice_from_raw_parts_as_ptr` before GVN
++ // MIR for `slice_from_raw_parts_as_ptr` after GVN
+  
+  fn slice_from_raw_parts_as_ptr(_1: *const u16, _2: usize) -> (*const u16, *const f32) {
+      debug x => _1;
+      debug n => _2;
+      let mut _0: (*const u16, *const f32);
+      let _3: *const [u16];
+      let mut _4: *const u16;
+      let mut _5: usize;
+      let mut _6: *const u16;
+      let mut _7: *const [u16];
+      let mut _8: *const f32;
+      let mut _9: *const [u16];
+      scope 1 {
+          debug ptr => _3;
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = _1;
+          StorageLive(_5);
+          _5 = _2;
+-         _3 = *const [u16] from (move _4, move _5);
++         _3 = *const [u16] from (_1, _2);
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = _3;
+-         _6 = move _7 as *const u16 (PtrToPtr);
++         _6 = _1;
+          StorageDead(_7);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = _3;
+-         _8 = move _9 as *const f32 (PtrToPtr);
++         _8 = _1 as *const f32 (PtrToPtr);
+          StorageDead(_9);
+-         _0 = (move _6, move _8);
++         _0 = (_1, move _8);
+          StorageDead(_8);
+          StorageDead(_6);
+-         StorageDead(_3);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..75bcd2a8d72
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff
@@ -0,0 +1,51 @@
+- // MIR for `slice_from_raw_parts_as_ptr` before GVN
++ // MIR for `slice_from_raw_parts_as_ptr` after GVN
+  
+  fn slice_from_raw_parts_as_ptr(_1: *const u16, _2: usize) -> (*const u16, *const f32) {
+      debug x => _1;
+      debug n => _2;
+      let mut _0: (*const u16, *const f32);
+      let _3: *const [u16];
+      let mut _4: *const u16;
+      let mut _5: usize;
+      let mut _6: *const u16;
+      let mut _7: *const [u16];
+      let mut _8: *const f32;
+      let mut _9: *const [u16];
+      scope 1 {
+          debug ptr => _3;
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = _1;
+          StorageLive(_5);
+          _5 = _2;
+-         _3 = *const [u16] from (move _4, move _5);
++         _3 = *const [u16] from (_1, _2);
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = _3;
+-         _6 = move _7 as *const u16 (PtrToPtr);
++         _6 = _1;
+          StorageDead(_7);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = _3;
+-         _8 = move _9 as *const f32 (PtrToPtr);
++         _8 = _1 as *const f32 (PtrToPtr);
+          StorageDead(_9);
+-         _0 = (move _6, move _8);
++         _0 = (_1, move _8);
+          StorageDead(_8);
+          StorageDead(_6);
+-         StorageDead(_3);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs
index 1826e38f894..651112ccfd7 100644
--- a/tests/mir-opt/inline/inline_cycle.rs
+++ b/tests/mir-opt/inline/inline_cycle.rs
@@ -32,7 +32,6 @@ impl<T: Call> Call for A<T> {
     }
 }
 
-
 impl<T: Call> Call for B<T> {
     #[inline]
     fn call() {
diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs
index 667bf7f9254..64f208b1c70 100644
--- a/tests/mir-opt/inline/inline_cycle_generic.rs
+++ b/tests/mir-opt/inline/inline_cycle_generic.rs
@@ -26,7 +26,6 @@ impl Call for A {
     }
 }
 
-
 impl<T: Call> Call for B<T> {
     #[inline]
     fn call() {
diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs
index 7d7c4f718bd..bd9e0e2d207 100644
--- a/tests/mir-opt/inline/inline_options.rs
+++ b/tests/mir-opt/inline/inline_options.rs
@@ -16,8 +16,16 @@ fn main() {
 
 // Cost is approximately 3 * 25 + 5 = 80.
 #[inline]
-pub fn not_inlined() { g(); g(); g(); }
-pub fn inlined<T>() { g(); g(); g(); }
+pub fn not_inlined() {
+    g();
+    g();
+    g();
+}
+pub fn inlined<T>() {
+    g();
+    g();
+    g();
+}
 
 #[inline(never)]
 fn g() {}
diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs
index 6453abc0081..b9d40aca3a4 100644
--- a/tests/mir-opt/inline/inline_specialization.rs
+++ b/tests/mir-opt/inline/inline_specialization.rs
@@ -5,7 +5,7 @@
 fn main() {
     // CHECK-LABEL: fn main(
     // CHECK: (inlined <Vec<()> as Foo>::bar)
-    let x = <Vec::<()> as Foo>::bar();
+    let x = <Vec<()> as Foo>::bar();
 }
 
 trait Foo {
@@ -14,5 +14,7 @@ trait Foo {
 
 impl<T> Foo for Vec<T> {
     #[inline(always)]
-    default fn bar() -> u32 { 123 }
+    default fn bar() -> u32 {
+        123
+    }
 }
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
index 24e5587f963..2ab79cc2a50 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
@@ -8,7 +8,7 @@
 +         let mut _2: bool;
 +         let mut _3: bool;
 +         scope 2 {
-+             debug buffer => const inner::promoted[0];
++             debug buffer => _1;
 +             scope 3 {
 +                 debug index => _0;
 +             }
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
index 4eb8a5c9847..4d96a862885 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
@@ -8,7 +8,7 @@
 +         let mut _2: bool;
 +         let mut _3: bool;
 +         scope 2 {
-+             debug buffer => const inner::promoted[0];
++             debug buffer => _1;
 +             scope 3 {
 +                 debug index => _0;
 +             }
diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs
index 1cca7d76b25..d311ad4527f 100644
--- a/tests/mir-opt/inline/issue_106141.rs
+++ b/tests/mir-opt/inline/issue_106141.rs
@@ -19,11 +19,7 @@ fn inner() -> usize {
     // CHECK: = {{.*}}[_0];
     let buffer = &[true];
     let index = index();
-    if buffer[index] {
-        index
-    } else {
-        0
-    }
+    if buffer[index] { index } else { 0 }
 }
 
 fn main() {
diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
index 75772c16127..021af7f81bb 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
@@ -13,6 +13,9 @@ fn main() {
     // CHECK-NEXT: }
     // CHECK-NEXT: }
     // CHECK-NEXT: }
-    let f = |x| { let y = x; y };
+    let f = |x| {
+        let y = x;
+        y
+    };
     f(())
 }
diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs
index 86455e8b52d..f12284f6482 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.rs
+++ b/tests/mir-opt/instsimplify/combine_array_len.rs
@@ -7,9 +7,9 @@ fn norm2(x: [f32; 2]) -> f32 {
     // CHECK-NOT: Len(
     let a = x[0];
     let b = x[1];
-    a*a + b*b
+    a * a + b * b
 }
 
 fn main() {
-    assert_eq!(norm2([3.0, 4.0]), 5.0*5.0);
+    assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0);
 }
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.rs b/tests/mir-opt/instsimplify/combine_transmutes.rs
index 0be7466001f..c3622c20697 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.rs
+++ b/tests/mir-opt/instsimplify/combine_transmutes.rs
@@ -5,7 +5,7 @@
 #![feature(custom_mir)]
 
 use std::intrinsics::mir::*;
-use std::mem::{MaybeUninit, ManuallyDrop, transmute};
+use std::mem::{transmute, ManuallyDrop, MaybeUninit};
 
 // EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify.diff
 pub unsafe fn identity_transmutes() {
@@ -61,4 +61,7 @@ pub unsafe fn adt_transmutes() {
     let _a: ManuallyDrop<String> = transmute(MaybeUninit::<String>::uninit());
 }
 
-pub union Union32 { u32: u32, i32: i32 }
+pub union Union32 {
+    u32: u32,
+    i32: i32,
+}
diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
index 454728249b1..a47d9d5a71d 100644
--- a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
+++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
@@ -10,7 +10,7 @@ use std::intrinsics::mir::*;
 pub unsafe fn assert_zero(x: u8) -> u8 {
     // CHECK-LABEL: fn assert_zero(
     // CHECK: switchInt({{.*}}) -> [0: {{bb.*}}, otherwise: {{bb.*}}]
-    mir!(
+    mir! {
         {
             match x {
                 0 => retblock,
@@ -25,5 +25,5 @@ pub unsafe fn assert_zero(x: u8) -> u8 {
             RET = x;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/mir-opt/issue_104451_unwindable_intrinsics.rs b/tests/mir-opt/issue_104451_unwindable_intrinsics.rs
index cd068f12236..80655a583c3 100644
--- a/tests/mir-opt/issue_104451_unwindable_intrinsics.rs
+++ b/tests/mir-opt/issue_104451_unwindable_intrinsics.rs
@@ -5,9 +5,7 @@
 
 // EMIT_MIR issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.mir
 fn main() {
-    unsafe {
-        core::intrinsics::const_eval_select((), ow_ct, ow_ct)
-    }
+    unsafe { core::intrinsics::const_eval_select((), ow_ct, ow_ct) }
 }
 
 const fn ow_ct() -> ! {
diff --git a/tests/mir-opt/issue_41110.rs b/tests/mir-opt/issue_41110.rs
index 38602d5eaef..5d042815f3b 100644
--- a/tests/mir-opt/issue_41110.rs
+++ b/tests/mir-opt/issue_41110.rs
@@ -3,7 +3,6 @@
 
 // check that we don't emit multiple drop flags when they are not needed.
 
-
 // EMIT_MIR issue_41110.main.ElaborateDrops.diff
 fn main() {
     let x = S.other(S.id());
@@ -21,11 +20,12 @@ pub fn test() {
 
 struct S;
 impl Drop for S {
-    fn drop(&mut self) {
-    }
+    fn drop(&mut self) {}
 }
 
 impl S {
-    fn id(self) -> Self { self }
+    fn id(self) -> Self {
+        self
+    }
     fn other(self, s: Self) {}
 }
diff --git a/tests/mir-opt/issue_41697.rs b/tests/mir-opt/issue_41697.rs
index 92d382c3940..b031f1dc720 100644
--- a/tests/mir-opt/issue_41697.rs
+++ b/tests/mir-opt/issue_41697.rs
@@ -14,9 +14,8 @@ trait Foo {
     fn get(&self) -> [u8; 2];
 }
 
-
 // EMIT_MIR issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir
-impl Foo for [u8; 1+1] {
+impl Foo for [u8; 1 + 1] {
     fn get(&self) -> [u8; 2] {
         *self
     }
@@ -33,7 +32,7 @@ fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
 }
 
 fn main() {
-    let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
+    let x: Box<Bar<Foo + Send>> = Box::new(Bar([1, 2]));
     assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);
 
     let x: Arc<Foo + Send> = Arc::new([3, 4]);
diff --git a/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir b/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir
index 7d2e97f8d56..27a5a8dd552 100644
--- a/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir
+++ b/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/issue_41697.rs:19:1: 19:23>::{constant#0}` after SimplifyCfg-promote-consts
+// MIR for `<impl at $DIR/issue_41697.rs:18:1: 18:25>::{constant#0}` after SimplifyCfg-promote-consts
 
-<impl at $DIR/issue_41697.rs:19:1: 19:23>::{constant#0}: usize = {
+<impl at $DIR/issue_41697.rs:18:1: 18:25>::{constant#0}: usize = {
     let mut _0: usize;
     let mut _1: (usize, bool);
 
diff --git a/tests/mir-opt/issue_41888.rs b/tests/mir-opt/issue_41888.rs
index 70b20218633..1744d9f8570 100644
--- a/tests/mir-opt/issue_41888.rs
+++ b/tests/mir-opt/issue_41888.rs
@@ -15,11 +15,13 @@ fn main() {
     }
 }
 
-fn cond() -> bool { false }
+fn cond() -> bool {
+    false
+}
 
 struct K;
 
 enum E {
     F(K),
-    G(Box<E>)
+    G(Box<E>),
 }
diff --git a/tests/mir-opt/issue_72181.rs b/tests/mir-opt/issue_72181.rs
index 3748c2af83d..dea8ecbd3ec 100644
--- a/tests/mir-opt/issue_72181.rs
+++ b/tests/mir-opt/issue_72181.rs
@@ -9,16 +9,18 @@ enum Never {}
 
 union Foo {
     a: u64,
-    b: Never
+    b: Never,
 }
 
-
 // EMIT_MIR issue_72181.foo.built.after.mir
-fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 }
+fn foo(xs: [(Never, u32); 1]) -> u32 {
+    xs[0].1
+}
 
 // EMIT_MIR issue_72181.bar.built.after.mir
-fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x }
-
+fn bar([(_, x)]: [(Never, u32); 1]) -> u32 {
+    x
+}
 
 // EMIT_MIR issue_72181.main.built.after.mir
 fn main() {
diff --git a/tests/mir-opt/issue_72181_1.rs b/tests/mir-opt/issue_72181_1.rs
index 32e946559d7..5c8346166ae 100644
--- a/tests/mir-opt/issue_72181_1.rs
+++ b/tests/mir-opt/issue_72181_1.rs
@@ -14,9 +14,7 @@ fn f(v: Void) -> ! {
 
 // EMIT_MIR issue_72181_1.main.built.after.mir
 fn main() {
-    let v: Void = unsafe {
-        std::mem::transmute::<(), Void>(())
-    };
+    let v: Void = unsafe { std::mem::transmute::<(), Void>(()) };
 
     f(v);
 }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index b2539f391d1..1f88339b586 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -29,8 +29,8 @@
           _3 = &_4;
           _2 = move _3 as &[T] (PointerCoercion(Unsize));
           StorageDead(_3);
-          _5 = const 3_usize;
-          _6 = const true;
+          nop;
+          nop;
           goto -> bb2;
       }
   
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index ff7f12c093c..19a581ba3f0 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -29,8 +29,8 @@
           _3 = &_4;
           _2 = move _3 as &[T] (PointerCoercion(Unsize));
           StorageDead(_3);
-          _5 = const 3_usize;
-          _6 = const true;
+          nop;
+          nop;
           goto -> bb2;
       }
   
diff --git a/tests/mir-opt/issue_91633.rs b/tests/mir-opt/issue_91633.rs
index f7d59f5adfb..d24c2e19aa7 100644
--- a/tests/mir-opt/issue_91633.rs
+++ b/tests/mir-opt/issue_91633.rs
@@ -1,32 +1,30 @@
 // skip-filecheck
 //@ compile-flags: -Z mir-opt-level=0
 // EMIT_MIR issue_91633.hey.built.after.mir
-fn hey<T> (it: &[T])
- where
-     [T] : std::ops::Index<usize>,
- {
-     let _ = &it[0];
- }
+fn hey<T>(it: &[T])
+where
+    [T]: std::ops::Index<usize>,
+{
+    let _ = &it[0];
+}
 
 // EMIT_MIR issue_91633.bar.built.after.mir
-fn bar<T> (it: Box<[T]>)
- where
-     [T] : std::ops::Index<usize>,
- {
-     let _ = it[0];
- }
+fn bar<T>(it: Box<[T]>)
+where
+    [T]: std::ops::Index<usize>,
+{
+    let _ = it[0];
+}
 
 // EMIT_MIR issue_91633.fun.built.after.mir
-fn fun<T> (it: &[T]) -> &T
- {
-     let f = &it[0];
-     f
- }
+fn fun<T>(it: &[T]) -> &T {
+    let f = &it[0];
+    f
+}
 
 // EMIT_MIR issue_91633.foo.built.after.mir
-fn foo<T: Clone> (it: Box<[T]>) -> T
- {
-     let f = it[0].clone();
-     f
- }
- fn main(){}
+fn foo<T: Clone>(it: Box<[T]>) -> T {
+    let f = it[0].clone();
+    f
+}
+fn main() {}
diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
index 0b0bac73e9f..b7a054b5d54 100644
--- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
@@ -2,7 +2,7 @@
 
 | User Type Annotations
 | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
index 0b0bac73e9f..b7a054b5d54 100644
--- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
@@ -2,7 +2,7 @@
 
 | User Type Annotations
 | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs
index 8c710a33aa8..ea763dd1b10 100644
--- a/tests/mir-opt/issues/issue_75439.rs
+++ b/tests/mir-opt/issues/issue_75439.rs
@@ -8,11 +8,7 @@ pub fn foo(bytes: [u8; 16]) -> Option<[u8; 4]> {
     // big endian `u32`s
     let dwords: [u32; 4] = unsafe { transmute(bytes) };
     const FF: u32 = 0x0000_ffff_u32.to_be();
-    if let [0, 0, 0 | FF, ip] = dwords {
-        Some(unsafe { transmute(ip) })
-    } else {
-        None
-    }
+    if let [0, 0, 0 | FF, ip] = dwords { Some(unsafe { transmute(ip) }) } else { None }
 }
 
 fn main() {
diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs
index 57f4e4a2654..b4c13371680 100644
--- a/tests/mir-opt/jump_threading.rs
+++ b/tests/mir-opt/jump_threading.rs
@@ -157,7 +157,7 @@ fn custom_discr(x: bool) -> u8 {
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn multiple_match(x: u8) -> u8 {
     // CHECK-LABEL: fn multiple_match(
-    mir!(
+    mir! {
         {
             // CHECK: bb0: {
             // CHECK:     switchInt([[x:_.*]]) -> [3: bb1, otherwise: bb2];
@@ -220,7 +220,7 @@ fn multiple_match(x: u8) -> u8 {
             RET = 11;
             Return()
         }
-    )
+    }
 }
 
 /// Both 1-3-4 and 2-3-4 are threadable. As 1 and 2 are the only predecessors of 3,
@@ -228,7 +228,7 @@ fn multiple_match(x: u8) -> u8 {
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn duplicate_chain(x: bool) -> u8 {
     // CHECK-LABEL: fn duplicate_chain(
-    mir!(
+    mir! {
         let a: u8;
         {
             // CHECK: bb0: {
@@ -278,7 +278,7 @@ fn duplicate_chain(x: bool) -> u8 {
             RET = 9;
             Return()
         }
-    )
+    }
 }
 
 #[rustc_layout_scalar_valid_range_start(1)]
@@ -292,7 +292,7 @@ fn mutate_discriminant() -> u8 {
     // CHECK-NOT: goto -> {{bb.*}};
     // CHECK: switchInt(
     // CHECK-NOT: goto -> {{bb.*}};
-    mir!(
+    mir! {
         let x: Option<NonZeroUsize>;
         {
             SetDiscriminant(x, 1);
@@ -313,7 +313,7 @@ fn mutate_discriminant() -> u8 {
             RET = 2;
             Unreachable()
         }
-    )
+    }
 }
 
 /// Verify that we do not try to reason when there are mutable pointers involved.
@@ -330,11 +330,7 @@ fn mutable_ref() -> bool {
     let a = std::ptr::addr_of_mut!(x);
     x = 7;
     unsafe { *a = 8 };
-    if x == 7 {
-        true
-    } else {
-        false
-    }
+    if x == 7 { true } else { false }
 }
 
 /// This function has 2 TOs: 1-3-4 and 0-1-3-4-6.
@@ -342,7 +338,7 @@ fn mutable_ref() -> bool {
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn renumbered_bb(x: bool) -> u8 {
     // CHECK-LABEL: fn renumbered_bb(
-    mir!(
+    mir! {
         let a: bool;
         let b: bool;
         {
@@ -398,7 +394,7 @@ fn renumbered_bb(x: bool) -> u8 {
         // Duplicate of bb4.
         // CHECK: bb9: {
         // CHECK-NEXT: goto -> bb6;
-    )
+    }
 }
 
 /// This function has 3 TOs: 1-4-5, 0-1-4-7-5-8 and 3-4-7-5-6
@@ -408,7 +404,7 @@ fn renumbered_bb(x: bool) -> u8 {
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn disappearing_bb(x: u8) -> u8 {
     // CHECK-LABEL: fn disappearing_bb(
-    mir!(
+    mir! {
         let a: bool;
         let b: bool;
         {
@@ -450,7 +446,7 @@ fn disappearing_bb(x: u8) -> u8 {
         // CHECK: goto -> bb5;
         // CHECK: bb10: {
         // CHECK: goto -> bb6;
-    )
+    }
 }
 
 /// Verify that we can thread jumps when we assign from an aggregate constant.
@@ -461,18 +457,14 @@ fn aggregate(x: u8) -> u8 {
     const FOO: (u8, u8) = (5, 13);
 
     let (a, b) = FOO;
-    if a == 7 {
-        b
-    } else {
-        a
-    }
+    if a == 7 { b } else { a }
 }
 
 /// Verify that we can leverage the existence of an `Assume` terminator.
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 fn assume(a: u8, b: bool) -> u8 {
     // CHECK-LABEL: fn assume(
-    mir!(
+    mir! {
         {
             // CHECK: bb0: {
             // CHECK-NEXT: switchInt(_1) -> [7: bb1, otherwise: bb2]
@@ -511,7 +503,7 @@ fn assume(a: u8, b: bool) -> u8 {
         }
         // CHECK: bb6: {
         // CHECK-NEXT: goto -> bb5;
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs
index 1c30c4c89b9..62fc9ef67d6 100644
--- a/tests/mir-opt/lower_array_len.rs
+++ b/tests/mir-opt/lower_array_len.rs
@@ -7,11 +7,7 @@ pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
     // CHECK-LABEL: fn array_bound(
     // CHECK: [[len:_.*]] = const N;
     // CHECK: Lt(move {{_.*}}, move [[len]]);
-    if index < slice.len() {
-        slice[index]
-    } else {
-        42
-    }
+    if index < slice.len() { slice[index] } else { 42 }
 }
 
 // EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff
diff --git a/tests/mir-opt/lower_slice_len.rs b/tests/mir-opt/lower_slice_len.rs
index b82094dc18f..6fd7e4bf72c 100644
--- a/tests/mir-opt/lower_slice_len.rs
+++ b/tests/mir-opt/lower_slice_len.rs
@@ -5,11 +5,7 @@
 pub fn bound(index: usize, slice: &[u8]) -> u8 {
     // CHECK-LABEL: fn bound(
     // CHECK-NOT: ::len(
-    if index < slice.len() {
-        slice[index]
-    } else {
-        42
-    }
+    if index < slice.len() { slice[index] } else { 42 }
 }
 
 fn main() {
diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs
index fa466220b65..176d68bcd40 100644
--- a/tests/mir-opt/matches_reduce_branches.rs
+++ b/tests/mir-opt/matches_reduce_branches.rs
@@ -88,7 +88,7 @@ fn match_u8_i16(i: EnumAu8) -> i16 {
 fn match_u8_i16_2(i: EnumAu8) -> i16 {
     // CHECK-LABEL: fn match_u8_i16_2(
     // CHECK: switchInt
-    mir!(
+    mir! {
         {
             let a = Discriminant(i);
             match a {
@@ -110,7 +110,7 @@ fn match_u8_i16_2(i: EnumAu8) -> i16 {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff
@@ -158,7 +158,7 @@ fn match_u8_u16(i: EnumBu8) -> u16 {
 fn match_u8_u16_2(i: EnumBu8) -> i16 {
     // CHECK-LABEL: fn match_u8_u16_2(
     // CHECK: switchInt
-    mir!(
+    mir! {
         {
             let a = Discriminant(i);
             match a {
@@ -187,7 +187,7 @@ fn match_u8_u16_2(i: EnumBu8) -> i16 {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 #[repr(i8)]
diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs
index f0be82d0257..86d64625674 100644
--- a/tests/mir-opt/matches_u8.rs
+++ b/tests/mir-opt/matches_u8.rs
@@ -1,7 +1,6 @@
 // skip-filecheck
 //@ test-mir-pass: MatchBranchSimplification
 
-
 // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
 // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
 
@@ -27,9 +26,9 @@ pub fn exhaustive_match_i8(e: E) -> i8 {
 }
 
 fn main() {
-  assert_eq!(exhaustive_match(E::A), 0);
-  assert_eq!(exhaustive_match(E::B), 1);
+    assert_eq!(exhaustive_match(E::A), 0);
+    assert_eq!(exhaustive_match(E::B), 1);
 
-  assert_eq!(exhaustive_match_i8(E::A), 0);
-  assert_eq!(exhaustive_match_i8(E::B), 1);
+    assert_eq!(exhaustive_match_i8(E::A), 0);
+    assert_eq!(exhaustive_match_i8(E::B), 1);
 }
diff --git a/tests/mir-opt/nll/named_lifetimes_basic.rs b/tests/mir-opt/nll/named_lifetimes_basic.rs
index cc838537003..93f4a8bfd59 100644
--- a/tests/mir-opt/nll/named_lifetimes_basic.rs
+++ b/tests/mir-opt/nll/named_lifetimes_basic.rs
@@ -10,7 +10,8 @@
 #![allow(warnings)]
 
 // EMIT_MIR named_lifetimes_basic.use_x.nll.0.mir
-fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { true }
-
-fn main() {
+fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool {
+    true
 }
+
+fn main() {}
diff --git a/tests/mir-opt/nrvo_miscompile_111005.rs b/tests/mir-opt/nrvo_miscompile_111005.rs
index 18814b0678f..03008fa8191 100644
--- a/tests/mir-opt/nrvo_miscompile_111005.rs
+++ b/tests/mir-opt/nrvo_miscompile_111005.rs
@@ -10,12 +10,14 @@ use core::intrinsics::mir::*;
 // EMIT_MIR nrvo_miscompile_111005.wrong.RenameReturnPlace.diff
 #[custom_mir(dialect = "runtime", phase = "initial")]
 pub fn wrong(arg: char) -> char {
-    mir!({
-        let temp = arg;
-        RET = temp;
-        temp = 'b';
-        Return()
-    })
+    mir! {
+        {
+            let temp = arg;
+            RET = temp;
+            temp = 'b';
+            Return()
+        }
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/nrvo_simple.rs
index 5d2894a704a..df540472e1c 100644
--- a/tests/mir-opt/nrvo_simple.rs
+++ b/tests/mir-opt/nrvo_simple.rs
@@ -10,5 +10,7 @@ fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
 }
 
 fn main() {
-    let _ = nrvo(|buf| { buf[4] = 4; });
+    let _ = nrvo(|buf| {
+        buf[4] = 4;
+    });
 }
diff --git a/tests/mir-opt/packed_struct_drop_aligned.rs b/tests/mir-opt/packed_struct_drop_aligned.rs
index dff941c4fa0..3abc6426e7f 100644
--- a/tests/mir-opt/packed_struct_drop_aligned.rs
+++ b/tests/mir-opt/packed_struct_drop_aligned.rs
@@ -1,7 +1,6 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-
 // EMIT_MIR packed_struct_drop_aligned.main.SimplifyCfg-pre-optimizations.after.mir
 fn main() {
     let mut x = Packed(Aligned(Droppy(0)));
diff --git a/tests/mir-opt/pre-codegen/intrinsics.rs b/tests/mir-opt/pre-codegen/intrinsics.rs
index e5c059cda12..0482b85e95f 100644
--- a/tests/mir-opt/pre-codegen/intrinsics.rs
+++ b/tests/mir-opt/pre-codegen/intrinsics.rs
@@ -12,7 +12,6 @@ pub fn f_unit() {
     f_dispatch(());
 }
 
-
 // EMIT_MIR intrinsics.f_u64.PreCodegen.after.mir
 pub fn f_u64() {
     f_dispatch(0u64);
@@ -28,8 +27,7 @@ pub fn f_dispatch<T>(t: T) {
 }
 
 #[inline(never)]
-pub fn f_zst<T>(_t: T) {
-}
+pub fn f_zst<T>(_t: T) {}
 
 #[inline(never)]
 pub fn f_non_zst<T>(_t: T) {}
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 17d83752fc1..465cb1a9b1f 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -23,16 +23,15 @@
               let mut _12: isize;
               let _13: std::alloc::AllocError;
               let mut _14: !;
-              let _15: &str;
-              let mut _16: &dyn std::fmt::Debug;
-              let mut _17: &std::alloc::AllocError;
+              let mut _15: &dyn std::fmt::Debug;
+              let mut _16: &std::alloc::AllocError;
               scope 7 {
               }
               scope 8 {
               }
           }
           scope 9 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _18: *const [u8];
+              let mut _17: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -87,36 +86,33 @@
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
-          StorageLive(_15);
           _12 = discriminant(_6);
           switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb5: {
-          _15 = const "called `Result::unwrap()` on an `Err` value";
+          StorageLive(_15);
           StorageLive(_16);
-          StorageLive(_17);
-          _17 = &_13;
-          _16 = move _17 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
-          StorageDead(_17);
-          _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
+          _16 = &_13;
+          _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
+          StorageDead(_16);
+          _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
       }
   
       bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
-          StorageDead(_15);
           StorageDead(_12);
           StorageDead(_6);
--         StorageLive(_18);
+-         StorageLive(_17);
 +         nop;
-          _18 = (_5.0: *const [u8]);
--         _4 = move _18 as *mut [u8] (PtrToPtr);
--         StorageDead(_18);
-+         _4 = _18 as *mut [u8] (PtrToPtr);
+          _17 = (_5.0: *const [u8]);
+-         _4 = move _17 as *mut [u8] (PtrToPtr);
+-         StorageDead(_17);
++         _4 = _17 as *mut [u8] (PtrToPtr);
 +         nop;
           StorageDead(_5);
 -         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = _18 as *mut u8 (PtrToPtr);
++         _3 = _17 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index 1cf950402c3..925d8997b8a 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -23,16 +23,15 @@
               let mut _12: isize;
               let _13: std::alloc::AllocError;
               let mut _14: !;
-              let _15: &str;
-              let mut _16: &dyn std::fmt::Debug;
-              let mut _17: &std::alloc::AllocError;
+              let mut _15: &dyn std::fmt::Debug;
+              let mut _16: &std::alloc::AllocError;
               scope 7 {
               }
               scope 8 {
               }
           }
           scope 9 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _18: *const [u8];
+              let mut _17: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -87,36 +86,33 @@
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
-          StorageLive(_15);
           _12 = discriminant(_6);
           switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb5: {
-          _15 = const "called `Result::unwrap()` on an `Err` value";
+          StorageLive(_15);
           StorageLive(_16);
-          StorageLive(_17);
-          _17 = &_13;
-          _16 = move _17 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
-          StorageDead(_17);
-          _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
+          _16 = &_13;
+          _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
+          StorageDead(_16);
+          _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
       }
   
       bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
-          StorageDead(_15);
           StorageDead(_12);
           StorageDead(_6);
--         StorageLive(_18);
+-         StorageLive(_17);
 +         nop;
-          _18 = (_5.0: *const [u8]);
--         _4 = move _18 as *mut [u8] (PtrToPtr);
--         StorageDead(_18);
-+         _4 = _18 as *mut [u8] (PtrToPtr);
+          _17 = (_5.0: *const [u8]);
+-         _4 = move _17 as *mut [u8] (PtrToPtr);
+-         StorageDead(_17);
++         _4 = _17 as *mut [u8] (PtrToPtr);
 +         nop;
           StorageDead(_5);
 -         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = _18 as *mut u8 (PtrToPtr);
++         _3 = _17 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs
index 7a1fb1e76c0..de5e2d5c312 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs
@@ -15,5 +15,5 @@ struct Point {
 fn main() {
     let x = 2 + 2;
     let y = [0, 1, 2, 3, 4, 5][3];
-    let z = (Point { x: 12, y: 42}).y;
+    let z = (Point { x: 12, y: 42 }).y;
 }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
index 2c6d93e10c1..2f6139712ff 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
@@ -12,8 +12,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
-            let mut _5: *const ();
-            let mut _6: usize;
+            let mut _5: usize;
             scope 5 (inlined std::ptr::metadata::<[u32]>) {
             }
             scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
@@ -28,11 +27,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         _4 = Offset(_3, _2);
         StorageDead(_3);
         StorageLive(_5);
-        _5 = _4 as *const () (PtrToPtr);
-        StorageLive(_6);
-        _6 = PtrMetadata(_1);
-        _0 = *const [u32] from (_5, _6);
-        StorageDead(_6);
+        _5 = PtrMetadata(_1);
+        _0 = *const [u32] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
         return;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
index 2c6d93e10c1..2f6139712ff 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
@@ -12,8 +12,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
-            let mut _5: *const ();
-            let mut _6: usize;
+            let mut _5: usize;
             scope 5 (inlined std::ptr::metadata::<[u32]>) {
             }
             scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
@@ -28,11 +27,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         _4 = Offset(_3, _2);
         StorageDead(_3);
         StorageLive(_5);
-        _5 = _4 as *const () (PtrToPtr);
-        StorageLive(_6);
-        _6 = PtrMetadata(_1);
-        _0 = *const [u32] from (_5, _6);
-        StorageDead(_6);
+        _5 = PtrMetadata(_1);
+        _0 = *const [u32] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
         return;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
index 04fb6b838f0..8d47e63eff2 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
@@ -20,11 +20,13 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     }
 
     bb0: {
+        StorageLive(_4);
         StorageLive(_3);
         _3 = _1 as *const u8 (PtrToPtr);
         _4 = Offset(_3, _2);
         StorageDead(_3);
         _0 = _4 as *const u32 (PtrToPtr);
+        StorageDead(_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
index 04fb6b838f0..8d47e63eff2 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
@@ -20,11 +20,13 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     }
 
     bb0: {
+        StorageLive(_4);
         StorageLive(_3);
         _3 = _1 as *const u8 (PtrToPtr);
         _4 = Offset(_3, _2);
         StorageDead(_3);
         _0 = _4 as *const u32 (PtrToPtr);
+        StorageDead(_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index d979c5ec1d5..8f41fb70925 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -4,35 +4,34 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _12: std::slice::Iter<'_, T>;
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
     let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _16: std::option::Option<(usize, &T)>;
-    let mut _17: isize;
-    let mut _20: &impl Fn(usize, &T);
-    let mut _21: (usize, &T);
-    let _22: ();
+    let mut _14: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _15: std::option::Option<(usize, &T)>;
+    let mut _16: isize;
+    let mut _19: &impl Fn(usize, &T);
+    let mut _20: (usize, &T);
+    let _21: ();
     scope 1 {
-        debug iter => _14;
-        let _18: usize;
-        let _19: &T;
+        debug iter => _13;
+        let _17: usize;
+        let _18: &T;
         scope 2 {
-            debug i => _18;
-            debug x => _19;
+            debug i => _17;
+            debug x => _18;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -61,7 +60,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_12);
+        StorageLive(_11);
         StorageLive(_3);
         StorageLive(_6);
         StorageLive(_4);
@@ -70,62 +69,59 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        _13 = Enumerate::<std::slice::Iter<'_, T>> { iter: _12, count: const 0_usize };
-        StorageDead(_12);
-        StorageLive(_14);
-        _14 = _13;
+        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: _11, count: const 0_usize };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
         StorageLive(_15);
-        _15 = &mut _14;
-        _16 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
+        StorageLive(_14);
+        _14 = &mut _13;
+        _15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_14);
+        StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -134,19 +130,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _18 = (((_16 as Some).0: (usize, &T)).0: usize);
-        _19 = (((_16 as Some).0: (usize, &T)).1: &T);
+        _17 = (((_15 as Some).0: (usize, &T)).0: usize);
+        _18 = (((_15 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_19);
+        _19 = &_2;
         StorageLive(_20);
-        _20 = &_2;
-        StorageLive(_21);
-        _21 = (_18, _19);
-        _22 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _20, move _21) -> [return: bb9, unwind unreachable];
+        _20 = (_17, _18);
+        _21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_21);
         StorageDead(_20);
-        StorageDead(_16);
+        StorageDead(_19);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 8491c49f767..17cf305468e 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -4,35 +4,34 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _12: std::slice::Iter<'_, T>;
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
     let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _16: std::option::Option<(usize, &T)>;
-    let mut _17: isize;
-    let mut _20: &impl Fn(usize, &T);
-    let mut _21: (usize, &T);
-    let _22: ();
+    let mut _14: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _15: std::option::Option<(usize, &T)>;
+    let mut _16: isize;
+    let mut _19: &impl Fn(usize, &T);
+    let mut _20: (usize, &T);
+    let _21: ();
     scope 1 {
-        debug iter => _14;
-        let _18: usize;
-        let _19: &T;
+        debug iter => _13;
+        let _17: usize;
+        let _18: &T;
         scope 2 {
-            debug i => _18;
-            debug x => _19;
+            debug i => _17;
+            debug x => _18;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -61,7 +60,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_12);
+        StorageLive(_11);
         StorageLive(_3);
         StorageLive(_6);
         StorageLive(_4);
@@ -70,62 +69,59 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        _13 = Enumerate::<std::slice::Iter<'_, T>> { iter: _12, count: const 0_usize };
-        StorageDead(_12);
-        StorageLive(_14);
-        _14 = _13;
+        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: _11, count: const 0_usize };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
         StorageLive(_15);
-        _15 = &mut _14;
-        _16 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11];
+        StorageLive(_14);
+        _14 = &mut _13;
+        _15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_14);
+        StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -134,19 +130,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _18 = (((_16 as Some).0: (usize, &T)).0: usize);
-        _19 = (((_16 as Some).0: (usize, &T)).1: &T);
+        _17 = (((_15 as Some).0: (usize, &T)).0: usize);
+        _18 = (((_15 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_19);
+        _19 = &_2;
         StorageLive(_20);
-        _20 = &_2;
-        StorageLive(_21);
-        _21 = (_18, _19);
-        _22 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _20, move _21) -> [return: bb9, unwind: bb11];
+        _20 = (_17, _18);
+        _21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_21);
         StorageDead(_20);
-        StorageDead(_16);
+        StorageDead(_19);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 67dd0c85ea1..3c1bbdc8742 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -4,32 +4,31 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
+    let mut _11: std::slice::Iter<'_, T>;
     let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: &mut std::slice::Iter<'_, T>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _13: &mut std::slice::Iter<'_, T>;
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _16;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -62,60 +61,57 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        StorageLive(_13);
-        _13 = _12;
+        StorageLive(_12);
+        _12 = _11;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
         StorageLive(_14);
-        _14 = &mut _13;
-        _15 = <std::slice::Iter<'_, T> as Iterator>::next(move _14) -> [return: bb5, unwind unreachable];
+        StorageLive(_13);
+        _13 = &mut _12;
+        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_13);
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_15);
-        StorageDead(_13);
+        StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -124,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = ((_15 as Some).0: &T);
+        _16 = ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
         StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (_17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
+        _18 = (_16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_19);
         StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 7c41e9e1f1b..b2ec1ea7b9f 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -4,32 +4,31 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
+    let mut _11: std::slice::Iter<'_, T>;
     let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: &mut std::slice::Iter<'_, T>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _13: &mut std::slice::Iter<'_, T>;
+    let mut _14: std::option::Option<&T>;
+    let mut _15: isize;
+    let mut _17: &impl Fn(&T);
+    let mut _18: (&T,);
+    let _19: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _12;
+        let _16: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _16;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -62,60 +61,57 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        StorageLive(_13);
-        _13 = _12;
+        StorageLive(_12);
+        _12 = _11;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
         StorageLive(_14);
-        _14 = &mut _13;
-        _15 = <std::slice::Iter<'_, T> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
+        StorageLive(_13);
+        _13 = &mut _12;
+        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_13);
+        _15 = discriminant(_14);
+        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_15);
-        StorageDead(_13);
+        StorageDead(_14);
+        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -124,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = ((_15 as Some).0: &T);
+        _16 = ((_14 as Some).0: &T);
+        StorageLive(_17);
+        _17 = &_2;
         StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (_17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
+        _18 = (_16,);
+        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_19);
         StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_17);
+        StorageDead(_14);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index ffeef1e04a1..bf982f076de 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -4,35 +4,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _12: std::slice::Iter<'_, T>;
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
     let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _15: std::option::Option<&T>;
+    let mut _16: isize;
+    let mut _18: &impl Fn(&T);
+    let mut _19: (&T,);
+    let _20: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _13;
+        let _17: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _17;
         }
         scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _15: &mut std::slice::Iter<'_, T>;
+            let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -61,7 +60,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_12);
+        StorageLive(_11);
         StorageLive(_3);
         StorageLive(_6);
         StorageLive(_4);
@@ -70,62 +69,59 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        _13 = Rev::<std::slice::Iter<'_, T>> { iter: _12 };
-        StorageDead(_12);
-        StorageLive(_14);
-        _14 = _13;
+        _12 = Rev::<std::slice::Iter<'_, T>> { iter: _11 };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
         StorageLive(_15);
-        _15 = &mut (_14.0: std::slice::Iter<'_, T>);
-        _16 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind unreachable];
+        StorageLive(_14);
+        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
+        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_14);
+        StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -134,18 +130,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = ((_16 as Some).0: &T);
+        _17 = ((_15 as Some).0: &T);
+        StorageLive(_18);
+        _18 = &_2;
         StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (_18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
+        _19 = (_17,);
+        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_20);
         StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_18);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index c7cd37afd86..532b8162521 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -4,35 +4,34 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _12: std::slice::Iter<'_, T>;
+    let mut _11: std::slice::Iter<'_, T>;
+    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
     let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _15: std::option::Option<&T>;
+    let mut _16: isize;
+    let mut _18: &impl Fn(&T);
+    let mut _19: (&T,);
+    let _20: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _13;
+        let _17: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _17;
         }
         scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _15: &mut std::slice::Iter<'_, T>;
+            let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: bool;
+            let mut _7: *mut T;
             let mut _8: *mut T;
-            let mut _9: *mut T;
-            let mut _11: *const T;
+            let mut _10: *const T;
             scope 5 {
                 let _6: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _10: *const T;
+                    let _9: *const T;
                     scope 7 {
                     }
                     scope 11 (inlined without_provenance::<T>) {
@@ -61,7 +60,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_12);
+        StorageLive(_11);
         StorageLive(_3);
         StorageLive(_6);
         StorageLive(_4);
@@ -70,62 +69,59 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _4 = &raw const (*_1);
         _5 = _4 as *const T (PtrToPtr);
         _6 = NonNull::<T> { pointer: _5 };
-        StorageLive(_10);
-        StorageLive(_7);
-        _7 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
-        switchInt(move _7) -> [0: bb1, otherwise: bb2];
+        StorageLive(_9);
+        switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_9);
         StorageLive(_8);
-        _8 = _4 as *mut T (PtrToPtr);
-        _9 = Offset(_8, _3);
+        StorageLive(_7);
+        _7 = _4 as *mut T (PtrToPtr);
+        _8 = Offset(_7, _3);
+        StorageDead(_7);
+        _9 = move _8 as *const T (PointerCoercion(MutToConstPointer));
         StorageDead(_8);
-        _10 = move _9 as *const T (PointerCoercion(MutToConstPointer));
-        StorageDead(_9);
         goto -> bb3;
     }
 
     bb2: {
-        _10 = _3 as *const T (Transmute);
+        _9 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_7);
-        StorageLive(_11);
-        _11 = _10;
-        _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_11);
+        StorageLive(_10);
+        _10 = _9;
+        _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_6);
         StorageDead(_3);
-        _13 = Rev::<std::slice::Iter<'_, T>> { iter: _12 };
-        StorageDead(_12);
-        StorageLive(_14);
-        _14 = _13;
+        _12 = Rev::<std::slice::Iter<'_, T>> { iter: _11 };
+        StorageDead(_11);
+        StorageLive(_13);
+        _13 = _12;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
         StorageLive(_15);
-        _15 = &mut (_14.0: std::slice::Iter<'_, T>);
-        _16 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind: bb11];
+        StorageLive(_14);
+        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
+        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_14);
+        _16 = discriminant(_15);
+        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_14);
+        StorageDead(_15);
+        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -134,18 +130,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = ((_16 as Some).0: &T);
+        _17 = ((_15 as Some).0: &T);
+        StorageLive(_18);
+        _18 = &_2;
         StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (_18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
+        _19 = (_17,);
+        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_20);
         StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_18);
+        StorageDead(_15);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/try_identity.rs b/tests/mir-opt/pre-codegen/try_identity.rs
index 2e17a3ae6e7..264b303e381 100644
--- a/tests/mir-opt/pre-codegen/try_identity.rs
+++ b/tests/mir-opt/pre-codegen/try_identity.rs
@@ -17,18 +17,16 @@ fn new<T, E>(x: Result<T, E>) -> Result<T, E> {
         } {
             ControlFlow::Continue(v) => v,
             ControlFlow::Break(e) => return Err(e),
-        }
+        },
     )
 }
 
 // EMIT_MIR try_identity.old.PreCodegen.after.mir
 fn old<T, E>(x: Result<T, E>) -> Result<T, E> {
-    Ok(
-        match x {
-            Ok(v) => v,
-            Err(e) => return Err(e),
-        }
-    )
+    Ok(match x {
+        Ok(v) => v,
+        Err(e) => return Err(e),
+    })
 }
 
 fn main() {
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index e0b0d699420..58d8b524ad6 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -658,7 +658,7 @@ fn read_through_raw(x: &mut usize) -> usize {
     // CHECK-NEXT: return;
 
     use std::intrinsics::mir::*;
-    mir!(
+    mir! {
         let r1: &mut usize;
         let r2: &mut usize;
         let p1: *mut usize;
@@ -674,7 +674,7 @@ fn read_through_raw(x: &mut usize) -> usize {
             RET = *p2;
             Return()
         }
-    )
+    }
 }
 
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
@@ -683,7 +683,7 @@ fn multiple_storage() {
     // CHECK: _3 = (*_2);
 
     use std::intrinsics::mir::*;
-    mir!(
+    mir! {
         let x: i32;
         {
             StorageLive(x);
@@ -700,7 +700,7 @@ fn multiple_storage() {
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
@@ -709,7 +709,7 @@ fn dominate_storage() {
     // CHECK: _5 = (*_2);
 
     use std::intrinsics::mir::*;
-    mir!(
+    mir! {
         let x: i32;
         let r: &i32;
         let c: i32;
@@ -730,7 +730,7 @@ fn dominate_storage() {
             let d = true;
             match d { false => bb2, _ => bb0 }
         }
-    )
+    }
 }
 
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
@@ -739,7 +739,7 @@ fn maybe_dead(m: bool) {
     // CHECK: (*_5) = const 7_i32;
 
     use std::intrinsics::mir::*;
-    mir!(
+    mir! {
         let x: i32;
         let y: i32;
         {
@@ -774,7 +774,7 @@ fn maybe_dead(m: bool) {
         retblock = {
             Return()
         }
-    )
+    }
 }
 
 fn mut_raw_then_mut_shr() -> (i32, i32) {
@@ -787,7 +787,9 @@ fn mut_raw_then_mut_shr() -> (i32, i32) {
     let xshr = &*xref;
     // Verify that we completely replace with `x` in both cases.
     let a = *xshr;
-    unsafe { *xraw = 4; }
+    unsafe {
+        *xraw = 4;
+    }
     (a, x)
 }
 
@@ -842,8 +844,7 @@ fn debuginfo() {
 
     // `constant_index_from_end` and `subslice` should not be promoted, as their value depends
     // on the slice length.
-    if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] {
-    }
+    if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] {}
 
     let multiple_borrow = &&&mut T(6).0;
 }
diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs
index 43d74aa5726..001c5599138 100644
--- a/tests/mir-opt/retag.rs
+++ b/tests/mir-opt/retag.rs
@@ -59,7 +59,9 @@ pub fn main() {
 fn array_casts() {
     let mut x: [usize; 2] = [0, 0];
     let p = &mut x as *mut usize;
-    unsafe { *p.add(1) = 1; }
+    unsafe {
+        *p.add(1) = 1;
+    }
 
     let x: [usize; 2] = [0, 1];
     let p = &x as *const usize;
diff --git a/tests/mir-opt/return_an_array.rs b/tests/mir-opt/return_an_array.rs
index 09146a824fc..673b5df7d73 100644
--- a/tests/mir-opt/return_an_array.rs
+++ b/tests/mir-opt/return_an_array.rs
@@ -2,8 +2,8 @@
 // this tests move up progration, which is not yet implemented
 
 fn foo() -> [u8; 1024] {
-        let x = [0; 1024];
-        return x;
+    let x = [0; 1024];
+    return x;
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/mir-opt/set_no_discriminant.rs b/tests/mir-opt/set_no_discriminant.rs
index 0c29d1faf02..586e28ae426 100644
--- a/tests/mir-opt/set_no_discriminant.rs
+++ b/tests/mir-opt/set_no_discriminant.rs
@@ -19,7 +19,7 @@ pub fn f() -> usize {
     // CHECK-NOT: goto
     // CHECK: switchInt(
     // CHECK-NOT: goto
-    mir!(
+    mir! {
         let a: isize;
         let e: E<char>;
         {
@@ -39,7 +39,7 @@ pub fn f() -> usize {
             RET = 1;
             Return()
         }
-    )
+    }
 }
 
 // EMIT_MIR set_no_discriminant.generic.JumpThreading.diff
@@ -49,7 +49,7 @@ pub fn generic<T>() -> usize {
     // CHECK-NOT: goto
     // CHECK: switchInt(
     // CHECK-NOT: goto
-    mir!(
+    mir! {
         let a: isize;
         let e: E<T>;
         {
@@ -69,7 +69,7 @@ pub fn generic<T>() -> usize {
             RET = 1;
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/mir-opt/simplify_dead_blocks.rs b/tests/mir-opt/simplify_dead_blocks.rs
index 686eac58236..b9a404fd35c 100644
--- a/tests/mir-opt/simplify_dead_blocks.rs
+++ b/tests/mir-opt/simplify_dead_blocks.rs
@@ -24,7 +24,7 @@ pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 {
     // CHECK-NEXT: _0 = _1;
     // CHECK-NEXT: return;
     // CHECK-NEXT: }
-    mir!(
+    mir! {
         {
             match x {
                 0 => unreachable,
@@ -48,5 +48,5 @@ pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 {
             RET = x;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/mir-opt/simplify_locals.rs b/tests/mir-opt/simplify_locals.rs
index f57611111cf..6511b5e87e4 100644
--- a/tests/mir-opt/simplify_locals.rs
+++ b/tests/mir-opt/simplify_locals.rs
@@ -1,13 +1,12 @@
 // skip-filecheck
 //@ test-mir-pass: SimplifyLocals-before-const-prop
 
-
 #![feature(thread_local)]
 
 #[derive(Copy, Clone)]
 enum E {
-     A,
-     B,
+    A,
+    B,
 }
 
 // EMIT_MIR simplify_locals.c.SimplifyLocals-before-const-prop.diff
@@ -26,7 +25,7 @@ fn d1() {
 // EMIT_MIR simplify_locals.d2.SimplifyLocals-before-const-prop.diff
 fn d2() {
     // Unused set discriminant
-    {(10, E::A)}.1 = E::B;
+    { (10, E::A) }.1 = E::B;
 }
 
 // EMIT_MIR simplify_locals.r.SimplifyLocals-before-const-prop.diff
@@ -37,7 +36,8 @@ fn r() {
     let _ = &mut a;
 }
 
-#[thread_local] static mut X: u32 = 0;
+#[thread_local]
+static mut X: u32 = 0;
 
 // EMIT_MIR simplify_locals.t1.SimplifyLocals-before-const-prop.diff
 fn t1() {
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.rs b/tests/mir-opt/simplify_locals_fixedpoint.rs
index 6947d31dc3e..0b6c95630c0 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.rs
+++ b/tests/mir-opt/simplify_locals_fixedpoint.rs
@@ -4,9 +4,7 @@
 
 fn foo<T>() {
     if let (Some(a), None) = (Option::<u8>::None, Option::<T>::None) {
-        if a > 42u8 {
-
-        }
+        if a > 42u8 {}
     }
 }
 
diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs
index 2eac93edbb8..b035b6339fa 100644
--- a/tests/mir-opt/simplify_match.rs
+++ b/tests/mir-opt/simplify_match.rs
@@ -5,8 +5,11 @@ fn noop() {}
 
 // EMIT_MIR simplify_match.main.GVN.diff
 fn main() {
-    match { let x = false; x } {
+    match {
+        let x = false;
+        x
+    } {
         true => noop(),
-        false => {},
+        false => {}
     }
 }
diff --git a/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..8818c891e94
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,12 @@
+- // MIR for `assign_const_to_return` before SingleUseConsts
++ // MIR for `assign_const_to_return` after SingleUseConsts
+  
+  fn assign_const_to_return() -> bool {
+      let mut _0: bool;
+  
+      bb0: {
+          _0 = const <T as MyTrait>::ASSOC_BOOL;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..8818c891e94
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.assign_const_to_return.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,12 @@
+- // MIR for `assign_const_to_return` before SingleUseConsts
++ // MIR for `assign_const_to_return` after SingleUseConsts
+  
+  fn assign_const_to_return() -> bool {
+      let mut _0: bool;
+  
+      bb0: {
+          _0 = const <T as MyTrait>::ASSOC_BOOL;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..468076e5ee3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,31 @@
+- // MIR for `if_const` before SingleUseConsts
++ // MIR for `if_const` after SingleUseConsts
+  
+  fn if_const() -> i32 {
+      let mut _0: i32;
+      let mut _1: bool;
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_BOOL;
+-         switchInt(move _1) -> [0: bb2, otherwise: bb1];
++         nop;
++         switchInt(const <T as MyTrait>::ASSOC_BOOL) -> [0: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          _0 = const 7_i32;
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _0 = const 42_i32;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..468076e5ee3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.if_const.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,31 @@
+- // MIR for `if_const` before SingleUseConsts
++ // MIR for `if_const` after SingleUseConsts
+  
+  fn if_const() -> i32 {
+      let mut _0: i32;
+      let mut _1: bool;
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_BOOL;
+-         switchInt(move _1) -> [0: bb2, otherwise: bb1];
++         nop;
++         switchInt(const <T as MyTrait>::ASSOC_BOOL) -> [0: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          _0 = const 7_i32;
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _0 = const 42_i32;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..ad1a2b300f2
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,46 @@
+- // MIR for `if_const_debug` before SingleUseConsts
++ // MIR for `if_const_debug` after SingleUseConsts
+  
+  fn if_const_debug() -> i32 {
+      let mut _0: i32;
+      let _1: bool;
+      let _2: ();
+      let mut _3: bool;
+      scope 1 {
+-         debug my_bool => _1;
++         debug my_bool => const <T as MyTrait>::ASSOC_BOOL;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_BOOL;
++         nop;
+          StorageLive(_2);
+          _2 = do_whatever() -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_2);
+          StorageLive(_3);
+-         _3 = _1;
++         _3 = const <T as MyTrait>::ASSOC_BOOL;
+          switchInt(move _3) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb2: {
+          _0 = const 7_i32;
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _0 = const 42_i32;
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_3);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..827a292e5d0
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.if_const_debug.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,46 @@
+- // MIR for `if_const_debug` before SingleUseConsts
++ // MIR for `if_const_debug` after SingleUseConsts
+  
+  fn if_const_debug() -> i32 {
+      let mut _0: i32;
+      let _1: bool;
+      let _2: ();
+      let mut _3: bool;
+      scope 1 {
+-         debug my_bool => _1;
++         debug my_bool => const <T as MyTrait>::ASSOC_BOOL;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_BOOL;
++         nop;
+          StorageLive(_2);
+          _2 = do_whatever() -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_2);
+          StorageLive(_3);
+-         _3 = _1;
++         _3 = const <T as MyTrait>::ASSOC_BOOL;
+          switchInt(move _3) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb2: {
+          _0 = const 7_i32;
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _0 = const 42_i32;
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_3);
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..f7d823af9e3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,14 @@
+- // MIR for `keep_parameter` before SingleUseConsts
++ // MIR for `keep_parameter` after SingleUseConsts
+  
+  fn keep_parameter(_1: i32) -> () {
+      debug other => _1;
+      let mut _0: ();
+  
+      bb0: {
+          _1 = const <T as MyTrait>::ASSOC_INT;
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..f7d823af9e3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.keep_parameter.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,14 @@
+- // MIR for `keep_parameter` before SingleUseConsts
++ // MIR for `keep_parameter` after SingleUseConsts
+  
+  fn keep_parameter(_1: i32) -> () {
+      debug other => _1;
+      let mut _0: ();
+  
+      bb0: {
+          _1 = const <T as MyTrait>::ASSOC_INT;
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..8d87438a47a
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,36 @@
+- // MIR for `match_const` before SingleUseConsts
++ // MIR for `match_const` after SingleUseConsts
+  
+  fn match_const() -> &str {
+      let mut _0: &str;
+      let mut _1: i32;
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
+-         switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
++         nop;
++         switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          _0 = const "world";
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _0 = const "hello";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _0 = const "towel";
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..8d87438a47a
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,36 @@
+- // MIR for `match_const` before SingleUseConsts
++ // MIR for `match_const` after SingleUseConsts
+  
+  fn match_const() -> &str {
+      let mut _0: &str;
+      let mut _1: i32;
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
+-         switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
++         nop;
++         switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          _0 = const "world";
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _0 = const "hello";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _0 = const "towel";
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..f192f3feb96
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_const_debug` before SingleUseConsts
++ // MIR for `match_const_debug` after SingleUseConsts
+  
+  fn match_const_debug() -> &str {
+      let mut _0: &str;
+      let _1: i32;
+      let _2: ();
+      scope 1 {
+-         debug my_int => _1;
++         debug my_int => const <T as MyTrait>::ASSOC_INT;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
++         nop;
+          StorageLive(_2);
+          _2 = do_whatever() -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_2);
+-         switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
++         switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+      }
+  
+      bb2: {
+          _0 = const "world";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          _0 = const "hello";
+          goto -> bb5;
+      }
+  
+      bb4: {
+          _0 = const "towel";
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..261faf415f3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_const_debug` before SingleUseConsts
++ // MIR for `match_const_debug` after SingleUseConsts
+  
+  fn match_const_debug() -> &str {
+      let mut _0: &str;
+      let _1: i32;
+      let _2: ();
+      scope 1 {
+-         debug my_int => _1;
++         debug my_int => const <T as MyTrait>::ASSOC_INT;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
++         nop;
+          StorageLive(_2);
+          _2 = do_whatever() -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_2);
+-         switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
++         switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+      }
+  
+      bb2: {
+          _0 = const "world";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          _0 = const "hello";
+          goto -> bb5;
+      }
+  
+      bb4: {
+          _0 = const "towel";
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-abort.diff
new file mode 100644
index 00000000000..8ef94a790a3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-abort.diff
@@ -0,0 +1,21 @@
+- // MIR for `never_used_debug` before SingleUseConsts
++ // MIR for `never_used_debug` after SingleUseConsts
+  
+  fn never_used_debug() -> () {
+      let mut _0: ();
+      let _1: i32;
+      scope 1 {
+-         debug my_int => _1;
++         debug my_int => const <T as MyTrait>::ASSOC_INT;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
++         nop;
+          _0 = const ();
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-unwind.diff
new file mode 100644
index 00000000000..8ef94a790a3
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.never_used_debug.SingleUseConsts.panic-unwind.diff
@@ -0,0 +1,21 @@
+- // MIR for `never_used_debug` before SingleUseConsts
++ // MIR for `never_used_debug` after SingleUseConsts
+  
+  fn never_used_debug() -> () {
+      let mut _0: ();
+      let _1: i32;
+      scope 1 {
+-         debug my_int => _1;
++         debug my_int => const <T as MyTrait>::ASSOC_INT;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+-         _1 = const <T as MyTrait>::ASSOC_INT;
++         nop;
+          _0 = const ();
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/single_use_consts.rs b/tests/mir-opt/single_use_consts.rs
new file mode 100644
index 00000000000..ecb602c647a
--- /dev/null
+++ b/tests/mir-opt/single_use_consts.rs
@@ -0,0 +1,80 @@
+//@ test-mir-pass: SingleUseConsts
+//@ compile-flags: -C debuginfo=full
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
+trait MyTrait {
+    const ASSOC_BOOL: bool;
+    const ASSOC_INT: i32;
+}
+
+// EMIT_MIR single_use_consts.if_const.SingleUseConsts.diff
+fn if_const<T: MyTrait>() -> i32 {
+    // CHECK-LABEL: fn if_const(
+    // CHECK: switchInt(const <T as MyTrait>::ASSOC_BOOL)
+    if T::ASSOC_BOOL { 7 } else { 42 }
+}
+
+// EMIT_MIR single_use_consts.match_const.SingleUseConsts.diff
+fn match_const<T: MyTrait>() -> &'static str {
+    // CHECK-LABEL: fn match_const(
+    // CHECK: switchInt(const <T as MyTrait>::ASSOC_INT)
+    match T::ASSOC_INT {
+        7 => "hello",
+        42 => "towel",
+        _ => "world",
+    }
+}
+
+// EMIT_MIR single_use_consts.if_const_debug.SingleUseConsts.diff
+fn if_const_debug<T: MyTrait>() -> i32 {
+    // CHECK-LABEL: fn if_const_debug(
+    // CHECK: my_bool => const <T as MyTrait>::ASSOC_BOOL;
+    // FIXME: `if` forces a temporary (unlike `match`), so the const isn't direct
+    // CHECK: _3 = const <T as MyTrait>::ASSOC_BOOL;
+    // CHECK: switchInt(move _3)
+    let my_bool = T::ASSOC_BOOL;
+    do_whatever();
+    if my_bool { 7 } else { 42 }
+}
+
+// EMIT_MIR single_use_consts.match_const_debug.SingleUseConsts.diff
+fn match_const_debug<T: MyTrait>() -> &'static str {
+    // CHECK-LABEL: fn match_const_debug(
+    // CHECK: my_int => const <T as MyTrait>::ASSOC_INT;
+    // CHECK: switchInt(const <T as MyTrait>::ASSOC_INT)
+    let my_int = T::ASSOC_INT;
+    do_whatever();
+    match my_int {
+        7 => "hello",
+        42 => "towel",
+        _ => "world",
+    }
+}
+
+// EMIT_MIR single_use_consts.never_used_debug.SingleUseConsts.diff
+#[allow(unused_variables)]
+fn never_used_debug<T: MyTrait>() {
+    // CHECK-LABEL: fn never_used_debug(
+    // CHECK: my_int => const <T as MyTrait>::ASSOC_INT;
+    // CHECK-NOT: ASSOC_INT
+    // CHECK: nop
+    // CHECK-NOT: ASSOC_INT
+    let my_int = T::ASSOC_INT;
+}
+
+// EMIT_MIR single_use_consts.assign_const_to_return.SingleUseConsts.diff
+fn assign_const_to_return<T: MyTrait>() -> bool {
+    // CHECK-LABEL: fn assign_const_to_return(
+    // CHECK: _0 = const <T as MyTrait>::ASSOC_BOOL;
+    T::ASSOC_BOOL
+}
+
+// EMIT_MIR single_use_consts.keep_parameter.SingleUseConsts.diff
+fn keep_parameter<T: MyTrait>(mut other: i32) {
+    // CHECK-LABEL: fn keep_parameter(
+    // CHECK: _1 = const <T as MyTrait>::ASSOC_INT;
+    // CHECK: _0 = const ();
+    other = T::ASSOC_INT;
+}
+
+fn do_whatever() {}
diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs
index 6c18dbaf5a2..90aa2a10938 100644
--- a/tests/mir-opt/sroa/lifetimes.rs
+++ b/tests/mir-opt/sroa/lifetimes.rs
@@ -19,10 +19,7 @@ fn foo<T: Err>() {
 
     // CHECK-NOT: [foo:_.*]: Foo
     // CHECK-NOT: Box<dyn std::fmt::Display + 'static>
-    let foo: Foo<T> = Foo {
-        x: Ok(Box::new(5_u32)),
-        y: 7_u32,
-    };
+    let foo: Foo<T> = Foo { x: Ok(Box::new(5_u32)), y: 7_u32 };
 
     let x = foo.x;
     let y = foo.y;
diff --git a/tests/mir-opt/switch_to_self.rs b/tests/mir-opt/switch_to_self.rs
index fc270fd33cf..51a7c13494f 100644
--- a/tests/mir-opt/switch_to_self.rs
+++ b/tests/mir-opt/switch_to_self.rs
@@ -8,7 +8,7 @@ use std::intrinsics::mir::*;
 // EMIT_MIR switch_to_self.test.MatchBranchSimplification.diff
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 pub fn test(x: bool) {
-    mir!(
+    mir! {
         {
             Goto(bb0)
         }
@@ -18,5 +18,5 @@ pub fn test(x: bool) {
         bb1 = {
             match x { false => bb0, _ => bb1 }
         }
-    )
+    }
 }
diff --git a/tests/mir-opt/uninhabited_enum.rs b/tests/mir-opt/uninhabited_enum.rs
index 8816f31f9df..859535852cf 100644
--- a/tests/mir-opt/uninhabited_enum.rs
+++ b/tests/mir-opt/uninhabited_enum.rs
@@ -6,15 +6,15 @@ pub enum Void {}
 // EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir
 #[no_mangle]
 pub fn process_never(input: *const !) {
-   let _input = unsafe { &*input };
+    let _input = unsafe { &*input };
 }
 
 // EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir
 #[no_mangle]
 pub fn process_void(input: *const Void) {
-   let _input = unsafe { &*input };
-   // In the future, this should end with `unreachable`, but we currently only do
-   // unreachability analysis for `!`.
+    let _input = unsafe { &*input };
+    // In the future, this should end with `unreachable`, but we currently only do
+    // unreachability analysis for `!`.
 }
 
 fn main() {}
diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs
index 5badfa1646b..cc0ac9a3427 100644
--- a/tests/mir-opt/unnamed-fields/field_access.rs
+++ b/tests/mir-opt/unnamed-fields/field_access.rs
@@ -17,7 +17,7 @@ struct Foo {
         _: struct {
             d: [u8; 1],
         }
-    }
+    },
 }
 
 #[repr(C)]
@@ -31,10 +31,9 @@ union Bar {
         _: union {
             d: [u8; 1],
         }
-    }
+    },
 }
 
-
 fn access<T>(_: T) {}
 
 // CHECK-LABEL: fn foo(
@@ -71,5 +70,4 @@ fn bar(bar: Bar) {
     }
 }
 
-
 fn main() {}
diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs
index 5838b35a553..881e3542f0a 100644
--- a/tests/mir-opt/unreachable.rs
+++ b/tests/mir-opt/unreachable.rs
@@ -35,7 +35,7 @@ fn if_let() {
             _y = 42;
         }
 
-        match _x { }
+        match _x {}
     }
 }
 
@@ -56,7 +56,7 @@ fn as_match() {
     // CHECK: return;
     match empty() {
         None => {}
-        Some(_x) => match _x {}
+        Some(_x) => match _x {},
     }
 }
 
diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs
index 78847543104..2f05981e812 100644
--- a/tests/mir-opt/unusual_item_types.rs
+++ b/tests/mir-opt/unusual_item_types.rs
@@ -3,7 +3,6 @@
 // that we don't create filenames containing `<` and `>`
 //@ compile-flags: -Zmir-opt-level=0
 
-
 struct A;
 
 // EMIT_MIR unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir
@@ -23,8 +22,8 @@ enum E {
     V = 5,
 }
 
+// EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
 pub fn main() {
     let f = Test::X as fn(usize) -> Test;
-// EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
     let v = Vec::<i32>::new();
 }
diff --git a/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir b/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir
index a5121ae550d..e2edbfcd4fa 100644
--- a/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir
+++ b/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/unusual_item_types.rs:10:1: 10:7>::ASSOCIATED_CONSTANT` after built
+// MIR for `<impl at $DIR/unusual_item_types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT` after built
 
-const <impl at $DIR/unusual_item_types.rs:10:1: 10:7>::ASSOCIATED_CONSTANT: i32 = {
+const <impl at $DIR/unusual_item_types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 = {
     let mut _0: i32;
 
     bb0: {
diff --git a/tests/pretty/ast-stmt-expr-attr.rs b/tests/pretty/ast-stmt-expr-attr.rs
index 899f7173f70..fd7272a1b1f 100644
--- a/tests/pretty/ast-stmt-expr-attr.rs
+++ b/tests/pretty/ast-stmt-expr-attr.rs
@@ -13,17 +13,17 @@ fn syntax() {
     let _ = #[attr] ();
     let _ = #[attr] (#[attr] 0,);
     let _ = #[attr] (#[attr] 0, 0);
-    let _ = (#[attr] 0) + #[attr] 0;
-    let _ = (#[attr] 0) / #[attr] 0;
-    let _ = (#[attr] 0) & #[attr] 0;
-    let _ = (#[attr] 0) % #[attr] 0;
+    let _ = #[attr] 0 + #[attr] 0;
+    let _ = #[attr] 0 / #[attr] 0;
+    let _ = #[attr] 0 & #[attr] 0;
+    let _ = #[attr] 0 % #[attr] 0;
     let _ = #[attr] (0 + 0);
     let _ = #[attr] !0;
     let _ = #[attr] -0;
     let _ = #[attr] false;
     let _ = #[attr] 0;
     let _ = #[attr] 'c';
-    let _ = (#[attr] x) as Y;
+    let _ = #[attr] x as Y;
     let _ = #[attr] (x as Y);
     let _ =
         #[attr] while true {
@@ -88,9 +88,9 @@ fn syntax() {
             let _ = ();
             foo
         };
-    let _ = (#[attr] x) = y;
+    let _ = #[attr] x = y;
     let _ = #[attr] (x = y);
-    let _ = (#[attr] x) += y;
+    let _ = #[attr] x += y;
     let _ = #[attr] (x += y);
     let _ = #[attr] foo.bar;
     let _ = (#[attr] foo).bar;
@@ -98,8 +98,8 @@ fn syntax() {
     let _ = (#[attr] foo).0;
     let _ = #[attr] foo[bar];
     let _ = (#[attr] foo)[bar];
-    let _ = (#[attr] 0)..#[attr] 0;
-    let _ = (#[attr] 0)..;
+    let _ = #[attr] 0..#[attr] 0;
+    let _ = #[attr] 0..;
     let _ = #[attr] (0..0);
     let _ = #[attr] (0..);
     let _ = #[attr] (..0);
diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp
index 978e65c825b..dfbaff69644 100644
--- a/tests/pretty/hir-fn-variadic.pp
+++ b/tests/pretty/hir-fn-variadic.pp
@@ -9,7 +9,7 @@ use ::std::prelude::rust_2015::*;
 extern crate std;
 
 extern "C" {
-    fn foo(x: i32, va1: ...);
+    unsafe fn foo(x: i32, va1: ...);
 }
 
 unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index f9041268211..01a503ce7ee 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -147,13 +147,13 @@ fn _11() {
     let _ = #[rustc_dummy] (0);
     let _ = #[rustc_dummy] (0,);
     let _ = #[rustc_dummy] (0, 0);
-    let _ = (#[rustc_dummy] 0) + #[rustc_dummy] 0;
+    let _ = #[rustc_dummy] 0 + #[rustc_dummy] 0;
     let _ = #[rustc_dummy] !0;
     let _ = #[rustc_dummy] -0i32;
     let _ = #[rustc_dummy] false;
     let _ = #[rustc_dummy] 'c';
     let _ = #[rustc_dummy] 0;
-    let _ = (#[rustc_dummy] 0) as usize;
+    let _ = #[rustc_dummy] 0 as usize;
     let _ =
         #[rustc_dummy] while false {
             #![rustc_dummy]
@@ -206,10 +206,15 @@ fn _11() {
             let _ = ();
             ()
         };
-    let const {} = #[rustc_dummy] const {};
+    let const {
+                    #![rustc_dummy]
+                } =
+        #[rustc_dummy] const {
+                #![rustc_dummy]
+            };
     let mut x = 0;
-    let _ = (#[rustc_dummy] x) = 15;
-    let _ = (#[rustc_dummy] x) += 15;
+    let _ = #[rustc_dummy] x = 15;
+    let _ = #[rustc_dummy] x += 15;
     let s = Foo { data: () };
     let _ = #[rustc_dummy] s.data;
     let _ = (#[rustc_dummy] s).data;
@@ -219,8 +224,8 @@ fn _11() {
     let v = vec!(0);
     let _ = #[rustc_dummy] v[0];
     let _ = (#[rustc_dummy] v)[0];
-    let _ = (#[rustc_dummy] 0)..#[rustc_dummy] 0;
-    let _ = (#[rustc_dummy] 0)..;
+    let _ = #[rustc_dummy] 0..#[rustc_dummy] 0;
+    let _ = #[rustc_dummy] 0..;
     let _ = #[rustc_dummy] (0..0);
     let _ = #[rustc_dummy] (0..);
     let _ = #[rustc_dummy] (..0);
diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile b/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile
deleted file mode 100644
index 3a5a66b6755..00000000000
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-include ../../run-make/tools.mk
-
-# ignore-stage1
-
-# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen
-# backends and that this external codegen backend is only included in the dep info if
-# -Zbinary-dep-depinfo is used.
-
-all:
-	$(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
-		-o $(TMPDIR)/the_backend.dylib
-
-	$(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
-		-Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
-		--emit link,dep-info
-	grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
-	# don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used.
-	grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d
-	
-	$(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
-		-Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
-		--emit link,dep-info -Zbinary-dep-depinfo
-	grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
-	# but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used.
-	grep "the_backend.dylib" $(TMPDIR)/some_crate.d
diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs
deleted file mode 100644
index da27b7f3463..00000000000
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#![feature(no_core)]
-#![no_core]
diff --git a/tests/run-make-fulldeps/issue-19371/Makefile b/tests/run-make-fulldeps/issue-19371/Makefile
deleted file mode 100644
index edec68f0862..00000000000
--- a/tests/run-make-fulldeps/issue-19371/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../../run-make/tools.mk
-
-# This test ensures that rustc compile_input can be called twice in one task
-# without causing a panic.
-# The program needs the path to rustc to get sysroot.
-
-all:
-	$(RUSTC) foo.rs
-	$(call RUN,foo $(TMPDIR) $(RUSTC))
diff --git a/tests/run-make-fulldeps/obtain-borrowck/Makefile b/tests/run-make-fulldeps/obtain-borrowck/Makefile
deleted file mode 100644
index 233f5c9eaf4..00000000000
--- a/tests/run-make-fulldeps/obtain-borrowck/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-include ../../run-make/tools.mk
-
-# This example shows how to implement a rustc driver that retrieves MIR bodies
-# together with the borrow checker information.
-
-# How to run this
-# $ ./x.py test tests/run-make-fulldeps/obtain-borrowck
-
-DRIVER_BINARY := "$(TMPDIR)"/driver
-SYSROOT := $(shell $(RUSTC) --print sysroot)
-
-ifdef IS_WINDOWS
-LIBSTD := -L "$(SYSROOT)\\lib\\rustlib\\$(TARGET)\\lib"
-else
-LIBSTD :=
-endif
-
-all:
-	$(RUSTC) driver.rs -o "$(DRIVER_BINARY)"
-	$(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) $(LIBSTD) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout
-
-ifdef RUSTC_BLESS_TEST
-	cp "$(TMPDIR)"/output.stdout output.stdout
-else
-	$(DIFF) output.stdout "$(TMPDIR)"/output.stdout
-endif
diff --git a/tests/run-make-fulldeps/pretty-expanded/Makefile b/tests/run-make-fulldeps/pretty-expanded/Makefile
deleted file mode 100644
index 48199179ece..00000000000
--- a/tests/run-make-fulldeps/pretty-expanded/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../../run-make/tools.mk
-
-all:
-	$(RUSTC) -o $(TMPDIR)/input.expanded.rs -Zunpretty=expanded input.rs
diff --git a/tests/run-make-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs
deleted file mode 100644
index 02b235068a1..00000000000
--- a/tests/run-make-fulldeps/pretty-expanded/input.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// #13544
-
-#[derive(Debug)] pub struct A;
-#[derive(Debug)] pub struct B(isize);
-#[derive(Debug)] pub struct C { x: isize }
-#[derive(Debug)] pub enum D {}
-#[derive(Debug)] pub enum E { y }
-#[derive(Debug)] pub enum F { z(isize) }
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index 1bdb6347571..f913aedcde7 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -5,19 +5,15 @@
 
 use std::path::PathBuf;
 
-use run_make_support::{aux_build, rustc};
+use run_make_support::{aux_build, rustc, source_root};
 
 fn main() {
     aux_build().input("stable.rs").emit("metadata").run();
 
-    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).command_output();
+        rustc().input("main.rs").emit("metadata").extern_("stable", "libstable.rmeta").run();
 
-    let stderr = String::from_utf8_lossy(&output.stderr);
-    let version = include_str!(concat!(env!("S"), "/src/version"));
+    let version = std::fs::read_to_string(source_root().join("src/version")).unwrap();
     let expected_string = format!("stable since {}", version.trim());
-    assert!(stderr.contains(&expected_string));
+    output.assert_stderr_contains(expected_string);
 }
diff --git a/tests/run-make/README.md b/tests/run-make/README.md
new file mode 100644
index 00000000000..a6c1b4b7db7
--- /dev/null
+++ b/tests/run-make/README.md
@@ -0,0 +1,43 @@
+# The `run-make` test suite
+
+The `run-make` test suite contains tests which are the most flexible out of all
+the [rust-lang/rust](https://github.com/rust-lang/rust) test suites. `run-make`
+tests can basically contain arbitrary code, and are supported by the
+[`run_make_support`] library.
+
+## Infrastructure
+
+There are two kinds of run-make tests:
+
+1. The new `rmake.rs` version: this allows run-make tests to be written in Rust
+   (with `rmake.rs` as the main test file).
+2. The legacy `Makefile` version: this is what run-make tests were written with
+   before support for `rmake.rs` was introduced.
+
+The implementation for collecting and building the `rmake.rs` recipes (or
+`Makefile`s) are in
+[`src/tools/compiletest/src/runtest.rs`](../../src/tools/compiletest/src/runtest.rs),
+in `run_rmake_v2_test` and `run_rmake_legacy_test`.
+
+### Rust-based `run-make` tests: `rmake.rs`
+
+The setup for the `rmake.rs` version is a 3-stage process:
+
+1. First, we build the [`run_make_support`] library in bootstrap as a tool lib.
+2. Then, we compile the `rmake.rs` "recipe" linking the support library and its
+   dependencies in, and provide a bunch of env vars. We setup a directory
+   structure within `build/<target>/test/run-make/`
+
+   ```
+   <test-name>/
+       rmake.exe              # recipe binary
+       rmake_out/             # sources from test sources copied over
+   ```
+
+   and copy non-`rmake.rs` input support files over to `rmake_out/`. The
+   support library is made available as an [*extern prelude*][extern_prelude].
+3. Finally, we run the recipe binary and set `rmake_out/` as the working
+   directory.
+
+[`run_make_support`]: ../../src/tools/run-make-support
+[extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude
diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs
index 4bca5d1f1ef..89a6636d9a0 100644
--- a/tests/run-make/alloc-no-oom-handling/rmake.rs
+++ b/tests/run-make/alloc-no-oom-handling/rmake.rs
@@ -2,14 +2,14 @@
 // when the unstable no_global_oom_handling feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
-use run_make_support::rustc;
+use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
         .edition("2021")
         .arg("-Dwarnings")
         .crate_type("rlib")
-        .input("../../../library/alloc/src/lib.rs")
+        .input(source_root().join("library/alloc/src/lib.rs"))
         .cfg("no_global_oom_handling")
         .run();
 }
diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs
index 8ff73324b08..12171c2148f 100644
--- a/tests/run-make/alloc-no-rc/rmake.rs
+++ b/tests/run-make/alloc-no-rc/rmake.rs
@@ -2,14 +2,14 @@
 // when the unstable no_rc feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
-use run_make_support::rustc;
+use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
         .edition("2021")
         .arg("-Dwarnings")
         .crate_type("rlib")
-        .input("../../../library/alloc/src/lib.rs")
+        .input(source_root().join("library/alloc/src/lib.rs"))
         .cfg("no_rc")
         .run();
 }
diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs
index 3a3ceed6867..29f204f3067 100644
--- a/tests/run-make/alloc-no-sync/rmake.rs
+++ b/tests/run-make/alloc-no-sync/rmake.rs
@@ -2,14 +2,14 @@
 // when the unstable no_sync feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
-use run_make_support::rustc;
+use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
         .edition("2021")
         .arg("-Dwarnings")
         .crate_type("rlib")
-        .input("../../../library/alloc/src/lib.rs")
+        .input(source_root().join("library/alloc/src/lib.rs"))
         .cfg("no_sync")
         .run();
 }
diff --git a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs
index 8f6fe6bd0b6..22a31266176 100644
--- a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs
+++ b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs
@@ -1,11 +1,13 @@
 // Test that `-Awarnings` suppresses warnings for unstable APIs.
 
-use run_make_support::{assert_not_contains, rustc};
+use run_make_support::rustc;
 
 fn main() {
     rustc().input("bar.rs").run();
-    let output = rustc().input("foo.rs").arg("-Awarnings").run();
-
-    assert_not_contains(&String::from_utf8(output.stdout).unwrap(), "warning");
-    assert_not_contains(&String::from_utf8(output.stderr).unwrap(), "warning");
+    rustc()
+        .input("foo.rs")
+        .arg("-Awarnings")
+        .run()
+        .assert_stdout_not_contains("warning")
+        .assert_stderr_not_contains("warning");
 }
diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs
index 13230206ca8..88f4d664aa6 100644
--- a/tests/run-make/arguments-non-c-like-enum/rmake.rs
+++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs
@@ -1,14 +1,14 @@
 //! Check that non-trivial `repr(C)` enum in Rust has valid C layout.
 //@ ignore-cross-compile
 
-use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib};
+use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib_name};
 
 pub fn main() {
     use std::path::Path;
 
     rustc().input("nonclike.rs").crate_type("staticlib").run();
     cc().input("test.c")
-        .input(static_lib("nonclike"))
+        .input(static_lib_name("nonclike"))
         .out_exe("test")
         .args(&extra_c_flags())
         .args(&extra_cxx_flags())
diff --git a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs
index 6613698ae1d..d5bc46dff47 100644
--- a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs
+++ b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs
@@ -5,17 +5,15 @@
 //
 // Fixes: rust-lang/rust#123234
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
-    let inc_dir = tmp_dir();
-
     for _ in 0..=1 {
         rustc()
             .input("lib.rs")
             .crate_type("lib")
             .emit("asm,dep-info,link,mir,llvm-ir,llvm-bc")
-            .incremental(&inc_dir)
+            .incremental("incremental")
             .run();
     }
 }
diff --git a/tests/run-make/artifact-incr-cache/rmake.rs b/tests/run-make/artifact-incr-cache/rmake.rs
index 106f363eb8d..b4b63313cfc 100644
--- a/tests/run-make/artifact-incr-cache/rmake.rs
+++ b/tests/run-make/artifact-incr-cache/rmake.rs
@@ -7,17 +7,15 @@
 // Also see discussion at
 // <https://internals.rust-lang.org/t/interaction-between-incremental-compilation-and-emit/20551>
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
-    let inc_dir = tmp_dir();
-
     for _ in 0..=1 {
         rustc()
             .input("lib.rs")
             .crate_type("lib")
             .emit("obj,asm,dep-info,link,mir,llvm-ir,llvm-bc")
-            .incremental(&inc_dir)
+            .incremental("incremental")
             .run();
     }
 }
diff --git a/tests/run-make/bare-outfile/Makefile b/tests/run-make/bare-outfile/Makefile
deleted file mode 100644
index ad6fe4bd167..00000000000
--- a/tests/run-make/bare-outfile/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# 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
-
-all:
-	cp foo.rs $(TMPDIR)
-	cd $(TMPDIR) && $(RUSTC) -o foo foo.rs
-	$(call RUN,foo)
diff --git a/tests/run-make/bare-outfile/rmake.rs b/tests/run-make/bare-outfile/rmake.rs
new file mode 100644
index 00000000000..badf1396b73
--- /dev/null
+++ b/tests/run-make/bare-outfile/rmake.rs
@@ -0,0 +1,11 @@
+// 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
+
+use run_make_support::{run, rustc};
+
+fn main() {
+    rustc().output("foo").input("foo.rs").run();
+    run("foo");
+}
diff --git a/tests/run-make/box-struct-no-segfault/rmake.rs b/tests/run-make/box-struct-no-segfault/rmake.rs
index 5406f765e6c..1bbefd03541 100644
--- a/tests/run-make/box-struct-no-segfault/rmake.rs
+++ b/tests/run-make/box-struct-no-segfault/rmake.rs
@@ -5,9 +5,9 @@
 // This test checks that this bug does not resurface.
 // See https://github.com/rust-lang/rust/issues/28766
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     rustc().opt().input("foo.rs").run();
-    rustc().opt().library_search_path(tmp_dir()).input("main.rs").run();
+    rustc().opt().input("main.rs").run();
 }
diff --git a/tests/run-make/c-link-to-rust-dylib/rmake.rs b/tests/run-make/c-link-to-rust-dylib/rmake.rs
index 5c4b6d78649..ec42e88032d 100644
--- a/tests/run-make/c-link-to-rust-dylib/rmake.rs
+++ b/tests/run-make/c-link-to-rust-dylib/rmake.rs
@@ -5,29 +5,23 @@
 
 use std::fs::remove_file;
 
-use run_make_support::{
-    cc, dynamic_lib_extension, is_msvc, read_dir, run, run_fail, rustc, tmp_dir,
-};
+use run_make_support::{cc, cwd, dynamic_lib_extension, is_msvc, read_dir, run, run_fail, rustc};
 
 fn main() {
     rustc().input("foo.rs").run();
 
     if is_msvc() {
-        let lib = tmp_dir().join("foo.dll.lib");
+        let lib = "foo.dll.lib";
 
         cc().input("bar.c").arg(lib).out_exe("bar").run();
     } else {
-        cc().input("bar.c")
-            .arg("-lfoo")
-            .output(tmp_dir().join("bar"))
-            .library_search_path(tmp_dir())
-            .run();
+        cc().input("bar.c").arg("-lfoo").output("bar").library_search_path(cwd()).run();
     }
 
     run("bar");
 
     let expected_extension = dynamic_lib_extension();
-    read_dir(tmp_dir(), |path| {
+    read_dir(cwd(), |path| {
         if path.is_file()
             && path.extension().is_some_and(|ext| ext == expected_extension)
             && path.file_name().and_then(|name| name.to_str()).is_some_and(|name| {
diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
index 63d5eb78c69..ca28944a026 100644
--- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs
+++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
@@ -3,13 +3,13 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};
 use std::fs;
 
 fn main() {
     rustc().input("foo.rs").run();
-    cc().input("bar.c").input(static_lib("foo")).out_exe("bar").args(&extra_c_flags()).run();
+    cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(&extra_c_flags()).run();
     run("bar");
-    fs::remove_file(static_lib("foo"));
+    fs::remove_file(static_lib_name("foo"));
     run("bar");
 }
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs
index 7a450efff94..a01e259bce0 100644
--- a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs
+++ b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs
@@ -5,12 +5,12 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};
 
 fn main() {
     rustc().input("checkrust.rs").run();
     cc().input("test.c")
-        .input(static_lib("checkrust"))
+        .input(static_lib_name("checkrust"))
         .out_exe("test")
         .args(&extra_c_flags())
         .run();
diff --git a/tests/run-make/cdylib/rmake.rs b/tests/run-make/cdylib/rmake.rs
index fcb4f56621f..81166867b79 100644
--- a/tests/run-make/cdylib/rmake.rs
+++ b/tests/run-make/cdylib/rmake.rs
@@ -12,24 +12,20 @@
 
 use std::fs::remove_file;
 
-use run_make_support::{cc, dynamic_lib, is_msvc, run, rustc, tmp_dir};
+use run_make_support::{cc, cwd, dynamic_lib_name, is_msvc, run, rustc};
 
 fn main() {
     rustc().input("bar.rs").run();
     rustc().input("foo.rs").run();
 
     if is_msvc() {
-        cc().input("foo.c").arg(tmp_dir().join("foo.dll.lib")).out_exe("foo").run();
+        cc().input("foo.c").arg("foo.dll.lib").out_exe("foo").run();
     } else {
-        cc().input("foo.c")
-            .arg("-lfoo")
-            .output(tmp_dir().join("foo"))
-            .library_search_path(tmp_dir())
-            .run();
+        cc().input("foo.c").arg("-lfoo").library_search_path(cwd()).output("foo").run();
     }
 
     run("foo");
-    remove_file(dynamic_lib("foo")).unwrap();
+    remove_file(dynamic_lib_name("foo")).unwrap();
 
     rustc().input("foo.rs").arg("-Clto").run();
     run("foo");
diff --git a/tests/run-make/compiler-builtins/Cargo.toml b/tests/run-make/compiler-builtins/Cargo.toml
new file mode 100644
index 00000000000..869210c4a68
--- /dev/null
+++ b/tests/run-make/compiler-builtins/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "scratch"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "lib.rs"
diff --git a/tests/run-make/compiler-builtins/lib.rs b/tests/run-make/compiler-builtins/lib.rs
new file mode 100644
index 00000000000..0c9ac1ac8e4
--- /dev/null
+++ b/tests/run-make/compiler-builtins/lib.rs
@@ -0,0 +1 @@
+#![no_std]
diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs
index f5da50ebb04..a2c0ad5f6de 100644
--- a/tests/run-make/compiler-builtins/rmake.rs
+++ b/tests/run-make/compiler-builtins/rmake.rs
@@ -14,40 +14,27 @@
 
 #![deny(warnings)]
 
-use run_make_support::object;
 use run_make_support::object::read::archive::ArchiveFile;
 use run_make_support::object::read::Object;
 use run_make_support::object::ObjectSection;
 use run_make_support::object::ObjectSymbol;
 use run_make_support::object::RelocationTarget;
-use run_make_support::set_host_rpath;
-use run_make_support::tmp_dir;
+use run_make_support::{cmd, env_var, object};
 use std::collections::HashSet;
-
-const MANIFEST: &str = r#"
-[package]
-name = "scratch"
-version = "0.1.0"
-edition = "2021"
-
-[lib]
-path = "lib.rs""#;
+use std::path::PathBuf;
 
 fn main() {
-    let target_dir = tmp_dir().join("target");
-    let target = std::env::var("TARGET").unwrap();
+    let target_dir = PathBuf::from("target");
+    let target = env_var("TARGET");
 
     println!("Testing compiler_builtins for {}", target);
 
-    // Set up the tiniest Cargo project: An empty no_std library. Just enough to run -Zbuild-std.
-    let manifest_path = tmp_dir().join("Cargo.toml");
-    std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap();
-    std::fs::write(tmp_dir().join("lib.rs"), b"#![no_std]").unwrap();
+    let manifest_path = PathBuf::from("Cargo.toml");
 
-    let path = std::env::var("PATH").unwrap();
-    let rustc = std::env::var("RUSTC").unwrap();
-    let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap();
-    let mut cmd = std::process::Command::new(bootstrap_cargo);
+    let path = env_var("PATH");
+    let rustc = env_var("RUSTC");
+    let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
+    let mut cmd = cmd(bootstrap_cargo);
     cmd.args([
         "build",
         "--manifest-path",
@@ -56,7 +43,6 @@ fn main() {
         "--target",
         &target,
     ])
-    .env_clear()
     .env("PATH", path)
     .env("RUSTC", rustc)
     .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes")
@@ -65,10 +51,8 @@ fn main() {
     // Visual Studio 2022 requires that the LIB env var be set so it can
     // find the Windows SDK.
     .env("LIB", std::env::var("LIB").unwrap_or_default());
-    set_host_rpath(&mut cmd);
 
-    let status = cmd.status().unwrap();
-    assert!(status.success());
+    cmd.run();
 
     let rlibs_path = target_dir.join(target).join("debug").join("deps");
     let compiler_builtins_rlib = std::fs::read_dir(rlibs_path)
diff --git a/tests/run-make/const-prop-lint/rmake.rs b/tests/run-make/const-prop-lint/rmake.rs
index fa27a18a591..c35294f2f5a 100644
--- a/tests/run-make/const-prop-lint/rmake.rs
+++ b/tests/run-make/const-prop-lint/rmake.rs
@@ -2,12 +2,12 @@
 
 use std::fs;
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::{cwd, rustc};
 
 fn main() {
-    rustc().input("input.rs").run_fail_assert_exit_code(1);
+    rustc().input("input.rs").run_fail().assert_exit_code(1);
 
-    for entry in fs::read_dir(tmp_dir()).unwrap() {
+    for entry in fs::read_dir(cwd()).unwrap() {
         let entry = entry.unwrap();
         let path = entry.path();
 
diff --git a/tests/run-make/core-no-fp-fmt-parse/rmake.rs b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
index aef28fd2528..3586922f28e 100644
--- a/tests/run-make/core-no-fp-fmt-parse/rmake.rs
+++ b/tests/run-make/core-no-fp-fmt-parse/rmake.rs
@@ -1,14 +1,14 @@
 // This test checks that the core library of Rust can be compiled without enabling
 // support for formatting and parsing floating-point numbers.
 
-use run_make_support::rustc;
+use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
         .edition("2021")
         .arg("-Dwarnings")
         .crate_type("rlib")
-        .input("../../../library/core/src/lib.rs")
+        .input(source_root().join("library/core/src/lib.rs"))
         .cfg("no_fp_fmt_parse")
         .run();
 }
diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs
index 75767421cd1..a9e2b33e210 100644
--- a/tests/run-make/core-no-oom-handling/rmake.rs
+++ b/tests/run-make/core-no-oom-handling/rmake.rs
@@ -2,15 +2,15 @@
 // when the no_global_oom_handling feature is turned on.
 // See https://github.com/rust-lang/rust/pull/110649
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
         .edition("2021")
         .arg("-Dwarnings")
         .crate_type("rlib")
-        .input("../../../library/core/src/lib.rs")
-        .sysroot(tmp_dir().join("fakeroot"))
+        .input(source_root().join("library/core/src/lib.rs"))
+        .sysroot("fakeroot")
         .cfg("no_global_oom_handling")
         .run();
 }
diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs
index 86fe5593e66..70f8e46b6d9 100644
--- a/tests/run-make/crate-data-smoke/rmake.rs
+++ b/tests/run-make/crate-data-smoke/rmake.rs
@@ -1,22 +1,21 @@
-use std::process::Output;
-
 use run_make_support::{bin_name, rust_lib_name, rustc};
 
-fn compare_stdout<S: AsRef<str>>(output: Output, expected: S) {
-    assert_eq!(String::from_utf8(output.stdout).unwrap().trim(), expected.as_ref());
-}
-
 fn main() {
-    compare_stdout(rustc().print("crate-name").input("crate.rs").run(), "foo");
-    compare_stdout(rustc().print("file-names").input("crate.rs").run(), bin_name("foo"));
-    compare_stdout(
-        rustc().print("file-names").crate_type("lib").arg("--test").input("crate.rs").run(),
-        bin_name("foo"),
-    );
-    compare_stdout(
-        rustc().print("file-names").arg("--test").input("lib.rs").run(),
-        bin_name("mylib"),
-    );
-    compare_stdout(rustc().print("file-names").input("lib.rs").run(), rust_lib_name("mylib"));
-    compare_stdout(rustc().print("file-names").input("rlib.rs").run(), rust_lib_name("mylib"));
+    rustc().print("crate-name").input("crate.rs").run().assert_stdout_equals("foo");
+    rustc().print("file-names").input("crate.rs").run().assert_stdout_equals(bin_name("foo"));
+    rustc()
+        .print("file-names")
+        .crate_type("lib")
+        .arg("--test")
+        .input("crate.rs")
+        .run()
+        .assert_stdout_equals(bin_name("foo"));
+    rustc()
+        .print("file-names")
+        .arg("--test")
+        .input("lib.rs")
+        .run()
+        .assert_stdout_equals(bin_name("mylib"));
+    rustc().print("file-names").input("lib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
+    rustc().print("file-names").input("rlib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
 }
diff --git a/tests/run-make/cross-lang-lto-clang/Makefile b/tests/run-make/cross-lang-lto-clang/Makefile
index acaebf439d6..acf49c8f5c8 100644
--- a/tests/run-make/cross-lang-lto-clang/Makefile
+++ b/tests/run-make/cross-lang-lto-clang/Makefile
@@ -1,4 +1,4 @@
-# needs-matching-clang
+# needs-force-clang-based-tests
 
 # This test makes sure that cross-language inlining actually works by checking
 # the generated machine code.
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
index 70085d9bde1..738e23f9c66 100644
--- a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
+++ b/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
@@ -1,4 +1,7 @@
-# needs-matching-clang
+# needs-force-clang-based-tests
+
+# FIXME(#126180): This test doesn't actually run anywhere, because the only
+# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
 
 # This test makes sure that cross-language inlining can be used in conjunction
 # with profile-guided optimization. The test only tests that the whole workflow
diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
index 61f32762d8b..f40da662128 100644
--- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
+++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
@@ -1,9 +1,12 @@
 //! Make sure that cross-language LTO works on riscv targets,
 //! which requires extra `target-abi` metadata to be emitted.
-//@ needs-matching-clang
+//@ needs-force-clang-based-tests
 //@ needs-llvm-components riscv
 
-use run_make_support::{bin_name, clang, llvm_readobj, rustc, tmp_dir};
+// FIXME(#126180): This test doesn't actually run anywhere, because the only
+// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
+
+use run_make_support::{bin_name, clang, llvm_readobj, rustc};
 use std::{
     env,
     path::PathBuf,
@@ -30,11 +33,11 @@ fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float:
         .no_stdlib()
         .out_exe("riscv-xlto")
         .input("cstart.c")
-        .input(tmp_dir().join("libriscv_xlto.rlib"))
+        .input("libriscv_xlto.rlib")
         .run();
 
     // Check that the built binary has correct float abi
-    let executable = tmp_dir().join(bin_name("riscv-xlto"));
+    let executable = bin_name("riscv-xlto");
     let output = llvm_readobj().input(&executable).file_header().run();
     let stdout = String::from_utf8_lossy(&output.stdout);
     eprintln!("obj:\n{}", stdout);
diff --git a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs
index c2156de03a9..91fc0a9025f 100644
--- a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs
+++ b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs
@@ -7,10 +7,10 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{rustc, rustdoc, tmp_dir};
+use run_make_support::{cwd, rustc, rustdoc};
 
 fn main() {
     rustc().input("foo.rs").run();
     rustc().input("bar.rs").run();
-    rustdoc().input("baz.rs").library_search_path(tmp_dir()).output(tmp_dir()).run();
+    rustdoc().input("baz.rs").library_search_path(cwd()).output(cwd()).run();
 }
diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs
index 0613ef4839b..5bc9480e4a3 100644
--- a/tests/run-make/doctests-keep-binaries/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries/rmake.rs
@@ -1,15 +1,15 @@
 // Check that valid binaries are persisted by running them, regardless of whether the
 // --run or --no-run option is used.
 
-use run_make_support::{run, rustc, rustdoc, tmp_dir};
+use run_make_support::{run, rustc, rustdoc};
 use std::fs::{create_dir, remove_dir_all};
 use std::path::Path;
 
 fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
-    let out_dir = tmp_dir().join("doctests");
+    let out_dir = Path::new("doctests");
     create_dir(&out_dir).expect("failed to create doctests folder");
     rustc().input("t.rs").crate_type("rlib").run();
-    callback(&out_dir, &tmp_dir().join("libt.rlib"));
+    callback(&out_dir, Path::new("libt.rlib"));
     remove_dir_all(out_dir);
 }
 
@@ -44,19 +44,17 @@ fn main() {
     });
     // Behavior with --test-run-directory with relative paths.
     setup_test_env(|_out_dir, extern_path| {
-        let run_dir = "rundir";
-        let run_dir_path = tmp_dir().join("rundir");
+        let run_dir_path = Path::new("rundir");
         create_dir(&run_dir_path).expect("failed to create rundir folder");
 
         rustdoc()
-            .current_dir(tmp_dir())
-            .input(std::env::current_dir().unwrap().join("t.rs"))
+            .input("t.rs")
             .arg("-Zunstable-options")
             .arg("--test")
             .arg("--persist-doctests")
             .arg("doctests")
             .arg("--test-run-directory")
-            .arg(run_dir)
+            .arg(run_dir_path)
             .extern_("t", "libt.rlib")
             .run();
 
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
index 6cc7c6bbdaf..6a7a931249e 100644
--- a/tests/run-make/doctests-runtool/rmake.rs
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -1,12 +1,11 @@
 // Tests behavior of rustdoc `--runtool`.
 
-use run_make_support::{rustc, rustdoc, tmp_dir};
-use std::env::current_dir;
+use run_make_support::{rustc, rustdoc};
 use std::fs::{create_dir, remove_dir_all};
 use std::path::PathBuf;
 
 fn mkdir(name: &str) -> PathBuf {
-    let dir = tmp_dir().join(name);
+    let dir = PathBuf::from(name);
     create_dir(&dir).expect("failed to create doctests folder");
     dir
 }
@@ -22,7 +21,7 @@ fn main() {
     rustc().input("runtool.rs").output(&run_tool_binary).run();
 
     rustdoc()
-        .input(current_dir().unwrap().join("t.rs"))
+        .input("t.rs")
         .arg("-Zunstable-options")
         .arg("--test")
         .arg("--test-run-directory")
@@ -30,7 +29,6 @@ fn main() {
         .arg("--runtool")
         .arg(&run_tool_binary)
         .extern_("t", "libt.rlib")
-        .current_dir(tmp_dir())
         .run();
 
     remove_dir_all(run_dir);
diff --git a/tests/run-make/emit-named-files/rmake.rs b/tests/run-make/emit-named-files/rmake.rs
index 068f9796d0e..c4b7b9aebf6 100644
--- a/tests/run-make/emit-named-files/rmake.rs
+++ b/tests/run-make/emit-named-files/rmake.rs
@@ -1,7 +1,7 @@
 use std::fs::create_dir;
 use std::path::Path;
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) {
     let out_file = out_dir.join(out_file);
@@ -10,7 +10,7 @@ fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) {
 }
 
 fn main() {
-    let out_dir = tmp_dir().join("emit");
+    let out_dir = Path::new("emit");
 
     create_dir(&out_dir).unwrap();
 
diff --git a/tests/run-make/emit/Makefile b/tests/run-make/emit/Makefile
deleted file mode 100644
index b3ca0b79fb0..00000000000
--- a/tests/run-make/emit/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
-	$(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
-	$(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
-	$(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
-	$(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
-	$(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
-	$(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
-	$(call RUN,test-26235) || exit 1
diff --git a/tests/run-make/emit/rmake.rs b/tests/run-make/emit/rmake.rs
new file mode 100644
index 00000000000..8b3ddb66f92
--- /dev/null
+++ b/tests/run-make/emit/rmake.rs
@@ -0,0 +1,19 @@
+// A bug from 2015 would cause errors when emitting multiple types of files
+// in the same rustc call. A fix was created in #30452. This test checks that rustc still compiles
+// a source file successfully when emission of multiple output artifacts are requested.
+// See https://github.com/rust-lang/rust/pull/30452
+
+//@ ignore-cross-compile
+
+use run_make_support::{run, rustc};
+
+fn main() {
+    let opt_levels = ["0", "1", "2", "3", "s", "z"];
+    for level in opt_levels {
+        rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-24876.rs").run();
+    }
+    for level in opt_levels {
+        rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-26235.rs").run();
+        run("test-26235");
+    }
+}
diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs
index 76d7777581b..f290554831d 100644
--- a/tests/run-make/exit-code/rmake.rs
+++ b/tests/run-make/exit-code/rmake.rs
@@ -1,25 +1,26 @@
 // Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations
 
-use run_make_support::{rustc, rustdoc, tmp_dir};
+use run_make_support::{rustc, rustdoc};
 
 fn main() {
     rustc().arg("success.rs").run();
 
-    rustc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1);
+    rustc().arg("--invalid-arg-foo").run_fail().assert_exit_code(1);
 
-    rustc().arg("compile-error.rs").run_fail_assert_exit_code(1);
+    rustc().arg("compile-error.rs").run_fail().assert_exit_code(1);
 
     rustc()
         .env("RUSTC_ICE", "0")
         .arg("-Ztreat-err-as-bug")
         .arg("compile-error.rs")
-        .run_fail_assert_exit_code(101);
+        .run_fail()
+        .assert_exit_code(101);
 
-    rustdoc().arg("success.rs").output(tmp_dir().join("exit-code")).run();
+    rustdoc().arg("success.rs").output("exit-code").run();
 
-    rustdoc().arg("--invalid-arg-foo").run_fail_assert_exit_code(1);
+    rustdoc().arg("--invalid-arg-foo").run_fail().assert_exit_code(1);
 
-    rustdoc().arg("compile-error.rs").run_fail_assert_exit_code(1);
+    rustdoc().arg("compile-error.rs").run_fail().assert_exit_code(1);
 
-    rustdoc().arg("lint-failure.rs").run_fail_assert_exit_code(1);
+    rustdoc().arg("lint-failure.rs").run_fail().assert_exit_code(1);
 }
diff --git a/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs
index de4023282ef..e54ef53e3dc 100644
--- a/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs
+++ b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs
@@ -4,9 +4,9 @@
 // and cause the test to fail.
 // See https://github.com/rust-lang/rust/issues/53964
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     rustc().input("panic.rs").run();
-    rustc().input("app.rs").panic("abort").emit("obj").library_search_path(tmp_dir()).run();
+    rustc().input("app.rs").panic("abort").emit("obj").run();
 }
diff --git a/tests/run-make/incr-prev-body-beyond-eof/Makefile b/tests/run-make/incr-prev-body-beyond-eof/Makefile
deleted file mode 100644
index aa47552f52c..00000000000
--- a/tests/run-make/incr-prev-body-beyond-eof/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-none no-std is not supported
-# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
-
-include ../tools.mk
-
-# Tests that we don't ICE during incremental compilation after modifying a
-# function span such that its previous end line exceeds the number of lines
-# in the new file, but its start line/column and length remain the same.
-
-SRC=$(TMPDIR)/src
-INCR=$(TMPDIR)/incr
-
-all:
-	mkdir $(SRC)
-	mkdir $(INCR)
-	cp a.rs $(SRC)/main.rs
-	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
-	cp b.rs $(SRC)/main.rs
-	$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET)
diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
new file mode 100644
index 00000000000..ccb1f95275e
--- /dev/null
+++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
@@ -0,0 +1,27 @@
+// After modifying the span of a function, if the length of
+// the span remained the same but the end line number became different,
+// this would cause an internal compiler error (ICE), fixed in #76256.
+
+// This test compiles main.rs twice, first with end line 16 and
+// then with end line 12. If compilation is successful, the end line
+// was hashed by rustc in addition to the span length, and the fix still
+// works.
+
+//@ ignore-none
+// reason: no-std is not supported
+
+//@ ignore-nvptx64-nvidia-cuda
+// FIXME: can't find crate for `std`
+
+use run_make_support::rustc;
+use std::fs;
+
+fn main() {
+    // FIXME(Oneirical): Use run_make_support::fs_wrapper here.
+    fs::create_dir("src").unwrap();
+    fs::create_dir("incr").unwrap();
+    fs::copy("a.rs", "src/main.rs").unwrap();
+    rustc().incremental("incr").input("src/main.rs").run();
+    fs::copy("b.rs", "src/main.rs").unwrap();
+    rustc().incremental("incr").input("src/main.rs").run();
+}
diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs
index db25e9b033c..72ceb10c591 100644
--- a/tests/run-make/issue-107495-archive-permissions/rmake.rs
+++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs
@@ -3,7 +3,7 @@
 #[cfg(unix)]
 extern crate libc;
 
-use run_make_support::{aux_build, tmp_dir};
+use run_make_support::aux_build;
 use std::fs;
 #[cfg(unix)]
 use std::os::unix::fs::PermissionsExt;
@@ -16,7 +16,7 @@ fn main() {
     }
 
     aux_build().arg("foo.rs").run();
-    verify(&tmp_dir().join("libfoo.rlib"));
+    verify(Path::new("libfoo.rlib"));
 }
 
 fn verify(path: &Path) {
diff --git a/tests/run-make/issue-125484-used-dependencies/dependency.rs b/tests/run-make/issue-125484-used-dependencies/dependency.rs
new file mode 100644
index 00000000000..d15abba5976
--- /dev/null
+++ b/tests/run-make/issue-125484-used-dependencies/dependency.rs
@@ -0,0 +1 @@
+// Empty
diff --git a/tests/run-make/issue-125484-used-dependencies/main.rs b/tests/run-make/issue-125484-used-dependencies/main.rs
new file mode 100644
index 00000000000..0c1a1f8208a
--- /dev/null
+++ b/tests/run-make/issue-125484-used-dependencies/main.rs
@@ -0,0 +1,9 @@
+pub type Foo = something::same::Thing;
+
+mod something {
+    pub mod same {
+        pub struct Thing;
+    }
+}
+
+fn main() {}
diff --git a/tests/run-make/issue-125484-used-dependencies/rmake.rs b/tests/run-make/issue-125484-used-dependencies/rmake.rs
new file mode 100644
index 00000000000..bc0a18de66e
--- /dev/null
+++ b/tests/run-make/issue-125484-used-dependencies/rmake.rs
@@ -0,0 +1,18 @@
+// Non-regression test for issues #125474, #125484, #125646, with the repro taken from #125484. Some
+// queries use "used dependencies" while others use "speculatively loaded dependencies", and an
+// indexing ICE appeared in some cases when these were unexpectedly used in the same context.
+
+// FIXME: this should probably be a UI test instead of a run-make test, but I *cannot* find a way to
+// make compiletest annotations reproduce the ICE with the minimizations from issues #125474 and
+// #125484.
+
+use run_make_support::rustc;
+
+fn main() {
+    // The dependency is not itself significant, apart from sharing a name with one of main's
+    // modules.
+    rustc().crate_name("same").crate_type("rlib").input("dependency.rs").run();
+
+    // Here, an ICE would happen when building the linker command.
+    rustc().input("main.rs").extern_("same", "libsame.rlib").run();
+}
diff --git a/tests/run-make/issue-84395-lto-embed-bitcode/Makefile b/tests/run-make/issue-84395-lto-embed-bitcode/Makefile
index 95c8d08a18b..aabe90754a6 100644
--- a/tests/run-make/issue-84395-lto-embed-bitcode/Makefile
+++ b/tests/run-make/issue-84395-lto-embed-bitcode/Makefile
@@ -1,4 +1,7 @@
-# needs-matching-clang
+# needs-force-clang-based-tests
+
+# FIXME(#126180): This test doesn't actually run anywhere, because the only
+# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
 
 # This test makes sure the embed bitcode in elf created with
 # lto-embed-bitcode=optimized is valid llvm BC module.
diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/issue-88756-default-output/output-default.stdout
index 12c1b389fb3..bc38d9e9dc6 100644
--- a/tests/run-make/issue-88756-default-output/output-default.stdout
+++ b/tests/run-make/issue-88756-default-output/output-default.stdout
@@ -157,6 +157,8 @@ Options:
                         Comma separated list of types of output for rustdoc to
                         emit
         --no-run        Compile doctests without running them
+        --remap-path-prefix FROM=TO
+                        Remap source names in compiler messages
         --show-type-layout 
                         Include the memory layout of types in the docs
         --nocapture     Don't capture stdout and stderr of tests
diff --git a/tests/run-make/llvm-outputs/Makefile b/tests/run-make/llvm-outputs/Makefile
deleted file mode 100644
index cccf1dd66fb..00000000000
--- a/tests/run-make/llvm-outputs/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir
-	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc
diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs
new file mode 100644
index 00000000000..2dc3030ca91
--- /dev/null
+++ b/tests/run-make/llvm-outputs/rmake.rs
@@ -0,0 +1,20 @@
+// test that directories get created when emitting llvm bitcode and IR
+
+use run_make_support::{cwd, run_in_tmpdir, rustc};
+use std::path::PathBuf;
+
+fn main() {
+    let mut path_bc = PathBuf::new();
+    let mut path_ir = PathBuf::new();
+    run_in_tmpdir(|| {
+        let p = cwd();
+        path_bc = p.join("nonexistant_dir_bc");
+        path_ir = p.join("nonexistant_dir_ir");
+        rustc().input("-").stdin("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
+        rustc().input("-").stdin("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
+        assert!(path_bc.exists());
+        assert!(path_ir.exists());
+    });
+    assert!(!path_bc.exists());
+    assert!(!path_ir.exists());
+}
diff --git a/tests/run-make/manual-crate-name/Makefile b/tests/run-make/manual-crate-name/Makefile
deleted file mode 100644
index c00e20c7c57..00000000000
--- a/tests/run-make/manual-crate-name/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-name foo bar.rs
-	rm $(TMPDIR)/libfoo.rlib
diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs
new file mode 100644
index 00000000000..f171f78087c
--- /dev/null
+++ b/tests/run-make/manual-crate-name/rmake.rs
@@ -0,0 +1,7 @@
+use run_make_support::rustc;
+use std::path::Path;
+
+fn main() {
+    rustc().input("bar.rs").crate_name("foo").run();
+    assert!(Path::new("libfoo.rlib").is_file());
+}
diff --git a/tests/run-make/mixing-formats/Makefile b/tests/run-make/mixing-formats/Makefile
deleted file mode 100644
index d01978a1599..00000000000
--- a/tests/run-make/mixing-formats/Makefile
+++ /dev/null
@@ -1,75 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Testing various mixings of rlibs and dylibs. Makes sure that it's possible to
-# link an rlib to a dylib. The dependency tree among the file looks like:
-#
-#				foo
-#			      /     \
-#			    bar1   bar2
-#			   /    \ /
-#			 baz    baz2
-#
-# This is generally testing the permutations of the foo/bar1/bar2 layer against
-# the baz/baz2 layer
-
-all:
-	# Building just baz
-	$(RUSTC) --crate-type=rlib  foo.rs
-	$(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=bin baz.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=rlib  bar1.rs
-	$(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=bin baz.rs
-	rm $(TMPDIR)/*
-	# Building baz2
-	$(RUSTC) --crate-type=rlib  foo.rs
-	$(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib baz2.rs && exit 1 || exit 0
-	$(RUSTC) --crate-type=bin baz2.rs && exit 1 || exit 0
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=rlib  foo.rs
-	$(RUSTC) --crate-type=rlib  bar1.rs
-	$(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=rlib  foo.rs
-	$(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=rlib  bar2.rs
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=rlib  foo.rs
-	$(RUSTC) --crate-type=rlib  bar1.rs
-	$(RUSTC) --crate-type=rlib  bar2.rs
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=rlib  bar1.rs
-	$(RUSTC) --crate-type=rlib  bar2.rs
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=rlib  bar2.rs
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=rlib  bar1.rs
-	$(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs
-	$(RUSTC) --crate-type=bin baz2.rs
-	rm $(TMPDIR)/*
-	$(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic
-	$(RUSTC) --crate-type=dylib,rlib baz2.rs
-	$(RUSTC) --crate-type=bin baz2.rs
diff --git a/tests/run-make/mixing-formats/rmake.rs b/tests/run-make/mixing-formats/rmake.rs
new file mode 100644
index 00000000000..9cbff94f670
--- /dev/null
+++ b/tests/run-make/mixing-formats/rmake.rs
@@ -0,0 +1,87 @@
+// Testing various mixings of rlibs and dylibs. Makes sure that it's possible to
+// link an rlib to a dylib. The dependency tree among the file looks like:
+//
+//                 foo
+//               /     \
+//             bar1   bar2
+//             /    \ /
+//          baz    baz2
+//
+// This is generally testing the permutations of the foo/bar1/bar2 layer against
+// the baz/baz2 layer
+
+//@ ignore-cross-compile
+
+use run_make_support::{run_in_tmpdir, rustc};
+use std::fs;
+
+fn main() {
+    run_in_tmpdir(|| {
+        // Building just baz
+        rustc().crate_type("rlib").input("foo.rs").run();
+        rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("bin").input("baz.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("rlib").input("bar1.rs").run();
+        rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("bin").input("baz.rs").run();
+    });
+    run_in_tmpdir(|| {
+        // Building baz2
+        rustc().crate_type("rlib").input("foo.rs").run();
+        rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib").input("baz2.rs").run_fail().assert_exit_code(1);
+        rustc().crate_type("bin").input("baz2.rs").run_fail().assert_exit_code(1);
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("rlib").input("foo.rs").run();
+        rustc().crate_type("rlib").input("bar1.rs").run();
+        rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("rlib").input("foo.rs").run();
+        rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("rlib").input("bar2.rs").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("rlib").input("foo.rs").run();
+        rustc().crate_type("rlib").input("bar1.rs").run();
+        rustc().crate_type("rlib").input("bar2.rs").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("rlib").input("bar1.rs").run();
+        rustc().crate_type("rlib").input("bar2.rs").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("rlib").input("bar2.rs").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    run_in_tmpdir(|| {
+        rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("rlib").input("bar1.rs").run();
+        rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run();
+        rustc().crate_type("dylib,rlib").input("baz2.rs").run();
+        rustc().crate_type("bin").input("baz2.rs").run();
+    });
+    rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run();
+    rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run();
+    rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run();
+    rustc().crate_type("dylib,rlib").input("baz2.rs").run();
+    rustc().crate_type("bin").input("baz2.rs").run();
+}
diff --git a/tests/run-make/multiple-emits/Makefile b/tests/run-make/multiple-emits/Makefile
deleted file mode 100644
index d1f29764485..00000000000
--- a/tests/run-make/multiple-emits/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out 2>&1
-	rm $(TMPDIR)/out.ll $(TMPDIR)/out.s
-	$(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out2.ext 2>&1
-	rm $(TMPDIR)/out2.ll $(TMPDIR)/out2.s
diff --git a/tests/run-make/multiple-emits/rmake.rs b/tests/run-make/multiple-emits/rmake.rs
new file mode 100644
index 00000000000..67c0ebb9864
--- /dev/null
+++ b/tests/run-make/multiple-emits/rmake.rs
@@ -0,0 +1,13 @@
+use run_make_support::{cwd, path, rustc};
+
+fn main() {
+    rustc().input("foo.rs").emit("asm,llvm-ir").output("out").run();
+
+    assert!(path("out.ll").is_file());
+    assert!(path("out.s").is_file());
+
+    rustc().input("foo.rs").emit("asm,llvm-ir").output("out2.ext").run();
+
+    assert!(path("out2.ll").is_file());
+    assert!(path("out2.s").is_file());
+}
diff --git a/tests/run-make/no-input-file/no-input-file.stderr b/tests/run-make/no-input-file/no-input-file.stderr
deleted file mode 100644
index b843eb524f3..00000000000
--- a/tests/run-make/no-input-file/no-input-file.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: no input filename given
-
diff --git a/tests/run-make/no-input-file/rmake.rs b/tests/run-make/no-input-file/rmake.rs
index 15e582311f0..fc558b22fb4 100644
--- a/tests/run-make/no-input-file/rmake.rs
+++ b/tests/run-make/no-input-file/rmake.rs
@@ -1,7 +1,9 @@
-use run_make_support::{diff, rustc};
+use run_make_support::rustc;
 
 fn main() {
-    let output = rustc().print("crate-name").run_fail_assert_exit_code(1);
-
-    diff().expected_file("no-input-file.stderr").actual_text("output", output.stderr).run();
+    rustc()
+        .print("crate-name")
+        .run_fail()
+        .assert_exit_code(1)
+        .assert_stderr_equals("error: no input filename given");
 }
diff --git a/tests/run-make/no-intermediate-extras/rmake.rs b/tests/run-make/no-intermediate-extras/rmake.rs
index 19479e3bd5b..0641417504e 100644
--- a/tests/run-make/no-intermediate-extras/rmake.rs
+++ b/tests/run-make/no-intermediate-extras/rmake.rs
@@ -5,13 +5,13 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 use std::fs;
 
 fn main() {
     rustc().crate_type("rlib").arg("--test").input("foo.rs").run();
     assert!(
-        fs::remove_file(tmp_dir().join("foo.bc")).is_err(),
+        fs::remove_file("foo.bc").is_err(),
         "An unwanted .bc file was created by run-make/no-intermediate-extras."
     );
 }
diff --git a/tests/run-make/non-pie-thread-local/rmake.rs b/tests/run-make/non-pie-thread-local/rmake.rs
index 1ef447e7860..1758f1a0855 100644
--- a/tests/run-make/non-pie-thread-local/rmake.rs
+++ b/tests/run-make/non-pie-thread-local/rmake.rs
@@ -7,13 +7,13 @@
 //@ ignore-cross-compile
 //@ only-linux
 
-use run_make_support::{cc, run, rustc, tmp_dir};
+use run_make_support::{cc, cwd, run, rustc};
 
 fn main() {
     rustc().input("foo.rs").run();
     cc().input("foo.c")
         .arg("-lfoo")
-        .library_search_path(tmp_dir())
+        .library_search_path(cwd())
         .arg("-Wl,--gc-sections")
         .arg("-lpthread")
         .arg("-ldl")
@@ -22,7 +22,7 @@ fn main() {
     run("foo");
     cc().input("foo.c")
         .arg("-lfoo")
-        .library_search_path(tmp_dir())
+        .library_search_path(cwd())
         .arg("-Wl,--gc-sections")
         .arg("-lpthread")
         .arg("-ldl")
diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs
index a4843a52efd..ed40d7a6d7f 100644
--- a/tests/run-make/non-unicode-env/rmake.rs
+++ b/tests/run-make/non-unicode-env/rmake.rs
@@ -6,7 +6,6 @@ fn main() {
     #[cfg(windows)]
     let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
     let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail();
-    let actual = std::str::from_utf8(&output.stderr).unwrap();
     let expected = std::fs::read_to_string("non_unicode_env.stderr").unwrap();
-    assert_eq!(actual, expected);
+    output.assert_stderr_equals(expected);
 }
diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
index 40152e0411d..ba1bd448743 100644
--- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
+++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
@@ -1,21 +1,21 @@
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     #[cfg(unix)]
     let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]);
     #[cfg(windows)]
     let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
-    match std::fs::create_dir(tmp_dir().join(&non_unicode)) {
+    match std::fs::create_dir(&non_unicode) {
         // If an error occurs, check if creating a directory with a valid Unicode name would
         // succeed.
-        Err(e) if std::fs::create_dir(tmp_dir().join("valid_unicode")).is_ok() => {
+        Err(e) if std::fs::create_dir("valid_unicode").is_ok() => {
             // Filesystem doesn't appear support non-Unicode paths.
             return;
         }
         Err(e) => panic!("error creating non-Unicode directory: {e}"),
         _ => {}
     }
-    let incr_dir = tmp_dir().join("incr-dir");
+    let incr_dir = "incr-dir";
     rustc().input("foo.rs").incremental(&incr_dir).run();
     for crate_dir in std::fs::read_dir(&incr_dir).unwrap() {
         std::fs::create_dir(crate_dir.unwrap().path().join(&non_unicode)).unwrap();
diff --git a/tests/run-make/notify-all-emit-artifacts/lib.rs b/tests/run-make/notify-all-emit-artifacts/lib.rs
new file mode 100644
index 00000000000..6ed194204b4
--- /dev/null
+++ b/tests/run-make/notify-all-emit-artifacts/lib.rs
@@ -0,0 +1,21 @@
+fn one() -> usize {
+    1
+}
+
+pub mod a {
+    pub fn two() -> usize {
+        ::one() + ::one()
+    }
+}
+
+pub mod b {
+    pub fn three() -> usize {
+        ::one() + ::a::two()
+    }
+}
+
+#[inline(never)]
+pub fn main() {
+    a::two();
+    b::three();
+}
diff --git a/tests/run-make/notify-all-emit-artifacts/rmake.rs b/tests/run-make/notify-all-emit-artifacts/rmake.rs
new file mode 100644
index 00000000000..321eda48941
--- /dev/null
+++ b/tests/run-make/notify-all-emit-artifacts/rmake.rs
@@ -0,0 +1,43 @@
+// rust should produce artifact notifications about files it was asked to --emit.
+//
+// It should work in incremental mode both on the first pass where files are generated as well
+// as on subsequent passes where they are taken from the incremental cache
+//
+// See <https://internals.rust-lang.org/t/easier-access-to-files-generated-by-emit-foo/20477>
+extern crate run_make_support;
+
+use run_make_support::{cwd, rustc};
+
+fn main() {
+    // With single codegen unit files are renamed to match the source file name
+    for _ in 0..=1 {
+        let output = rustc()
+            .input("lib.rs")
+            .emit("obj,asm,llvm-ir,llvm-bc,mir")
+            .codegen_units(1)
+            .json("artifacts")
+            .error_format("json")
+            .incremental(cwd())
+            .run();
+        let stderr = output.stderr_utf8();
+        for file in &["lib.o", "lib.ll", "lib.bc", "lib.s"] {
+            assert!(stderr.contains(file), "No {:?} in {:?}", file, stderr);
+        }
+    }
+
+    // with multiple codegen units files keep codegen unit id part.
+    for _ in 0..=1 {
+        let output = rustc()
+            .input("lib.rs")
+            .emit("obj,asm,llvm-ir,llvm-bc,mir")
+            .codegen_units(2)
+            .json("artifacts")
+            .error_format("json")
+            .incremental(cwd())
+            .run();
+        let stderr = output.stderr_utf8();
+        for file in &["rcgu.o", "rcgu.ll", "rcgu.bc", "rcgu.s"] {
+            assert!(stderr.contains(file), "No {:?} in {:?}", file, stderr);
+        }
+    }
+}
diff --git a/tests/run-make/panic-impl-transitive/rmake.rs b/tests/run-make/panic-impl-transitive/rmake.rs
index 86308f593b3..c09b233b23e 100644
--- a/tests/run-make/panic-impl-transitive/rmake.rs
+++ b/tests/run-make/panic-impl-transitive/rmake.rs
@@ -6,14 +6,9 @@
 // function in the crate.
 // See https://github.com/rust-lang/rust/pull/50338
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     rustc().input("panic-impl-provider.rs").run();
-    rustc()
-        .input("panic-impl-consumer.rs")
-        .panic("abort")
-        .emit("llvm-ir")
-        .library_search_path(tmp_dir())
-        .run();
+    rustc().input("panic-impl-consumer.rs").panic("abort").emit("llvm-ir").run();
 }
diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs
index 6e72c16f1f9..f382d952db4 100644
--- a/tests/run-make/print-cfg/rmake.rs
+++ b/tests/run-make/print-cfg/rmake.rs
@@ -7,10 +7,10 @@
 
 use std::collections::HashSet;
 use std::ffi::OsString;
-use std::io::BufRead;
 use std::iter::FromIterator;
+use std::path::PathBuf;
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 struct PrintCfg {
     target: &'static str,
@@ -83,19 +83,18 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) {
     // --print=cfg
     {
         let output = rustc().target(target).print("cfg").run();
-
-        let stdout = String::from_utf8(output.stdout).unwrap();
+        let stdout = output.stdout_utf8();
 
         check_(&stdout, includes, disallow);
     }
 
     // --print=cfg=PATH
     {
-        let tmp_path = tmp_dir().join(format!("{target}.cfg"));
+        let tmp_path = PathBuf::from(format!("{target}.cfg"));
         let mut print_arg = OsString::from("--print=cfg=");
         print_arg.push(tmp_path.as_os_str());
 
-        let output = rustc().target(target).arg(print_arg).run();
+        rustc().target(target).arg(print_arg).run();
 
         let output = std::fs::read_to_string(&tmp_path).unwrap();
 
diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs
index 2d522164426..f4b02b5e265 100644
--- a/tests/run-make/print-check-cfg/rmake.rs
+++ b/tests/run-make/print-check-cfg/rmake.rs
@@ -49,6 +49,20 @@ fn main() {
         },
     });
     check(CheckCfg {
+        args: &["--check-cfg=cfg(feature, values())"],
+        contains: Contains::Some {
+            contains: &["feature="],
+            doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature"],
+        },
+    });
+    check(CheckCfg {
+        args: &["--check-cfg=cfg(feature, values())", "--check-cfg=cfg(feature, values(none()))"],
+        contains: Contains::Some {
+            contains: &["feature"],
+            doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
+        },
+    });
+    check(CheckCfg {
         args: &[
             r#"--check-cfg=cfg(feature, values(any()))"#,
             r#"--check-cfg=cfg(feature, values("tmp"))"#,
@@ -79,7 +93,7 @@ fn check(CheckCfg { args, contains }: CheckCfg) {
         .args(&*args)
         .run();
 
-    let stdout = String::from_utf8(output.stdout).unwrap();
+    let stdout = output.stdout_utf8();
 
     let mut found = HashSet::<String>::new();
 
diff --git a/tests/run-make/print-native-static-libs/rmake.rs b/tests/run-make/print-native-static-libs/rmake.rs
index edb85d568c6..b4e7c0e17ff 100644
--- a/tests/run-make/print-native-static-libs/rmake.rs
+++ b/tests/run-make/print-native-static-libs/rmake.rs
@@ -30,9 +30,7 @@ fn main() {
         .run();
 
     let mut found_note = false;
-    for l in output.stderr.lines() {
-        let l = l.expect("utf-8 string");
-
+    for l in output.stderr_utf8().lines() {
         let Some(args) = l.strip_prefix("note: native-static-libs:") else {
             continue;
         };
diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs
index 1763cd378d2..ff5e6cacf4f 100644
--- a/tests/run-make/print-to-output/rmake.rs
+++ b/tests/run-make/print-to-output/rmake.rs
@@ -2,8 +2,9 @@
 //! output to a file (instead of stdout)
 
 use std::ffi::OsString;
+use std::path::PathBuf;
 
-use run_make_support::{rustc, target, tmp_dir};
+use run_make_support::{rustc, target};
 
 struct Option<'a> {
     target: &'a str,
@@ -38,19 +39,15 @@ fn check(args: Option) {
     }
 
     // --print={option}
-    let stdout = {
-        let output = rustc().target(args.target).print(args.option).run();
-
-        String::from_utf8(output.stdout).unwrap()
-    };
+    let stdout = rustc().target(args.target).print(args.option).run().stdout_utf8();
 
     // --print={option}=PATH
     let output = {
-        let tmp_path = tmp_dir().join(format!("{}.txt", args.option));
+        let tmp_path = PathBuf::from(format!("{}.txt", args.option));
         let mut print_arg = OsString::from(format!("--print={}=", args.option));
         print_arg.push(tmp_path.as_os_str());
 
-        let _output = rustc().target(args.target).arg(print_arg).run();
+        rustc().target(args.target).arg(print_arg).run();
 
         std::fs::read_to_string(&tmp_path).unwrap()
     };
diff --git a/tests/run-make/reachable-extern-fn-available-lto/rmake.rs b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs
index c7262b9461b..558444846fd 100644
--- a/tests/run-make/reachable-extern-fn-available-lto/rmake.rs
+++ b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs
@@ -9,10 +9,10 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};
 
 fn main() {
-    let libbar_path = static_lib("bar");
+    let libbar_path = static_lib_name("bar");
     rustc().input("foo.rs").crate_type("rlib").run();
     rustc()
         .input("bar.rs")
diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs
index fd5dd810444..27e32099396 100644
--- a/tests/run-make/repr128-dwarf/rmake.rs
+++ b/tests/run-make/repr128-dwarf/rmake.rs
@@ -1,15 +1,15 @@
 //@ ignore-windows
 // This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums.
 
-use gimli::{AttributeValue, Dwarf, EndianRcSlice, Reader, RunTimeEndian};
+use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian};
 use object::{Object, ObjectSection};
-use run_make_support::{gimli, object, rustc, tmp_dir};
-use std::borrow::Cow;
+use run_make_support::{gimli, object, rustc};
 use std::collections::HashMap;
+use std::path::PathBuf;
 use std::rc::Rc;
 
 fn main() {
-    let output = tmp_dir().join("repr128");
+    let output = PathBuf::from("repr128");
     rustc().input("main.rs").output(&output).arg("-Cdebuginfo=2").run();
     // Mach-O uses packed debug info
     let dsym_location = output
diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs
index 4b91ba7df90..c1385b2e015 100644
--- a/tests/run-make/reset-codegen-1/rmake.rs
+++ b/tests/run-make/reset-codegen-1/rmake.rs
@@ -7,12 +7,12 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 use std::fs;
 
 fn compile(output_file: &str, emit: Option<&str>) {
     let mut rustc = rustc();
-    let rustc = rustc.codegen_units(4).output(tmp_dir().join(output_file)).input("foo.rs");
+    let rustc = rustc.codegen_units(4).output(output_file).input("foo.rs");
     if let Some(emit) = emit {
         rustc.emit(emit);
     }
diff --git a/tests/run-make/resolve-rename/Makefile b/tests/run-make/resolve-rename/Makefile
deleted file mode 100644
index 00f83a5d6b2..00000000000
--- a/tests/run-make/resolve-rename/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) -C extra-filename=-hash foo.rs
-	$(RUSTC) bar.rs
-	mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib
-	$(RUSTC) baz.rs
diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs
new file mode 100644
index 00000000000..a5f48c2bbcc
--- /dev/null
+++ b/tests/run-make/resolve-rename/rmake.rs
@@ -0,0 +1,15 @@
+// If a library is compiled with -C extra-filename, the rust compiler
+// will take this into account when searching for libraries. However,
+// if that library is then renamed, the rust compiler should fall back
+// to its regular library location logic and not immediately fail to find
+// the renamed library.
+// See https://github.com/rust-lang/rust/pull/49253
+
+use run_make_support::rustc;
+use std::fs;
+fn main() {
+    rustc().extra_filename("-hash").input("foo.rs").run();
+    rustc().input("bar.rs").run();
+    fs::rename("libfoo-hash.rlib", "libfoo-another-hash.rlib").unwrap();
+    rustc().input("baz.rs").run();
+}
diff --git a/tests/run-make/run-in-tmpdir-self-test/rmake.rs b/tests/run-make/run-in-tmpdir-self-test/rmake.rs
new file mode 100644
index 00000000000..83b99bfe863
--- /dev/null
+++ b/tests/run-make/run-in-tmpdir-self-test/rmake.rs
@@ -0,0 +1,38 @@
+//! This is a self-test for the `run_in_tmpdir` helper in the support library. This test tries to
+//! check that files and directories created within the temporary directory gets properly cleared
+//! when returning from the closure.
+
+use std::fs;
+use std::path::{Path, PathBuf};
+
+use run_make_support::{cwd, run_in_tmpdir};
+
+fn main() {
+    let mut file_path = PathBuf::new();
+    let mut dir_path = PathBuf::new();
+    let mut readonly_file_path = PathBuf::new();
+    let test_cwd = cwd();
+    run_in_tmpdir(|| {
+        assert_ne!(test_cwd, cwd(), "test cwd should not be the same as tmpdir cwd");
+
+        file_path = cwd().join("foo.txt");
+        fs::write(&file_path, "hi").unwrap();
+
+        dir_path = cwd().join("bar");
+        fs::create_dir_all(&dir_path).unwrap();
+
+        readonly_file_path = cwd().join("readonly-file.txt");
+        fs::write(&readonly_file_path, "owo").unwrap();
+        let mut perms = fs::metadata(&readonly_file_path).unwrap().permissions();
+        perms.set_readonly(true);
+        fs::set_permissions(&mut readonly_file_path, perms).unwrap();
+
+        assert!(file_path.exists());
+        assert!(dir_path.exists());
+        assert!(readonly_file_path.exists());
+    });
+    assert!(!file_path.exists());
+    assert!(!dir_path.exists());
+    assert!(!readonly_file_path.exists());
+    assert_eq!(test_cwd, cwd(), "test cwd is not correctly restored");
+}
diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs
index 8ab16394a91..5b065f86f53 100644
--- a/tests/run-make/rust-lld-by-default/rmake.rs
+++ b/tests/run-make/rust-lld-by-default/rmake.rs
@@ -17,9 +17,9 @@ fn main() {
         .input("main.rs")
         .run();
     assert!(
-        find_lld_version_in_logs(&output),
+        find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 
     // But it can still be disabled by turning the linker feature off.
@@ -30,14 +30,13 @@ fn main() {
         .input("main.rs")
         .run();
     assert!(
-        !find_lld_version_in_logs(&output),
+        !find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should not be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 }
 
-fn find_lld_version_in_logs(output: &Output) -> bool {
+fn find_lld_version_in_logs(stderr: String) -> bool {
     let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
-    let stderr = std::str::from_utf8(&output.stderr).unwrap();
     stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
 }
diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs
index e6c4a321d00..f3dc2275f62 100644
--- a/tests/run-make/rust-lld-custom-target/rmake.rs
+++ b/tests/run-make/rust-lld-custom-target/rmake.rs
@@ -23,9 +23,9 @@ fn main() {
         .input("lib.rs")
         .run();
     assert!(
-        find_lld_version_in_logs(&output),
+        find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 
     // But it can also be disabled via linker features.
@@ -38,14 +38,13 @@ fn main() {
         .input("lib.rs")
         .run();
     assert!(
-        !find_lld_version_in_logs(&output),
+        !find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should not be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 }
 
-fn find_lld_version_in_logs(output: &Output) -> bool {
+fn find_lld_version_in_logs(stderr: String) -> bool {
     let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
-    let stderr = std::str::from_utf8(&output.stderr).unwrap();
     stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
 }
diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs
index a74e858045d..3eb60367c7f 100644
--- a/tests/run-make/rust-lld/rmake.rs
+++ b/tests/run-make/rust-lld/rmake.rs
@@ -21,9 +21,9 @@ fn main() {
         .input("main.rs")
         .run();
     assert!(
-        find_lld_version_in_logs(&output),
+        find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 
     // It should not be used when we explictly opt-out of lld.
@@ -34,9 +34,9 @@ fn main() {
         .input("main.rs")
         .run();
     assert!(
-        !find_lld_version_in_logs(&output),
+        !find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should not be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 
     // While we're here, also check that the last linker feature flag "wins" when passed multiple
@@ -52,14 +52,13 @@ fn main() {
         .input("main.rs")
         .run();
     assert!(
-        find_lld_version_in_logs(&output),
+        find_lld_version_in_logs(output.stderr_utf8()),
         "the LLD version string should be present in the output logs:\n{}",
-        std::str::from_utf8(&output.stderr).unwrap()
+        output.stderr_utf8()
     );
 }
 
-fn find_lld_version_in_logs(output: &Output) -> bool {
+fn find_lld_version_in_logs(stderr: String) -> bool {
     let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
-    let stderr = std::str::from_utf8(&output.stderr).unwrap();
     stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
 }
diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs
index 09097d4507d..2d4f357d681 100644
--- a/tests/run-make/rustdoc-determinism/rmake.rs
+++ b/tests/run-make/rustdoc-determinism/rmake.rs
@@ -1,14 +1,15 @@
 // 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};
+use run_make_support::{diff, rustdoc};
+use std::path::Path;
 
 fn main() {
-    let foo_first = tmp_dir().join("foo_first");
+    let foo_first = Path::new("foo_first");
     rustdoc().input("foo.rs").output(&foo_first).run();
     rustdoc().input("bar.rs").output(&foo_first).run();
 
-    let bar_first = tmp_dir().join("bar_first");
+    let bar_first = Path::new("bar_first");
     rustdoc().input("bar.rs").output(&bar_first).run();
     rustdoc().input("foo.rs").output(&bar_first).run();
 
diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs
index db6e28e4feb..ea5ec2faed9 100644
--- a/tests/run-make/rustdoc-error-lines/rmake.rs
+++ b/tests/run-make/rustdoc-error-lines/rmake.rs
@@ -4,9 +4,7 @@
 use run_make_support::rustdoc;
 
 fn main() {
-    let output =
-        String::from_utf8(rustdoc().input("input.rs").arg("--test").command_output().stdout)
-            .unwrap();
+    let output = rustdoc().input("input.rs").arg("--test").run_fail().stdout_utf8();
 
     let should_contain = &[
         "input.rs - foo (line 5)",
diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs
index d017b41bcdd..de75561c9fb 100644
--- a/tests/run-make/rustdoc-map-file/rmake.rs
+++ b/tests/run-make/rustdoc-map-file/rmake.rs
@@ -1,7 +1,7 @@
-use run_make_support::{python_command, rustdoc, tmp_dir};
+use run_make_support::{python_command, rustdoc};
 
 fn main() {
-    let out_dir = tmp_dir().join("out");
+    let out_dir = "out";
     rustdoc()
         .input("foo.rs")
         .arg("-Zunstable-options")
diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs
index 74fb0a56ac6..28e0fd98f93 100644
--- a/tests/run-make/rustdoc-output-path/rmake.rs
+++ b/tests/run-make/rustdoc-output-path/rmake.rs
@@ -1,9 +1,10 @@
 // Checks that if the output folder doesn't exist, rustdoc will create it.
 
-use run_make_support::{rustdoc, tmp_dir};
+use run_make_support::rustdoc;
+use std::path::Path;
 
 fn main() {
-    let out_dir = tmp_dir().join("foo/bar/doc");
+    let out_dir = Path::new("foo/bar/doc");
     rustdoc().input("foo.rs").output(&out_dir).run();
     assert!(out_dir.exists());
 }
diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
index 81b7defafc6..c9650def347 100644
--- a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
@@ -1,25 +1,21 @@
 //@ ignore-cross-compile
 
-use run_make_support::{htmldocck, rustc, rustdoc, tmp_dir};
+use run_make_support::{htmldocck, rust_lib_name, rustc, rustdoc};
 
 fn main() {
-    let tmp_dir = tmp_dir();
-    let out_dir = tmp_dir.join("rustdoc");
-    let ex_dir = tmp_dir.join("ex.calls");
+    let out_dir = "rustdoc";
+    let ex_dir = "ex.calls";
     let proc_crate_name = "foobar_macro";
     let crate_name = "foobar";
 
-    let dylib_name = String::from_utf8(
-        rustc()
-            .crate_name(proc_crate_name)
-            .crate_type("dylib")
-            .arg("--print")
-            .arg("file-names")
-            .arg("-")
-            .command_output()
-            .stdout,
-    )
-    .unwrap();
+    let dylib_name = rustc()
+        .crate_name(proc_crate_name)
+        .crate_type("dylib")
+        .arg("--print")
+        .arg("file-names")
+        .arg("-")
+        .run()
+        .stdout_utf8();
 
     rustc()
         .input("src/proc.rs")
@@ -41,8 +37,8 @@ fn main() {
         .crate_name("ex")
         .crate_type("bin")
         .output(&out_dir)
-        .extern_(crate_name, tmp_dir.join(format!("lib{crate_name}.rlib")))
-        .extern_(proc_crate_name, tmp_dir.join(dylib_name.trim()))
+        .extern_(crate_name, rust_lib_name(crate_name))
+        .extern_(proc_crate_name, dylib_name.trim())
         .arg("-Zunstable-options")
         .arg("--scrape-examples-output-path")
         .arg(&ex_dir)
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
index 563e3aca9ae..41efb837458 100644
--- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
+++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
@@ -1,10 +1,9 @@
-use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir};
+use run_make_support::{htmldocck, rustc, rustdoc, source_root};
 use std::fs::read_dir;
 use std::path::Path;
 
 pub fn scrape(extra_args: &[&str]) {
-    let lib_dir = tmp_dir();
-    let out_dir = tmp_dir().join("rustdoc");
+    let out_dir = Path::new("rustdoc");
     let crate_name = "foobar";
     let deps = read_dir("examples")
         .unwrap()
@@ -23,7 +22,7 @@ pub fn scrape(extra_args: &[&str]) {
             .crate_name(&dep_stem)
             .crate_type("bin")
             .output(&out_dir)
-            .extern_(crate_name, lib_dir.join(format!("lib{crate_name}.rmeta")))
+            .extern_(crate_name, format!("lib{crate_name}.rmeta"))
             .arg("-Zunstable-options")
             .arg("--scrape-examples-output-path")
             .arg(&out_example)
diff --git a/tests/run-make/rustdoc-shared-flags/rmake.rs b/tests/run-make/rustdoc-shared-flags/rmake.rs
index 2db613f7817..d9a16d78a34 100644
--- a/tests/run-make/rustdoc-shared-flags/rmake.rs
+++ b/tests/run-make/rustdoc-shared-flags/rmake.rs
@@ -1,8 +1,8 @@
 use run_make_support::{rustc, rustdoc, Diff};
 
 fn compare_outputs(args: &[&str]) {
-    let rustc_output = String::from_utf8(rustc().args(args).command_output().stdout).unwrap();
-    let rustdoc_output = String::from_utf8(rustdoc().args(args).command_output().stdout).unwrap();
+    let rustc_output = rustc().args(args).run().stdout_utf8();
+    let rustdoc_output = rustdoc().args(args).run().stdout_utf8();
 
     Diff::new().expected_text("rustc", rustc_output).actual_text("rustdoc", rustdoc_output).run();
 }
diff --git a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs
index 66530a4f08e..3246fc56506 100644
--- a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs
+++ b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs
@@ -1,14 +1,14 @@
 // Test that rustdoc will properly canonicalize the target spec json path just like rustc.
 
-use run_make_support::{rustc, rustdoc, tmp_dir};
+use run_make_support::{cwd, rustc, rustdoc};
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc-target-spec-json-path");
+    let out_dir = "rustdoc-target-spec-json-path";
     rustc().crate_type("lib").input("dummy_core.rs").target("target.json").run();
     rustdoc()
         .input("my_crate.rs")
         .output(out_dir)
-        .library_search_path(tmp_dir())
+        .library_search_path(cwd())
         .target("target.json")
         .run();
 }
diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs
index 66f3f7cf131..340ab022880 100644
--- a/tests/run-make/rustdoc-test-args/rmake.rs
+++ b/tests/run-make/rustdoc-test-args/rmake.rs
@@ -1,4 +1,4 @@
-use run_make_support::{rustdoc, tmp_dir};
+use run_make_support::rustdoc;
 use std::path::Path;
 use std::{fs, iter};
 
@@ -8,8 +8,8 @@ fn generate_a_lot_of_cfgs(path: &Path) {
 }
 
 fn main() {
-    let arg_file = tmp_dir().join("args");
+    let arg_file = Path::new("args");
     generate_a_lot_of_cfgs(&arg_file);
 
-    rustdoc().out_dir(tmp_dir()).input("foo.rs").arg_file(&arg_file).arg("--test").run();
+    rustdoc().input("foo.rs").arg_file(&arg_file).arg("--test").run();
 }
diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs
index e9da4e25940..c28821b7628 100644
--- a/tests/run-make/rustdoc-themes/rmake.rs
+++ b/tests/run-make/rustdoc-themes/rmake.rs
@@ -1,13 +1,14 @@
 // Test that rustdoc will properly load in a theme file and display it in the theme selector.
 
-use run_make_support::{htmldocck, rustdoc, source_path, tmp_dir};
+use run_make_support::{htmldocck, rustdoc, source_root};
+use std::path::Path;
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc-themes");
-    let test_css = out_dir.join("test.css");
+    let out_dir = Path::new("rustdoc-themes");
+    let test_css = "test.css";
 
     let no_script =
-        std::fs::read_to_string(source_path().join("src/librustdoc/html/static/css/noscript.css"))
+        std::fs::read_to_string(source_root().join("src/librustdoc/html/static/css/noscript.css"))
             .unwrap();
 
     let mut test_content = String::new();
diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs
index 212e7eaba2d..d2d12ae83a2 100644
--- a/tests/run-make/rustdoc-verify-output-files/rmake.rs
+++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs
@@ -1,7 +1,7 @@
 use std::fs::copy;
 use std::path::{Path, PathBuf};
 
-use run_make_support::{copy_dir_all, recursive_diff, rustdoc, tmp_dir};
+use run_make_support::{copy_dir_all, recursive_diff, rustdoc};
 
 #[derive(PartialEq)]
 enum JsonOutput {
@@ -19,8 +19,8 @@ fn generate_docs(out_dir: &Path, json_output: JsonOutput) {
 }
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc");
-    let tmp_out_dir = tmp_dir().join("tmp-rustdoc");
+    let out_dir = PathBuf::from("rustdoc");
+    let tmp_out_dir = PathBuf::from("tmp-rustdoc");
 
     // Generate HTML docs.
     generate_docs(&out_dir, JsonOutput::No);
diff --git a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs
index 86471093834..405da8412ae 100644
--- a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs
+++ b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs
@@ -1,7 +1,7 @@
-use run_make_support::{htmldocck, rustdoc, tmp_dir};
+use run_make_support::{htmldocck, rustdoc};
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc");
+    let out_dir = "rustdoc";
     rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").output(&out_dir).run();
     assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
 }
diff --git a/tests/run-make/rustdoc-with-output-option/rmake.rs b/tests/run-make/rustdoc-with-output-option/rmake.rs
index 1a009419273..a3b1c8ca0dd 100644
--- a/tests/run-make/rustdoc-with-output-option/rmake.rs
+++ b/tests/run-make/rustdoc-with-output-option/rmake.rs
@@ -1,7 +1,7 @@
-use run_make_support::{htmldocck, rustdoc, tmp_dir};
+use run_make_support::{htmldocck, rustdoc};
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc");
+    let out_dir = "rustdoc";
 
     rustdoc()
         .input("src/lib.rs")
diff --git a/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs
index 6206173ecf1..b536fbe2303 100644
--- a/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs
+++ b/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs
@@ -1,7 +1,7 @@
-use run_make_support::{htmldocck, rustdoc, tmp_dir};
+use run_make_support::{htmldocck, rustdoc};
 
 fn main() {
-    let out_dir = tmp_dir().join("rustdoc");
+    let out_dir = "rustdoc";
 
     rustdoc()
         .input("src/lib.rs")
diff --git a/tests/run-make/same-lib-two-locations-no-panic/bar.rs b/tests/run-make/same-lib-two-locations-no-panic/bar.rs
deleted file mode 100644
index bb7b36c496e..00000000000
--- a/tests/run-make/same-lib-two-locations-no-panic/bar.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-extern crate foo;
-
-fn main() {}
diff --git a/tests/run-make/same-lib-two-locations-no-panic/foo.rs b/tests/run-make/same-lib-two-locations-no-panic/foo.rs
deleted file mode 100644
index 82b2dfe9fdb..00000000000
--- a/tests/run-make/same-lib-two-locations-no-panic/foo.rs
+++ /dev/null
@@ -1 +0,0 @@
-#![crate_name = "foo"]
diff --git a/tests/run-make/same-lib-two-locations-no-panic/rmake.rs b/tests/run-make/same-lib-two-locations-no-panic/rmake.rs
deleted file mode 100644
index 2900c3c8b74..00000000000
--- a/tests/run-make/same-lib-two-locations-no-panic/rmake.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// A path which contains the same rlib or dylib in two locations
-// should not cause an assertion panic in the compiler.
-// This test tries to replicate the linked issue and checks
-// if the bugged error makes a resurgence.
-
-// See https://github.com/rust-lang/rust/issues/11908
-
-//@ ignore-cross-compile
-
-use run_make_support::{dynamic_lib, rust_lib, rustc, tmp_dir};
-use std::fs;
-
-fn main() {
-    let tmp_dir_other = tmp_dir().join("other");
-
-    fs::create_dir(&tmp_dir_other);
-    rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
-    fs::rename(dynamic_lib("foo"), &tmp_dir_other);
-    rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
-    rustc().input("bar.rs").library_search_path(&tmp_dir_other).run();
-    fs::remove_dir_all(tmp_dir());
-
-    fs::create_dir_all(&tmp_dir_other);
-    rustc().input("foo.rs").crate_type("rlib").run();
-    fs::rename(rust_lib("foo"), &tmp_dir_other);
-    rustc().input("foo.rs").crate_type("rlib").run();
-    rustc().input("bar.rs").library_search_path(tmp_dir_other).run();
-}
diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs
index c07a6df4d84..d599f813563 100644
--- a/tests/run-make/stdin-rustc/rmake.rs
+++ b/tests/run-make/stdin-rustc/rmake.rs
@@ -1,6 +1,7 @@
 //! This test checks rustc `-` (stdin) support
 
-use run_make_support::{is_windows, rustc, tmp_dir};
+use run_make_support::{is_windows, rustc};
+use std::path::PathBuf;
 
 const HELLO_WORLD: &str = r#"
 fn main() {
@@ -11,16 +12,16 @@ fn main() {
 const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff];
 
 fn main() {
-    let out_dir = tmp_dir();
-
     // echo $HELLO_WORLD | rustc -
     rustc().arg("-").stdin(HELLO_WORLD).run();
     assert!(
-        out_dir.join(if !is_windows() { "rust_out" } else { "rust_out.exe" }).try_exists().unwrap()
+        PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" })
+            .try_exists()
+            .unwrap()
     );
 
     // echo $NOT_UTF8 | rustc -
-    let output = rustc().arg("-").stdin(NOT_UTF8).run_fail();
-    let stderr = String::from_utf8(output.stderr).unwrap();
-    assert!(stderr.contains("error: couldn't read from stdin, as it did not contain valid UTF-8"));
+    rustc().arg("-").stdin(NOT_UTF8).run_fail().assert_stderr_contains(
+        "error: couldn't read from stdin, as it did not contain valid UTF-8",
+    );
 }
diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs
index 584a610ed63..a72fe1bc7da 100644
--- a/tests/run-make/stdin-rustdoc/rmake.rs
+++ b/tests/run-make/stdin-rustdoc/rmake.rs
@@ -1,6 +1,7 @@
 //! This test checks rustdoc `-` (stdin) handling
 
-use run_make_support::{rustdoc, tmp_dir};
+use run_make_support::rustdoc;
+use std::path::PathBuf;
 
 static INPUT: &str = r#"
 //! ```
@@ -10,8 +11,7 @@ pub struct F;
 "#;
 
 fn main() {
-    let tmp_dir = tmp_dir();
-    let out_dir = tmp_dir.join("doc");
+    let out_dir = PathBuf::from("doc");
 
     // rustdoc -
     rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run();
diff --git a/tests/run-make/suspicious-library/Makefile b/tests/run-make/suspicious-library/Makefile
deleted file mode 100644
index 3b5ab3c53a5..00000000000
--- a/tests/run-make/suspicious-library/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) foo.rs -C prefer-dynamic
-	touch $(call DYLIB,foo-something-special)
-	touch $(call DYLIB,foo-something-special2)
-	$(RUSTC) bar.rs
diff --git a/tests/run-make/suspicious-library/rmake.rs b/tests/run-make/suspicious-library/rmake.rs
new file mode 100644
index 00000000000..e789607482b
--- /dev/null
+++ b/tests/run-make/suspicious-library/rmake.rs
@@ -0,0 +1,14 @@
+// This test creates some fake dynamic libraries with nothing inside,
+// and checks if rustc avoids them and successfully compiles as a result.
+
+//@ ignore-cross-compile
+
+use run_make_support::{dynamic_lib_name, rustc};
+use std::fs::File;
+
+fn main() {
+    rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
+    File::create(dynamic_lib_name("foo-something-special")).unwrap();
+    File::create(dynamic_lib_name("foo-something-special2")).unwrap();
+    rustc().input("bar.rs").run();
+}
diff --git a/tests/run-make/wasm-abi/rmake.rs b/tests/run-make/wasm-abi/rmake.rs
index a2dcafbbe0f..0fc326babd9 100644
--- a/tests/run-make/wasm-abi/rmake.rs
+++ b/tests/run-make/wasm-abi/rmake.rs
@@ -1,14 +1,14 @@
 //@ only-wasm32-wasip1
 //@ needs-wasmtime
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 use std::path::Path;
 use std::process::Command;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
 
-    let file = tmp_dir().join("foo.wasm");
+    let file = Path::new("foo.wasm");
 
     run(&file, "return_two_i32", "1\n2\n");
     run(&file, "return_two_i64", "3\n4\n");
diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs
index 0303ca05ca6..65f6d0bf347 100644
--- a/tests/run-make/wasm-custom-section/rmake.rs
+++ b/tests/run-make/wasm-custom-section/rmake.rs
@@ -1,13 +1,13 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::HashMap;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
     rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap();
+    let file = std::fs::read("bar.wasm").unwrap();
 
     let mut custom = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs
index 50916b1bf81..8e66caa6d68 100644
--- a/tests/run-make/wasm-custom-sections-opt/rmake.rs
+++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs
@@ -1,13 +1,13 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::HashMap;
 use std::path::Path;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
 
-    verify(&tmp_dir().join("foo.wasm"));
+    verify(&Path::new("foo.wasm"));
 }
 
 fn verify(path: &Path) {
diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs
index f4c51bc4ab4..a6fec1fb0eb 100644
--- a/tests/run-make/wasm-export-all-symbols/rmake.rs
+++ b/tests/run-make/wasm-export-all-symbols/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::HashMap;
 use std::path::Path;
 use wasmparser::ExternalKind::*;
@@ -18,12 +18,9 @@ fn test(args: &[&str]) {
     rustc().input("foo.rs").target("wasm32-wasip1").args(args).run();
     rustc().input("main.rs").target("wasm32-wasip1").args(args).run();
 
+    verify_exports(Path::new("foo.wasm"), &[("foo", Func), ("FOO", Global), ("memory", Memory)]);
     verify_exports(
-        &tmp_dir().join("foo.wasm"),
-        &[("foo", Func), ("FOO", Global), ("memory", Memory)],
-    );
-    verify_exports(
-        &tmp_dir().join("main.wasm"),
+        Path::new("main.wasm"),
         &[
             ("foo", Func),
             ("FOO", Global),
diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs
index 6eed229e907..0d3152ae99c 100644
--- a/tests/run-make/wasm-import-module/rmake.rs
+++ b/tests/run-make/wasm-import-module/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::HashMap;
 use wasmparser::TypeRef::Func;
 
@@ -8,7 +8,7 @@ fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
     rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let file = std::fs::read(&tmp_dir().join("bar.wasm")).unwrap();
+    let file = std::fs::read("bar.wasm").unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-override-linker/Makefile b/tests/run-make/wasm-override-linker/Makefile
index 52339f9261c..1a01a574dee 100644
--- a/tests/run-make/wasm-override-linker/Makefile
+++ b/tests/run-make/wasm-override-linker/Makefile
@@ -1,4 +1,7 @@
-# needs-matching-clang
+# needs-force-clang-based-tests
+
+# FIXME(#126180): This test doesn't actually run anywhere, because the only
+# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
 
 include ../tools.mk
 
diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs
index 373b966401c..304e5d04833 100644
--- a/tests/run-make/wasm-panic-small/rmake.rs
+++ b/tests/run-make/wasm-panic-small/rmake.rs
@@ -1,7 +1,7 @@
 //@ only-wasm32-wasip1
 #![deny(warnings)]
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     test("a");
@@ -15,7 +15,7 @@ fn test(cfg: &str) {
 
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().cfg(cfg).run();
 
-    let bytes = std::fs::read(&tmp_dir().join("foo.wasm")).unwrap();
+    let bytes = std::fs::read("foo.wasm").unwrap();
     println!("{}", bytes.len());
     assert!(bytes.len() < 40_000);
 }
diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs
index 458c7bfccb7..eb28fdb2b01 100644
--- a/tests/run-make/wasm-spurious-import/rmake.rs
+++ b/tests/run-make/wasm-spurious-import/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::HashMap;
 
 fn main() {
@@ -13,7 +13,7 @@ fn main() {
         .arg("-Copt-level=z")
         .run();
 
-    let file = std::fs::read(&tmp_dir().join("main.wasm")).unwrap();
+    let file = std::fs::read("main.wasm").unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs
index 9fac0c0c215..8c51e26cc33 100644
--- a/tests/run-make/wasm-stringify-ints-small/rmake.rs
+++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs
@@ -1,12 +1,12 @@
 //@ only-wasm32-wasip1
 #![deny(warnings)]
 
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let bytes = std::fs::read(&tmp_dir().join("foo.wasm")).unwrap();
+    let bytes = std::fs::read("foo.wasm").unwrap();
     println!("{}", bytes.len());
     assert!(bytes.len() < 50_000);
 }
diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs
index 521d2c31ee6..83970ef0b24 100644
--- a/tests/run-make/wasm-symbols-different-module/rmake.rs
+++ b/tests/run-make/wasm-symbols-different-module/rmake.rs
@@ -1,7 +1,8 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::collections::{HashMap, HashSet};
+use std::path::Path;
 
 fn main() {
     test_file("foo.rs", &[("a", &["foo"]), ("b", &["foo"])]);
@@ -22,7 +23,7 @@ fn test(file: &str, args: &[&str], expected_imports: &[(&str, &[&str])]) {
 
     rustc().input(file).target("wasm32-wasip1").args(args).run();
 
-    let file = std::fs::read(&tmp_dir().join(file).with_extension("wasm")).unwrap();
+    let file = std::fs::read(Path::new(file).with_extension("wasm")).unwrap();
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs
index 1b020b67a38..54604f51a9e 100644
--- a/tests/run-make/wasm-symbols-not-exported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs
@@ -1,18 +1,18 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::path::Path;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
     rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
 
     rustc().input("bar.rs").target("wasm32-wasip1").run();
-    verify_symbols(&tmp_dir().join("bar.wasm"));
+    verify_symbols(Path::new("bar.wasm"));
     rustc().input("bar.rs").target("wasm32-wasip1").opt().run();
-    verify_symbols(&tmp_dir().join("bar.wasm"));
+    verify_symbols(Path::new("bar.wasm"));
 }
 
 fn verify_symbols(path: &Path) {
diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs
index a653ab61b2c..30408f078bc 100644
--- a/tests/run-make/wasm-symbols-not-imported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs
@@ -1,17 +1,17 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{rustc, tmp_dir, wasmparser};
+use run_make_support::{rustc, wasmparser};
 use std::path::Path;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
     rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
-    verify_symbols(&tmp_dir().join("foo.wasm"));
+    verify_symbols(Path::new("foo.wasm"));
 }
 
 fn verify_symbols(path: &Path) {
diff --git a/tests/run-make/windows-binary-no-external-deps/rmake.rs b/tests/run-make/windows-binary-no-external-deps/rmake.rs
index 6704fe04148..61fdb202221 100644
--- a/tests/run-make/windows-binary-no-external-deps/rmake.rs
+++ b/tests/run-make/windows-binary-no-external-deps/rmake.rs
@@ -2,18 +2,17 @@
 //! a "hello world" application by setting `PATH` to `C:\Windows\System32`.
 //@ only-windows
 
-use run_make_support::{rustc, tmp_dir};
-use std::env;
+use run_make_support::{cwd, env_var, rustc};
 use std::path::PathBuf;
 use std::process::Command;
 
 fn main() {
     rustc().input("hello.rs").run();
 
-    let windows_dir = env::var("SystemRoot").unwrap();
+    let windows_dir = env_var("SystemRoot");
     let system32: PathBuf = [&windows_dir, "System32"].iter().collect();
     // Note: This does not use the support wrappers so that we can precisely control the PATH
-    let exe = tmp_dir().join("hello.exe");
+    let exe = cwd().join("hello.exe");
     let status = Command::new(exe).env("PATH", &system32).spawn().unwrap().wait().unwrap();
     if !status.success() {
         panic!("Command failed!\noutput status: `{status}`");
diff --git a/tests/run-make/windows-spawn/rmake.rs b/tests/run-make/windows-spawn/rmake.rs
index fb9cf1e2149..a6a7acd7ccb 100644
--- a/tests/run-make/windows-spawn/rmake.rs
+++ b/tests/run-make/windows-spawn/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-windows
 
-use run_make_support::{run, rustc, tmp_dir};
+use run_make_support::{run, rustc};
 
 // On Windows `Command` uses `CreateProcessW` to run a new process.
 // However, in the past std used to not pass in the application name, leaving
@@ -10,8 +10,7 @@ use run_make_support::{run, rustc, tmp_dir};
 // `foo bar.exe` if foo.exe does not exist. Which is clearly not desired.
 
 fn main() {
-    let out_dir = tmp_dir();
-    rustc().input("hello.rs").output(out_dir.join("hopefullydoesntexist bar.exe")).run();
+    rustc().input("hello.rs").output("hopefullydoesntexist bar.exe").run();
     rustc().input("spawn.rs").run();
     run("spawn");
 }
diff --git a/tests/run-make/windows-ws2_32/rmake.rs b/tests/run-make/windows-ws2_32/rmake.rs
index 543f8594478..b3c70c354b4 100644
--- a/tests/run-make/windows-ws2_32/rmake.rs
+++ b/tests/run-make/windows-ws2_32/rmake.rs
@@ -3,7 +3,7 @@
 // Tests that WS2_32.dll is not unnecessarily linked, see issue #85441
 
 use run_make_support::object::{self, read::Object};
-use run_make_support::{rustc, tmp_dir};
+use run_make_support::rustc;
 use std::fs;
 
 fn main() {
@@ -15,8 +15,7 @@ fn main() {
 }
 
 fn links_ws2_32(exe: &str) -> bool {
-    let path = tmp_dir().join(exe);
-    let binary_data = fs::read(path).unwrap();
+    let binary_data = fs::read(exe).unwrap();
     let file = object::File::parse(&*binary_data).unwrap();
     for import in file.imports().unwrap() {
         if import.library().eq_ignore_ascii_case(b"WS2_32.dll") {
diff --git a/tests/run-pass-valgrind/cast-enum-with-dtor.rs b/tests/run-pass-valgrind/cast-enum-with-dtor.rs
index f7ef92df8fb..a57dc373478 100644
--- a/tests/run-pass-valgrind/cast-enum-with-dtor.rs
+++ b/tests/run-pass-valgrind/cast-enum-with-dtor.rs
@@ -2,14 +2,14 @@
 
 // check dtor calling order when casting enums.
 
+use std::mem;
 use std::sync::atomic;
 use std::sync::atomic::Ordering;
-use std::mem;
 
 enum E {
     A = 0,
     B = 1,
-    C = 2
+    C = 2,
 }
 
 static FLAG: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
@@ -19,7 +19,7 @@ impl Drop for E {
         // avoid dtor loop
         unsafe { mem::forget(mem::replace(self, E::B)) };
 
-        FLAG.store(FLAG.load(Ordering::SeqCst)+1, Ordering::SeqCst);
+        FLAG.store(FLAG.load(Ordering::SeqCst) + 1, Ordering::SeqCst);
     }
 }
 
diff --git a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs
index dfc094abeb9..e4ce80b3305 100644
--- a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs
+++ b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs
@@ -7,12 +7,15 @@ static mut DROP_RAN: bool = false;
 struct Foo;
 impl Drop for Foo {
     fn drop(&mut self) {
-        unsafe { DROP_RAN = true; }
+        unsafe {
+            DROP_RAN = true;
+        }
     }
 }
 
-
-trait Trait { fn dummy(&self) { } }
+trait Trait {
+    fn dummy(&self) {}
+}
 impl Trait for Foo {}
 
 pub fn main() {
diff --git a/tests/run-pass-valgrind/coerce-match-calls.rs b/tests/run-pass-valgrind/coerce-match-calls.rs
index f6c7151ff10..8c7375610dd 100644
--- a/tests/run-pass-valgrind/coerce-match-calls.rs
+++ b/tests/run-pass-valgrind/coerce-match-calls.rs
@@ -7,9 +7,15 @@ use std::boxed::Box;
 pub fn main() {
     let _: Box<[isize]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) };
 
-    let _: Box<[isize]> = match true { true => Box::new([1, 2, 3]), false => Box::new([1]) };
+    let _: Box<[isize]> = match true {
+        true => Box::new([1, 2, 3]),
+        false => Box::new([1]),
+    };
 
     // Check we don't get over-keen at propagating coercions in the case of casts.
     let x = if true { 42 } else { 42u8 } as u16;
-    let x = match true { true => 42, false => 42u8 } as u16;
+    let x = match true {
+        true => 42,
+        false => 42u8,
+    } as u16;
 }
diff --git a/tests/run-pass-valgrind/coerce-match.rs b/tests/run-pass-valgrind/coerce-match.rs
index 3f33264c5a8..95f16a8cc89 100644
--- a/tests/run-pass-valgrind/coerce-match.rs
+++ b/tests/run-pass-valgrind/coerce-match.rs
@@ -12,11 +12,20 @@ pub fn main() {
     };
 
     let _: Box<[isize]> = match true {
-        true => { let b: Box<_> = Box::new([1, 2, 3]); b }
-        false => { let b: Box<_> = Box::new([1]); b }
+        true => {
+            let b: Box<_> = Box::new([1, 2, 3]);
+            b
+        }
+        false => {
+            let b: Box<_> = Box::new([1]);
+            b
+        }
     };
 
     // Check we don't get over-keen at propagating coercions in the case of casts.
     let x = if true { 42 } else { 42u8 } as u16;
-    let x = match true { true => 42, false => 42u8 } as u16;
+    let x = match true {
+        true => 42,
+        false => 42u8,
+    } as u16;
 }
diff --git a/tests/run-pass-valgrind/down-with-thread-dtors.rs b/tests/run-pass-valgrind/down-with-thread-dtors.rs
index 15aeac98c66..0d3745bba5b 100644
--- a/tests/run-pass-valgrind/down-with-thread-dtors.rs
+++ b/tests/run-pass-valgrind/down-with-thread-dtors.rs
@@ -27,13 +27,17 @@ impl Drop for Bar {
 
 impl Drop for Baz {
     fn drop(&mut self) {
-        unsafe { HIT = true; }
+        unsafe {
+            HIT = true;
+        }
     }
 }
 
 fn main() {
     std::thread::spawn(|| {
         FOO.with(|_| {});
-    }).join().unwrap();
+    })
+    .join()
+    .unwrap();
     assert!(unsafe { HIT });
 }
diff --git a/tests/run-pass-valgrind/dst-dtor-1.rs b/tests/run-pass-valgrind/dst-dtor-1.rs
index 5b8433f6145..47065151a03 100644
--- a/tests/run-pass-valgrind/dst-dtor-1.rs
+++ b/tests/run-pass-valgrind/dst-dtor-1.rs
@@ -3,15 +3,19 @@ static mut DROP_RAN: bool = false;
 struct Foo;
 impl Drop for Foo {
     fn drop(&mut self) {
-        unsafe { DROP_RAN = true; }
+        unsafe {
+            DROP_RAN = true;
+        }
     }
 }
 
-trait Trait { fn dummy(&self) { } }
+trait Trait {
+    fn dummy(&self) {}
+}
 impl Trait for Foo {}
 
 struct Fat<T: ?Sized> {
-    f: T
+    f: T,
 }
 
 pub fn main() {
diff --git a/tests/run-pass-valgrind/dst-dtor-2.rs b/tests/run-pass-valgrind/dst-dtor-2.rs
index 991fe00950b..d8abebfb447 100644
--- a/tests/run-pass-valgrind/dst-dtor-2.rs
+++ b/tests/run-pass-valgrind/dst-dtor-2.rs
@@ -3,12 +3,14 @@ static mut DROP_RAN: isize = 0;
 struct Foo;
 impl Drop for Foo {
     fn drop(&mut self) {
-        unsafe { DROP_RAN += 1; }
+        unsafe {
+            DROP_RAN += 1;
+        }
     }
 }
 
 struct Fat<T: ?Sized> {
-    f: T
+    f: T,
 }
 
 pub fn main() {
diff --git a/tests/run-pass-valgrind/dst-dtor-3.rs b/tests/run-pass-valgrind/dst-dtor-3.rs
index f0c2dda5ab0..09adaca21c7 100644
--- a/tests/run-pass-valgrind/dst-dtor-3.rs
+++ b/tests/run-pass-valgrind/dst-dtor-3.rs
@@ -5,11 +5,15 @@ static mut DROP_RAN: bool = false;
 struct Foo;
 impl Drop for Foo {
     fn drop(&mut self) {
-        unsafe { DROP_RAN = true; }
+        unsafe {
+            DROP_RAN = true;
+        }
     }
 }
 
-trait Trait { fn dummy(&self) { } }
+trait Trait {
+    fn dummy(&self) {}
+}
 impl Trait for Foo {}
 
 pub fn main() {
diff --git a/tests/run-pass-valgrind/dst-dtor-4.rs b/tests/run-pass-valgrind/dst-dtor-4.rs
index ad6d46f7c08..a66ac8e3cfc 100644
--- a/tests/run-pass-valgrind/dst-dtor-4.rs
+++ b/tests/run-pass-valgrind/dst-dtor-4.rs
@@ -5,7 +5,9 @@ static mut DROP_RAN: isize = 0;
 struct Foo;
 impl Drop for Foo {
     fn drop(&mut self) {
-        unsafe { DROP_RAN += 1; }
+        unsafe {
+            DROP_RAN += 1;
+        }
     }
 }
 
diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
index ece4dea9aaf..5d3f558a63a 100644
--- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
+++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs
@@ -43,7 +43,6 @@ impl FnOnce<()> for D {
     }
 }
 
-
 fn main() {
     let x = *(Box::new(A) as Box<dyn FnOnce<(), Output = String>>);
     assert_eq!(x.call_once(()), format!("hello"));
diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
index 94df2b0b83f..9b6648f2e27 100644
--- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
+++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs
@@ -51,7 +51,6 @@ impl FnOnce<(String, Box<str>)> for D {
     }
 }
 
-
 fn main() {
     let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
     let x = *(Box::new(A) as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
@@ -61,10 +60,10 @@ fn main() {
     assert_eq!(x.call_once((s1, s2)), format!("42"));
     let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
     let x = *(Box::new(C(format!("jumping fox")))
-              as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
+        as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
     assert_eq!(x.call_once((s1, s2)), format!("jumping fox"));
     let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str());
     let x = *(Box::new(D(Box::new(format!("lazy dog"))))
-              as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
+        as Box<dyn FnOnce<(String, Box<str>), Output = String>>);
     assert_eq!(x.call_once((s1, s2)), format!("lazy dog"));
 }
diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs
index 3d67101e734..3f6b6d262b5 100644
--- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs
+++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs
@@ -36,7 +36,6 @@ impl Foo for D {
     }
 }
 
-
 fn main() {
     let x = *(Box::new(A) as Box<dyn Foo>);
     assert_eq!(x.foo(), format!("hello"));
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index ffd169812b6..c4d7c2b0b85 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -24,7 +24,7 @@ const PARSED = [
         original: "-> *",
         returned: [],
         userQuery: "-> *",
-        error: "Unexpected `*` after ` `",
+        error: "Unexpected `*` after ` ` (not a valid identifier)",
     },
     {
         query: 'a<"P">',
@@ -204,16 +204,25 @@ const PARSED = [
         original: "_:",
         returned: [],
         userQuery: "_:",
-        error: "Unexpected `:` (expected path after type filter `_:`)",
+        error: "Unexpected `_` (not a valid identifier)",
     },
     {
-        query: "_:a",
+        query: "ab:",
         elems: [],
         foundElems: 0,
-        original: "_:a",
+        original: "ab:",
         returned: [],
-        userQuery: "_:a",
-        error: "Unknown type filter `_`",
+        userQuery: "ab:",
+        error: "Unexpected `:` (expected path after type filter `ab:`)",
+    },
+    {
+        query: "a:b",
+        elems: [],
+        foundElems: 0,
+        original: "a:b",
+        returned: [],
+        userQuery: "a:b",
+        error: "Unknown type filter `a`",
     },
     {
         query: "a-bb",
@@ -240,7 +249,7 @@ const PARSED = [
         original: "ab'",
         returned: [],
         userQuery: "ab'",
-        error: "Unexpected `'` after `b`",
+        error: "Unexpected `'` after `b` (not a valid identifier)",
     },
     {
         query: "a->",
diff --git a/tests/rustdoc-js/assoc-type-backtrack.rs b/tests/rustdoc-js/assoc-type-backtrack.rs
index c3cdd78c6e1..2dfede9dc38 100644
--- a/tests/rustdoc-js/assoc-type-backtrack.rs
+++ b/tests/rustdoc-js/assoc-type-backtrack.rs
@@ -5,22 +5,27 @@ pub trait MyTrait2<X> {
 pub trait MyTrait {
     type Item;
     fn next(&mut self) -> Option<Self::Item>;
-    fn fold<B, F>(self, init: B, f: F) -> B where
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
         Self: Sized,
-        F: MyTrait2<(B, Self::Item), Output=B>;
+        F: MyTrait2<(B, Self::Item), Output = B>;
 }
 
 pub struct Cloned<I>(I);
 
-impl<'a, T, I> MyTrait for Cloned<I> where
+impl<'a, T, I> MyTrait for Cloned<I>
+where
     T: 'a + Clone,
-    I: MyTrait<Item = &'a T>
+    I: MyTrait<Item = &'a T>,
 {
     type Item = T;
-    fn next(&mut self) -> Option<Self::Item> { loop {} }
-    fn fold<B, F>(self, init: B, f: F) -> B where
+    fn next(&mut self) -> Option<Self::Item> {
+        loop {}
+    }
+    fn fold<B, F>(self, init: B, f: F) -> B
+    where
         Self: Sized,
-        F: MyTrait2<(B, Self::Item), Output=B>
+        F: MyTrait2<(B, Self::Item), Output = B>,
     {
         loop {}
     }
@@ -32,7 +37,7 @@ pub trait MyFuture {
 
 pub trait MyIntoFuture {
     type Output;
-    type Fut: MyFuture<Output=Self::Output>;
+    type Fut: MyFuture<Output = Self::Output>;
     fn into_future(self) -> Self::Fut;
     fn into_future_2(self, other: Self) -> Self::Fut;
 }
diff --git a/tests/rustdoc-js/assoc-type-loop.rs b/tests/rustdoc-js/assoc-type-loop.rs
index f123c83f50f..09efe8c7be5 100644
--- a/tests/rustdoc-js/assoc-type-loop.rs
+++ b/tests/rustdoc-js/assoc-type-loop.rs
@@ -1,9 +1,9 @@
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 // reduced from sqlx 0.7.3
 use std::future::Future;
-use std::pin::Pin;
 use std::ops::{Deref, DerefMut};
+use std::pin::Pin;
 pub enum Error {}
 pub trait Acquire<'c> {
     type Database: Database;
@@ -16,7 +16,7 @@ pub trait Connection {
     type Database: Database;
     type Options: ConnectionOptions<Connection = Self>;
     fn begin(
-        &mut self
+        &mut self,
     ) -> Pin<Box<dyn Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_>>
     where
         Self: Sized;
@@ -28,7 +28,8 @@ pub struct Transaction<'c, DB: Database> {
     _db: &'c DB,
 }
 impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB>
-    where <DB as Database>::Connection: Send
+where
+    <DB as Database>::Connection: Send,
 {
     type Database = DB;
     type Connection = &'t mut <DB as Database>::Connection;
diff --git a/tests/rustdoc-js/auxiliary/interner.rs b/tests/rustdoc-js/auxiliary/interner.rs
index c95029be9f0..e4e4ff6276d 100644
--- a/tests/rustdoc-js/auxiliary/interner.rs
+++ b/tests/rustdoc-js/auxiliary/interner.rs
@@ -77,17 +77,14 @@ pub trait Interner: Sized {
     type ClosureKind: Copy + Debug + Hash + Eq;
 
     // Required method
-    fn mk_canonical_var_infos(
-        self,
-        infos: &[CanonicalVarInfo<Self>]
-    ) -> Self::CanonicalVars;
+    fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
 }
 
 pub trait DebugWithInfcx<I: Interner>: Debug {
     // Required method
     fn fmt<Infcx: InferCtxtLike<Interner = I>>(
         this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut Formatter<'_>
+        f: &mut Formatter<'_>,
     ) -> std::fmt::Result;
 }
 
@@ -130,11 +127,7 @@ pub struct TypeFlags;
 
 pub trait Ty<I: Interner<Ty = Self>> {
     // Required method
-    fn new_anon_bound(
-        interner: I,
-        debruijn: DebruijnIndex,
-        var: BoundVar
-    ) -> Self;
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
 }
 
 pub trait PlaceholderLike {
@@ -152,12 +145,7 @@ pub struct BoundVar;
 pub struct ConstKind<I>(std::marker::PhantomData<I>);
 pub trait Const<I: Interner<Const = Self>> {
     // Required method
-    fn new_anon_bound(
-        interner: I,
-        debruijn: DebruijnIndex,
-        var: BoundVar,
-        ty: I::Ty
-    ) -> Self;
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
 }
 
 pub trait ConstTy<I: Interner> {
@@ -170,25 +158,28 @@ pub struct DebruijnIndex;
 pub struct RegionKind<I>(std::marker::PhantomData<I>);
 pub trait Region<I: Interner<Region = Self>> {
     // Required method
-    fn new_anon_bound(
-        interner: I,
-        debruijn: DebruijnIndex,
-        var: BoundVar
-    ) -> Self;
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
 }
 
 pub trait TypeVisitor<I: Interner>: Sized {
     type Result: VisitorResult = ();
 
     // Provided methods
-    fn visit_binder<T: TypeVisitable<I>>(
-        &mut self,
-        t: &I::Binder<T>
-    ) -> Self::Result { unimplemented!() }
-    fn visit_ty(&mut self, t: I::Ty) -> Self::Result { unimplemented!() }
-    fn visit_region(&mut self, _r: I::Region) -> Self::Result { unimplemented!() }
-    fn visit_const(&mut self, c: I::Const) -> Self::Result { unimplemented!() }
-    fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { unimplemented!() }
+    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
+        unimplemented!()
+    }
+    fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
+        unimplemented!()
+    }
+    fn visit_region(&mut self, _r: I::Region) -> Self::Result {
+        unimplemented!()
+    }
+    fn visit_const(&mut self, c: I::Const) -> Self::Result {
+        unimplemented!()
+    }
+    fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
+        unimplemented!()
+    }
 }
 
 pub trait VisitorResult {
@@ -206,7 +197,9 @@ impl VisitorResult for () {
     fn output() -> Self {}
     fn from_residual(_: Self::Residual) -> Self {}
     fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
-    fn branch(self) -> ControlFlow<Self::Residual> { ControlFlow::Continue(()) }
+    fn branch(self) -> ControlFlow<Self::Residual> {
+        ControlFlow::Continue(())
+    }
 }
 
 pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> {
@@ -221,24 +214,18 @@ pub trait InferCtxtLike {
     fn interner(&self) -> Self::Interner;
     fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
     fn root_ty_var(&self, vid: TyVid) -> TyVid;
-    fn probe_ty_var(
-        &self,
-        vid: TyVid
-    ) -> Option<<Self::Interner as Interner>::Ty>;
+    fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
     fn universe_of_lt(
         &self,
-        lt: <Self::Interner as Interner>::InferRegion
+        lt: <Self::Interner as Interner>::InferRegion,
     ) -> Option<UniverseIndex>;
     fn opportunistic_resolve_lt_var(
         &self,
-        vid: <Self::Interner as Interner>::InferRegion
+        vid: <Self::Interner as Interner>::InferRegion,
     ) -> Option<<Self::Interner as Interner>::Region>;
     fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
     fn root_ct_var(&self, vid: ConstVid) -> ConstVid;
-    fn probe_ct_var(
-        &self,
-        vid: ConstVid
-    ) -> Option<<Self::Interner as Interner>::Const>;
+    fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
 }
 
 pub struct TyVid;
diff --git a/tests/rustdoc-js/basic.js b/tests/rustdoc-js/basic.js
index e186d510887..c38b8435c2d 100644
--- a/tests/rustdoc-js/basic.js
+++ b/tests/rustdoc-js/basic.js
@@ -1,6 +1,6 @@
 const EXPECTED = {
     'query': 'Fo',
     'others': [
-        { 'path': 'basic', 'name': 'Foo' },
+        { 'path': 'basic', 'name': 'Foo', 'desc': 'Docs for Foo' },
     ],
 };
diff --git a/tests/rustdoc-js/doc-alias.js b/tests/rustdoc-js/doc-alias.js
index 7e4e8a776d8..e57bd71419d 100644
--- a/tests/rustdoc-js/doc-alias.js
+++ b/tests/rustdoc-js/doc-alias.js
@@ -5,6 +5,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Struct',
+                'desc': 'Doc for <code>Struct</code>',
                 'alias': 'StructItem',
                 'href': '../doc_alias/struct.Struct.html',
                 'is_alias': true
@@ -17,6 +18,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Struct',
                 'name': 'field',
+                'desc': 'Doc for <code>Struct</code>’s <code>field</code>',
                 'alias': 'StructFieldItem',
                 'href': '../doc_alias/struct.Struct.html#structfield.field',
                 'is_alias': true
@@ -29,6 +31,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Struct',
                 'name': 'method',
+                'desc': 'Doc for <code>Struct::method</code>',
                 'alias': 'StructMethodItem',
                 'href': '../doc_alias/struct.Struct.html#method.method',
                 'is_alias': true
@@ -45,6 +48,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Struct',
                 'name': 'ImplConstItem',
+                'desc': 'Doc for <code>Struct::ImplConstItem</code>',
                 'alias': 'StructImplConstItem',
                 'href': '../doc_alias/struct.Struct.html#associatedconstant.ImplConstItem',
                 'is_alias': true
@@ -57,6 +61,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Struct',
                 'name': 'function',
+                'desc': 'Doc for <code>Trait::function</code> implemented for Struct',
                 'alias': 'ImplTraitFunction',
                 'href': '../doc_alias/struct.Struct.html#method.function',
                 'is_alias': true
@@ -69,6 +74,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Enum',
+                'desc': 'Doc for <code>Enum</code>',
                 'alias': 'EnumItem',
                 'href': '../doc_alias/enum.Enum.html',
                 'is_alias': true
@@ -81,6 +87,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Enum',
                 'name': 'Variant',
+                'desc': 'Doc for <code>Enum::Variant</code>',
                 'alias': 'VariantItem',
                 'href': '../doc_alias/enum.Enum.html#variant.Variant',
                 'is_alias': true
@@ -93,6 +100,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Enum',
                 'name': 'method',
+                'desc': 'Doc for <code>Enum::method</code>',
                 'alias': 'EnumMethodItem',
                 'href': '../doc_alias/enum.Enum.html#method.method',
                 'is_alias': true
@@ -105,6 +113,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Typedef',
+                'desc': 'Doc for type alias <code>Typedef</code>',
                 'alias': 'TypedefItem',
                 'href': '../doc_alias/type.Typedef.html',
                 'is_alias': true
@@ -117,6 +126,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Trait',
+                'desc': 'Doc for <code>Trait</code>',
                 'alias': 'TraitItem',
                 'href': '../doc_alias/trait.Trait.html',
                 'is_alias': true
@@ -129,6 +139,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Trait',
                 'name': 'Target',
+                'desc': 'Doc for <code>Trait::Target</code>',
                 'alias': 'TraitTypeItem',
                 'href': '../doc_alias/trait.Trait.html#associatedtype.Target',
                 'is_alias': true
@@ -141,6 +152,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Trait',
                 'name': 'AssociatedConst',
+                'desc': 'Doc for <code>Trait::AssociatedConst</code>',
                 'alias': 'AssociatedConstItem',
                 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst',
                 'is_alias': true
@@ -153,6 +165,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Trait',
                 'name': 'function',
+                'desc': 'Doc for <code>Trait::function</code>',
                 'alias': 'TraitFunctionItem',
                 'href': '../doc_alias/trait.Trait.html#tymethod.function',
                 'is_alias': true
@@ -165,6 +178,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'function',
+                'desc': 'Doc for <code>function</code>',
                 'alias': 'FunctionItem',
                 'href': '../doc_alias/fn.function.html',
                 'is_alias': true
@@ -177,6 +191,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Module',
+                'desc': 'Doc for <code>Module</code>',
                 'alias': 'ModuleItem',
                 'href': '../doc_alias/Module/index.html',
                 'is_alias': true
@@ -189,6 +204,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Const',
+                'desc': 'Doc for <code>Const</code>',
                 'alias': 'ConstItem',
                 'href': '../doc_alias/constant.Const.html',
                 'is_alias': true
@@ -205,6 +221,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Static',
+                'desc': 'Doc for <code>Static</code>',
                 'alias': 'StaticItem',
                 'href': '../doc_alias/static.Static.html',
                 'is_alias': true
@@ -217,6 +234,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Union',
+                'desc': 'Doc for <code>Union</code>',
                 'alias': 'UnionItem',
                 'href': '../doc_alias/union.Union.html',
                 'is_alias': true
@@ -225,6 +243,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Union',
                 'name': 'union_item',
+                'desc': 'Doc for <code>Union::union_item</code>',
                 'href': '../doc_alias/union.Union.html#structfield.union_item'
             },
         ],
@@ -235,6 +254,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Union',
                 'name': 'union_item',
+                'desc': 'Doc for <code>Union::union_item</code>',
                 'alias': 'UnionFieldItem',
                 'href': '../doc_alias/union.Union.html#structfield.union_item',
                 'is_alias': true
@@ -247,6 +267,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias::Union',
                 'name': 'method',
+                'desc': 'Doc for <code>Union::method</code>',
                 'alias': 'UnionMethodItem',
                 'href': '../doc_alias/union.Union.html#method.method',
                 'is_alias': true
@@ -259,6 +280,7 @@ const EXPECTED = [
             {
                 'path': 'doc_alias',
                 'name': 'Macro',
+                'desc': 'Doc for <code>Macro</code>',
                 'alias': 'MacroItem',
                 'href': '../doc_alias/macro.Macro.html',
                 'is_alias': true
diff --git a/tests/rustdoc-js/doc-alias.rs b/tests/rustdoc-js/doc-alias.rs
index 750b7b757bc..bf075385327 100644
--- a/tests/rustdoc-js/doc-alias.rs
+++ b/tests/rustdoc-js/doc-alias.rs
@@ -1,12 +1,16 @@
+/// Doc for `Struct`
 #[doc(alias = "StructItem")]
 pub struct Struct {
+    /// Doc for `Struct`'s `field`
     #[doc(alias = "StructFieldItem")]
     pub field: u32,
 }
 
 impl Struct {
+    /// Doc for `Struct::ImplConstItem`
     #[doc(alias = "StructImplConstItem")]
     pub const ImplConstItem: i32 = 0;
+    /// Doc for `Struct::method`
     #[doc(alias = "StructMethodItem")]
     pub fn method(&self) {}
 }
@@ -15,61 +19,80 @@ impl Trait for Struct {
     type Target = u32;
     const AssociatedConst: i32 = 12;
 
+    /// Doc for `Trait::function` implemented for Struct
     #[doc(alias = "ImplTraitFunction")]
-    fn function() -> Self::Target { 0 }
+    fn function() -> Self::Target {
+        0
+    }
 }
 
+/// Doc for `Enum`
 #[doc(alias = "EnumItem")]
 pub enum Enum {
+    /// Doc for `Enum::Variant`
     #[doc(alias = "VariantItem")]
     Variant,
 }
 
 impl Enum {
+    /// Doc for `Enum::method`
     #[doc(alias = "EnumMethodItem")]
     pub fn method(&self) {}
 }
 
+/// Doc for type alias `Typedef`
 #[doc(alias = "TypedefItem")]
 pub type Typedef = i32;
 
+/// Doc for `Trait`
 #[doc(alias = "TraitItem")]
 pub trait Trait {
+    /// Doc for `Trait::Target`
     #[doc(alias = "TraitTypeItem")]
     type Target;
+    /// Doc for `Trait::AssociatedConst`
     #[doc(alias = "AssociatedConstItem")]
     const AssociatedConst: i32;
 
+    /// Doc for `Trait::function`
     #[doc(alias = "TraitFunctionItem")]
     fn function() -> Self::Target;
 }
 
+/// Doc for `function`
 #[doc(alias = "FunctionItem")]
 pub fn function() {}
 
+/// Doc for `Module`
 #[doc(alias = "ModuleItem")]
 pub mod Module {}
 
+/// Doc for `Const`
 #[doc(alias = "ConstItem")]
 pub const Const: u32 = 0;
 
+/// Doc for `Static`
 #[doc(alias = "StaticItem")]
 pub static Static: u32 = 0;
 
+/// Doc for `Union`
 #[doc(alias = "UnionItem")]
 pub union Union {
+    /// Doc for `Union::union_item`
     #[doc(alias = "UnionFieldItem")]
     pub union_item: u32,
     pub y: f32,
 }
 
 impl Union {
+    /// Doc for `Union::method`
     #[doc(alias = "UnionMethodItem")]
     pub fn method(&self) {}
 }
 
+/// Doc for `Macro`
 #[doc(alias = "MacroItem")]
 #[macro_export]
 macro_rules! Macro {
-    () => {}
+    () => {};
 }
diff --git a/tests/rustdoc-js/enum-variant-not-type.rs b/tests/rustdoc-js/enum-variant-not-type.rs
index 421bddf6289..f0facd63cfc 100644
--- a/tests/rustdoc-js/enum-variant-not-type.rs
+++ b/tests/rustdoc-js/enum-variant-not-type.rs
@@ -5,10 +5,14 @@ pub trait MyTrait {
     fn not_appearing(&self) -> Option<&Self::T>;
 }
 
-pub fn my_fn<X>(t: X) -> X { t }
+pub fn my_fn<X>(t: X) -> X {
+    t
+}
 
 pub trait AutoCorrectConfounder {
     type InsertUnnecessarilyLongTypeNameHere;
-    fn assoc_type_acts_like_generic(&self, x: &Self::InsertUnnecessarilyLongTypeNameHere)
-        -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>;
+    fn assoc_type_acts_like_generic(
+        &self,
+        x: &Self::InsertUnnecessarilyLongTypeNameHere,
+    ) -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>;
 }
diff --git a/tests/rustdoc-js/foreign-type-path.rs b/tests/rustdoc-js/foreign-type-path.rs
index 83400104ea7..f9228c7b9ac 100644
--- a/tests/rustdoc-js/foreign-type-path.rs
+++ b/tests/rustdoc-js/foreign-type-path.rs
@@ -2,12 +2,11 @@
 
 pub mod aaaaaaa {
 
-    extern {
+    extern "C" {
         pub type MyForeignType;
     }
 
     impl MyForeignType {
         pub fn my_method() {}
     }
-
 }
diff --git a/tests/rustdoc-js/full-path-function.rs b/tests/rustdoc-js/full-path-function.rs
index 8dcc3f2b69d..a1a9220654d 100644
--- a/tests/rustdoc-js/full-path-function.rs
+++ b/tests/rustdoc-js/full-path-function.rs
@@ -2,16 +2,26 @@ pub mod sac {
     pub struct Sac;
 
     impl Sac {
-        pub fn len(&self) -> usize { 0 }
+        pub fn len(&self) -> usize {
+            0
+        }
     }
 }
 
 pub mod b {
     pub struct Sac;
     impl Sac {
-        pub fn len(&self) -> usize { 0 }
-        pub fn bar(&self, w: u32) -> usize { 0 }
-        pub fn bar2(&self, w: u32) -> u32 { 0 }
-        pub fn string(w: String) -> u32 { 0 }
+        pub fn len(&self) -> usize {
+            0
+        }
+        pub fn bar(&self, w: u32) -> usize {
+            0
+        }
+        pub fn bar2(&self, w: u32) -> u32 {
+            0
+        }
+        pub fn string(w: String) -> u32 {
+            0
+        }
     }
 }
diff --git a/tests/rustdoc-js/gat.rs b/tests/rustdoc-js/gat.rs
index b4861cc683f..7a2b5551114 100644
--- a/tests/rustdoc-js/gat.rs
+++ b/tests/rustdoc-js/gat.rs
@@ -2,7 +2,15 @@ pub trait Foo {
     type Assoc<T>;
 }
 
-pub fn sample<X: Foo<Assoc<u8> = u8>>(_: X) -> u32 { loop {} }
-pub fn synergy(_: impl Foo<Assoc<u8> = u8>) -> ! { loop {} }
-pub fn consider(_: impl Foo<Assoc<u8> = u32>) -> bool { loop {} }
-pub fn integrate<T>(_: impl Foo<Assoc<T> = T>) -> T { loop {} }
+pub fn sample<X: Foo<Assoc<u8> = u8>>(_: X) -> u32 {
+    loop {}
+}
+pub fn synergy(_: impl Foo<Assoc<u8> = u8>) -> ! {
+    loop {}
+}
+pub fn consider(_: impl Foo<Assoc<u8> = u32>) -> bool {
+    loop {}
+}
+pub fn integrate<T>(_: impl Foo<Assoc<T> = T>) -> T {
+    loop {}
+}
diff --git a/tests/rustdoc-js/generics-impl.rs b/tests/rustdoc-js/generics-impl.rs
index 696218021d5..27d44fdd7e9 100644
--- a/tests/rustdoc-js/generics-impl.rs
+++ b/tests/rustdoc-js/generics-impl.rs
@@ -1,4 +1,4 @@
-use std::io::{Result as IoResult, Read};
+use std::io::{Read, Result as IoResult};
 
 pub struct Aaaaaaa;
 
@@ -29,7 +29,10 @@ impl<T: Read> Ddddddd<T> {
     pub fn ggggggg(self) -> u64 {
         1
     }
-    pub fn hhhhhhh() -> Self where T: Default {
+    pub fn hhhhhhh() -> Self
+    where
+        T: Default,
+    {
         Ddddddd(T::default())
     }
 }
diff --git a/tests/rustdoc-js/generics-trait.rs b/tests/rustdoc-js/generics-trait.rs
index 20db117ccd5..58c86361e41 100644
--- a/tests/rustdoc-js/generics-trait.rs
+++ b/tests/rustdoc-js/generics-trait.rs
@@ -1,8 +1,16 @@
 pub trait SomeTrait {}
 pub trait OtherThingxxxxxxxx {}
 
-pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> { loop {} }
-pub fn bet<T: SomeTrait>() -> Result<T, ()> { loop {} }
+pub fn alef<T: OtherThingxxxxxxxx>() -> Result<T, ()> {
+    loop {}
+}
+pub fn bet<T: SomeTrait>() -> Result<T, ()> {
+    loop {}
+}
 
-pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) { loop {} }
-pub fn beta<T: SomeTrait>(_param: Result<T, ()>) { loop {} }
+pub fn alpha<T: OtherThingxxxxxxxx>(_param: Result<T, ()>) {
+    loop {}
+}
+pub fn beta<T: SomeTrait>(_param: Result<T, ()>) {
+    loop {}
+}
diff --git a/tests/rustdoc-js/generics.rs b/tests/rustdoc-js/generics.rs
index 055c51c7ec5..c3ca1366614 100644
--- a/tests/rustdoc-js/generics.rs
+++ b/tests/rustdoc-js/generics.rs
@@ -3,26 +3,41 @@ pub struct Q;
 pub struct R<T>(T);
 
 // returns test
-pub fn alef() -> R<P> { loop {} }
-pub fn bet() -> R<Q> { loop {} }
+pub fn alef() -> R<P> {
+    loop {}
+}
+pub fn bet() -> R<Q> {
+    loop {}
+}
 
 // in_args test
-pub fn alpha(_x: R<P>) { loop {} }
-pub fn beta(_x: R<Q>) { loop {} }
+pub fn alpha(_x: R<P>) {
+    loop {}
+}
+pub fn beta(_x: R<Q>) {
+    loop {}
+}
 
 // test case with multiple appearances of the same type
-pub struct ExtraCreditStructMulti<T, U> { t: T, u: U }
+pub struct ExtraCreditStructMulti<T, U> {
+    t: T,
+    u: U,
+}
 pub struct ExtraCreditInnerMulti {}
 pub fn extracreditlabhomework(
-    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
-) { loop {} }
-pub fn redherringmatchforextracredit(
-    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>
-) { loop {} }
+    _param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>,
+) {
+    loop {}
+}
+pub fn redherringmatchforextracredit(_param: ExtraCreditStructMulti<ExtraCreditInnerMulti, ()>) {
+    loop {}
+}
 
 pub trait TraitCat {}
 pub trait TraitDog {}
 
 pub fn gamma<T: TraitCat + TraitDog>(t: T) {}
 
-pub fn super_soup(s: Result<String, i32>) -> Result<String, i32> { s }
+pub fn super_soup(s: Result<String, i32>) -> Result<String, i32> {
+    s
+}
diff --git a/tests/rustdoc-js/hof.rs b/tests/rustdoc-js/hof.rs
index 4d2c6e331ca..e4d550250e8 100644
--- a/tests/rustdoc-js/hof.rs
+++ b/tests/rustdoc-js/hof.rs
@@ -4,9 +4,9 @@ pub struct First<T>(T);
 pub struct Second<T>(T);
 pub struct Third<T>(T);
 
-pub fn fn_ptr(_: fn (First<u32>) -> !, _: bool) {}
-pub fn fn_once(_: impl FnOnce (Second<u32>) -> !, _: u8) {}
-pub fn fn_mut(_: impl FnMut (Third<u32>) -> !, _: i8) {}
-pub fn fn_(_: impl Fn (u32) -> !, _: char) {}
+pub fn fn_ptr(_: fn(First<u32>) -> !, _: bool) {}
+pub fn fn_once(_: impl FnOnce(Second<u32>) -> !, _: u8) {}
+pub fn fn_mut(_: impl FnMut(Third<u32>) -> !, _: i8) {}
+pub fn fn_(_: impl Fn(u32) -> !, _: char) {}
 
 pub fn multiple(_: impl Fn(&'static str, &'static str) -> i8) {}
diff --git a/tests/rustdoc-js/macro-search.rs b/tests/rustdoc-js/macro-search.rs
index dc397490cf5..7fa9cbc4ab2 100644
--- a/tests/rustdoc-js/macro-search.rs
+++ b/tests/rustdoc-js/macro-search.rs
@@ -1,10 +1,10 @@
 #[macro_export]
 macro_rules! abracadabra {
-    () => {}
+    () => {};
 }
 #[macro_export]
 macro_rules! abracadabra_b {
-    () => {}
+    () => {};
 }
 pub fn abracadabra() {}
 pub fn abracadabra_c() {}
diff --git a/tests/rustdoc-js/never-search.rs b/tests/rustdoc-js/never-search.rs
index 299b4660dae..800f9ead8b3 100644
--- a/tests/rustdoc-js/never-search.rs
+++ b/tests/rustdoc-js/never-search.rs
@@ -3,11 +3,27 @@
 #[allow(nonstandard_style)]
 pub struct never;
 
-pub fn loops() -> ! { loop {} }
-pub fn returns() -> never { never }
+pub fn loops() -> ! {
+    loop {}
+}
+pub fn returns() -> never {
+    never
+}
 
-pub fn impossible(x: !) { match x {} }
-pub fn uninteresting(x: never) { match x { never => {} } }
+pub fn impossible(x: !) {
+    match x {}
+}
+pub fn uninteresting(x: never) {
+    match x {
+        never => {}
+    }
+}
 
-pub fn box_impossible(x: Box<!>) { match *x {} }
-pub fn box_uninteresting(x: Box<never>) { match *x { never => {} } }
+pub fn box_impossible(x: Box<!>) {
+    match *x {}
+}
+pub fn box_uninteresting(x: Box<never>) {
+    match *x {
+        never => {}
+    }
+}
diff --git a/tests/rustdoc-js/non-english-identifier.js b/tests/rustdoc-js/non-english-identifier.js
new file mode 100644
index 00000000000..1765a69152a
--- /dev/null
+++ b/tests/rustdoc-js/non-english-identifier.js
@@ -0,0 +1,163 @@
+const PARSED = [
+    {
+        query: '中文',
+        elems: [{
+            name: "中文",
+            fullPath: ["中文"],
+            pathWithoutLast: [],
+            pathLast: "中文",
+            generics: [],
+            typeFilter: -1,
+        }],
+        returned: [],
+        foundElems: 1,
+        original: "中文",
+        userQuery: "中文",
+        error: null,
+    },
+    {
+        query: '_0Mixed中英文',
+        elems: [{
+            name: "_0mixed中英文",
+            fullPath: ["_0mixed中英文"],
+            pathWithoutLast: [],
+            pathLast: "_0mixed中英文",
+            generics: [],
+            typeFilter: -1,
+        }],
+        foundElems: 1,
+        original: "_0Mixed中英文",
+        returned: [],
+        userQuery: "_0mixed中英文",
+        error: null,
+    },
+    {
+        query: 'my_crate::中文API',
+        elems: [{
+            name: "my_crate::中文api",
+            fullPath: ["my_crate", "中文api"],
+            pathWithoutLast: ["my_crate"],
+            pathLast: "中文api",
+            generics: [],
+            typeFilter: -1,
+        }],
+        foundElems: 1,
+        original: "my_crate::中文API",
+        returned: [],
+        userQuery: "my_crate::中文api",
+        error: null,
+    },
+    {
+        query: '类型A,类型B<约束C>->返回类型<关联类型=路径::约束D>',
+        elems: [{
+            name: "类型a",
+            fullPath: ["类型a"],
+            pathWithoutLast: [],
+            pathLast: "类型a",
+            generics: [],
+        }, {
+            name: "类型b",
+            fullPath: ["类型b"],
+            pathWithoutLast: [],
+            pathLast: "类型b",
+            generics: [{
+                name: "约束c",
+                fullPath: ["约束c"],
+                pathWithoutLast: [],
+                pathLast: "约束c",
+                generics: [],
+            }],
+        }],
+        foundElems: 3,
+        totalElems: 5,
+        literalSearch: true,
+        original: "类型A,类型B<约束C>->返回类型<关联类型=路径::约束D>",
+        returned: [{
+            name: "返回类型",
+            fullPath: ["返回类型"],
+            pathWithoutLast: [],
+            pathLast: "返回类型",
+            generics: [],
+        }],
+        userQuery: "类型a,类型b<约束c>->返回类型<关联类型=路径::约束d>",
+        error: null,
+    },
+    {
+        query: 'my_crate 中文宏!',
+        elems: [{
+            name: "my_crate 中文宏",
+            fullPath: ["my_crate", "中文宏"],
+            pathWithoutLast: ["my_crate"],
+            pathLast: "中文宏",
+            generics: [],
+            typeFilter: 16,
+        }],
+        foundElems: 1,
+        original: "my_crate 中文宏!",
+        returned: [],
+        userQuery: "my_crate 中文宏!",
+        error: null,
+    },
+    {
+        query: '非法符号——',
+        elems: [],
+        foundElems: 0,
+        original: "非法符号——",
+        returned: [],
+        userQuery: "非法符号——",
+        error: "Unexpected `—` after `号` (not a valid identifier)",
+    }
+]
+const EXPECTED = [
+    {
+        query: '加法',
+        others: [
+            {
+                name: "add",
+                path: "non_english_identifier",
+                is_alias: true,
+                alias: "加法",
+                href: "../non_english_identifier/macro.add.html"
+            },
+            {
+                name: "add",
+                path: "non_english_identifier",
+                is_alias: true,
+                alias: "加法",
+                href: "../non_english_identifier/fn.add.html"
+            },
+            {
+                name: "加法",
+                path: "non_english_identifier",
+                href: "../non_english_identifier/trait.加法.html",
+                desc: "Add"
+            },
+            {
+                name: "中文名称的加法宏",
+                path: "non_english_identifier",
+                href: "../non_english_identifier/macro.中文名称的加法宏.html",
+            },
+            {
+                name: "中文名称的加法API",
+                path: "non_english_identifier",
+                href: "../non_english_identifier/fn.中文名称的加法API.html",
+            }],
+        in_args: [{
+            name: "加上",
+            path: "non_english_identifier::加法",
+            href: "../non_english_identifier/trait.加法.html#tymethod.加上",
+        }],
+        returned: [],
+    },
+    { // Extensive type-based search is still buggy, experimental & work-in-progress.
+        query: '可迭代->可选',
+        others: [{
+            name: "总计",
+            path: "non_english_identifier",
+            href: "../non_english_identifier/fn.总计.html",
+            desc: "“sum”"
+        }],
+        in_args: [],
+        returned: [],
+    },
+];
diff --git a/tests/rustdoc-js/non-english-identifier.rs b/tests/rustdoc-js/non-english-identifier.rs
new file mode 100644
index 00000000000..70b5141472c
--- /dev/null
+++ b/tests/rustdoc-js/non-english-identifier.rs
@@ -0,0 +1,47 @@
+#[doc(alias = "加法")]
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+
+pub fn 中文名称的加法API(left: usize, right: usize) -> usize {
+    left + right
+}
+
+#[macro_export]
+macro_rules! 中文名称的加法宏 {
+    ($left:expr, $right:expr) => {
+        ($left) + ($right)
+    };
+}
+
+#[doc(alias = "加法")]
+#[macro_export]
+macro_rules! add {
+    ($left:expr, $right:expr) => {
+        ($left) + ($right)
+    };
+}
+
+/// Add
+pub trait 加法<类型> {
+    type 结果;
+    fn 加上(self, 被加数: 类型) -> Self::结果;
+}
+
+/// IntoIterator
+pub trait 可迭代 {
+    type 项;
+    type 转为迭代器: Iterator<Item = Self::项>;
+    fn 迭代(self) -> Self::转为迭代器;
+}
+
+pub type 可选<类型> = Option<类型>;
+
+/// "sum"
+pub fn 总计<集合, 个体>(容器: 集合) -> 可选<集合::项>
+where
+    集合: 可迭代<项 = 个体>,
+    个体: 加法<个体, 结果 = 个体>,
+{
+    容器.迭代().reduce(|累计值, 当前值| 累计值.加上(当前值))
+}
diff --git a/tests/rustdoc-js/path-maxeditdistance.rs b/tests/rustdoc-js/path-maxeditdistance.rs
index 3861280d59b..88af4f48774 100644
--- a/tests/rustdoc-js/path-maxeditdistance.rs
+++ b/tests/rustdoc-js/path-maxeditdistance.rs
@@ -1,3 +1,3 @@
-#![crate_name="abracadabra"]
+#![crate_name = "abracadabra"]
 
 pub struct HocusPocusPrestidigitation;
diff --git a/tests/rustdoc-js/prototype.rs b/tests/rustdoc-js/prototype.rs
index 5f6d73cc196..77553561238 100644
--- a/tests/rustdoc-js/prototype.rs
+++ b/tests/rustdoc-js/prototype.rs
@@ -1,4 +1,4 @@
 // The alias needed to be there to reproduce the bug
 // that used to be here.
-#[doc(alias="other_alias")]
+#[doc(alias = "other_alias")]
 pub fn something_else() {}
diff --git a/tests/rustdoc-js/reexport-dedup-macro.rs b/tests/rustdoc-js/reexport-dedup-macro.rs
index 3d18da3951c..f70b9c3d733 100644
--- a/tests/rustdoc-js/reexport-dedup-macro.rs
+++ b/tests/rustdoc-js/reexport-dedup-macro.rs
@@ -1,5 +1,5 @@
 //@ aux-crate: macro_in_module=macro-in-module.rs
-#![crate_name="foo"]
+#![crate_name = "foo"]
 extern crate macro_in_module;
 
 // Test case based on the relationship between alloc and std.
diff --git a/tests/rustdoc-js/reexport-dedup-method.rs b/tests/rustdoc-js/reexport-dedup-method.rs
index 5dbd66e9c8e..c00df094d7a 100644
--- a/tests/rustdoc-js/reexport-dedup-method.rs
+++ b/tests/rustdoc-js/reexport-dedup-method.rs
@@ -1,5 +1,5 @@
 // This test enforces that the (renamed) reexports are present in the search results.
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 pub mod fmt {
     pub struct Subscriber;
@@ -14,5 +14,5 @@ mod foo {
     }
 }
 
-pub use foo::AnotherOne;
 pub use fmt::Subscriber;
+pub use foo::AnotherOne;
diff --git a/tests/rustdoc-js/reexport-dedup.rs b/tests/rustdoc-js/reexport-dedup.rs
index 40aea963303..83c23d5c366 100644
--- a/tests/rustdoc-js/reexport-dedup.rs
+++ b/tests/rustdoc-js/reexport-dedup.rs
@@ -1,5 +1,5 @@
 // This test enforces that the (renamed) reexports are present in the search results.
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 pub mod fmt {
     pub struct Subscriber;
@@ -8,5 +8,5 @@ mod foo {
     pub struct AnotherOne;
 }
 
-pub use foo::AnotherOne;
 pub use fmt::Subscriber;
+pub use foo::AnotherOne;
diff --git a/tests/rustdoc-js/reexport.rs b/tests/rustdoc-js/reexport.rs
index d51b7fb369c..0b3718cd9a3 100644
--- a/tests/rustdoc-js/reexport.rs
+++ b/tests/rustdoc-js/reexport.rs
@@ -9,5 +9,5 @@ mod foo {
     pub struct AnotherOne;
 }
 
-pub use foo::AnotherOne;
 pub use fmt::Subscriber as FmtSubscriber;
+pub use foo::AnotherOne;
diff --git a/tests/rustdoc-js/reference.rs b/tests/rustdoc-js/reference.rs
index 3a0a23c65d5..93b2a6df8e6 100644
--- a/tests/rustdoc-js/reference.rs
+++ b/tests/rustdoc-js/reference.rs
@@ -7,13 +7,17 @@ pub fn pinky(input: &usize, manage: usize) {
 pub struct Thumb;
 
 impl Thumb {
-    pub fn up(&self, finger: Thumb) { unimplemented!() }
+    pub fn up(&self, finger: Thumb) {
+        unimplemented!()
+    }
 }
 
 pub enum Index {}
 
 impl Index {
-    pub fn point(self, data: &Index) { unimplemented!() }
+    pub fn point(self, data: &Index) {
+        unimplemented!()
+    }
 }
 
 pub union Ring {
@@ -22,11 +26,15 @@ pub union Ring {
 }
 
 impl Ring {
-    pub fn wear(&mut self, extra: &Ring) { unimplemented!() }
+    pub fn wear(&mut self, extra: &Ring) {
+        unimplemented!()
+    }
 }
 
 extern "C" {
     pub type Middle;
 }
 
-pub fn show(left: &&mut Middle, right: &mut &Middle) { unimplemented!() }
+pub fn show(left: &&mut Middle, right: &mut &Middle) {
+    unimplemented!()
+}
diff --git a/tests/rustdoc-js/slice-array.rs b/tests/rustdoc-js/slice-array.rs
index 15ac4294f3d..e4e34a26fa2 100644
--- a/tests/rustdoc-js/slice-array.rs
+++ b/tests/rustdoc-js/slice-array.rs
@@ -3,12 +3,20 @@ pub struct Q;
 pub struct R<T>(T);
 
 // returns test
-pub fn alef() -> &'static [R<P>] { loop {} }
-pub fn bet() -> R<[Q; 32]> { loop {} }
+pub fn alef() -> &'static [R<P>] {
+    loop {}
+}
+pub fn bet() -> R<[Q; 32]> {
+    loop {}
+}
 
 // in_args test
-pub fn alpha(_x: R<&'static [P]>) { loop {} }
-pub fn beta(_x: [R<Q>; 32]) { loop {} }
+pub fn alpha(_x: R<&'static [P]>) {
+    loop {}
+}
+pub fn beta(_x: [R<Q>; 32]) {
+    loop {}
+}
 
 pub trait TraitCat {}
 pub trait TraitDog {}
diff --git a/tests/rustdoc-js/struct-like-variant.rs b/tests/rustdoc-js/struct-like-variant.rs
index 2f52a319ab9..aafde9957ff 100644
--- a/tests/rustdoc-js/struct-like-variant.rs
+++ b/tests/rustdoc-js/struct-like-variant.rs
@@ -3,6 +3,6 @@
 pub enum Enum {
     Bar {
         /// This is a name.
-        name: String
-    }
+        name: String,
+    },
 }
diff --git a/tests/rustdoc-js/summaries.rs b/tests/rustdoc-js/summaries.rs
index 1ee1c34aa15..9e8fc820245 100644
--- a/tests/rustdoc-js/summaries.rs
+++ b/tests/rustdoc-js/summaries.rs
@@ -1,6 +1,5 @@
 #![crate_type = "lib"]
 #![crate_name = "summaries"]
-
 #![allow(rustdoc::broken_intra_doc_links)]
 
 //! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc.
diff --git a/tests/rustdoc-js/tuple-unit.rs b/tests/rustdoc-js/tuple-unit.rs
index 93f9a671cbc..4531545cf6c 100644
--- a/tests/rustdoc-js/tuple-unit.rs
+++ b/tests/rustdoc-js/tuple-unit.rs
@@ -3,16 +3,24 @@ pub struct Q;
 pub struct R<T>(T);
 
 // Checks that tuple and unit both work
-pub fn side_effect() { }
+pub fn side_effect() {}
 
 // Check a non-tuple
-pub fn not_tuple() -> P { loop {} }
+pub fn not_tuple() -> P {
+    loop {}
+}
 
 // Check a 1-tuple
-pub fn one() -> (P,) { loop {} }
+pub fn one() -> (P,) {
+    loop {}
+}
 
 // Check a 2-tuple
-pub fn two() -> (P,P) { loop {} }
+pub fn two() -> (P, P) {
+    loop {}
+}
 
 // Check a nested tuple
-pub fn nest() -> (Q, R<(u32,)>) { loop {} }
+pub fn nest() -> (Q, R<(u32,)>) {
+    loop {}
+}
diff --git a/tests/rustdoc-js/type-parameters.rs b/tests/rustdoc-js/type-parameters.rs
index cda5e26171f..0edbfbea178 100644
--- a/tests/rustdoc-js/type-parameters.rs
+++ b/tests/rustdoc-js/type-parameters.rs
@@ -1,15 +1,23 @@
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 pub trait Some {}
 impl Some for () {}
 pub trait Other {}
 impl Other for () {}
 
-pub fn alef<T: Some>() -> T { loop {} }
-pub fn alpha() -> impl Some { }
+pub fn alef<T: Some>() -> T {
+    loop {}
+}
+pub fn alpha() -> impl Some {}
 
-pub fn bet<T, U>(t: T) -> U { loop {} }
+pub fn bet<T, U>(t: T) -> U {
+    loop {}
+}
 pub fn beta<T>(t: T) -> T {}
 
-pub fn other<T: Other, U: Other>(t: T, u: U) { loop {} }
-pub fn alternate<T: Other>(t: T, u: T) { loop {} }
+pub fn other<T: Other, U: Other>(t: T, u: U) {
+    loop {}
+}
+pub fn alternate<T: Other>(t: T, u: T) {
+    loop {}
+}
diff --git a/tests/rustdoc-js/underscoredtype.js b/tests/rustdoc-js/underscoredtype.js
new file mode 100644
index 00000000000..06e3b07b096
--- /dev/null
+++ b/tests/rustdoc-js/underscoredtype.js
@@ -0,0 +1,62 @@
+const EXPECTED = [
+    {
+        'query': 'pid_t',
+        'correction': null,
+        'proposeCorrectionFrom': null,
+        'proposeCorrectionTo': null,
+        'others': [
+            { 'path': 'underscoredtype::unix', 'name': 'pid_t' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'set_pid' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'get_pid' },
+        ],
+    },
+    {
+        'query': 'pidt',
+        'correction': 'pid_t',
+        'proposeCorrectionFrom': null,
+        'proposeCorrectionTo': null,
+        'others': [
+            { 'path': 'underscoredtype::unix', 'name': 'pid_t' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'set_pid' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'get_pid' },
+        ],
+    },
+    {
+        'query': 'unix::pid_t',
+        'correction': null,
+        'proposeCorrectionFrom': null,
+        'proposeCorrectionTo': null,
+        'others': [
+            { 'path': 'underscoredtype::unix', 'name': 'pid_t' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'set_pid' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'get_pid' },
+        ],
+    },
+    {
+        'query': 'unix::pidt',
+        'correction': 'pid_t',
+        'proposeCorrectionFrom': null,
+        'proposeCorrectionTo': null,
+        'others': [
+            { 'path': 'underscoredtype::unix', 'name': 'pid_t' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'set_pid' },
+        ],
+        'returned': [
+            { 'path': 'underscoredtype::unix', 'name': 'get_pid' },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/underscoredtype.rs b/tests/rustdoc-js/underscoredtype.rs
new file mode 100644
index 00000000000..83c532cf855
--- /dev/null
+++ b/tests/rustdoc-js/underscoredtype.rs
@@ -0,0 +1,8 @@
+pub mod unix {
+    #[allow(non_camel_case_types)]
+    pub type pid_t = i32;
+    pub fn get_pid() -> pid_t {
+        0
+    }
+    pub fn set_pid(_: pid_t) {}
+}
diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs
index 56c01019fb6..c0fede1cfd5 100644
--- a/tests/rustdoc-js/where-clause.rs
+++ b/tests/rustdoc-js/where-clause.rs
@@ -4,27 +4,46 @@ pub trait Trait<T> {
     fn thank_you(x: T);
 }
 
-pub fn abracadabra<X>(_: X) where X: Trait<Nested> {}
+pub fn abracadabra<X>(_: X)
+where
+    X: Trait<Nested>,
+{
+}
 
-pub fn alacazam<X>() -> X where X: Trait<Nested> {}
+pub fn alacazam<X>() -> X
+where
+    X: Trait<Nested>,
+{
+}
 
 pub trait T1 {}
 pub trait T2<'a, T> {
     fn please(_: &'a T);
 }
 
-pub fn presto<A, B>(_: A, _: B) where A: T1, B: for <'b> T2<'b, Nested> {}
+pub fn presto<A, B>(_: A, _: B)
+where
+    A: T1,
+    B: for<'b> T2<'b, Nested>,
+{
+}
 
 pub trait Shazam {}
 
-pub fn bippety<X>() -> &'static X where X: Shazam {
+pub fn bippety<X>() -> &'static X
+where
+    X: Shazam,
+{
     panic!()
 }
 
 pub struct Drizzel<T>(T);
 
 impl<T> Drizzel<T> {
-    pub fn boppety(&self) -> &T where T: Shazam {
+    pub fn boppety(&self) -> &T
+    where
+        T: Shazam,
+    {
         panic!();
     }
 }
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 419b0b4fcab..dccad41a861 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -23,9 +23,5 @@
 // @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
 
 pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
-    if l.len() > r.len() {
-        l
-    } else {
-        r
-    }
+    if l.len() > r.len() { l } else { r }
 }
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index d925fcd5221..6f0732646ca 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -12,4 +12,8 @@ pub struct Wrapper<T_>(std::marker::PhantomData<T_>);
 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
-pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}
+pub fn foo()
+where
+    for<'a, T> &'a Wrapper<T>: Trait,
+{
+}
diff --git a/tests/rustdoc-json/output_generics.rs b/tests/rustdoc-json/output_generics.rs
index d421eafbb47..e9df64b79e3 100644
--- a/tests/rustdoc-json/output_generics.rs
+++ b/tests/rustdoc-json/output_generics.rs
@@ -16,12 +16,19 @@ pub trait Trait<T> {
     fn handle(value: T) -> Self;
 }
 
-impl<T, U> Trait<U> for T where T: From<U> {
-    fn handle(_: U) -> Self { unimplemented!() }
+impl<T, U> Trait<U> for T
+where
+    T: From<U>,
+{
+    fn handle(_: U) -> Self {
+        unimplemented!()
+    }
 }
 
 impl<'a, R> Trait<&'a mut Events<R>> for Other {
-    fn handle(_: &'a mut Events<R>) -> Self { unimplemented!() }
+    fn handle(_: &'a mut Events<R>) -> Self {
+        unimplemented!()
+    }
 }
 
 fn this_compiles<'a, R>(value: &'a mut Events<R>) {
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index c30146ce9e0..59e099ec9fc 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -1,6 +1,6 @@
 #![feature(extern_types)]
 
-extern {
+extern "C" {
     /// No inner information
     pub type Foo;
 }
diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs
index 7456892df1b..1515f7d9397 100644
--- a/tests/rustdoc-json/unions/impl.rs
+++ b/tests/rustdoc-json/unions/impl.rs
@@ -4,7 +4,7 @@
 // @has "$.index[*][?(@.name=='Ux')].inner.union"
 pub union Ux {
     a: u32,
-    b: u64
+    b: u64,
 }
 
 // @is "$.index[*][?(@.name=='Num')].visibility" \"public\"
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index 22b70e1ce8c..1089d9c4558 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -7,7 +7,6 @@ pub union Union {
     float: f32,
 }
 
-
 // @has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path"
 // @is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union
 pub fn make_int_union(int: i32) -> Union {
diff --git a/tests/rustdoc-ui/ice-blanket-impl-119792.rs b/tests/rustdoc-ui/ice-blanket-impl-119792.rs
new file mode 100644
index 00000000000..90f0ea8469b
--- /dev/null
+++ b/tests/rustdoc-ui/ice-blanket-impl-119792.rs
@@ -0,0 +1,19 @@
+//@ check-pass
+// https://github.com/rust-lang/rust/issues/119792
+
+struct Wrapper<T>(T);
+
+trait Div<Rhs> {}
+trait Mul<Rhs> {
+    type Output;
+}
+
+impl<T> Mul<T> for Wrapper<T> {
+    type Output = ();
+}
+
+impl<T> Div<Self> for Wrapper<T> {}
+
+pub trait NumOps<Rhs> {}
+
+impl<T, Rhs> NumOps<Rhs> for T where T: Mul<Rhs, Output = ()> + Div<Rhs> {}
diff --git a/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.rs b/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.rs
new file mode 100644
index 00000000000..2b220370d77
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.rs
@@ -0,0 +1,14 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+//@ failure-status: 101
+//@ compile-flags:--test -Z unstable-options --remap-path-prefix={{src-base}}=remapped_path --test-args --test-threads=1
+//@ rustc-env:RUST_BACKTRACE=0
+//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ normalize-stdout-test "exit (status|code): 101" -> "exit status: 101"
+
+// doctest fails at runtime
+/// ```
+/// panic!("oh no");
+/// ```
+pub struct SomeStruct;
diff --git a/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.stdout b/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.stdout
new file mode 100644
index 00000000000..2102e2c3891
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-failed-doctest-output.stdout
@@ -0,0 +1,21 @@
+
+running 1 test
+test remapped_path/remap-path-prefix-failed-doctest-output.rs - SomeStruct (line 11) ... FAILED
+
+failures:
+
+---- remapped_path/remap-path-prefix-failed-doctest-output.rs - SomeStruct (line 11) stdout ----
+Test executable failed (exit status: 101).
+
+stderr:
+thread 'main' panicked at remapped_path/remap-path-prefix-failed-doctest-output.rs:3:1:
+oh no
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+
+
+failures:
+    remapped_path/remap-path-prefix-failed-doctest-output.rs - SomeStruct (line 11)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.rs b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.rs
new file mode 100644
index 00000000000..2e023e32d7a
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.rs
@@ -0,0 +1,13 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+//@ failure-status: 101
+//@ compile-flags:--test -Z unstable-options --remap-path-prefix={{src-base}}=remapped_path --test-args --test-threads=1
+//@ rustc-env:RUST_BACKTRACE=0
+//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// doctest fails to compile
+/// ```
+/// this is not real code
+/// ```
+pub struct SomeStruct;
diff --git a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
new file mode 100644
index 00000000000..a05b5169989
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
@@ -0,0 +1,22 @@
+
+running 1 test
+test remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) ... FAILED
+
+failures:
+
+---- remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) stdout ----
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `is`
+  --> remapped_path/remap-path-prefix-invalid-doctest.rs:11:6
+   |
+LL | this is not real code
+   |      ^^ expected one of 8 possible tokens
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.rs b/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.rs
new file mode 100644
index 00000000000..c58f3faeb53
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+//@ check-run-results
+
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+//@ compile-flags:--test -Z unstable-options --remap-path-prefix={{src-base}}=remapped_path --test-args --test-threads=1
+//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// doctest passes at runtime
+/// ```
+/// assert!(true);
+/// ```
+pub struct SomeStruct;
diff --git a/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.stdout b/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.stdout
new file mode 100644
index 00000000000..8ffb5694885
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-passed-doctest-output.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test remapped_path/remap-path-prefix-passed-doctest-output.rs - SomeStruct (line 11) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/unable-fulfill-trait.rs b/tests/rustdoc-ui/unable-fulfill-trait.rs
index a69f74b09ac..f3b6256346f 100644
--- a/tests/rustdoc-ui/unable-fulfill-trait.rs
+++ b/tests/rustdoc-ui/unable-fulfill-trait.rs
@@ -1,13 +1,16 @@
 // This test ensures that it's not crashing rustdoc.
 
 pub struct Foo<'a, 'b, T> {
-    field1: dyn Bar<'a, 'b,>,
+    field1: dyn Bar<'a, 'b>,
     //~^ ERROR
     //~| ERROR
+    //~| ERROR
 }
 
 pub trait Bar<'x, 's, U>
-    where U: 'x,
-    Self:'x,
-    Self:'s
-{}
+where
+    U: 'x,
+    Self: 'x,
+    Self: 's,
+{
+}
diff --git a/tests/rustdoc-ui/unable-fulfill-trait.stderr b/tests/rustdoc-ui/unable-fulfill-trait.stderr
index 72f35cb9224..40d103f2a62 100644
--- a/tests/rustdoc-ui/unable-fulfill-trait.stderr
+++ b/tests/rustdoc-ui/unable-fulfill-trait.stderr
@@ -1,26 +1,43 @@
 error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/unable-fulfill-trait.rs:4:17
    |
-LL |     field1: dyn Bar<'a, 'b,>,
+LL |     field1: dyn Bar<'a, 'b>,
    |                 ^^^ expected 1 generic argument
    |
 note: trait defined here, with 1 generic parameter: `U`
-  --> $DIR/unable-fulfill-trait.rs:9:11
+  --> $DIR/unable-fulfill-trait.rs:10:11
    |
 LL | pub trait Bar<'x, 's, U>
    |           ^^^         -
 help: add missing generic argument
    |
-LL |     field1: dyn Bar<'a, 'b, U,>,
+LL |     field1: dyn Bar<'a, 'b, U>,
    |                           +++
 
 error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
   --> $DIR/unable-fulfill-trait.rs:4:13
    |
-LL |     field1: dyn Bar<'a, 'b,>,
-   |             ^^^^^^^^^^^^^^^^
+LL |     field1: dyn Bar<'a, 'b>,
+   |             ^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/unable-fulfill-trait.rs:4:13
+   |
+LL |     field1: dyn Bar<'a, 'b>,
+   |             ^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'b` as defined here
+  --> $DIR/unable-fulfill-trait.rs:3:20
+   |
+LL | pub struct Foo<'a, 'b, T> {
+   |                    ^^
+note: but lifetime parameter must outlive the lifetime `'a` as defined here
+  --> $DIR/unable-fulfill-trait.rs:3:16
+   |
+LL | pub struct Foo<'a, 'b, T> {
+   |                ^^
+
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0227.
+Some errors have detailed explanations: E0107, E0227, E0478.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs
index 010263f6ad3..4de5d8575b0 100644
--- a/tests/rustdoc/async-fn.rs
+++ b/tests/rustdoc/async-fn.rs
@@ -79,7 +79,7 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T }
 
 impl Foo {
     // @has async_fn/struct.Foo.html
-    // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator<Item = &usize>'
+    // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar, ) -> impl Iterator<Item = &usize>'
     pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {
         [0].iter()
     }
diff --git a/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html b/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html
index 29c08c5bd5d..12c6bc214a7 100644
--- a/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html
+++ b/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html
@@ -1,2 +1 @@
-<pre class="rust item-decl"><code>pub fn create(
-) -&gt; <a class="struct" href="struct.Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000.html" title="struct decl_line_wrapping_empty_arg_list::Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000">Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000</a></code></pre>
\ No newline at end of file
+<pre class="rust item-decl"><code>pub fn create() -&gt; <a class="struct" href="struct.Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000.html" title="struct decl_line_wrapping_empty_arg_list::Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000">Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000</a></code></pre>
\ No newline at end of file
diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html
index 59c318c16f3..0cc3f0fa244 100644
--- a/tests/rustdoc/decl-trailing-whitespace.declaration.html
+++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html
@@ -3,7 +3,7 @@
     fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(
         self,
         cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
-        buf: &amp;mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]
+        buf: &amp;mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>],
     ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
 <span class="item-spacer" />    fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(self, cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
 <span class="item-spacer" />    fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(self, cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
@@ -12,6 +12,6 @@
     fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(
         self,
         cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
-        bufs: &amp;[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]
+        bufs: &amp;[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>],
     ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt; { ... }
 }</code>
\ No newline at end of file
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index 47e2c9dc76b..19d1673f2eb 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -11,7 +11,7 @@ pub use impl_trait_aux::func;
 // @has impl_trait/fn.func2.html
 // @has - '//pre[@class="rust item-decl"]' "func2<T>("
 // @has - '//pre[@class="rust item-decl"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
-// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator<Item = u8> )"
+// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator<Item = u8>, )"
 // @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func2;
 
diff --git a/tests/rustdoc/line-breaks.rs b/tests/rustdoc/line-breaks.rs
index 21aa3a03ce4..0f760d51973 100644
--- a/tests/rustdoc/line-breaks.rs
+++ b/tests/rustdoc/line-breaks.rs
@@ -6,7 +6,7 @@ use std::ops::Add;
 // @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\
 //     function_with_a_really_long_name\(\n\
 //    \    parameter_one: i32,\n\
-//    \    parameter_two: i32\n\
+//    \    parameter_two: i32,\n\
 //    \) -> Option<i32>$"
 pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option<i32> {
     Some(parameter_one + parameter_two)
diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs
index 1eee262d233..97318a01410 100644
--- a/tests/rustdoc/reexports-priv.rs
+++ b/tests/rustdoc/reexports-priv.rs
@@ -98,7 +98,7 @@ pub mod outer {
         pub use reexports::foo;
         // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()'
         pub(crate) use reexports::foo_crate;
-        // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super( )'
+        // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super()'
         pub(super) use::reexports::foo_super;
         // @!has 'foo/outer/inner/fn.foo_self.html'
         pub(self) use reexports::foo_self;
diff --git a/tests/run-make-fulldeps/obtain-borrowck/test.rs b/tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs
index f7b4b41feaf..7213e06792a 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/test.rs
+++ b/tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs
@@ -1,3 +1,5 @@
+#![allow(dead_code)]
+
 trait X {
     fn provided(&self) -> usize {
         5
diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs
index 28a1e27cccc..f273bbc99a8 100644
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs
@@ -1,3 +1,5 @@
+//@ edition: 2021
+
 #![feature(rustc_private)]
 #![deny(warnings)]
 
@@ -27,7 +29,9 @@ use std::any::Any;
 struct TheBackend;
 
 impl CodegenBackend for TheBackend {
-    fn locale_resource(&self) -> &'static str { "" }
+    fn locale_resource(&self) -> &'static str {
+        ""
+    }
 
     fn codegen_crate<'a, 'tcx>(
         &self,
@@ -62,7 +66,10 @@ impl CodegenBackend for TheBackend {
         codegen_results: CodegenResults,
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorGuaranteed> {
-        use rustc_session::{config::{CrateType, OutFileName}, output::out_filename};
+        use rustc_session::{
+            config::{CrateType, OutFileName},
+            output::out_filename,
+        };
         use std::io::Write;
         let crate_name = codegen_results.crate_info.local_crate_name;
         for &crate_type in sess.opts.crate_types.iter() {
@@ -73,11 +80,11 @@ impl CodegenBackend for TheBackend {
             match output_name {
                 OutFileName::Real(ref path) => {
                     let mut out_file = ::std::fs::File::create(path).unwrap();
-                    write!(out_file, "This has been \"compiled\" successfully.").unwrap();
+                    writeln!(out_file, "This has been 'compiled' successfully.").unwrap();
                 }
                 OutFileName::Stdout => {
                     let mut stdout = std::io::stdout();
-                    write!(stdout, "This has been \"compiled\" successfully.").unwrap();
+                    writeln!(stdout, "This has been 'compiled' successfully.").unwrap();
                 }
             }
         }
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout
new file mode 100644
index 00000000000..4d58fd503d0
--- /dev/null
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout
@@ -0,0 +1,4 @@
+$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/libhotplug.rlib: $DIR/hotplug.rs $TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so
+
+$DIR/hotplug.rs:
+$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so:
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout
new file mode 100644
index 00000000000..48b7534d8fa
--- /dev/null
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout
@@ -0,0 +1,3 @@
+$TEST_BUILD_DIR/codegen-backend/hotplug.dep/libhotplug.rlib: $DIR/hotplug.rs
+
+$DIR/hotplug.rs:
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout
new file mode 100644
index 00000000000..1aa032de9e4
--- /dev/null
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout
@@ -0,0 +1 @@
+This has been 'compiled' successfully.
diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.rs b/tests/ui-fulldeps/codegen-backend/hotplug.rs
new file mode 100644
index 00000000000..dc0fb3f9efd
--- /dev/null
+++ b/tests/ui-fulldeps/codegen-backend/hotplug.rs
@@ -0,0 +1,20 @@
+//@ edition: 2021
+//@ build-pass
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+
+//@ aux-codegen-backend: the_backend.rs
+//@ normalize-stdout-test: "libthe_backend.dylib" -> "libthe_backend.so"
+//@ normalize-stdout-test: "the_backend.dll" -> "libthe_backend.so"
+
+//@ revisions: normal dep bindep
+//@ compile-flags: --crate-type=lib
+//@ [normal] compile-flags: --emit=link=-
+//@ [dep]    compile-flags: --emit=link,dep-info=-
+//@ [bindep] compile-flags: --emit=link,dep-info=- -Zbinary-dep-depinfo
+
+#![feature(no_core)]
+#![no_core]
+
+// This test both exists as a check that -Zcodegen-backend is capable of loading external codegen
+// backends and that this external codegen backend is only included in the dep info if
+// -Zbinary-dep-depinfo is used.
diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
index ef70e64ed7e..99cb5fc5aa1 100644
--- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
+++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
@@ -16,7 +16,7 @@ extern crate rustc_span;
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
 
-use rustc_parse::new_parser_from_file;
+use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use std::path::Path;
 
@@ -34,6 +34,6 @@ fn parse() {
 
     let path = Path::new(file!());
     let path = path.canonicalize().unwrap();
-    let mut parser = new_parser_from_file(&psess, &path, None);
+    let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&psess, &path, None));
     let _ = parser.parse_crate_mod();
 }
diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/ui-fulldeps/obtain-borrowck.rs
index e67ec8690f8..e6c703addd9 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/tests/ui-fulldeps/obtain-borrowck.rs
@@ -1,3 +1,10 @@
+//@ edition: 2021
+//@ run-pass
+//@ check-run-results
+//@ run-flags: --sysroot {{sysroot-base}} --edition=2021 {{src-base}}/auxiliary/obtain-borrowck-input.rs
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+// ignore-tidy-linelength
+
 #![feature(rustc_private)]
 
 //! This program implements a rustc driver that retrieves MIR bodies with
diff --git a/tests/run-make-fulldeps/obtain-borrowck/output.stdout b/tests/ui-fulldeps/obtain-borrowck.run.stdout
index e011622e6b2..e011622e6b2 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/output.stdout
+++ b/tests/ui-fulldeps/obtain-borrowck.run.stdout
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 2b1fec94387..762ad0b79ec 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -36,7 +36,7 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
-use rustc_parse::new_parser_from_source_str;
+use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
@@ -46,8 +46,9 @@ use thin_vec::{thin_vec, ThinVec};
 fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
 
-    let mut p =
-        new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string);
+    let mut p = unwrap_or_emit_fatal(
+        new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string)
+    );
     p.parse_expr().map_err(|e| e.cancel()).ok()
 }
 
diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/ui-fulldeps/run-compiler-twice.rs
index 327c99a02c6..02748626723 100644
--- a/tests/run-make-fulldeps/issue-19371/foo.rs
+++ b/tests/ui-fulldeps/run-compiler-twice.rs
@@ -1,3 +1,13 @@
+//@ edition: 2021
+//@ run-pass
+//@ run-flags: {{sysroot-base}} {{target-linker}}
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+
+// Regression test for <https://github.com/rust-lang/rust/issues/19371>.
+//
+// This test ensures that `compile_input` can be called twice in one task
+// without causing a panic.
+
 #![feature(rustc_private)]
 
 extern crate rustc_driver;
@@ -5,12 +15,12 @@ extern crate rustc_interface;
 extern crate rustc_session;
 extern crate rustc_span;
 
+use std::path::{Path, PathBuf};
+
 use rustc_interface::interface;
 use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
 use rustc_span::FileName;
 
-use std::path::PathBuf;
-
 fn main() {
     let src = r#"
     fn main() {}
@@ -18,28 +28,28 @@ fn main() {
 
     let args: Vec<String> = std::env::args().collect();
 
-    if args.len() < 4 {
-        panic!("expected rustc path");
+    if args.len() < 2 {
+        panic!("expected sysroot (and optional linker)");
     }
 
-    let tmpdir = PathBuf::from(&args[1]);
-
-    let mut sysroot = PathBuf::from(&args[3]);
-    sysroot.pop();
-    sysroot.pop();
+    let sysroot = PathBuf::from(&args[1]);
+    let linker = args.get(2).map(PathBuf::from);
 
-    compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
+    // compiletest sets the current dir to `output_base_dir` when running.
+    let tmpdir = std::env::current_dir().unwrap().join("tmp");
+    std::fs::create_dir_all(&tmpdir).unwrap();
 
-    compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
+    compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
+    compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
 }
 
-fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
+fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
     let mut opts = Options::default();
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
 
-    if let Ok(linker) = std::env::var("RUSTC_LINKER") {
-        opts.cg.linker = Some(linker.into());
+    if let Some(linker) = linker {
+        opts.cg.linker = Some(linker.to_owned());
     }
 
     let name = FileName::anon_source_code(&code);
diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index 218c7b3e386..f971426723f 100644
--- a/tests/ui-fulldeps/stable-mir/check_instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -33,7 +33,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     // Get all items and split generic vs monomorphic items.
     let (generic, mono): (Vec<_>, Vec<_>) =
         items.into_iter().partition(|item| item.requires_monomorphization());
-    assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant");
+    assert_eq!(mono.len(), 4, "Expected 2 mono functions and one constant");
     assert_eq!(generic.len(), 2, "Expected 2 generic functions");
 
     // For all monomorphic items, get the correspondent instances.
@@ -57,8 +57,9 @@ fn test_body(body: mir::Body) {
     for term in body.blocks.iter().map(|bb| &bb.terminator) {
         match &term.kind {
             Call { func, .. } => {
-                let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { unreachable!
-                () };
+                let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else {
+                    unreachable!()
+                };
                 let RigidTy::FnDef(def, args) = ty else { unreachable!() };
                 let instance = Instance::resolve(def, &args).unwrap();
                 let mangled_name = instance.mangled_name();
@@ -102,6 +103,9 @@ fn generate_input(path: &str) -> std::io::Result<()> {
     write!(
         file,
         r#"
+
+    struct Foo(());
+
     pub fn ty_param<T>(t: &T) -> T where T: Clone {{
         t.clone()
     }}
@@ -116,6 +120,7 @@ fn generate_input(path: &str) -> std::io::Result<()> {
     }}
 
     pub fn monomorphic() {{
+        Foo(());
         let v = vec![10];
         let dup = ty_param(&v);
         assert_eq!(v, dup);
diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs
index 6345ee24f78..b203e76e54f 100644
--- a/tests/ui-fulldeps/stable-mir/check_transform.rs
+++ b/tests/ui-fulldeps/stable-mir/check_transform.rs
@@ -22,7 +22,7 @@ use rustc_smir::rustc_internal;
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::mono::Instance;
 use stable_mir::mir::{Body, Constant, Operand, Rvalue, StatementKind, TerminatorKind};
-use stable_mir::ty::{Const, ConstantKind};
+use stable_mir::ty::{ConstantKind, MirConst};
 use stable_mir::{CrateDef, CrateItems, ItemKind};
 use std::convert::TryFrom;
 use std::io::Write;
@@ -77,7 +77,7 @@ fn check_msg(body: &Body, expected: &str) {
                 };
                 assert_eq!(alloc.provenance.ptrs.len(), 1);
 
-                let alloc_prov_id = alloc.provenance.ptrs[0].1 .0;
+                let alloc_prov_id = alloc.provenance.ptrs[0].1.0;
                 let GlobalAlloc::Memory(val) = GlobalAlloc::from(alloc_prov_id) else {
                     unreachable!()
                 };
@@ -95,7 +95,7 @@ fn change_panic_msg(mut body: Body, new_msg: &str) -> Body {
     for bb in &mut body.blocks {
         match &mut bb.terminator.kind {
             TerminatorKind::Call { args, .. } => {
-                let new_const = Const::from_str(new_msg);
+                let new_const = MirConst::from_str(new_msg);
                 args[0] = Operand::Constant(Constant {
                     literal: new_const,
                     span: bb.terminator.span,
diff --git a/tests/ui/associated-inherent-types/issue-109071.rs b/tests/ui/associated-inherent-types/issue-109071.rs
index 29eef081a32..97803ae7191 100644
--- a/tests/ui/associated-inherent-types/issue-109071.rs
+++ b/tests/ui/associated-inherent-types/issue-109071.rs
@@ -13,7 +13,7 @@ impl<T> Windows { //~ ERROR: missing generics for struct `Windows`
 
 impl<T> Windows<T> {
     fn T() -> Option<Self::Item> {}
-    //~^ ERROR: ambiguous associated type
+    //[no_gate]~^ ERROR: ambiguous associated type
 }
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
index a7d17e2d5eb..1324cb9bb9b 100644
--- a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
@@ -20,20 +20,7 @@ help: add missing generic argument
 LL | impl<T> Windows<T> {
    |                +++
 
-error[E0223]: ambiguous associated type
-  --> $DIR/issue-109071.rs:15:22
-   |
-LL |     fn T() -> Option<Self::Item> {}
-   |                      ^^^^^^^^^^
-   |
-help: use fully-qualified syntax
-   |
-LL |     fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0223, E0637.
+Some errors have detailed explanations: E0107, E0637.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/associated-inherent-types/issue-109299.rs b/tests/ui/associated-inherent-types/issue-109299.rs
index b6c010c34e4..84e4f9e7252 100644
--- a/tests/ui/associated-inherent-types/issue-109299.rs
+++ b/tests/ui/associated-inherent-types/issue-109299.rs
@@ -8,6 +8,5 @@ impl Lexer<'d> { //~ ERROR use of undeclared lifetime name `'d`
 }
 
 fn test(_: Lexer::Cursor) {}
-//~^ ERROR: lifetime may not live long enough
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-109299.stderr b/tests/ui/associated-inherent-types/issue-109299.stderr
index f108a52b92c..1e11c0e8c2a 100644
--- a/tests/ui/associated-inherent-types/issue-109299.stderr
+++ b/tests/ui/associated-inherent-types/issue-109299.stderr
@@ -6,15 +6,6 @@ LL | impl Lexer<'d> {
    |     |
    |     help: consider introducing lifetime `'d` here: `<'d>`
 
-error: lifetime may not live long enough
-  --> $DIR/issue-109299.rs:10:1
-   |
-LL | fn test(_: Lexer::Cursor) {}
-   | ^^^^^^^^-^^^^^^^^^^^^^^^^
-   | |       |
-   | |       has type `Lexer<'1>::Cursor`
-   | requires that `'1` must outlive `'static`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr
index 1f1e303ea4c..4c165ff619a 100644
--- a/tests/ui/async-await/coroutine-desc.stderr
+++ b/tests/ui/async-await/coroutine-desc.stderr
@@ -10,6 +10,8 @@ LL |     fun(async {}, async {});
    |
    = note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
               found `async` block `{async block@$DIR/coroutine-desc.rs:10:19: 10:27}`
+   = note: no two async blocks, even if identical, have the same type
+   = help: consider pinning your async block and casting it to a trait object
 note: function defined here
   --> $DIR/coroutine-desc.rs:8:4
    |
@@ -51,6 +53,8 @@ LL |     fun((async || {})(), (async || {})());
    |
    = note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}`
               found `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:36: 14:38}`
+   = note: no two async blocks, even if identical, have the same type
+   = help: consider pinning your async block and casting it to a trait object
 note: function defined here
   --> $DIR/coroutine-desc.rs:8:4
    |
diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs
index c5485ebc9b6..38a5df3576b 100644
--- a/tests/ui/async-await/no-async-const.rs
+++ b/tests/ui/async-await/no-async-const.rs
@@ -2,5 +2,5 @@
 //@ compile-flags: --crate-type lib
 
 pub async const fn x() {}
-//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
+//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
 //~| ERROR functions cannot be both `const` and `async`
diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr
index 524d778c09b..d692ba8f473 100644
--- a/tests/ui/async-await/no-async-const.stderr
+++ b/tests/ui/async-await/no-async-const.stderr
@@ -1,10 +1,10 @@
-error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
+error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
   --> $DIR/no-async-const.rs:4:11
    |
 LL | pub async const fn x() {}
    |     ------^^^^^
    |     |     |
-   |     |     expected one of `extern`, `fn`, or `unsafe`
+   |     |     expected one of `extern`, `fn`, `safe`, or `unsafe`
    |     help: `const` must come before `async`: `const async`
    |
    = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
diff --git a/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs b/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs
new file mode 100644
index 00000000000..ce365d1a8b1
--- /dev/null
+++ b/tests/ui/attributes/unsafe/cfg-unsafe-attributes.rs
@@ -0,0 +1,7 @@
+//@ build-pass
+#![feature(unsafe_attributes)]
+
+#[cfg_attr(all(), unsafe(no_mangle))]
+fn a() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
new file mode 100644
index 00000000000..774ce86c096
--- /dev/null
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
@@ -0,0 +1,6 @@
+#![feature(unsafe_attributes)]
+
+#[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)`
+struct Foo;
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
new file mode 100644
index 00000000000..fc0daf16790
--- /dev/null
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
@@ -0,0 +1,8 @@
+error: traits in `#[derive(...)]` don't accept `unsafe(...)`
+  --> $DIR/derive-unsafe-attributes.rs:3:10
+   |
+LL | #[derive(unsafe(Debug))]
+   |          ^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.rs b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs
new file mode 100644
index 00000000000..a6c0ea578f2
--- /dev/null
+++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.rs
@@ -0,0 +1,9 @@
+#![feature(unsafe_attributes)]
+
+#[unsafe(unsafe(no_mangle))]
+//~^ ERROR expected identifier, found keyword `unsafe`
+//~| ERROR cannot find attribute `r#unsafe` in this scope
+//~| ERROR `r#unsafe` is not an unsafe attribute
+fn a() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
new file mode 100644
index 00000000000..1c07a5bf8ba
--- /dev/null
+++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
@@ -0,0 +1,27 @@
+error: expected identifier, found keyword `unsafe`
+  --> $DIR/double-unsafe-attributes.rs:3:10
+   |
+LL | #[unsafe(unsafe(no_mangle))]
+   |          ^^^^^^ expected identifier, found keyword
+   |
+help: escape `unsafe` to use it as an identifier
+   |
+LL | #[unsafe(r#unsafe(no_mangle))]
+   |          ++
+
+error: cannot find attribute `r#unsafe` in this scope
+  --> $DIR/double-unsafe-attributes.rs:3:10
+   |
+LL | #[unsafe(unsafe(no_mangle))]
+   |          ^^^^^^
+
+error: `r#unsafe` is not an unsafe attribute
+  --> $DIR/double-unsafe-attributes.rs:3:3
+   |
+LL | #[unsafe(unsafe(no_mangle))]
+   |   ^^^^^^
+   |
+   = note: extraneous unsafe is not allowed in attributes
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/attributes/unsafe/unsafe-attributes.rs b/tests/ui/attributes/unsafe/unsafe-attributes.rs
new file mode 100644
index 00000000000..e7620a18048
--- /dev/null
+++ b/tests/ui/attributes/unsafe/unsafe-attributes.rs
@@ -0,0 +1,7 @@
+//@ build-pass
+#![feature(unsafe_attributes)]
+
+#[unsafe(no_mangle)]
+fn a() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs b/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs
new file mode 100644
index 00000000000..67db36afd2e
--- /dev/null
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.rs
@@ -0,0 +1,6 @@
+#![feature(unsafe_attributes)]
+
+#[unsafe(repr(C))] //~ ERROR: is not an unsafe attribute
+struct Foo {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
new file mode 100644
index 00000000000..0602af34e4f
--- /dev/null
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
@@ -0,0 +1,10 @@
+error: `repr` is not an unsafe attribute
+  --> $DIR/unsafe-safe-attribute.rs:3:3
+   |
+LL | #[unsafe(repr(C))]
+   |   ^^^^^^
+   |
+   = note: extraneous unsafe is not allowed in attributes
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs
new file mode 100644
index 00000000000..ff2eb61b405
--- /dev/null
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.rs
@@ -0,0 +1,8 @@
+#![feature(unsafe_attributes)]
+
+#[unsafe(diagnostic::on_unimplemented( //~ ERROR: is not an unsafe attribute
+    message = "testing",
+))]
+trait Foo {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr
new file mode 100644
index 00000000000..584dacf4d8c
--- /dev/null
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr
@@ -0,0 +1,10 @@
+error: `diagnostic::on_unimplemented` is not an unsafe attribute
+  --> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3
+   |
+LL | #[unsafe(diagnostic::on_unimplemented(
+   |   ^^^^^^
+   |
+   = note: extraneous unsafe is not allowed in attributes
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/borrowck/generic_const_early_param.rs b/tests/ui/borrowck/generic_const_early_param.rs
index f601e45d21f..0d07b6869f1 100644
--- a/tests/ui/borrowck/generic_const_early_param.rs
+++ b/tests/ui/borrowck/generic_const_early_param.rs
@@ -5,7 +5,6 @@ struct DataWrapper<'static> {
     //~^ ERROR invalid lifetime parameter name: `'static`
     data: &'a [u8; Self::SIZE],
     //~^ ERROR use of undeclared lifetime name `'a`
-    //~^^ ERROR lifetime may not live long enough
 }
 
 impl DataWrapper<'a> {
diff --git a/tests/ui/borrowck/generic_const_early_param.stderr b/tests/ui/borrowck/generic_const_early_param.stderr
index a71ab09396e..3f56d6a3325 100644
--- a/tests/ui/borrowck/generic_const_early_param.stderr
+++ b/tests/ui/borrowck/generic_const_early_param.stderr
@@ -14,7 +14,7 @@ LL |     data: &'a [u8; Self::SIZE],
    |            ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic_const_early_param.rs:11:18
+  --> $DIR/generic_const_early_param.rs:10:18
    |
 LL | impl DataWrapper<'a> {
    |     -            ^^ undeclared lifetime
@@ -30,13 +30,7 @@ LL | #![feature(generic_const_exprs)]
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: lifetime may not live long enough
-  --> $DIR/generic_const_early_param.rs:6:20
-   |
-LL |     data: &'a [u8; Self::SIZE],
-   |                    ^^^^^^^^^^ requires that `'_` must outlive `'static`
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0261, E0262.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr
index 2d2c5064043..f529a056b0f 100644
--- a/tests/ui/coherence/coherence-impls-copy.stderr
+++ b/tests/ui/coherence/coherence-impls-copy.stderr
@@ -1,14 +1,3 @@
-error[E0117]: only traits defined in the current crate can be implemented for primitive types
-  --> $DIR/coherence-impls-copy.rs:5:1
-   |
-LL | impl Copy for i32 {}
-   | ^^^^^^^^^^^^^^---
-   | |             |
-   | |             `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error[E0119]: conflicting implementations of trait `Copy` for type `&NotSync`
   --> $DIR/coherence-impls-copy.rs:28:1
    |
@@ -30,6 +19,17 @@ LL | impl Copy for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
+  --> $DIR/coherence-impls-copy.rs:5:1
+   |
+LL | impl Copy for i32 {}
+   | ^^^^^^^^^^^^^^---
+   | |             |
+   | |             `i32` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error[E0206]: the trait `Copy` cannot be implemented for this type
   --> $DIR/coherence-impls-copy.rs:21:15
    |
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
new file mode 100644
index 00000000000..44f76f321cf
--- /dev/null
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
@@ -0,0 +1,21 @@
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
+   |
+LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
+   |
+LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
new file mode 100644
index 00000000000..44f76f321cf
--- /dev/null
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
@@ -0,0 +1,21 @@
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
+   |
+LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
+   |
+LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
new file mode 100644
index 00000000000..8dc02b081c5
--- /dev/null
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
@@ -0,0 +1,31 @@
+// Opaque types never cover type parameters.
+
+//@ revisions: classic next
+//@[next] compile-flags: -Znext-solver
+
+//@ aux-crate:foreign=parametrized-trait.rs
+//@ edition:2021
+
+#![feature(type_alias_impl_trait)]
+
+type Identity<T> = impl Sized;
+
+fn define_identity<T>(x: T) -> Identity<T> {
+    x
+}
+
+impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
+//~^ ERROR type parameter `T` must be covered by another type
+
+type Opaque<T> = impl Sized;
+
+fn define_local<T>() -> Opaque<T> {
+    Local
+}
+
+impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
+//~^ ERROR type parameter `T` must be covered by another type
+
+struct Local;
+
+fn main() {}
diff --git a/tests/ui/coherence/re-rebalance-coherence.rs b/tests/ui/coherence/re-rebalance-coherence.rs
index 9c176d5b1b1..5383a634617 100644
--- a/tests/ui/coherence/re-rebalance-coherence.rs
+++ b/tests/ui/coherence/re-rebalance-coherence.rs
@@ -4,6 +4,7 @@
 extern crate re_rebalance_coherence_lib as lib;
 use lib::*;
 
+#[allow(dead_code)]
 struct Oracle;
 impl Backend for Oracle {}
 impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
index 05bd0d91168..c55f3dcec68 100644
--- a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
+++ b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
@@ -1,4 +1,5 @@
 //@ edition:2021
+//@ check-pass
 // issues rust-lang/rust#111911
 // test for ICE opaque type with non-universal region substs
 
@@ -6,8 +7,6 @@
 #![allow(incomplete_features)]
 
 pub async fn foo<const X: &'static str>() {}
-//~^ ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-//~| ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias
 fn bar<const N: &'static u8>() -> impl Sized {}
 
 pub fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr
deleted file mode 100644
index 1bdb9cd9501..00000000000
--- a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43
-   |
-LL | pub async fn foo<const X: &'static str>() {}
-   |                                           ^^
-
-error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43
-   |
-LL | pub async fn foo<const X: &'static str>() {}
-   |                                           ^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs
index 68b8b489816..569e57fa326 100644
--- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs
+++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs
@@ -24,7 +24,6 @@ fn via_associated_const() {
     trait Trait {
         const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>();
         //~^ ERROR mismatched types
-        //~| ERROR `Src` cannot be safely transmuted into `Dst`
         //~| ERROR mismatched types
     }
 }
diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr
index 1dbacaee3c2..a8fc742e89f 100644
--- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr
+++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr
@@ -12,28 +12,13 @@ error[E0308]: mismatched types
 LL |         const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>();
    |                                                                          ^^ expected `Assume`, found `()`
 
-error[E0277]: `Src` cannot be safely transmuted into `Dst`
-  --> $DIR/transmutable-ice-110969.rs:25:60
-   |
-LL |         const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>();
-   |                                                            ^^^ `Dst` may carry safety invariants
-   |
-note: required by a bound in `is_transmutable`
-  --> $DIR/transmutable-ice-110969.rs:11:14
-   |
-LL |     pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>()
-   |            --------------- required by a bound in this function
-LL |     where
-LL |         Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>,
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
-
 error[E0308]: mismatched types
   --> $DIR/transmutable-ice-110969.rs:25:29
    |
 LL |         const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>();
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0277, E0308.
+Some errors have detailed explanations: E0107, E0308.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr
index 2bfa604fc56..49cf4281323 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr
@@ -6,6 +6,16 @@ LL | pub struct Dependent<T, const X: T>([(); X]);
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: aborting due to 1 previous error
+error[E0392]: type parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:11:22
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                      ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr
index 2bfa604fc56..49cf4281323 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr
@@ -6,6 +6,16 @@ LL | pub struct Dependent<T, const X: T>([(); X]);
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: aborting due to 1 previous error
+error[E0392]: type parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:11:22
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                      ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs
index 1583fc4ee6c..5503b08930b 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs
@@ -10,5 +10,6 @@
 
 pub struct Dependent<T, const X: T>([(); X]);
 //~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~| ERROR: type parameter `T` is never used
 
 fn main() {}
diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
index c23187598bc..4bf2fa761ea 100644
--- a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
+++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -2,6 +2,7 @@
 
 //@ run-pass
 
+#[allow(dead_code)]
 #[repr(C)]
 pub struct Loaf<T: Sized, const N: usize = 1> {
     head: [T; N],
diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
index 5d2198f50ad..50a6102c605 100644
--- a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
+++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
@@ -16,7 +16,8 @@ impl BlockCipher for BarCipher {
     const BLOCK_SIZE: usize = 32;
 }
 
-pub struct Block<C>(#[allow(dead_code)] C);
+#[allow(dead_code)]
+pub struct Block<C>(C);
 
 pub fn test<C: BlockCipher, const M: usize>()
 where
diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs
new file mode 100644
index 00000000000..29ad935c014
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Znext-solver=coherence
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub struct A<const z: [usize; x]> {}
+//~^ ERROR: cannot find value `x` in this scope
+//~| ERROR: `[usize; x]` is forbidden as the type of a const generic parameter
+
+impl A<2> {
+    //~^ ERROR: mismatched types
+    pub const fn B() {}
+    //~^ ERROR: duplicate definitions
+}
+
+impl A<2> {
+    //~^ ERROR: mismatched types
+    pub const fn B() {}
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr
new file mode 100644
index 00000000000..0e40255bcf5
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr
@@ -0,0 +1,45 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/error_in_ty.rs:6:31
+   |
+LL | pub struct A<const z: [usize; x]> {}
+   |                    -          ^ help: a const parameter with a similar name exists: `z`
+   |                    |
+   |                    similarly named const parameter `z` defined here
+
+error: `[usize; x]` is forbidden as the type of a const generic parameter
+  --> $DIR/error_in_ty.rs:6:23
+   |
+LL | pub struct A<const z: [usize; x]> {}
+   |                       ^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   |
+LL + #![feature(adt_const_params)]
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/error_in_ty.rs:10:8
+   |
+LL | impl A<2> {
+   |        ^ expected `[usize; x]`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/error_in_ty.rs:16:8
+   |
+LL | impl A<2> {
+   |        ^ expected `[usize; x]`, found integer
+
+error[E0592]: duplicate definitions with name `B`
+  --> $DIR/error_in_ty.rs:12:5
+   |
+LL |     pub const fn B() {}
+   |     ^^^^^^^^^^^^^^^^ duplicate definitions for `B`
+...
+LL |     pub const fn B() {}
+   |     ---------------- other definition for `B`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0592.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
index 8023b998a40..b662939c27e 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
@@ -9,12 +9,14 @@ pub trait Trait {
     fn assoc_fn() -> Self::AssocTy;
 }
 
-impl<const U: u8> Trait for Const<U> // OK, trait impl predicates
+impl<const U: u8> Trait for Const<U>
 where
-    Const<{ my_const_fn(U) }>: ,
+    // OK, trait impl predicates
+    Const<{ my_const_fn(U) }>:,
 {
     type AssocTy = Const<{ my_const_fn(U) }>;
     //~^ ERROR private type
+    //~| ERROR private type
     fn assoc_fn() -> Self::AssocTy {
         Const
     }
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
index 043fa34d605..98dac313be4 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
@@ -1,5 +1,5 @@
 error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
-  --> $DIR/eval-privacy.rs:16:5
+  --> $DIR/eval-privacy.rs:17:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
    |     ^^^^^^^^^^^^ can't leak private type
@@ -7,6 +7,17 @@ LL |     type AssocTy = Const<{ my_const_fn(U) }>;
 LL | const fn my_const_fn(val: u8) -> u8 {
    | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
 
-error: aborting due to 1 previous error
+error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
+  --> $DIR/eval-privacy.rs:17:5
+   |
+LL |     type AssocTy = Const<{ my_const_fn(U) }>;
+   |     ^^^^^^^^^^^^ can't leak private type
+...
+LL | const fn my_const_fn(val: u8) -> u8 {
+   | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0446`.
diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs
index 42c1cc507b5..b3bbb842638 100644
--- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs
+++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs
@@ -1,14 +1,11 @@
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
-#![deny(where_clauses_object_safety)]
 
 
 const fn bar<T: ?Sized>() -> usize { 7 }
 
 trait Foo {
     fn test(&self) where [u8; bar::<Self>()]: Sized;
-    //~^ ERROR the trait `Foo` cannot be made into an object
-    //~| WARN this was previously accepted by the compiler but is being phased out
 }
 
 impl Foo for () {
@@ -16,7 +13,9 @@ impl Foo for () {
 }
 
 fn use_dyn(v: &dyn Foo) {
+    //~^ ERROR the trait `Foo` cannot be made into an object
     v.test();
+    //~^ ERROR the trait `Foo` cannot be made into an object
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
index 9e480ce9b85..fde5d3ce772 100644
--- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
@@ -1,24 +1,35 @@
-error: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-where-bounds.rs:9:8
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-err-where-bounds.rs:15:16
    |
-LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
-   |        ^^^^
+LL | fn use_dyn(v: &dyn Foo) {
+   |                ^^^^^^^ `Foo` cannot be made into an object
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
 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/object-safety-err-where-bounds.rs:9:8
+  --> $DIR/object-safety-err-where-bounds.rs:8:8
    |
 LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
    |        ^^^^ ...because method `test` references the `Self` type in its `where` clause
    = help: consider moving `test` to another trait
-note: the lint level is defined here
-  --> $DIR/object-safety-err-where-bounds.rs:3:9
+   = help: only type `()` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-err-where-bounds.rs:17:5
+   |
+LL |     v.test();
+   |     ^^^^^^^^ `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/object-safety-err-where-bounds.rs:8:8
    |
-LL | #![deny(where_clauses_object_safety)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
+   |        ^^^^ ...because method `test` references the `Self` type in its `where` clause
+   = help: consider moving `test` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr
index 5d780074696..05e847cf4c8 100644
--- a/tests/ui/const-generics/issues/issue-71381.full.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.full.stderr
@@ -7,13 +7,25 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    = note: type parameters may not be used in the type of const parameters
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/issue-71381.rs:22:40
+  --> $DIR/issue-71381.rs:24:40
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: aborting due to 2 previous errors
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
+  --> $DIR/issue-71381.rs:17:9
+   |
+LL |         self.0 = Self::trampiline::<Args, IDX, FN> as _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+   |
+help: consider changing this to be a mutable reference
+   |
+LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&mut self) {
+   |                                                                                         ~~~~~~~~~
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0594, E0770.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr
index 5d780074696..1c30e885d1b 100644
--- a/tests/ui/const-generics/issues/issue-71381.min.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.min.stderr
@@ -7,13 +7,41 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    = note: type parameters may not be used in the type of const parameters
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/issue-71381.rs:22:40
+  --> $DIR/issue-71381.rs:24:40
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: aborting due to 2 previous errors
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-71381.rs:14:61
+   |
+LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
+   |                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-71381.rs:24:19
+   |
+LL |         const FN: unsafe extern "C" fn(Args),
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
+  --> $DIR/issue-71381.rs:17:9
+   |
+LL |         self.0 = Self::trampiline::<Args, IDX, FN> as _
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
+   |
+help: consider changing this to be a mutable reference
+   |
+LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&mut self) {
+   |                                                                                         ~~~~~~~~~
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
+Some errors have detailed explanations: E0594, E0770.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs
index 7f2e14944e2..166b724a7a3 100644
--- a/tests/ui/const-generics/issues/issue-71381.rs
+++ b/tests/ui/const-generics/issues/issue-71381.rs
@@ -13,7 +13,9 @@ unsafe extern "C" fn pass(args: PassArg) {
 impl Test {
     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
         //~^ ERROR: the type of const parameters must not depend on other generic parameters
+        //[min]~^^ ERROR: using function pointers as const generic parameters is forbidden
         self.0 = Self::trampiline::<Args, IDX, FN> as _
+        //~^ ERROR: cannot assign to `self.0`
     }
 
     unsafe extern "C" fn trampiline<
@@ -21,6 +23,7 @@ impl Test {
         const IDX: usize,
         const FN: unsafe extern "C" fn(Args),
         //~^ ERROR: the type of const parameters must not depend on other generic parameters
+        //[min]~^^ ERROR: using function pointers as const generic parameters is forbidden
     >(
         args: Args,
     ) {
diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr
index 6f6a9fc21a6..b01936f4d25 100644
--- a/tests/ui/const-generics/issues/issue-71611.min.stderr
+++ b/tests/ui/const-generics/issues/issue-71611.min.stderr
@@ -6,6 +6,14 @@ LL | fn func<A, const F: fn(inner: A)>(outer: A) {
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: aborting due to 1 previous error
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-71611.rs:5:21
+   |
+LL | fn func<A, const F: fn(inner: A)>(outer: A) {
+   |                     ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs
index 0e0c08146b2..c6c1e267171 100644
--- a/tests/ui/const-generics/issues/issue-71611.rs
+++ b/tests/ui/const-generics/issues/issue-71611.rs
@@ -4,6 +4,7 @@
 
 fn func<A, const F: fn(inner: A)>(outer: A) {
     //~^ ERROR: the type of const parameters must not depend on other generic parameters
+    //[min]~| ERROR: using function pointers as const generic parameters is forbidden
     F(outer);
 }
 
diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs
new file mode 100644
index 00000000000..5471dc9022f
--- /dev/null
+++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs
@@ -0,0 +1,14 @@
+//@ edition:2021
+
+trait Trait<const N: Trait = bar> {
+    //~^ ERROR: cannot find value `bar` in this scope
+    //~| ERROR: cycle detected when computing type of `Trait::N`
+    //~| ERROR: the trait `Trait` cannot be made into an object
+    //~| ERROR: the trait `Trait` cannot be made into an object
+    //~| ERROR: the trait `Trait` cannot be made into an object
+    //~| ERROR: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
+    //~| ERROR: trait objects must include the `dyn` keyword
+    async fn a() {}
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr
new file mode 100644
index 00000000000..9095948d22b
--- /dev/null
+++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr
@@ -0,0 +1,113 @@
+error[E0425]: cannot find value `bar` in this scope
+  --> $DIR/not_wf_param_in_rpitit.rs:3:30
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                              ^^^ not found in this scope
+
+error[E0391]: cycle detected when computing type of `Trait::N`
+  --> $DIR/not_wf_param_in_rpitit.rs:3:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+   = note: ...which immediately requires computing type of `Trait::N` again
+note: cycle used when computing explicit predicates of trait `Trait`
+  --> $DIR/not_wf_param_in_rpitit.rs:3:1
+   |
+LL | trait Trait<const N: Trait = bar> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/not_wf_param_in_rpitit.rs:3:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |       ----- this trait cannot be made into an object...
+...
+LL |     async fn a() {}
+   |              ^ ...because associated function `a` has no `self` parameter
+help: consider turning `a` into a method by giving it a `&self` argument
+   |
+LL |     async fn a(&self) {}
+   |                +++++
+help: alternatively, consider constraining `a` so it does not apply to trait objects
+   |
+LL |     async fn a() where Self: Sized {}
+   |                  +++++++++++++++++
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/not_wf_param_in_rpitit.rs:3:13
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |             ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |       ----- this trait cannot be made into an object...
+...
+LL |     async fn a() {}
+   |              ^ ...because associated function `a` has no `self` parameter
+help: consider turning `a` into a method by giving it a `&self` argument
+   |
+LL |     async fn a(&self) {}
+   |                +++++
+help: alternatively, consider constraining `a` so it does not apply to trait objects
+   |
+LL |     async fn a() where Self: Sized {}
+   |                  +++++++++++++++++
+
+error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
+  --> $DIR/not_wf_param_in_rpitit.rs:3:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error[E0038]: the trait `Trait` cannot be made into an object
+  --> $DIR/not_wf_param_in_rpitit.rs:3:13
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |             ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |       ----- this trait cannot be made into an object...
+...
+LL |     async fn a() {}
+   |              ^ ...because associated function `a` has no `self` parameter
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider turning `a` into a method by giving it a `&self` argument
+   |
+LL |     async fn a(&self) {}
+   |                +++++
+help: alternatively, consider constraining `a` so it does not apply to trait objects
+   |
+LL |     async fn a() where Self: Sized {}
+   |                  +++++++++++++++++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/not_wf_param_in_rpitit.rs:3:22
+   |
+LL | trait Trait<const N: Trait = bar> {
+   |                      ^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | trait Trait<const N: dyn Trait = bar> {
+   |                      +++
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0038, E0391, E0425, E0782.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 1b0d1ea50d0..b76ec10bd3f 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -13,7 +13,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
index 419d605d0c8..35c41ae4615 100644
--- a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
+++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
@@ -6,6 +6,7 @@
 
 use std::mem::MaybeUninit;
 
+#[allow(dead_code)]
 #[repr(transparent)]
 pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>);
 
diff --git a/tests/ui/const-generics/type_not_in_scope.rs b/tests/ui/const-generics/type_not_in_scope.rs
index 917abaed15e..1eb265d74d1 100644
--- a/tests/ui/const-generics/type_not_in_scope.rs
+++ b/tests/ui/const-generics/type_not_in_scope.rs
@@ -5,6 +5,7 @@ impl X {
     }
 }
 fn getn<const N: cfg_attr>() -> [u8; N] {}
-//~^ ERROR expected type, found built-in attribute `cfg_attr`
+//~^ ERROR: expected type, found built-in attribute `cfg_attr`
+//~| ERROR: mismatched types
 
 fn main() {}
diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr
index 5eb81ca0522..5f45550a627 100644
--- a/tests/ui/const-generics/type_not_in_scope.stderr
+++ b/tests/ui/const-generics/type_not_in_scope.stderr
@@ -10,7 +10,15 @@ error[E0573]: expected type, found built-in attribute `cfg_attr`
 LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
    |                  ^^^^^^^^ not a type
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/type_not_in_scope.rs:7:33
+   |
+LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
+   |    ----                         ^^^^^^^ expected `[u8; N]`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0412, E0573.
-For more information about an error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0308, E0412, E0573.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
index a41a159c1fd..09f7e2ba5b1 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
@@ -13,6 +13,7 @@ impl Opcode2 {
 pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
     move |i| match msg_type {
         Opcode2::OP2 => unimplemented!(),
+        //~^ ERROR: could not evaluate constant pattern
     }
 }
 
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
index d95a8861230..9442eac0cf5 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
@@ -17,7 +17,13 @@ help: you might be missing a type parameter
 LL | pub struct Opcode2<S>(&'a S);
    |                   +++
 
-error: aborting due to 2 previous errors
+error: could not evaluate constant pattern
+  --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
+   |
+LL |         Opcode2::OP2 => unimplemented!(),
+   |         ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0261, E0412.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/consts/issue-103790.rs b/tests/ui/consts/issue-103790.rs
index 5d130821dc8..d19115ede74 100644
--- a/tests/ui/consts/issue-103790.rs
+++ b/tests/ui/consts/issue-103790.rs
@@ -5,7 +5,7 @@ struct S<const S: (), const S: S = { S }>;
 //~^ ERROR the name `S` is already used for a generic parameter in this item's generic parameters
 //~| ERROR missing generics for struct `S`
 //~| ERROR cycle detected when computing type of `S::S`
-//~| ERROR cycle detected when computing type of `S`
 //~| ERROR `()` is forbidden as the type of a const generic parameter
+//~| ERROR `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr
index eecaf5ff63a..c671f078cb5 100644
--- a/tests/ui/consts/issue-103790.stderr
+++ b/tests/ui/consts/issue-103790.stderr
@@ -29,37 +29,30 @@ LL | struct S<const S: (), const S: S = { S }>;
    |                                ^
    |
    = note: ...which immediately requires computing type of `S::S` again
-note: cycle used when computing type of `S`
+note: cycle used when computing explicit predicates of `S`
   --> $DIR/issue-103790.rs:4:1
    |
 LL | struct S<const S: (), const S: S = { S }>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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 `S`
-  --> $DIR/issue-103790.rs:4:1
+error: `()` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-103790.rs:4:19
    |
 LL | struct S<const S: (), const S: S = { S }>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^
    |
-note: ...which requires computing type of `S::S`...
-  --> $DIR/issue-103790.rs:4:32
+   = note: the only supported types are integers, `bool` and `char`
+help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
    |
-LL | struct S<const S: (), const S: S = { S }>;
-   |                                ^
-   = note: ...which again requires computing type of `S`, completing the cycle
-note: cycle used when checking that `S` is well-formed
-  --> $DIR/issue-103790.rs:4:1
+LL + #![feature(adt_const_params)]
    |
-LL | struct S<const S: (), const S: S = { S }>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = 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: `()` is forbidden as the type of a const generic parameter
-  --> $DIR/issue-103790.rs:4:19
+error: `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-103790.rs:4:32
    |
 LL | struct S<const S: (), const S: S = { S }>;
-   |                   ^^
+   |                                ^
    |
    = note: the only supported types are integers, `bool` and `char`
 help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
diff --git a/tests/ui/coroutine/async_gen_fn.none.stderr b/tests/ui/coroutine/async_gen_fn.none.stderr
index 7950251a75d..047f4d82486 100644
--- a/tests/ui/coroutine/async_gen_fn.none.stderr
+++ b/tests/ui/coroutine/async_gen_fn.none.stderr
@@ -7,11 +7,11 @@ LL | async gen fn foo() {}
    = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error: expected one of `extern`, `fn`, or `unsafe`, found `gen`
+error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen`
   --> $DIR/async_gen_fn.rs:4:7
    |
 LL | async gen fn foo() {}
-   |       ^^^ expected one of `extern`, `fn`, or `unsafe`
+   |       ^^^ expected one of `extern`, `fn`, `safe`, or `unsafe`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coroutine/async_gen_fn.rs b/tests/ui/coroutine/async_gen_fn.rs
index 9e96ecf3ea6..e8be0434b9e 100644
--- a/tests/ui/coroutine/async_gen_fn.rs
+++ b/tests/ui/coroutine/async_gen_fn.rs
@@ -3,7 +3,7 @@
 
 async gen fn foo() {}
 //[none]~^ ERROR: `async fn` is not permitted in Rust 2015
-//[none]~| ERROR: expected one of `extern`, `fn`, or `unsafe`, found `gen`
+//[none]~| ERROR: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen`
 //[e2024]~^^^ ERROR: gen blocks are experimental
 
 fn main() {}
diff --git a/tests/ui/coroutine/gen_fn.none.stderr b/tests/ui/coroutine/gen_fn.none.stderr
index c5342ee22e6..590210641ae 100644
--- a/tests/ui/coroutine/gen_fn.none.stderr
+++ b/tests/ui/coroutine/gen_fn.none.stderr
@@ -1,8 +1,8 @@
-error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
+error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
   --> $DIR/gen_fn.rs:4:1
    |
 LL | gen fn foo() {}
-   | ^^^ expected one of 9 possible tokens
+   | ^^^ expected one of 10 possible tokens
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/gen_fn.rs b/tests/ui/coroutine/gen_fn.rs
index 3228650f415..d47b7e576d0 100644
--- a/tests/ui/coroutine/gen_fn.rs
+++ b/tests/ui/coroutine/gen_fn.rs
@@ -2,7 +2,7 @@
 //@[e2024] compile-flags: --edition 2024 -Zunstable-options
 
 gen fn foo() {}
-//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
+//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
 //[e2024]~^^ ERROR: gen blocks are experimental
 
 fn main() {}
diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
index dca708733b9..832cee8d4d4 100644
--- a/tests/ui/cross-crate/auxiliary/static_init_aux.rs
+++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
@@ -3,6 +3,12 @@ pub static F: fn() = f;
 pub static G: fn() = G0;
 pub static H: &(dyn Fn() + Sync) = &h;
 pub static I: fn() = Helper(j).mk();
+pub static K: fn() -> fn() = {
+    #[inline(never)]
+    fn k() {}
+    #[inline(always)]
+    || -> fn() { k }
+};
 
 static X: u32 = 42;
 static G0: fn() = g;
diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs
index c4697a1d010..f8003856c5c 100644
--- a/tests/ui/cross-crate/static-init.rs
+++ b/tests/ui/cross-crate/static-init.rs
@@ -8,6 +8,7 @@ static F: fn() = aux::F;
 static G: fn() = aux::G;
 static H: &(dyn Fn() + Sync) = aux::H;
 static I: fn() = aux::I;
+static K: fn() -> fn() = aux::K;
 
 fn v() -> *const u32 {
     V
@@ -19,4 +20,5 @@ fn main() {
     G();
     H();
     I();
+    K()();
 }
diff --git a/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
index 86117965016..3322660d1a8 100644
--- a/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
+++ b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
@@ -1,5 +1,6 @@
 //@ build-pass
 //@ only-linux
+//@ ignore-riscv64 On this platform `-Csplit-debuginfo=unpacked` is unstable, see #120518
 //
 //@ compile-flags: -g --emit=llvm-ir -Csplit-debuginfo=unpacked
 //
diff --git a/tests/ui/delegation/ice-issue-124342.rs b/tests/ui/delegation/ice-issue-124342.rs
new file mode 100644
index 00000000000..ad62f6bd54a
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-124342.rs
@@ -0,0 +1,12 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {}
+
+trait Trait {
+    reuse to_reuse::foo { foo }
+    //~^ ERROR cannot find function `foo` in module `to_reuse`
+    //~| ERROR cannot find value `foo` in this scope
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/ice-issue-124342.stderr b/tests/ui/delegation/ice-issue-124342.stderr
new file mode 100644
index 00000000000..f9a3684d649
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-124342.stderr
@@ -0,0 +1,20 @@
+error[E0425]: cannot find function `foo` in module `to_reuse`
+  --> $DIR/ice-issue-124342.rs:7:21
+   |
+LL |     reuse to_reuse::foo { foo }
+   |                     ^^^ not found in `to_reuse`
+
+error[E0425]: cannot find value `foo` in this scope
+  --> $DIR/ice-issue-124342.rs:7:27
+   |
+LL |     reuse to_reuse::foo { foo }
+   |                           ^^^
+   |
+help: you might have meant to refer to the associated function
+   |
+LL |     reuse to_reuse::foo { Self::foo }
+   |                           ++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs
new file mode 100644
index 00000000000..82a96055099
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-124347.rs
@@ -0,0 +1,12 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    reuse Trait::foo { &self.0 }
+    //~^ ERROR recursive delegation is not supported yet
+}
+
+reuse foo;
+//~^ ERROR recursive delegation is not supported yet
+
+fn main() {}
diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr
new file mode 100644
index 00000000000..5a3f4525d29
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-124347.stderr
@@ -0,0 +1,14 @@
+error: recursive delegation is not supported yet
+  --> $DIR/ice-issue-124347.rs:5:18
+   |
+LL |     reuse Trait::foo { &self.0 }
+   |                  ^^^ callee defined here
+
+error: recursive delegation is not supported yet
+  --> $DIR/ice-issue-124347.rs:9:7
+   |
+LL | reuse foo;
+   |       ^^^ callee defined here
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
index 6ab1fb7b039..885dacc727a 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
@@ -1,9 +1,9 @@
 #![forbid(dead_code)]
 
 #[derive(Debug)]
-pub struct Whatever {
+pub struct Whatever { //~ ERROR struct `Whatever` is never constructed
     pub field0: (),
-    field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
+    field1: (),
     field2: (),
     field3: (),
     field4: (),
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index e9b757b6bae..e10d28ad03a 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -1,19 +1,9 @@
-error: fields `field1`, `field2`, `field3`, and `field4` are never read
-  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
+error: struct `Whatever` is never constructed
+  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12
    |
 LL | pub struct Whatever {
-   |            -------- fields in this struct
-LL |     pub field0: (),
-LL |     field1: (),
-   |     ^^^^^^
-LL |     field2: (),
-   |     ^^^^^^
-LL |     field3: (),
-   |     ^^^^^^
-LL |     field4: (),
-   |     ^^^^^^
+   |            ^^^^^^^^
    |
-   = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 note: the lint level is defined here
   --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
    |
diff --git a/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs
new file mode 100644
index 00000000000..b8a42be6832
--- /dev/null
+++ b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs
@@ -0,0 +1,13 @@
+//@ run-pass
+// Issue #122622: `#[derive(Clone)]` should work for HRTB function type taking an associated type
+#![allow(dead_code)]
+trait SomeTrait {
+    type SomeType<'a>;
+}
+
+#[derive(Clone)]
+struct Foo<T: SomeTrait> {
+    x: for<'a> fn(T::SomeType<'a>)
+}
+
+fn main() {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr
new file mode 100644
index 00000000000..bcede8a255f
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr
@@ -0,0 +1,15 @@
+error[E0277]: Very important message!
+  --> $DIR/type_mismatch.rs:25:14
+   |
+LL |     verify::<u8>();
+   |              ^^ the trait `TheImportantOne` is not implemented for `u8`
+   |
+note: required by a bound in `verify`
+  --> $DIR/type_mismatch.rs:22:14
+   |
+LL | fn verify<T: TheImportantOne>() {}
+   |              ^^^^^^^^^^^^^^^ required by this bound in `verify`
+
+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/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr
new file mode 100644
index 00000000000..bcede8a255f
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: Very important message!
+  --> $DIR/type_mismatch.rs:25:14
+   |
+LL |     verify::<u8>();
+   |              ^^ the trait `TheImportantOne` is not implemented for `u8`
+   |
+note: required by a bound in `verify`
+  --> $DIR/type_mismatch.rs:22:14
+   |
+LL | fn verify<T: TheImportantOne>() {}
+   |              ^^^^^^^^^^^^^^^ required by this bound in `verify`
+
+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/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs
new file mode 100644
index 00000000000..d6721ccc848
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs
@@ -0,0 +1,27 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+#[diagnostic::on_unimplemented(message = "Very important message!")]
+trait TheImportantOne {}
+
+trait ImplementationDetail {
+    type Restriction;
+}
+
+#[diagnostic::do_not_recommend]
+impl<T: ImplementationDetail<Restriction = ()>> TheImportantOne for T {}
+
+// Comment out this `impl` to show the expected error message.
+impl ImplementationDetail for u8 {
+    type Restriction = u8;
+}
+
+fn verify<T: TheImportantOne>() {}
+
+pub fn main() {
+    verify::<u8>();
+    //~^ERROR: Very important message! [E0277]
+}
diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr
index 6ad3effe0e2..2785b12a0ae 100644
--- a/tests/ui/extern-flag/empty-extern-arg.stderr
+++ b/tests/ui/extern-flag/empty-extern-arg.stderr
@@ -1,6 +1,13 @@
 error: extern location for std does not exist: 
 
+error: `#[panic_handler]` function required, but not found
+
+error: unwinding panics are not supported without std
+   |
+   = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
+   = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
+
 error: requires `sized` lang_item
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/extern-flag/no-nounused.rs b/tests/ui/extern-flag/no-nounused.rs
index bed8006542c..30b66339876 100644
--- a/tests/ui/extern-flag/no-nounused.rs
+++ b/tests/ui/extern-flag/no-nounused.rs
@@ -2,5 +2,5 @@
 //@ compile-flags: -Zunstable-options -Dunused-crate-dependencies
 //@ edition:2018
 
-fn main() { //~ ERROR external crate `somedep` unused in `no_nounused`
+fn main() { //~ ERROR extern crate `somedep` is unused in crate `no_nounused`
 }
diff --git a/tests/ui/extern-flag/no-nounused.stderr b/tests/ui/extern-flag/no-nounused.stderr
index 171079287f0..2b42e851561 100644
--- a/tests/ui/extern-flag/no-nounused.stderr
+++ b/tests/ui/extern-flag/no-nounused.stderr
@@ -1,9 +1,10 @@
-error: external crate `somedep` unused in `no_nounused`: remove the dependency or add `use somedep as _;`
+error: extern crate `somedep` is unused in crate `no_nounused`
   --> $DIR/no-nounused.rs:5:1
    |
 LL | fn main() {
    | ^
    |
+   = help: remove the dependency or add `use somedep as _;` to the crate root
    = note: requested on the command line with `-D unused-crate-dependencies`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/feature-gates/feature-gate-extern_prelude.rs b/tests/ui/feature-gates/feature-gate-extern_prelude.rs
deleted file mode 100644
index 237099e7901..00000000000
--- a/tests/ui/feature-gates/feature-gate-extern_prelude.rs
+++ /dev/null
@@ -1 +0,0 @@
-can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
diff --git a/tests/ui/feature-gates/feature-gate-extern_prelude.stderr b/tests/ui/feature-gates/feature-gate-extern_prelude.stderr
deleted file mode 100644
index 3b0ffae8696..00000000000
--- a/tests/ui/feature-gates/feature-gate-extern_prelude.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `!` or `::`, found `-`
-  --> $DIR/feature-gate-extern_prelude.rs:1:4
-   |
-LL | can-only-test-this-in-run-make-fulldeps
-   |    ^ expected one of `!` or `::`
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-slice.rs b/tests/ui/feature-gates/feature-gate-offset-of-slice.rs
new file mode 100644
index 00000000000..23e8668bc68
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-slice.rs
@@ -0,0 +1,26 @@
+use std::mem::offset_of;
+
+struct S {
+    a: u8,
+    b: (u8, u8),
+    c: [i32],
+}
+
+struct T {
+    x: i32,
+    y: S,
+}
+
+type Tup = (i32, [i32]);
+
+fn main() {
+    offset_of!(S, c); //~ ERROR size for values of type `[i32]` cannot be known at compilation time
+}
+
+fn other() {
+    offset_of!(T, y); //~ ERROR size for values of type `[i32]` cannot be known at compilation time
+}
+
+fn tuple() {
+    offset_of!(Tup, 1); //~ ERROR size for values of type `[i32]` cannot be known at compilation time
+}
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr
new file mode 100644
index 00000000000..5cf34a897f4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/feature-gate-offset-of-slice.rs:17:5
+   |
+LL |     offset_of!(S, c);
+   |     ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/feature-gate-offset-of-slice.rs:21:5
+   |
+LL |     offset_of!(T, y);
+   |     ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `S`, the trait `Sized` is not implemented for `[i32]`, which is required by `S: Sized`
+note: required because it appears within the type `S`
+  --> $DIR/feature-gate-offset-of-slice.rs:3:8
+   |
+LL | struct S {
+   |        ^
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/feature-gate-offset-of-slice.rs:25:5
+   |
+LL |     offset_of!(Tup, 1);
+   |     ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
deleted file mode 100644
index ed5db56e0e8..00000000000
--- a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-pub fn main() {
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-    if let Some(&Some(x)) = &Some(Some(0)) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr
deleted file mode 100644
index 0f0051325cd..00000000000
--- a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr
+++ /dev/null
@@ -1,49 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-ref_pat_everywhere.rs:2:22
-   |
-LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
-   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL |     if let Some(Some(x)) = &Some(&Some(0)) {
-   |                      ~
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-ref_pat_everywhere.rs:6:17
-   |
-LL |     if let Some(&Some(x)) = &Some(Some(0)) {
-   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&_`
-   |
-   = note:   expected enum `Option<{integer}>`
-           found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&mut _`
-   |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL |     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
-   |                      ~
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs b/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs
new file mode 100644
index 00000000000..9eba415dda0
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-attributes.rs
@@ -0,0 +1,8 @@
+#[unsafe(no_mangle)] //~ ERROR [E0658]
+extern "C" fn foo() {
+
+}
+
+fn main() {
+    foo();
+}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr b/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr
new file mode 100644
index 00000000000..dfcea756b02
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `#[unsafe()]` markers for attributes are experimental
+  --> $DIR/feature-gate-unsafe-attributes.rs:1:3
+   |
+LL | #[unsafe(no_mangle)]
+   |   ^^^^^^
+   |
+   = note: see issue #123757 <https://github.com/rust-lang/rust/issues/123757> for more information
+   = help: add `#![feature(unsafe_attributes)]` 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: 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-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
new file mode 100644
index 00000000000..eab134a4a4d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
@@ -0,0 +1,5 @@
+unsafe extern "C" {
+    //~^ ERROR extern block cannot be declared unsafe
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
new file mode 100644
index 00000000000..7e9b199a2db
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
@@ -0,0 +1,8 @@
+error: extern block cannot be declared unsafe
+  --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
+   |
+LL | unsafe extern "C" {
+   | ^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.stderr b/tests/ui/feature-gates/feature-gate-vectorcall.stderr
index df93e8812c1..b20e41887b9 100644
--- a/tests/ui/feature-gates/feature-gate-vectorcall.stderr
+++ b/tests/ui/feature-gates/feature-gate-vectorcall.stderr
@@ -4,6 +4,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL | extern "vectorcall" fn f() {}
    |        ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -13,6 +14,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL |     extern "vectorcall" fn m();
    |            ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -22,6 +24,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL |     extern "vectorcall" fn dm() {}
    |            ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -31,6 +34,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL |     extern "vectorcall" fn m() {}
    |            ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -40,6 +44,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL |     extern "vectorcall" fn im() {}
    |            ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -49,6 +54,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL | type TA = extern "vectorcall" fn();
    |                  ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -58,6 +64,7 @@ error[E0658]: vectorcall is experimental and subject to change
 LL | extern "vectorcall" {}
    |        ^^^^^^^^^^^^
    |
+   = note: see issue #124485 <https://github.com/rust-lang/rust/issues/124485> for more information
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
index 671d17f36f1..285493132b6 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
@@ -9,7 +9,6 @@ impl<T> X for T { //~ ERROR: not all trait items implemented
     //~^ ERROR missing generics for associated type
     //~^^ ERROR missing generics for associated type
     //~| ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-    //~| ERROR may not live long enough
     t
   }
 }
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
index 65854ed7158..6a600aee11f 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -51,16 +51,7 @@ help: add missing lifetime argument
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
    |                     ++++
 
-error: lifetime may not live long enough
-  --> $DIR/gat-trait-path-missing-lifetime.rs:8:3
-   |
-LL |   fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
-   |   ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |   |      |
-   |   |      lifetime `'a` defined here
-   |   requires that `'a` must outlive `'static`
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0046, E0049, E0107.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs
index 935d3f7a4ba..8898d4c7d13 100644
--- a/tests/ui/generic-associated-types/issue-70304.rs
+++ b/tests/ui/generic-associated-types/issue-70304.rs
@@ -52,5 +52,4 @@ fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
 pub fn main() {
     let doc = create_doc();
     let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
-    //~^ ERROR: `doc` does not live long enough
 }
diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr
index 8e012cc6d93..9b02c1b0768 100644
--- a/tests/ui/generic-associated-types/issue-70304.stderr
+++ b/tests/ui/generic-associated-types/issue-70304.stderr
@@ -27,21 +27,7 @@ LL |     type Cursor<'a>: DocCursor<'a>;
    = note: this bound is currently required to ensure that impls have maximum flexibility
    = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error[E0597]: `doc` does not live long enough
-  --> $DIR/issue-70304.rs:54:59
-   |
-LL |     let doc = create_doc();
-   |         --- binding `doc` declared here
-LL |     let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
-   |                                               ------------^^^^-
-   |                                               |           |
-   |                                               |           borrowed value does not live long enough
-   |                                               argument requires that `doc` is borrowed for `'static`
-LL |
-LL | }
-   | - `doc` dropped here while still borrowed
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0106, E0597, E0637.
+Some errors have detailed explanations: E0106, E0637.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs
index f0e162d825f..e58b6f6091e 100644
--- a/tests/ui/generic-associated-types/issue-71176.rs
+++ b/tests/ui/generic-associated-types/issue-71176.rs
@@ -9,6 +9,9 @@ impl Provider for () {
 struct Holder<B> {
   inner: Box<dyn Provider<A = B>>,
   //~^ ERROR: missing generics for associated type
+  //~| ERROR: missing generics for associated type
+  //~| ERROR: missing generics for associated type
+  //~| ERROR: the trait `Provider` cannot be made into an object
 }
 
 fn main() {
diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr
index ed837f34753..a1913bb618b 100644
--- a/tests/ui/generic-associated-types/issue-71176.stderr
+++ b/tests/ui/generic-associated-types/issue-71176.stderr
@@ -14,6 +14,57 @@ help: add missing lifetime argument
 LL |   inner: Box<dyn Provider<A<'a> = B>>,
    |                            ++++
 
-error: aborting due to 1 previous error
+error[E0107]: missing generics for associated type `Provider::A`
+  --> $DIR/issue-71176.rs:10:27
+   |
+LL |   inner: Box<dyn Provider<A = B>>,
+   |                           ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-71176.rs:2:10
+   |
+LL |     type A<'a>;
+   |          ^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: add missing lifetime argument
+   |
+LL |   inner: Box<dyn Provider<A<'a> = B>>,
+   |                            ++++
+
+error[E0107]: missing generics for associated type `Provider::A`
+  --> $DIR/issue-71176.rs:10:27
+   |
+LL |   inner: Box<dyn Provider<A = B>>,
+   |                           ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-71176.rs:2:10
+   |
+LL |     type A<'a>;
+   |          ^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: add missing lifetime argument
+   |
+LL |   inner: Box<dyn Provider<A<'a> = B>>,
+   |                            ++++
+
+error[E0038]: the trait `Provider` cannot be made into an object
+  --> $DIR/issue-71176.rs:10:14
+   |
+LL |   inner: Box<dyn Provider<A = B>>,
+   |              ^^^^^^^^^^^^^^^^^^^ `Provider` 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/issue-71176.rs:2:10
+   |
+LL | trait Provider {
+   |       -------- this trait cannot be made into an object...
+LL |     type A<'a>;
+   |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs
index 53057542440..bdba78c2ccd 100644
--- a/tests/ui/generic-associated-types/issue-80433.rs
+++ b/tests/ui/generic-associated-types/issue-80433.rs
@@ -22,8 +22,7 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
   //~^ ERROR missing generics for associated type
 {
     for n in 0i16..100 {
-        *dst.test_mut() = n.into(); //~ ERROR: cannot borrow
-        //~^ ERROR: borrowed data escapes outside of function
+        *dst.test_mut() = n.into();
     }
 }
 
diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr
index a9a14d3f51c..8ab6fdcb815 100644
--- a/tests/ui/generic-associated-types/issue-80433.stderr
+++ b/tests/ui/generic-associated-types/issue-80433.stderr
@@ -25,30 +25,6 @@ help: add missing lifetime argument
 LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output<'a> = &'a mut f32>)
    |                                                     ++++
 
-error[E0499]: cannot borrow `*dst` as mutable more than once at a time
-  --> $DIR/issue-80433.rs:25:10
-   |
-LL |         *dst.test_mut() = n.into();
-   |          ^^^-----------
-   |          |
-   |          `*dst` was mutably borrowed here in the previous iteration of the loop
-   |          argument requires that `*dst` is borrowed for `'static`
-
-error[E0521]: borrowed data escapes outside of function
-  --> $DIR/issue-80433.rs:25:10
-   |
-LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
-   |                 --  --- `dst` is a reference that is only valid in the function body
-   |                 |
-   |                 lifetime `'a` defined here
-...
-LL |         *dst.test_mut() = n.into();
-   |          ^^^^^^^^^^^^^^
-   |          |
-   |          `dst` escapes the function body here
-   |          argument requires that `'a` must outlive `'static`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0499, E0521.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr
new file mode 100644
index 00000000000..14a3d5e178d
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
+  --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50
+   |
+LL |     let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>();
+   |                                                  ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.rs b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.rs
new file mode 100644
index 00000000000..10dbc2a4a82
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.rs
@@ -0,0 +1,30 @@
+//@ revisions: current next
+//@[current] check-pass
+//@[next] compile-flags: -Znext-solver
+//@[next] check-fail
+//@ ignore-compare-mode-next-solver (explicit revisions)
+
+/// This triggers an ICE with (and without) `--emit metadata` using the old
+/// trait solver:
+/// ```
+/// rustc +nightly-2023-01-09 \
+///   tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.rs
+/// ```
+/// The ICE was unknowingly fixed by
+/// <https://github.com/rust-lang/rust/pull/101947> in `nightly-2023-01-10`.
+/// This is a regression test for that fixed ICE. For the next solver we simply
+/// make sure there is a compiler error.
+
+trait Trait<'a> {
+    type Assoc;
+}
+
+fn foo<T: for<'a> Trait<'a>>() -> for<'a> fn(<T as Trait<'a>>::Assoc) {
+    todo!()
+}
+
+fn bar<T: for<'a> Trait<'a>>() {
+    let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>(); //[next]~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.rs b/tests/ui/impl-header-lifetime-elision/assoc-type.rs
index b0089a37aa0..db3c416540f 100644
--- a/tests/ui/impl-header-lifetime-elision/assoc-type.rs
+++ b/tests/ui/impl-header-lifetime-elision/assoc-type.rs
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for &i32 {
     type Output = &i32;
-    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
 }
 
 impl MyTrait for &u32 {
diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr
index c4f27e0b80e..e650eeca48a 100644
--- a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr
+++ b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr
@@ -1,8 +1,8 @@
-error[E0637]: `&` without an explicit lifetime name cannot be used here
+error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
   --> $DIR/assoc-type.rs:11:19
    |
 LL |     type Output = &i32;
-   |                   ^ explicit lifetime name needed here
+   |                   ^ this lifetime must come from the implemented type
 
 error[E0637]: `'_` cannot be used here
   --> $DIR/assoc-type.rs:16:20
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs
new file mode 100644
index 00000000000..65e90c1ca53
--- /dev/null
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs
@@ -0,0 +1,38 @@
+// This test should never pass!
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Captures<'a> {}
+impl<T> Captures<'_> for T {}
+
+pub struct MyTy<'a, 'b>(Option<*mut &'a &'b ()>);
+unsafe impl Send for MyTy<'_, 'static> {}
+
+pub mod step1 {
+    use super::*;
+    pub type Step1<'a, 'b: 'a> = impl Sized + Captures<'b> + 'a;
+    pub fn step1<'a, 'b: 'a>() -> Step1<'a, 'b> {
+        MyTy::<'a, 'b>(None)
+    }
+}
+
+pub mod step2 {
+    pub type Step2<'a> = impl Send + 'a;
+
+    // Although `Step2` is WF at the definition site, it's not WF in its
+    // declaration site (above). We check this in `check_opaque_meets_bounds`,
+    // which must remain sound.
+    pub fn step2<'a, 'b: 'a>() -> Step2<'a>
+        where crate::step1::Step1<'a, 'b>: Send
+    {
+        crate::step1::step1::<'a, 'b>()
+        //~^ ERROR hidden type for `Step2<'a>` captures lifetime that does not appear in bounds
+    }
+}
+
+fn step3<'a, 'b>() {
+    fn is_send<T: Send>() {}
+    is_send::<crate::step2::Step2::<'a>>();
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr
new file mode 100644
index 00000000000..58d7f9959d3
--- /dev/null
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr
@@ -0,0 +1,15 @@
+error[E0700]: hidden type for `Step2<'a>` captures lifetime that does not appear in bounds
+  --> $DIR/tait-hidden-erased-unsoundness-2.rs:28:9
+   |
+LL |     pub type Step2<'a> = impl Send + 'a;
+   |                          -------------- opaque type defined here
+...
+LL |     pub fn step2<'a, 'b: 'a>() -> Step2<'a>
+   |                      -- hidden type `Step1<'a, 'b>` captures the lifetime `'b` as defined here
+...
+LL |         crate::step1::step1::<'a, 'b>()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
index 5b3a4eb53ff..14b1ebea8db 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs
@@ -1,11 +1,9 @@
 // issue: 114146
 
-
 trait Foo {
     fn bar<'other: 'a>() -> impl Sized + 'a {}
     //~^ ERROR use of undeclared lifetime name `'a`
     //~| ERROR use of undeclared lifetime name `'a`
-    //~| ERROR expected generic lifetime parameter, found `'static`
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
index 8975578dabd..f1b006da1db 100644
--- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
+++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/bad-item-bound-within-rpitit-2.rs:5:20
+  --> $DIR/bad-item-bound-within-rpitit-2.rs:4:20
    |
 LL |     fn bar<'other: 'a>() -> impl Sized + 'a {}
    |                    ^^ undeclared lifetime
@@ -14,7 +14,7 @@ LL | trait Foo<'a> {
    |          ++++
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/bad-item-bound-within-rpitit-2.rs:5:42
+  --> $DIR/bad-item-bound-within-rpitit-2.rs:4:42
    |
 LL |     fn bar<'other: 'a>() -> impl Sized + 'a {}
    |                                          ^^ undeclared lifetime
@@ -28,15 +28,6 @@ help: consider introducing lifetime `'a` here
 LL | trait Foo<'a> {
    |          ++++
 
-error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/bad-item-bound-within-rpitit-2.rs:5:45
-   |
-LL |     fn bar<'other: 'a>() -> impl Sized + 'a {}
-   |            ------                           ^^
-   |            |
-   |            cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0261, E0792.
-For more information about an error, try `rustc --explain E0261`.
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs
index 939eca82a8f..28772fa5272 100644
--- a/tests/ui/impl-trait/issues/issue-67830.rs
+++ b/tests/ui/impl-trait/issues/issue-67830.rs
@@ -7,7 +7,7 @@ struct Wrap<F>(F);
 
 impl<A, B, F> MyFn<A> for Wrap<F>
 where
-    F: Fn(A) -> B
+    F: Fn(A) -> B,
 {
     type Output = B;
 
@@ -16,13 +16,10 @@ where
     }
 }
 
-
 struct A;
-fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
     //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     Wrap(|a| Some(a).into_iter())
-    //~^ ERROR implementation of `FnOnce` is not general enough
-    //~| ERROR implementation of `FnOnce` is not general enough
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr
index ef513a40cf3..a7633c7f20b 100644
--- a/tests/ui/impl-trait/issues/issue-67830.stderr
+++ b/tests/ui/impl-trait/issues/issue-67830.stderr
@@ -1,34 +1,15 @@
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
-  --> $DIR/issue-67830.rs:21:62
+  --> $DIR/issue-67830.rs:20:64
    |
-LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
-   |                                                              ^^
+LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
+   |                                                                ^^
    |
 note: lifetime declared here
-  --> $DIR/issue-67830.rs:21:23
+  --> $DIR/issue-67830.rs:20:23
    |
-LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
    |                       ^^
 
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-67830.rs:23:5
-   |
-LL |     Wrap(|a| Some(a).into_iter())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-67830.rs:23:5
-   |
-LL |     Wrap(|a| Some(a).into_iter())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs
index 7ff08d8174f..5005af46ee1 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.rs
+++ b/tests/ui/impl-trait/issues/issue-88236-2.rs
@@ -18,16 +18,11 @@ fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
 fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
     //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     &()
-    //~^ ERROR implementation of `Hrtb` is not general enough
-    //~| ERROR implementation of `Hrtb` is not general enough
 }
 
 fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
     //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     x
-    //~^ ERROR implementation of `Hrtb` is not general enough
-    //~| ERROR implementation of `Hrtb` is not general enough
-    //~| ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr
index 09fd58056a5..4ded9ed386f 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr
@@ -22,72 +22,18 @@ note: lifetime declared here
 LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
    |                                               ^^
 
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:20:5
-   |
-LL |     &()
-   |     ^^^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:20:5
-   |
-LL |     &()
-   |     ^^^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'a>` would have to be implemented for the type `&()`
-   = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0`
-
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
-  --> $DIR/issue-88236-2.rs:25:78
+  --> $DIR/issue-88236-2.rs:23:78
    |
 LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
    |                                                                              ^^
    |
 note: lifetime declared here
-  --> $DIR/issue-88236-2.rs:25:45
+  --> $DIR/issue-88236-2.rs:23:45
    |
 LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
    |                                             ^^
 
-error: lifetime may not live long enough
-  --> $DIR/issue-88236-2.rs:27:5
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                  -- lifetime `'b` defined here
-LL |
-LL |     x
-   |     ^ returning this value requires that `'b` must outlive `'static`
-   |
-help: to declare that `impl for<'a> Hrtb<'a, Assoc = impl Send + '_>` captures data from argument `x`, you can add an explicit `'b` lifetime bound
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b {
-   |                                                                                  ++++
-help: to declare that `impl Send + 'a` captures data from argument `x`, you can add an explicit `'b` lifetime bound
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a + 'b> {
-   |                                                                                 ++++
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:27:5
-   |
-LL |     x
-   |     ^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:27:5
-   |
-LL |     x
-   |     ^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'a>` would have to be implemented for the type `&()`
-   = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0`
-
-error: aborting due to 8 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs
index 9b18aceb4a7..11d79bcff73 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.rs
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs
@@ -31,7 +31,6 @@ fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
 
 fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
 //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
-//~| ERROR implementation of `Bar` is not general enough
 
 fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
 //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
@@ -64,6 +63,5 @@ fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<
 // `'b` is not in scope for the outlives bound.
 fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
 //~^ ERROR use of undeclared lifetime name `'b` [E0261]
-//~| ERROR implementation of `Bar` is not general enough
 
 fn main() {}
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
index 2fa036f35fa..d98de650d0d 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/nested-rpit-hrtb.rs:57:77
+  --> $DIR/nested-rpit-hrtb.rs:56:77
    |
 LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
    |                                                                             ^^ undeclared lifetime
@@ -15,7 +15,7 @@ LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Siz
    |                     ++++
 
 error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/nested-rpit-hrtb.rs:65:82
+  --> $DIR/nested-rpit-hrtb.rs:64:82
    |
 LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
    |                                                                                  ^^ undeclared lifetime
@@ -65,29 +65,20 @@ note: lifetime declared here
 LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
    |                                         ^^
 
-error: implementation of `Bar` is not general enough
-  --> $DIR/nested-rpit-hrtb.rs:32:78
-   |
-LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
-   |                                                                              ^^ implementation of `Bar` is not general enough
-   |
-   = note: `()` must implement `Bar<'a>`
-   = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
-
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
-  --> $DIR/nested-rpit-hrtb.rs:36:73
+  --> $DIR/nested-rpit-hrtb.rs:35:73
    |
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
    |                                                                         ^^
    |
 note: lifetime declared here
-  --> $DIR/nested-rpit-hrtb.rs:36:44
+  --> $DIR/nested-rpit-hrtb.rs:35:44
    |
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
    |                                            ^^
 
 error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied
-  --> $DIR/nested-rpit-hrtb.rs:46:79
+  --> $DIR/nested-rpit-hrtb.rs:45:79
    |
 LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
    |                                                                               ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()`
@@ -96,7 +87,7 @@ LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc
    = help: for that trait implementation, expected `()`, found `&'a ()`
 
 error: implementation of `Bar` is not general enough
-  --> $DIR/nested-rpit-hrtb.rs:50:93
+  --> $DIR/nested-rpit-hrtb.rs:49:93
    |
 LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
    |                                                                                             ^^ implementation of `Bar` is not general enough
@@ -105,7 +96,7 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc =
    = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
 
 error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied
-  --> $DIR/nested-rpit-hrtb.rs:61:64
+  --> $DIR/nested-rpit-hrtb.rs:60:64
    |
 LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
    |                                                                ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()`
@@ -113,16 +104,7 @@ LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b>
    = help: the trait `Qux<'_>` is implemented for `()`
    = help: for that trait implementation, expected `()`, found `&'a ()`
 
-error: implementation of `Bar` is not general enough
-  --> $DIR/nested-rpit-hrtb.rs:65:86
-   |
-LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
-   |                                                                                      ^^ implementation of `Bar` is not general enough
-   |
-   = note: `()` must implement `Bar<'a>`
-   = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
-
-error: aborting due to 11 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0261, E0277, E0657.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/imports/cycle-import-in-diff-module-0.rs b/tests/ui/imports/cycle-import-in-diff-module-0.rs
new file mode 100644
index 00000000000..962603a8971
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-diff-module-0.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+
+// https://github.com/rust-lang/rust/pull/124840#issuecomment-2098148587
+
+mod a {
+    pub(crate) use crate::S;
+}
+mod b {
+    pub struct S;
+}
+use self::a::S;
+use self::b::*;
+
+fn main() {}
diff --git a/tests/ui/imports/cycle-import-in-diff-module-1.rs b/tests/ui/imports/cycle-import-in-diff-module-1.rs
new file mode 100644
index 00000000000..8c67df376c3
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-diff-module-1.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+
+// similar `cycle-import-in-diff-module-0.rs`
+
+mod a {
+    pub(crate) use crate::s;
+}
+mod b {
+    pub mod s {}
+}
+use self::b::*;
+use self::a::s;
+
+fn main() {}
diff --git a/tests/ui/imports/cycle-import-in-std-1.rs b/tests/ui/imports/cycle-import-in-std-1.rs
new file mode 100644
index 00000000000..2fa492c155d
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-std-1.rs
@@ -0,0 +1,9 @@
+//@ edition: 2018
+
+// https://github.com/rust-lang/rust/issues/124490
+
+use ops::{self as std};
+//~^ ERROR: unresolved import `ops`
+use std::collections::{self as ops};
+
+fn main() {}
diff --git a/tests/ui/imports/cycle-import-in-std-1.stderr b/tests/ui/imports/cycle-import-in-std-1.stderr
new file mode 100644
index 00000000000..d4e6f32cc10
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-std-1.stderr
@@ -0,0 +1,13 @@
+error[E0432]: unresolved import `ops`
+  --> $DIR/cycle-import-in-std-1.rs:5:11
+   |
+LL | use ops::{self as std};
+   |           ^^^^^^^^^^^ no external crate `ops`
+   |
+   = help: consider importing one of these items instead:
+           core::ops
+           std::ops
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/cycle-import-in-std-2.rs b/tests/ui/imports/cycle-import-in-std-2.rs
new file mode 100644
index 00000000000..d73c57944bc
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-std-2.rs
@@ -0,0 +1,9 @@
+//@ edition: 2018
+
+// https://github.com/rust-lang/rust/issues/125013
+
+use ops::{self as std};
+//~^ ERROR: unresolved import `ops`
+use std::ops::Deref::{self as ops};
+
+fn main() {}
diff --git a/tests/ui/imports/cycle-import-in-std-2.stderr b/tests/ui/imports/cycle-import-in-std-2.stderr
new file mode 100644
index 00000000000..dc0270dffe4
--- /dev/null
+++ b/tests/ui/imports/cycle-import-in-std-2.stderr
@@ -0,0 +1,13 @@
+error[E0432]: unresolved import `ops`
+  --> $DIR/cycle-import-in-std-2.rs:5:11
+   |
+LL | use ops::{self as std};
+   |           ^^^^^^^^^^^ no external crate `ops`
+   |
+   = help: consider importing one of these items instead:
+           core::ops
+           std::ops
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.rs b/tests/ui/imports/shadow-glob-module-resolution-1.rs
new file mode 100644
index 00000000000..ba1e65cddc6
--- /dev/null
+++ b/tests/ui/imports/shadow-glob-module-resolution-1.rs
@@ -0,0 +1,17 @@
+// https://github.com/rust-lang/rust/issues/124490
+
+mod a {
+    pub mod b {
+        pub mod c {}
+    }
+}
+
+use a::*;
+
+use b::c;
+//~^ ERROR: cannot determine resolution for the import
+//~| ERROR: cannot determine resolution for the import
+//~| ERROR: unresolved import `b::c`
+use c as b;
+
+fn main() {}
diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.stderr b/tests/ui/imports/shadow-glob-module-resolution-1.stderr
new file mode 100644
index 00000000000..f9135963fe9
--- /dev/null
+++ b/tests/ui/imports/shadow-glob-module-resolution-1.stderr
@@ -0,0 +1,23 @@
+error: cannot determine resolution for the import
+  --> $DIR/shadow-glob-module-resolution-1.rs:11:5
+   |
+LL | use b::c;
+   |     ^^^^
+
+error: cannot determine resolution for the import
+  --> $DIR/shadow-glob-module-resolution-1.rs:11:5
+   |
+LL | use b::c;
+   |     ^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0432]: unresolved import `b::c`
+  --> $DIR/shadow-glob-module-resolution-1.rs:11:5
+   |
+LL | use b::c;
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs
new file mode 100644
index 00000000000..36bd72658ae
--- /dev/null
+++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs
@@ -0,0 +1,19 @@
+// https://github.com/rust-lang/rust/issues/125013
+
+mod a {
+  pub mod b {
+    pub mod c {
+      pub trait D {}
+    }
+  }
+}
+
+use a::*;
+
+use e as b;
+//~^ ERROR: unresolved import `e`
+use b::c::D as e;
+//~^ ERROR: cannot determine resolution for the import
+//~| ERROR: cannot determine resolution for the import
+
+fn main() { }
diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr
new file mode 100644
index 00000000000..644fcb84162
--- /dev/null
+++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr
@@ -0,0 +1,26 @@
+error: cannot determine resolution for the import
+  --> $DIR/shadow-glob-module-resolution-2.rs:15:5
+   |
+LL | use b::c::D as e;
+   |     ^^^^^^^^^^^^
+
+error: cannot determine resolution for the import
+  --> $DIR/shadow-glob-module-resolution-2.rs:15:5
+   |
+LL | use b::c::D as e;
+   |     ^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0432]: unresolved import `e`
+  --> $DIR/shadow-glob-module-resolution-2.rs:13:5
+   |
+LL | use e as b;
+   |     -^^^^^
+   |     |
+   |     no `e` in the root
+   |     help: a similar name exists in the module: `a`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/inline-const/const_block_pat_liveness.rs b/tests/ui/inline-const/const_block_pat_liveness.rs
new file mode 100644
index 00000000000..26393a4f65b
--- /dev/null
+++ b/tests/ui/inline-const/const_block_pat_liveness.rs
@@ -0,0 +1,18 @@
+//! This test used to ICE because const blocks didn't have a body
+//! anymore, making a lot of logic very fragile around handling the
+//! HIR of a const block.
+//! https://github.com/rust-lang/rust/issues/125846
+
+//@ check-pass
+
+#![feature(inline_const_pat)]
+
+fn main() {
+    match 0 {
+        const {
+            let a = 10_usize;
+            *&a
+        }
+        | _ => {}
+    }
+}
diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
index 5775a4032c3..48cae82feb0 100644
--- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
+++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
@@ -1,6 +1,4 @@
-warning: ignoring --out-dir flag due to -o flag
-
 error: io error modifying ./does-not-exist/
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr
index ddc1027c16b..d30fb3cfe58 100644
--- a/tests/ui/issues/issue-28344.stderr
+++ b/tests/ui/issues/issue-28344.stderr
@@ -52,7 +52,7 @@ error[E0599]: no function or associated item named `bitor` found for trait objec
 LL |     let g = BitXor::bitor;
    |                     ^^^^^ function or associated item not found in `dyn BitXor<_>`
    |
-help: there is a method `bitxor` with a similar name, but with different arguments
+help: there is a method `bitxor` with a similar name
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
 error: aborting due to 4 previous errors; 2 warnings emitted
diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs
index 3c5e5a9f69a..32253c3c236 100644
--- a/tests/ui/issues/issue-50781.rs
+++ b/tests/ui/issues/issue-50781.rs
@@ -1,10 +1,7 @@
-#![deny(where_clauses_object_safety)]
-
 trait Trait {}
 
 trait X {
-    fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object
-    //~^ WARN this was previously accepted by the compiler but is being phased out
+    fn foo(&self) where Self: Trait;
 }
 
 impl X for () {
@@ -12,8 +9,11 @@ impl X for () {
 }
 
 impl Trait for dyn X {}
+//~^ ERROR the trait `X` cannot be made into an object
 
 pub fn main() {
     // Check that this does not segfault.
     <dyn X as X>::foo(&());
+    //~^ ERROR the trait `X` cannot be made into an object
+    //~| ERROR the trait `X` cannot be made into an object
 }
diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr
index beaea1e634c..6b0b42ca53a 100644
--- a/tests/ui/issues/issue-50781.stderr
+++ b/tests/ui/issues/issue-50781.stderr
@@ -1,24 +1,52 @@
-error: the trait `X` cannot be made into an object
-  --> $DIR/issue-50781.rs:6:8
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-50781.rs:11:16
    |
+LL | impl Trait for dyn X {}
+   |                ^^^^^ `X` 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/issue-50781.rs:4:8
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
 LL |     fn foo(&self) where Self: Trait;
-   |        ^^^
+   |        ^^^ ...because method `foo` references the `Self` type in its `where` clause
+   = help: consider moving `foo` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
+
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-50781.rs:16:23
+   |
+LL |     <dyn X as X>::foo(&());
+   |                       ^^^ `X` cannot be made into an object
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
 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/issue-50781.rs:6:8
+  --> $DIR/issue-50781.rs:4:8
    |
 LL | trait X {
    |       - this trait cannot be made into an object...
 LL |     fn foo(&self) where Self: Trait;
    |        ^^^ ...because method `foo` references the `Self` type in its `where` clause
    = help: consider moving `foo` to another trait
-note: the lint level is defined here
-  --> $DIR/issue-50781.rs:1:9
+   = help: only type `()` implements the trait, consider using it directly instead
+   = note: required for the cast from `&()` to `&dyn X`
+
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-50781.rs:16:6
+   |
+LL |     <dyn X as X>::foo(&());
+   |      ^^^^^ `X` cannot be made into an object
    |
-LL | #![deny(where_clauses_object_safety)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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/issue-50781.rs:4:8
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
+LL |     fn foo(&self) where Self: Trait;
+   |        ^^^ ...because method `foo` references the `Self` type in its `where` clause
+   = help: consider moving `foo` to another trait
+   = help: only type `()` implements the trait, consider using it directly instead
 
-error: aborting due to 1 previous error
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs
deleted file mode 100644
index 9e0437c46f4..00000000000
--- a/tests/ui/issues/issue-53498.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-pub mod test {
-    pub struct A;
-    pub struct B;
-    pub struct Foo<T>(T);
-
-    impl Foo<A> {
-        fn foo() {}
-    }
-
-    impl Foo<B> {
-        fn foo() {}
-    }
-}
-
-fn main() {
-    test::Foo::<test::B>::foo(); //~ ERROR associated function `foo` is private
-}
diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/issues/issue-5708.rs
index ce9ef78ffcd..89ea9fbdcd8 100644
--- a/tests/ui/issues/issue-5708.rs
+++ b/tests/ui/issues/issue-5708.rs
@@ -44,6 +44,7 @@ pub trait MyTrait<T> {
     fn dummy(&self, t: T) -> T { panic!() }
 }
 
+#[allow(dead_code)]
 pub struct MyContainer<'a, T:'a> {
     foos: Vec<&'a (dyn MyTrait<T>+'a)> ,
 }
diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs
index 425da65b990..974d5310f6b 100644
--- a/tests/ui/layout/issue-84108.rs
+++ b/tests/ui/layout/issue-84108.rs
@@ -8,6 +8,9 @@ static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
 
 const BAR: (&Path, [u8], usize) = ("hello", [], 42);
 //~^ ERROR cannot find type `Path` in this scope
+//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
+//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
+//~| ERROR mismatched types
 
 static BAZ: ([u8], usize) = ([], 0);
 //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr
index 6c168cc5fa8..8ddce285e23 100644
--- a/tests/ui/layout/issue-84108.stderr
+++ b/tests/ui/layout/issue-84108.stderr
@@ -21,7 +21,35 @@ LL + use std::path::Path;
    |
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:12:13
+  --> $DIR/issue-84108.rs:9:12
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |            ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:9:12
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |            ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-84108.rs:9:45
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |                                             ^^ expected `[u8]`, found `[_; 0]`
+   |
+   = note: expected slice `[u8]`
+              found array `[_; 0]`
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:15:13
    |
 LL | static BAZ: ([u8], usize) = ([], 0);
    |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -30,7 +58,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:12:13
+  --> $DIR/issue-84108.rs:15:13
    |
 LL | static BAZ: ([u8], usize) = ([], 0);
    |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -40,7 +68,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-84108.rs:12:30
+  --> $DIR/issue-84108.rs:15:30
    |
 LL | static BAZ: ([u8], usize) = ([], 0);
    |                              ^^ expected `[u8]`, found `[_; 0]`
@@ -48,7 +76,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: expected slice `[u8]`
               found array `[_; 0]`
 
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/lifetimes/issue-69314.fixed b/tests/ui/lifetimes/issue-69314.fixed
index 285d192b44c..ee1675724fb 100644
--- a/tests/ui/lifetimes/issue-69314.fixed
+++ b/tests/ui/lifetimes/issue-69314.fixed
@@ -11,7 +11,7 @@ impl A {
     }
     async fn f() {
         let mut buf = [0; 512];
-        let m2 = &buf[..]; //~ ERROR `buf` does not live long enough
+        let m2 = &buf[..];
         let m = Self::g(m2).await;
         Self::f2(m).await;
     }
diff --git a/tests/ui/lifetimes/issue-69314.rs b/tests/ui/lifetimes/issue-69314.rs
index 345f7785060..f9e5196b2c7 100644
--- a/tests/ui/lifetimes/issue-69314.rs
+++ b/tests/ui/lifetimes/issue-69314.rs
@@ -11,7 +11,7 @@ impl A {
     }
     async fn f() {
         let mut buf = [0; 512];
-        let m2 = &buf[..]; //~ ERROR `buf` does not live long enough
+        let m2 = &buf[..];
         let m = Self::g(m2).await;
         Self::f2(m).await;
     }
diff --git a/tests/ui/lifetimes/issue-69314.stderr b/tests/ui/lifetimes/issue-69314.stderr
index 3879f35505c..67da54e8dcd 100644
--- a/tests/ui/lifetimes/issue-69314.stderr
+++ b/tests/ui/lifetimes/issue-69314.stderr
@@ -9,20 +9,6 @@ help: indicate the anonymous lifetime
 LL |     async fn f2(m: Msg<'_>) {}
    |                       ++++
 
-error[E0597]: `buf` does not live long enough
-  --> $DIR/issue-69314.rs:14:19
-   |
-LL |         let mut buf = [0; 512];
-   |             ------- binding `buf` declared here
-LL |         let m2 = &buf[..];
-   |                   ^^^ borrowed value does not live long enough
-LL |         let m = Self::g(m2).await;
-   |                 ----------- argument requires that `buf` is borrowed for `'static`
-LL |         Self::f2(m).await;
-LL |     }
-   |     - `buf` dropped here while still borrowed
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0597, E0726.
-For more information about an error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0726`.
diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs
new file mode 100644
index 00000000000..21395475fb3
--- /dev/null
+++ b/tests/ui/lifetimes/no_lending_iterators.rs
@@ -0,0 +1,35 @@
+struct Data(String);
+
+impl Iterator for Data {
+    type Item = &str;
+    //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+
+    fn next(&mut self) -> Option<Self::Item> {
+        Some(&self.0)
+    }
+}
+
+trait Bar {
+    type Item;
+    fn poke(&mut self, item: Self::Item);
+}
+
+impl Bar for usize {
+    type Item = &usize;
+    //~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+
+    fn poke(&mut self, item: Self::Item) {
+        self += *item;
+    }
+}
+
+impl Bar for isize {
+    type Item<'a> = &'a isize;
+    //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195]
+
+    fn poke(&mut self, item: Self::Item) {
+        self += *item;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr
new file mode 100644
index 00000000000..c3784770d79
--- /dev/null
+++ b/tests/ui/lifetimes/no_lending_iterators.stderr
@@ -0,0 +1,30 @@
+error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+  --> $DIR/no_lending_iterators.rs:4:17
+   |
+LL |     type Item = &str;
+   |                 ^
+   |
+note: you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type.
+  --> $DIR/no_lending_iterators.rs:3:19
+   |
+LL | impl Iterator for Data {
+   |                   ^^^^
+
+error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+  --> $DIR/no_lending_iterators.rs:18:17
+   |
+LL |     type Item = &usize;
+   |                 ^ this lifetime must come from the implemented type
+
+error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration
+  --> $DIR/no_lending_iterators.rs:27:14
+   |
+LL |     type Item;
+   |              - lifetimes in impl do not match this type in trait
+...
+LL |     type Item<'a> = &'a isize;
+   |              ^^^^ lifetimes do not match type in trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/lifetimes/noisy-follow-up-erro.rs b/tests/ui/lifetimes/noisy-follow-up-erro.rs
new file mode 100644
index 00000000000..47a87068d8f
--- /dev/null
+++ b/tests/ui/lifetimes/noisy-follow-up-erro.rs
@@ -0,0 +1,23 @@
+struct Foo<'c, 'd>(&'c (), &'d ());
+
+impl<'c, 'd> Foo<'c, 'd> {
+    fn acc(&mut self, _bar: &Bar) -> &'d () {
+        todo!()
+    }
+}
+
+struct Bar;
+
+impl<'a> Bar {
+    fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> {
+        //~^ ERROR: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
+        self.bar().map_err(|()| foo.acc(self))?;
+        //~^ ERROR: explicit lifetime required in the type of `foo`
+        Ok(())
+    }
+    fn bar(&self) -> Result<(), &'a ()> {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/noisy-follow-up-erro.stderr b/tests/ui/lifetimes/noisy-follow-up-erro.stderr
new file mode 100644
index 00000000000..f549009a87c
--- /dev/null
+++ b/tests/ui/lifetimes/noisy-follow-up-erro.stderr
@@ -0,0 +1,27 @@
+error[E0107]: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
+  --> $DIR/noisy-follow-up-erro.rs:12:30
+   |
+LL |     fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> {
+   |                              ^^^         -- help: remove this lifetime argument
+   |                              |
+   |                              expected 2 lifetime arguments
+   |
+note: struct defined here, with 2 lifetime parameters: `'c`, `'d`
+  --> $DIR/noisy-follow-up-erro.rs:1:8
+   |
+LL | struct Foo<'c, 'd>(&'c (), &'d ());
+   |        ^^^ --  --
+
+error[E0621]: explicit lifetime required in the type of `foo`
+  --> $DIR/noisy-follow-up-erro.rs:14:9
+   |
+LL |     fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> {
+   |                         -------------------- help: add explicit lifetime `'a` to the type of `foo`: `&mut Foo<'_, 'a>`
+LL |
+LL |         self.bar().map_err(|()| foo.acc(self))?;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0621.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs
index 3bc87b9d480..0708a00d371 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.rs
+++ b/tests/ui/lifetimes/unusual-rib-combinations.rs
@@ -2,9 +2,8 @@ struct S<'a>(&'a u8);
 fn foo() {}
 
 // Paren generic args in AnonConst
-fn a() -> [u8; foo::()] {
-//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
-//~| ERROR mismatched types
+fn a() -> [u8; foo()] {
+    //~^ ERROR mismatched types
     panic!()
 }
 
@@ -26,5 +25,6 @@ fn d<const C: S>() {}
 trait Foo<'a> {}
 struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
 //~^ ERROR the type of const parameters must not depend on other generic parameters
+//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 2857fc72ea1..70f06b4be60 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -1,11 +1,11 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/unusual-rib-combinations.rs:22:15
+  --> $DIR/unusual-rib-combinations.rs:21:15
    |
 LL | fn d<const C: S>() {}
    |               ^ expected named lifetime parameter
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/unusual-rib-combinations.rs:27:22
+  --> $DIR/unusual-rib-combinations.rs:26:22
    |
 LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
    |                      ^^ the type must not depend on the parameter `'a`
@@ -13,25 +13,19 @@ LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
    = note: lifetime parameters may not be used in the type of const parameters
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:5:16
-   |
-LL | fn a() -> [u8; foo::()] {
-   |                ^^^^^^^ only `Fn` traits may use parentheses
-
-error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:12:15
+  --> $DIR/unusual-rib-combinations.rs:11:15
    |
 LL | fn b<const C: u8()>() {}
    |               ^^^^ only `Fn` traits may use parentheses
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/unusual-rib-combinations.rs:16:10
+  --> $DIR/unusual-rib-combinations.rs:15:10
    |
 LL | fn c<T = u8()>() {}
    |          ^^^^ only `Fn` traits may use parentheses
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/unusual-rib-combinations.rs:16:6
+  --> $DIR/unusual-rib-combinations.rs:15:6
    |
 LL | fn c<T = u8()>() {}
    |      ^^^^^^^^
@@ -43,14 +37,11 @@ LL | fn c<T = u8()>() {}
 error[E0308]: mismatched types
   --> $DIR/unusual-rib-combinations.rs:5:16
    |
-LL | fn a() -> [u8; foo::()] {
-   |                ^^^^^^^ expected `usize`, found fn item
-   |
-   = note: expected type `usize`
-           found fn item `fn() {foo}`
+LL | fn a() -> [u8; foo()] {
+   |                ^^^^^ expected `usize`, found `()`
 
 error: `S<'_>` is forbidden as the type of a const generic parameter
-  --> $DIR/unusual-rib-combinations.rs:22:15
+  --> $DIR/unusual-rib-combinations.rs:21:15
    |
 LL | fn d<const C: S>() {}
    |               ^
@@ -61,6 +52,18 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
 LL + #![feature(adt_const_params)]
    |
 
+error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
+  --> $DIR/unusual-rib-combinations.rs:26:21
+   |
+LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   |
+LL + #![feature(adt_const_params)]
+   |
+
 error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0106, E0214, E0308, E0770.
diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
index a7109c6d930..ed11947f59e 100644
--- a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
+++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
@@ -4,12 +4,21 @@
 #![feature(linkage)]
 
 fn main() {
+    #[rustfmt::skip]
     extern "C" {
-        #[linkage = "weak"] //~ ERROR mutable statics are not allowed with `#[linkage]`
-        static mut ABC: *const u8;
+        #[linkage = "extern_weak"] //~ ERROR extern mutable statics are not allowed with `#[linkage]`
+        static mut EXTERN_WEAK: *const u8;
     }
 
     unsafe {
-        assert_eq!(ABC as usize, 0);
+        assert_eq!(EXTERN_WEAK as usize, 0);
+    }
+
+    // static mut is fine here as this is a definition rather than declaration.
+    #[linkage = "weak"]
+    static mut WEAK_DEF: u8 = 42;
+
+    unsafe {
+        assert_eq!(WEAK_DEF, 0);
     }
 }
diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
index 4db41b62393..ad999769047 100644
--- a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
+++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
@@ -1,10 +1,10 @@
-error: mutable statics are not allowed with `#[linkage]`
-  --> $DIR/linkage-attr-mutable-static.rs:8:9
+error: extern mutable statics are not allowed with `#[linkage]`
+  --> $DIR/linkage-attr-mutable-static.rs:9:9
    |
-LL |         #[linkage = "weak"]
-   |         ^^^^^^^^^^^^^^^^^^^
+LL |         #[linkage = "extern_weak"]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: making the static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable
+   = note: marking the extern static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs
index ddcafedf7bc..3386dfa4747 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-1.rs
+++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs
@@ -46,11 +46,10 @@ struct SemiUsedStruct;
 impl SemiUsedStruct {
     fn la_la_la() {}
 }
-struct StructUsedAsField;
+struct StructUsedAsField; //~ ERROR struct `StructUsedAsField` is never constructed
 pub struct StructUsedInEnum;
 struct StructUsedInGeneric;
-pub struct PubStruct2 {
-    #[allow(dead_code)]
+pub struct PubStruct2 { //~ ERROR struct `PubStruct2` is never constructed
     struct_used_as_field: *const StructUsedAsField
 }
 
diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr
index eb728b5b930..b0163df8855 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-1.stderr
+++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr
@@ -22,14 +22,26 @@ error: struct `PrivStruct` is never constructed
 LL | struct PrivStruct;
    |        ^^^^^^^^^^
 
+error: struct `StructUsedAsField` is never constructed
+  --> $DIR/lint-dead-code-1.rs:49:8
+   |
+LL | struct StructUsedAsField;
+   |        ^^^^^^^^^^^^^^^^^
+
+error: struct `PubStruct2` is never constructed
+  --> $DIR/lint-dead-code-1.rs:52:12
+   |
+LL | pub struct PubStruct2 {
+   |            ^^^^^^^^^^
+
 error: enum `priv_enum` is never used
-  --> $DIR/lint-dead-code-1.rs:64:6
+  --> $DIR/lint-dead-code-1.rs:63:6
    |
 LL | enum priv_enum { foo2, bar2 }
    |      ^^^^^^^^^
 
 error: variant `bar3` is never constructed
-  --> $DIR/lint-dead-code-1.rs:67:5
+  --> $DIR/lint-dead-code-1.rs:66:5
    |
 LL | enum used_enum {
    |      --------- variant in this enum
@@ -38,25 +50,25 @@ LL |     bar3
    |     ^^^^
 
 error: function `priv_fn` is never used
-  --> $DIR/lint-dead-code-1.rs:88:4
+  --> $DIR/lint-dead-code-1.rs:87:4
    |
 LL | fn priv_fn() {
    |    ^^^^^^^
 
 error: function `foo` is never used
-  --> $DIR/lint-dead-code-1.rs:93:4
+  --> $DIR/lint-dead-code-1.rs:92:4
    |
 LL | fn foo() {
    |    ^^^
 
 error: function `bar` is never used
-  --> $DIR/lint-dead-code-1.rs:98:4
+  --> $DIR/lint-dead-code-1.rs:97:4
    |
 LL | fn bar() {
    |    ^^^
 
 error: function `baz` is never used
-  --> $DIR/lint-dead-code-1.rs:102:4
+  --> $DIR/lint-dead-code-1.rs:101:4
    |
 LL | fn baz() -> impl Copy {
    |    ^^^
@@ -67,5 +79,5 @@ error: struct `Bar` is never constructed
 LL |     pub struct Bar;
    |                ^^^
 
-error: aborting due to 10 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/lint/dead-code/unused-assoc-const.rs b/tests/ui/lint/dead-code/unused-assoc-const.rs
new file mode 100644
index 00000000000..36e8315ad36
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-assoc-const.rs
@@ -0,0 +1,20 @@
+#![deny(dead_code)]
+
+trait Trait {
+    const UNUSED_CONST: i32; //~ ERROR associated constant `UNUSED_CONST` is never used
+    const USED_CONST: i32;
+
+    fn foo(&self) {}
+}
+
+pub struct T(());
+
+impl Trait for T {
+    const UNUSED_CONST: i32 = 0;
+    const USED_CONST: i32 = 1;
+}
+
+fn main() {
+    T(()).foo();
+    T::USED_CONST;
+}
diff --git a/tests/ui/lint/dead-code/unused-assoc-const.stderr b/tests/ui/lint/dead-code/unused-assoc-const.stderr
new file mode 100644
index 00000000000..78296d70663
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-assoc-const.stderr
@@ -0,0 +1,16 @@
+error: associated constant `UNUSED_CONST` is never used
+  --> $DIR/unused-assoc-const.rs:4:11
+   |
+LL | trait Trait {
+   |       ----- associated constant in this trait
+LL |     const UNUSED_CONST: i32;
+   |           ^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-assoc-const.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/dead-code/unused-pub-struct.rs b/tests/ui/lint/dead-code/unused-pub-struct.rs
new file mode 100644
index 00000000000..aaf4dd612de
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-pub-struct.rs
@@ -0,0 +1,48 @@
+#![deny(dead_code)]
+
+pub struct NotLint1(());
+pub struct NotLint2(std::marker::PhantomData<i32>);
+
+pub struct NeverConstructed(i32); //~ ERROR struct `NeverConstructed` is never constructed
+
+impl NeverConstructed {
+    pub fn not_construct_self(&self) {}
+}
+
+impl Clone for NeverConstructed {
+    fn clone(&self) -> NeverConstructed {
+        NeverConstructed(0)
+    }
+}
+
+pub trait Trait {
+    fn not_construct_self(&self);
+}
+
+impl Trait for NeverConstructed {
+    fn not_construct_self(&self) {
+        self.0;
+    }
+}
+
+pub struct Constructed(i32);
+
+impl Constructed {
+    pub fn construct_self() -> Self {
+        Constructed(0)
+    }
+}
+
+impl Clone for Constructed {
+    fn clone(&self) -> Constructed {
+        Constructed(0)
+    }
+}
+
+impl Trait for Constructed {
+    fn not_construct_self(&self) {
+        self.0;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-pub-struct.stderr b/tests/ui/lint/dead-code/unused-pub-struct.stderr
new file mode 100644
index 00000000000..3667ddb97bd
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-pub-struct.stderr
@@ -0,0 +1,14 @@
+error: struct `NeverConstructed` is never constructed
+  --> $DIR/unused-pub-struct.rs:6:12
+   |
+LL | pub struct NeverConstructed(i32);
+   |            ^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-pub-struct.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr
index 48bdaa60823..2756ea40138 100644
--- a/tests/ui/lint/non-local-defs/consts.stderr
+++ b/tests/ui/lint/non-local-defs/consts.stderr
@@ -67,13 +67,18 @@ LL |     impl Test {
 warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
   --> $DIR/consts.rs:50:9
    |
-LL | fn main() {
-   | --------- move the `impl` block outside of this function `main`
-...
-LL |         impl Test {
-   |         ^^^^^----
-   |              |
-   |              `Test` is not local
+LL |       const {
+   |  ___________-
+LL | |         impl Test {
+   | |         ^^^^^----
+   | |              |
+   | |              `Test` is not local
+LL | |
+LL | |             fn hoo() {}
+...  |
+LL | |         1
+LL | |     };
+   | |_____- move the `impl` block outside of this inline constant `<unnameable>` and up 2 bodies
    |
    = note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
diff --git a/tests/ui/lint/unreachable_pub.rs b/tests/ui/lint/unreachable_pub.rs
index 22c091e112b..f21f6640342 100644
--- a/tests/ui/lint/unreachable_pub.rs
+++ b/tests/ui/lint/unreachable_pub.rs
@@ -9,12 +9,16 @@ mod private_mod {
     pub use std::env::{Args}; // braced-use has different item spans than unbraced
     //~^ WARNING unreachable_pub
 
+    // we lint on struct definition
     pub struct Hydrogen { //~ WARNING unreachable_pub
-        // `pub` struct fields, too
-        pub neutrons: usize, //~ WARNING unreachable_pub
-        // (... but not more-restricted fields)
+        // but not on fields, even if they are `pub` as putting `pub(crate)`
+        // it would clutter the source code for little value
+        pub neutrons: usize,
         pub(crate) electrons: usize
     }
+    pub(crate) struct Calcium {
+        pub neutrons: usize,
+    }
     impl Hydrogen {
         // impls, too
         pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr
index 762834b97b9..705a537a3f1 100644
--- a/tests/ui/lint/unreachable_pub.stderr
+++ b/tests/ui/lint/unreachable_pub.stderr
@@ -24,7 +24,7 @@ LL |     pub use std::env::{Args}; // braced-use has different item spans than u
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:12:5
+  --> $DIR/unreachable_pub.rs:13:5
    |
 LL |     pub struct Hydrogen {
    |     ---^^^^^^^^^^^^^^^^
@@ -33,16 +33,8 @@ LL |     pub struct Hydrogen {
    |
    = help: or consider exporting it for use by other crates
 
-warning: unreachable `pub` field
-  --> $DIR/unreachable_pub.rs:14:9
-   |
-LL |         pub neutrons: usize,
-   |         ---^^^^^^^^^^^^^^^^
-   |         |
-   |         help: consider restricting its visibility: `pub(crate)`
-
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:20:9
+  --> $DIR/unreachable_pub.rs:24:9
    |
 LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +42,7 @@ LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         help: consider restricting its visibility: `pub(crate)`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:29:5
+  --> $DIR/unreachable_pub.rs:33:5
    |
 LL |     pub enum Helium {}
    |     ---^^^^^^^^^^^^
@@ -60,7 +52,7 @@ LL |     pub enum Helium {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:30:5
+  --> $DIR/unreachable_pub.rs:34:5
    |
 LL |     pub union Lithium { c1: usize, c2: u8 }
    |     ---^^^^^^^^^^^^^^
@@ -70,7 +62,7 @@ LL |     pub union Lithium { c1: usize, c2: u8 }
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:31:5
+  --> $DIR/unreachable_pub.rs:35:5
    |
 LL |     pub fn beryllium() {}
    |     ---^^^^^^^^^^^^^^^
@@ -80,7 +72,7 @@ LL |     pub fn beryllium() {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:32:5
+  --> $DIR/unreachable_pub.rs:36:5
    |
 LL |     pub trait Boron {}
    |     ---^^^^^^^^^^^^
@@ -90,7 +82,7 @@ LL |     pub trait Boron {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:33:5
+  --> $DIR/unreachable_pub.rs:37:5
    |
 LL |     pub const CARBON: usize = 1;
    |     ---^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +92,7 @@ LL |     pub const CARBON: usize = 1;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:34:5
+  --> $DIR/unreachable_pub.rs:38:5
    |
 LL |     pub static NITROGEN: usize = 2;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +102,7 @@ LL |     pub static NITROGEN: usize = 2;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:35:5
+  --> $DIR/unreachable_pub.rs:39:5
    |
 LL |     pub type Oxygen = bool;
    |     ---^^^^^^^^^^^^
@@ -120,7 +112,7 @@ LL |     pub type Oxygen = bool;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:38:47
+  --> $DIR/unreachable_pub.rs:42:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -135,7 +127,7 @@ LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:44:9
+  --> $DIR/unreachable_pub.rs:48:9
    |
 LL |         pub fn catalyze() -> bool;
    |         ---^^^^^^^^^^^^^^^^^^^^^^
@@ -144,5 +136,5 @@ LL |         pub fn catalyze() -> bool;
    |
    = help: or consider exporting it for use by other crates
 
-warning: 14 warnings emitted
+warning: 13 warnings emitted
 
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
index 0f9eac93930..ba32fb566e8 100644
--- a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
@@ -20,10 +20,10 @@ fn doc_comment_between_if_else(num: u8) -> bool {
 }
 
 fn doc_comment_on_expr(num: u8) -> bool {
-    (/// useless doc comment
+    /// useless doc comment
     //~^ ERROR: attributes on expressions are experimental
     //~| ERROR: unused doc comment
-    num) == 3
+    num == 3
 }
 
 fn doc_comment_on_expr_field() -> bool {
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
index 1ff5c8d8825..c0741174554 100644
--- a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
@@ -5,10 +5,10 @@ LL |     else {
    |     ^^^^ expected expression
 
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/unused-doc-comments-edge-cases.rs:23:6
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
    |
-LL |     (/// useless doc comment
-   |      ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
@@ -32,12 +32,12 @@ LL | #![deny(unused_doc_comments)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unused doc comment
-  --> $DIR/unused-doc-comments-edge-cases.rs:23:6
+  --> $DIR/unused-doc-comments-edge-cases.rs:23:5
    |
-LL |     (/// useless doc comment
-   |      ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     /// useless doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 ...
-LL |     num) == 3
+LL |     num == 3
    |     --- rustdoc does not generate documentation for expressions
    |
    = help: use `//` for a plain comment
diff --git a/tests/ui/macros/expand-full-no-resolution.stderr b/tests/ui/macros/expand-full-no-resolution.stderr
index 2537a5032a9..df6f20332bf 100644
--- a/tests/ui/macros/expand-full-no-resolution.stderr
+++ b/tests/ui/macros/expand-full-no-resolution.stderr
@@ -7,7 +7,7 @@ LL |         macro_rules! _a {
 LL |     format_args!(a!());
    |                  ^
    |
-help: a macro with a similar name exists, consider renaming `_a` into `a`
+help: the leading underscore in `_a` marks it as unused, consider renaming it to `a`
    |
 LL |         macro_rules! a {
    |                      ~
@@ -21,7 +21,7 @@ LL |         macro_rules! _a {
 LL |     env!(a!());
    |          ^
    |
-help: a macro with a similar name exists, consider renaming `_a` into `a`
+help: the leading underscore in `_a` marks it as unused, consider renaming it to `a`
    |
 LL |         macro_rules! a {
    |                      ~
diff --git a/tests/ui/macros/issue-61053-missing-repetition.rs b/tests/ui/macros/issue-61053-missing-repetition.rs
index 6b36c730b82..77c94f24171 100644
--- a/tests/ui/macros/issue-61053-missing-repetition.rs
+++ b/tests/ui/macros/issue-61053-missing-repetition.rs
@@ -3,7 +3,7 @@
 macro_rules! foo {
     () => {};
     ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* };
-    //~^ ERROR variable 'j' is still repeating
+    //~^ ERROR variable `j` is still repeating
 }
 
 macro_rules! bar {
@@ -12,12 +12,12 @@ macro_rules! bar {
         macro_rules! nested {
             () => {};
             ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* };
-            //~^ ERROR variable 'j' is still repeating
+            //~^ ERROR variable `j` is still repeating
         }
     };
     ( $( $i:ident = $($j:ident),+ );* ) => {
         $(macro_rules! $i {
-            () => { $j }; //~ ERROR variable 'j' is still repeating
+            () => { $j }; //~ ERROR variable `j` is still repeating
         })*
     };
 }
diff --git a/tests/ui/macros/issue-61053-missing-repetition.stderr b/tests/ui/macros/issue-61053-missing-repetition.stderr
index 738f711f04e..ba254401f17 100644
--- a/tests/ui/macros/issue-61053-missing-repetition.stderr
+++ b/tests/ui/macros/issue-61053-missing-repetition.stderr
@@ -1,4 +1,4 @@
-error: variable 'j' is still repeating at this depth
+error: variable `j` is still repeating at this depth
   --> $DIR/issue-61053-missing-repetition.rs:5:52
    |
 LL |     ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* };
@@ -12,7 +12,7 @@ note: the lint level is defined here
 LL | #![deny(meta_variable_misuse)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: variable 'j' is still repeating at this depth
+error: variable `j` is still repeating at this depth
   --> $DIR/issue-61053-missing-repetition.rs:14:60
    |
 LL |             ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* };
@@ -20,7 +20,7 @@ LL |             ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* };
    |                                        |
    |                                        expected repetition
 
-error: variable 'j' is still repeating at this depth
+error: variable `j` is still repeating at this depth
   --> $DIR/issue-61053-missing-repetition.rs:20:21
    |
 LL |     ( $( $i:ident = $($j:ident),+ );* ) => {
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
index 9fec546ecd6..1eda5f5bb6b 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
@@ -35,7 +35,7 @@ macro_rules! no_curly__no_rhs_dollar__no_round {
 #[rustfmt::skip] // autoformatters can break a few of the error traces
 macro_rules! no_curly__rhs_dollar__round {
     ( $( $i:ident ),* ) => { count($i) };
-    //~^ ERROR variable 'i' is still repeating at this depth
+    //~^ ERROR variable `i` is still repeating at this depth
 }
 
 #[rustfmt::skip] // autoformatters can break a few of the error traces
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index e9cef5ec6cc..3fa3839bae2 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -208,7 +208,7 @@ error: `count` can not be placed inside the inner-most repetition
 LL |     ( $i:ident ) => { ${ count($i) } };
    |                        ^^^^^^^^^^^^^
 
-error: variable 'i' is still repeating at this depth
+error: variable `i` is still repeating at this depth
   --> $DIR/syntax-errors.rs:37:36
    |
 LL |     ( $( $i:ident ),* ) => { count($i) };
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
index 62e4f82a3ff..829b7f86e26 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs
@@ -23,9 +23,6 @@ pub fn main() {
     if let Some(Some(&x)) = &Some(&Some(0)) {
         let _: u32 = x;
     }
-    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-        let _: u32 = x;
-    }
     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
         let _: u32 = x;
     }
@@ -35,9 +32,6 @@ pub fn main() {
     if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) {
         let _: &u32 = x;
     }
-    if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
-        let _: &u32 = x;
-    }
     if let &Some(Some(x)) = &Some(&mut Some(0)) {
         let _: &u32 = x;
     }
@@ -59,13 +53,4 @@ pub fn main() {
     if let Some(&Some(x)) = &mut Some(Some(0)) {
         let _: u32 = x;
     }
-
-    let &mut x = &&mut 0;
-    let _: &u32 = x;
-
-    let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
-    let _: &u32 = x;
-
-    let &mut &mut &mut &mut x = &mut &&&&mut &&&mut &mut 0;
-    let _: &u32 = x;
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
index 96b4ff77ddb..40e8293e241 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
@@ -5,26 +5,26 @@
 
 pub fn main() {
     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
     if let Some(&Some(x)) = &mut Some(&Some(0)) {
         let _: &mut u32 = x;
         //~^ ERROR: mismatched types
     }
     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
     if let Some(&mut Some(x)) = &Some(Some(0)) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
     if let Some(&mut Some(x)) = &Some(Some(0)) {
-        //~^ ERROR: mismatched types
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
     }
 
     let &mut _ = &&0;
@@ -32,4 +32,31 @@ pub fn main() {
 
     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
     //~^ ERROR: mismatched types
+
+    if let Some(&mut Some(&_)) = &Some(&mut Some(0)) {
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
+    }
+
+    if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
+        //~^ ERROR: cannot match inherited `&` with `&mut` pattern
+    }
+
+    let &mut _ = &&mut 0;
+    //~^ ERROR: mismatched types
+
+    let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
+    //~^ ERROR: mismatched types
+
+    let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
+    //~^ ERROR: mismatched types
+
+    struct Foo(u8);
+
+    let Foo(mut a) = &Foo(0);
+    //~^ ERROR: binding cannot be both mutable and by-reference
+    a = &42;
+
+    let Foo(mut a) = &mut Foo(0);
+    //~^ ERROR: binding cannot be both mutable and by-reference
+    a = &mut 42;
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
index e06a645fc0d..26317e43d02 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
@@ -1,24 +1,24 @@
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
-   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&mut _`
+   |                 ^^^^^
    |
-   = note:           expected enum `Option<{integer}>`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(&_)) = &Some(&Some(0)) {
+   |                 ~
 
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23
    |
 LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
-   |                       |
-   |                       expected integer, found `&mut _`
+   |                       ^^^^^
    |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(&_)) = &Some(&mut Some(0)) {
+   |                       ~
 
 error[E0308]: mismatched types
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27
@@ -31,49 +31,49 @@ LL |         let _: &mut u32 = x;
    = note: expected mutable reference `&mut u32`
                       found reference `&{integer}`
 
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
-   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
-   |                       |
-   |                       expected integer, found `&mut _`
+   |                       ^^^^^
    |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(&_)) = &mut Some(&Some(0)) {
+   |                       ~
 
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29
    |
 LL |     if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
-   |                             ^^^^^^       ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
-   |                             |
-   |                             expected integer, found `&mut _`
+   |                             ^^^^^
    |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) {
+   |                             ~
 
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
-   |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&mut _`
+   |                 ^^^^^
    |
-   = note:           expected enum `Option<{integer}>`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(x)) = &Some(Some(0)) {
+   |                 ~
 
-error[E0308]: mismatched types
+error: cannot match inherited `&` with `&mut` pattern
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
-   |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&mut _`
+   |                 ^^^^^
    |
-   = note:           expected enum `Option<{integer}>`
-           found mutable reference `&mut _`
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(x)) = &Some(Some(0)) {
+   |                 ~
 
 error[E0308]: mismatched types
   --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9
@@ -81,9 +81,9 @@ error[E0308]: mismatched types
 LL |     let &mut _ = &&0;
    |         ^^^^^^   --- this expression has type `&&{integer}`
    |         |
-   |         expected integer, found `&mut _`
+   |         types differ in mutability
    |
-   = note:           expected type `{integer}`
+   = note:      expected reference `&&{integer}`
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
@@ -92,11 +92,87 @@ error[E0308]: mismatched types
 LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
    |         ^^^^^^   ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
    |         |
-   |         expected integer, found `&mut _`
+   |         types differ in mutability
    |
-   = note:           expected type `{integer}`
+   = note:      expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
            found mutable reference `&mut _`
 
-error: aborting due to 9 previous errors
+error: cannot match inherited `&` with `&mut` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&mut Some(0)) {
+   |                 ^^^^^
+   |
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(&Some(&_)) = &Some(&mut Some(0)) {
+   |                 ~
+
+error: cannot match inherited `&` with `&mut` pattern
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:40:22
+   |
+LL |     if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
+   |                      ^^^^^
+   |
+help: replace this `&mut` pattern with `&`
+   |
+LL |     if let Some(Some(&x)) = &Some(Some(&mut 0)) {
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:44:9
+   |
+LL |     let &mut _ = &&mut 0;
+   |         ^^^^^^   ------- this expression has type `&&mut {integer}`
+   |         |
+   |         types differ in mutability
+   |
+   = note:      expected reference `&&mut {integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:47:9
+   |
+LL |     let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
+   |         ^^^^^^   --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}`
+   |         |
+   |         types differ in mutability
+   |
+   = note:      expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:50:14
+   |
+LL |     let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
+   |              ^^^^^^^^^^^^^^^^   -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}`
+   |              |
+   |              types differ in mutability
+   |
+   = note:      expected reference `&&&&mut &&&mut &mut {integer}`
+           found mutable reference `&mut _`
+
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:13
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` 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]: binding cannot be both mutable and by-reference
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:59:13
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` 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: aborting due to 16 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere-fail.rs b/tests/ui/match/ref_pat_everywhere-fail.rs
deleted file mode 100644
index d1b1c04730d..00000000000
--- a/tests/ui/match/ref_pat_everywhere-fail.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![allow(incomplete_features)]
-#![feature(ref_pat_everywhere)]
-pub fn main() {
-    if let Some(&x) = Some(0) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-    if let Some(&mut x) = Some(&0) {
-        //~^ ERROR: mismatched types [E0308]
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/match/ref_pat_everywhere-fail.stderr b/tests/ui/match/ref_pat_everywhere-fail.stderr
deleted file mode 100644
index 25a01129f4a..00000000000
--- a/tests/ui/match/ref_pat_everywhere-fail.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_everywhere-fail.rs:4:17
-   |
-LL |     if let Some(&x) = Some(0) {
-   |                 ^^    ------- this expression has type `Option<{integer}>`
-   |                 |
-   |                 expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL |     if let Some(x) = Some(0) {
-   |                 ~
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_everywhere-fail.rs:8:17
-   |
-LL |     if let Some(&mut x) = Some(&0) {
-   |                 ^^^^^^    -------- this expression has type `Option<&{integer}>`
-   |                 |
-   |                 types differ in mutability
-   |
-   = note:      expected reference `&{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/ref_pat_everywhere-fail.rs:8:17
-   |
-LL |     if let Some(&mut x) = Some(&0) {
-   |                 ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL |     if let Some(x) = Some(&0) {
-   |                 ~
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/ref_pat_everywhere.rs b/tests/ui/match/ref_pat_everywhere.rs
deleted file mode 100644
index 9a79c548475..00000000000
--- a/tests/ui/match/ref_pat_everywhere.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ run-pass
-#![allow(incomplete_features)]
-#![feature(ref_pat_everywhere)]
-
-pub fn main() {
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        let _: u32 = x;
-    }
-    if let Some(&Some(x)) = &Some(Some(0)) {
-        let _: u32 = x;
-    }
-    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-        let _: u32 = x;
-    }
-    if let Some(Some(&x)) = &Some(&mut Some(0)) {
-        let _: u32 = x;
-    }
-    if let &Some(x) = &mut Some(0) {
-        let _: u32 = x;
-    }
-    if let Some(&x) = &mut Some(0) {
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs
index 806d09cda85..6396cccd4e8 100644
--- a/tests/ui/mir/lint/assignment-overlap.rs
+++ b/tests/ui/mir/lint/assignment-overlap.rs
@@ -9,11 +9,11 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn main() {
-    mir!(
+    mir! {
         let a: [u8; 1024];
         {
             a = a;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs
index eb806378fe5..def78ea1e3b 100644
--- a/tests/ui/mir/lint/call-overlap.rs
+++ b/tests/ui/mir/lint/call-overlap.rs
@@ -9,7 +9,7 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn main() {
-    mir!(
+    mir! {
         let a: [u8; 1024];
         {
             Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable())
@@ -17,7 +17,7 @@ pub fn main() {
         bb1 = {
             Return()
         }
-    )
+    }
 }
 
 pub fn f<T: Copy>(a: T) -> T { a }
diff --git a/tests/ui/mir/lint/no-storage.rs b/tests/ui/mir/lint/no-storage.rs
index 42dd1b963dc..a6af8646f6e 100644
--- a/tests/ui/mir/lint/no-storage.rs
+++ b/tests/ui/mir/lint/no-storage.rs
@@ -8,7 +8,7 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "built")]
 pub fn f(a: bool) {
-    mir!(
+    mir! {
         let b: ();
         {
             match a { true => bb1, _ => bb2 }
@@ -26,5 +26,5 @@ pub fn f(a: bool) {
             StorageDead(b);
             Return()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/lint/storage-live.rs b/tests/ui/mir/lint/storage-live.rs
index 5dea1cb3567..8273544b56a 100644
--- a/tests/ui/mir/lint/storage-live.rs
+++ b/tests/ui/mir/lint/storage-live.rs
@@ -15,14 +15,14 @@ use core::ptr::{addr_of, addr_of_mut};
 
 #[custom_mir(dialect = "built")]
 fn multiple_storage() {
-    mir!(
+    mir! {
         let a: usize;
         {
             StorageLive(a);
             StorageLive(a);
             Return()
         }
-    )
+    }
 }
 
 fn main() {
diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs
index b6281d4b2a8..d51aee9518f 100644
--- a/tests/ui/mir/lint/storage-return.rs
+++ b/tests/ui/mir/lint/storage-return.rs
@@ -8,12 +8,12 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "built")]
 fn main() {
-    mir!(
+    mir! {
         let a: ();
         {
             StorageLive(a);
             RET = a;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/mir_codegen_ssa.rs b/tests/ui/mir/mir_codegen_ssa.rs
index bf01edcbaa8..1666b8293eb 100644
--- a/tests/ui/mir/mir_codegen_ssa.rs
+++ b/tests/ui/mir/mir_codegen_ssa.rs
@@ -5,7 +5,7 @@ use std::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn f(a: u32) -> u32 {
-    mir!(
+    mir! {
         let x: u32;
         {
             // Previously code generation failed with ICE "use of .. before def ..." because the
@@ -15,5 +15,5 @@ pub fn f(a: u32) -> u32 {
             RET = x;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs
index 9b2c78c737f..baaa7326fd8 100644
--- a/tests/ui/mir/ssa_call_ret.rs
+++ b/tests/ui/mir/ssa_call_ret.rs
@@ -10,7 +10,7 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn f() -> u32 {
-    mir!(
+    mir! {
         let a: u32;
         {
             Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2))
@@ -23,7 +23,7 @@ pub fn f() -> u32 {
             RET = a;
             UnwindResume()
         }
-    )
+    }
 }
 
 #[inline(never)]
diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs
index 0a548ae8e58..9048d08a22a 100644
--- a/tests/ui/mir/validate/critical-edge.rs
+++ b/tests/ui/mir/validate/critical-edge.rs
@@ -12,7 +12,7 @@ use core::intrinsics::mir::*;
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 #[inline(always)]
 pub fn f(a: u32) -> u32 {
-    mir!(
+    mir! {
         {
             match a {
                 0 => bb1,
@@ -27,5 +27,5 @@ pub fn f(a: u32) -> u32 {
             RET = 2;
             Return()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs
index 744e71e99b1..b46bb46952b 100644
--- a/tests/ui/mir/validate/noncleanup-cleanup.rs
+++ b/tests/ui/mir/validate/noncleanup-cleanup.rs
@@ -9,13 +9,12 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "built")]
 pub fn main() {
-    mir!(
+    mir! {
         {
             Call(RET = main(), ReturnTo(block), UnwindCleanup(block))
         }
         block = {
             Return()
         }
-    )
-
+    }
 }
diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs
index 5bf6b03c9e9..b2a0e92e068 100644
--- a/tests/ui/mir/validate/noncleanup-resume.rs
+++ b/tests/ui/mir/validate/noncleanup-resume.rs
@@ -9,9 +9,9 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "built")]
 pub fn main() {
-    mir!(
+    mir! {
         {
             UnwindResume()
         }
-    )
+    }
 }
diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs
index b5bf2604cce..24cf75e7d8e 100644
--- a/tests/ui/mir/validate/noncleanup-terminate.rs
+++ b/tests/ui/mir/validate/noncleanup-terminate.rs
@@ -9,9 +9,9 @@ use core::intrinsics::mir::*;
 
 #[custom_mir(dialect = "built")]
 pub fn main() {
-    mir!(
+    mir! {
         {
             UnwindTerminate(ReasonAbi)
         }
-    )
+    }
 }
diff --git a/tests/ui/object-safety/issue-106247.rs b/tests/ui/object-safety/issue-106247.rs
index 78bae568161..20a451a59a1 100644
--- a/tests/ui/object-safety/issue-106247.rs
+++ b/tests/ui/object-safety/issue-106247.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![deny(where_clauses_object_safety)]
-
 pub trait Trait {
     fn method(&self) where Self: Sync;
 }
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index 016ebfadd14..5ae15f32357 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -49,3 +49,7 @@ fn delta() {
 fn generic_with_maybe_sized<T: ?Sized>() -> usize {
     offset_of!(Delta<T>, z) //~ ERROR the size for values of type
 }
+
+fn illformed_tuple() {
+    offset_of!(([u8], u8), 1); //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index adfd16c6f2b..bcfe796897e 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -81,6 +81,15 @@ LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
 LL + fn generic_with_maybe_sized<T>() -> usize {
    |
 
-error: aborting due to 8 previous errors
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:54:16
+   |
+LL |     offset_of!(([u8], u8), 1);
+   |                ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-slice.rs b/tests/ui/offset-of/offset-of-slice.rs
new file mode 100644
index 00000000000..a0fe3198f68
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-slice.rs
@@ -0,0 +1,26 @@
+//@run-pass
+#![feature(offset_of_slice, offset_of_nested)]
+
+use std::mem::offset_of;
+
+#[repr(C)]
+struct S {
+    a: u8,
+    b: (u8, u8),
+    c: [i32],
+}
+
+#[repr(C)]
+struct T {
+    x: i8,
+    y: S,
+}
+
+type Tup = (i16, [i32]);
+
+fn main() {
+    assert_eq!(offset_of!(S, c), 4);
+    assert_eq!(offset_of!(T, y), 4);
+    assert_eq!(offset_of!(T, y.c), 8);
+    assert_eq!(offset_of!(Tup, 1), 4);
+}
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed b/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed
deleted file mode 100644
index aae71ede771..00000000000
--- a/tests/ui/parser/attribute/attr-binary-expr-ambigous.fixed
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ run-rustfix
-#![feature(stmt_expr_attributes)]
-#![allow(unused_assignments, unused_attributes)]
-
-fn main() {
-    let mut x = (#[deprecated] 1) + 2; //~ ERROR ambiguous
-
-    (#[deprecated] x) = 4; //~ ERROR ambiguous
-
-    x = (#[deprecated] 5) as i32; //~ ERROR ambiguous
-
-    let _r = (#[deprecated] 1)..6; //~ ERROR ambiguous
-
-    println!("{}", x);
-}
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs b/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs
deleted file mode 100644
index 613e01d743b..00000000000
--- a/tests/ui/parser/attribute/attr-binary-expr-ambigous.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ run-rustfix
-#![feature(stmt_expr_attributes)]
-#![allow(unused_assignments, unused_attributes)]
-
-fn main() {
-    let mut x = #[deprecated] 1 + 2; //~ ERROR ambiguous
-
-    #[deprecated] x = 4; //~ ERROR ambiguous
-
-    x = #[deprecated] 5 as i32; //~ ERROR ambiguous
-
-    let _r = #[deprecated] 1..6; //~ ERROR ambiguous
-
-    println!("{}", x);
-}
diff --git a/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr b/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr
deleted file mode 100644
index 0430570fd49..00000000000
--- a/tests/ui/parser/attribute/attr-binary-expr-ambigous.stderr
+++ /dev/null
@@ -1,46 +0,0 @@
-error: ambiguous outer attributes
-  --> $DIR/attr-binary-expr-ambigous.rs:6:17
-   |
-LL |     let mut x = #[deprecated] 1 + 2;
-   |                 ^^^^^^^^^^^^^^^^^^^
-   |
-help: wrap the expression in parentheses
-   |
-LL |     let mut x = (#[deprecated] 1) + 2;
-   |                 +               +
-
-error: ambiguous outer attributes
-  --> $DIR/attr-binary-expr-ambigous.rs:8:5
-   |
-LL |     #[deprecated] x = 4;
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-help: wrap the expression in parentheses
-   |
-LL |     (#[deprecated] x) = 4;
-   |     +               +
-
-error: ambiguous outer attributes
-  --> $DIR/attr-binary-expr-ambigous.rs:10:9
-   |
-LL |     x = #[deprecated] 5 as i32;
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: wrap the expression in parentheses
-   |
-LL |     x = (#[deprecated] 5) as i32;
-   |         +               +
-
-error: ambiguous outer attributes
-  --> $DIR/attr-binary-expr-ambigous.rs:12:14
-   |
-LL |     let _r = #[deprecated] 1..6;
-   |              ^^^^^^^^^^^^^^^^^^
-   |
-help: wrap the expression in parentheses
-   |
-LL |     let _r = (#[deprecated] 1)..6;
-   |              +               +
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/parser/duplicate-visibility.rs b/tests/ui/parser/duplicate-visibility.rs
index 54955944c7d..f0ee60873da 100644
--- a/tests/ui/parser/duplicate-visibility.rs
+++ b/tests/ui/parser/duplicate-visibility.rs
@@ -2,8 +2,8 @@ fn main() {}
 
 extern "C" { //~ NOTE while parsing this item list starting here
     pub pub fn foo();
-    //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
-    //~| NOTE expected one of 8 possible tokens
+    //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
+    //~| NOTE expected one of 9 possible tokens
     //~| HELP there is already a visibility modifier, remove one
     //~| NOTE explicit visibility first seen here
 } //~ NOTE the item list ends here
diff --git a/tests/ui/parser/duplicate-visibility.stderr b/tests/ui/parser/duplicate-visibility.stderr
index b578b1fe26e..0d1421ee7f4 100644
--- a/tests/ui/parser/duplicate-visibility.stderr
+++ b/tests/ui/parser/duplicate-visibility.stderr
@@ -1,4 +1,4 @@
-error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
+error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
   --> $DIR/duplicate-visibility.rs:4:9
    |
 LL | extern "C" {
@@ -6,7 +6,7 @@ LL | extern "C" {
 LL |     pub pub fn foo();
    |         ^^^
    |         |
-   |         expected one of 8 possible tokens
+   |         expected one of 9 possible tokens
    |         help: there is already a visibility modifier, remove one
 ...
 LL | }
diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs
index 6ed173b6854..5907ac05260 100644
--- a/tests/ui/parser/fn-header-semantic-fail.rs
+++ b/tests/ui/parser/fn-header-semantic-fail.rs
@@ -44,13 +44,14 @@ fn main() {
 
     extern "C" {
         async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers
-        unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers
+        unsafe fn fe2(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
         const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
         extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers
-        const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks
-        //~| ERROR functions in `extern` blocks
+        const async unsafe extern "C" fn fe5();
+        //~^ ERROR functions in `extern` blocks
         //~| ERROR functions in `extern` blocks
         //~| ERROR functions in `extern` blocks
         //~| ERROR functions cannot be both `const` and `async`
+        //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers
     }
 }
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index cfc54839eb7..abaa6527b0a 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -78,14 +78,14 @@ LL |     extern "C" {
 LL |         async fn fe1();
    |         ^^^^^ help: remove this qualifier
 
-error: functions in `extern` blocks cannot have qualifiers
+error: items in unadorned `extern` blocks cannot have safety qualifiers
   --> $DIR/fn-header-semantic-fail.rs:47:9
    |
 LL |     extern "C" {
-   |     ---------- in this `extern` block
+   |     ---------- help: add unsafe to this `extern` block
 LL |         async fn fe1();
 LL |         unsafe fn fe2();
-   |         ^^^^^^ help: remove this qualifier
+   |         ^^^^^^^^^^^^^^^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:48:9
@@ -105,14 +105,14 @@ LL |     extern "C" {
 LL |         extern "C" fn fe4();
    |         ^^^^^^^^^^ help: remove this qualifier
 
-error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:50:21
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:50:9
    |
 LL |     extern "C" {
-   |     ---------- in this `extern` block
+   |     ---------- help: add unsafe to this `extern` block
 ...
 LL |         const async unsafe extern "C" fn fe5();
-   |                     ^^^^^^ help: remove this qualifier
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/fn-header-semantic-fail.rs:50:15
diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
index f6aa39df27d..1c28c0632fa 100644
--- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
+++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
@@ -5,3 +5,4 @@ struct Apple((Apple, Option(Banana ? Citron)));
 //~| ERROR expected one of `)` or `,`, found `Citron`
 //~| ERROR cannot find type `Citron` in this scope [E0412]
 //~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214]
+//~| ERROR `Apple` has infinite size
diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
index 71d2d7b7975..b0d8b03ae08 100644
--- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
+++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
@@ -34,7 +34,18 @@ help: use angle brackets instead
 LL | struct Apple((Apple, Option<Banana ? Citron>));
    |                            ~               ~
 
-error: aborting due to 4 previous errors
+error[E0072]: recursive type `Apple` has infinite size
+  --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1
+   |
+LL | struct Apple((Apple, Option(Banana ? Citron)));
+   | ^^^^^^^^^^^^  ----- recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL | struct Apple((Box<Apple>, Option(Banana ? Citron)));
+   |               ++++     +
+
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0214, E0412.
-For more information about an error, try `rustc --explain E0214`.
+Some errors have detailed explanations: E0072, E0214, E0412.
+For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/parser/issues/issue-76437-async.rs b/tests/ui/parser/issues/issue-76437-async.rs
index 497e269d634..3fafaad0277 100644
--- a/tests/ui/parser/issues/issue-76437-async.rs
+++ b/tests/ui/parser/issues/issue-76437-async.rs
@@ -2,6 +2,6 @@
 
 mod t {
     async pub fn t() {}
-    //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
     //~| HELP visibility `pub` must come before `async`
 }
diff --git a/tests/ui/parser/issues/issue-76437-async.stderr b/tests/ui/parser/issues/issue-76437-async.stderr
index 7f2df5c8736..483599135f5 100644
--- a/tests/ui/parser/issues/issue-76437-async.stderr
+++ b/tests/ui/parser/issues/issue-76437-async.stderr
@@ -1,10 +1,10 @@
-error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-76437-async.rs:4:11
    |
 LL |     async pub fn t() {}
    |     ------^^^
    |     |     |
-   |     |     expected one of `extern`, `fn`, or `unsafe`
+   |     |     expected one of `extern`, `fn`, `safe`, or `unsafe`
    |     help: visibility `pub` must come before `async`: `pub async`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-76437-const-async.rs b/tests/ui/parser/issues/issue-76437-const-async.rs
index 45d53c63933..d8eb6cdecf1 100644
--- a/tests/ui/parser/issues/issue-76437-const-async.rs
+++ b/tests/ui/parser/issues/issue-76437-const-async.rs
@@ -2,6 +2,6 @@
 
 mod t {
     const async pub fn t() {}
-    //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
     //~| HELP visibility `pub` must come before `const async`
 }
diff --git a/tests/ui/parser/issues/issue-76437-const-async.stderr b/tests/ui/parser/issues/issue-76437-const-async.stderr
index a9acccdce18..81fa8a5f557 100644
--- a/tests/ui/parser/issues/issue-76437-const-async.stderr
+++ b/tests/ui/parser/issues/issue-76437-const-async.stderr
@@ -1,10 +1,10 @@
-error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-76437-const-async.rs:4:17
    |
 LL |     const async pub fn t() {}
    |     ------------^^^
    |     |           |
-   |     |           expected one of `extern`, `fn`, or `unsafe`
+   |     |           expected one of `extern`, `fn`, `safe`, or `unsafe`
    |     help: visibility `pub` must come before `const async`: `pub const async`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-76437-const.rs b/tests/ui/parser/issues/issue-76437-const.rs
index c3431e3567b..dad63f137c0 100644
--- a/tests/ui/parser/issues/issue-76437-const.rs
+++ b/tests/ui/parser/issues/issue-76437-const.rs
@@ -2,6 +2,6 @@
 
 mod t {
     const pub fn t() {}
-    //~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+    //~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
     //~| HELP visibility `pub` must come before `const`
 }
diff --git a/tests/ui/parser/issues/issue-76437-const.stderr b/tests/ui/parser/issues/issue-76437-const.stderr
index 4c36d773d60..005a27b7c24 100644
--- a/tests/ui/parser/issues/issue-76437-const.stderr
+++ b/tests/ui/parser/issues/issue-76437-const.stderr
@@ -1,10 +1,10 @@
-error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-76437-const.rs:4:11
    |
 LL |     const pub fn t() {}
    |     ------^^^
    |     |     |
-   |     |     expected one of `async`, `extern`, `fn`, or `unsafe`
+   |     |     expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
    |     help: visibility `pub` must come before `const`: `pub const`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-86895.rs b/tests/ui/parser/issues/issue-86895.rs
index 4cd09843107..3e5dc41e2f4 100644
--- a/tests/ui/parser/issues/issue-86895.rs
+++ b/tests/ui/parser/issues/issue-86895.rs
@@ -1,3 +1,3 @@
 const pub () {}
-//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`
+//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
 pub fn main() {}
diff --git a/tests/ui/parser/issues/issue-86895.stderr b/tests/ui/parser/issues/issue-86895.stderr
index dcde7242d39..14183ee0a5c 100644
--- a/tests/ui/parser/issues/issue-86895.stderr
+++ b/tests/ui/parser/issues/issue-86895.stderr
@@ -1,8 +1,8 @@
-error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-86895.rs:1:7
    |
 LL | const pub () {}
-   |       ^^^ expected one of `async`, `extern`, `fn`, or `unsafe`
+   |       ^^^ expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs
index 694729376ba..e6235b1e892 100644
--- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs
+++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs
@@ -3,8 +3,8 @@
 // Test that even when `const` is already present, the proposed fix is to remove the second `const`
 
 const async const fn test() {}
-//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
-//~| NOTE expected one of `extern`, `fn`, or `unsafe`
+//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
+//~| NOTE expected one of `extern`, `fn`, `safe`, or `unsafe`
 //~| HELP `const` already used earlier, remove this one
 //~| NOTE `const` first seen here
 //~| ERROR functions cannot be both `const` and `async`
diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr
index 4c55179ce23..ed2e4d81549 100644
--- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr
+++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr
@@ -1,10 +1,10 @@
-error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
+error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
   --> $DIR/const-async-const.rs:5:13
    |
 LL | const async const fn test() {}
    |             ^^^^^
    |             |
-   |             expected one of `extern`, `fn`, or `unsafe`
+   |             expected one of `extern`, `fn`, `safe`, or `unsafe`
    |             help: `const` already used earlier, remove this one
    |
 note: `const` first seen here
diff --git a/tests/ui/parser/issues/issue-87694-duplicated-pub.rs b/tests/ui/parser/issues/issue-87694-duplicated-pub.rs
index e3ea61dc4ad..816c8ff2a9f 100644
--- a/tests/ui/parser/issues/issue-87694-duplicated-pub.rs
+++ b/tests/ui/parser/issues/issue-87694-duplicated-pub.rs
@@ -1,5 +1,5 @@
 pub const pub fn test() {}
-//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
-//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe`
+//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
+//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
 //~| HELP there is already a visibility modifier, remove one
 //~| NOTE explicit visibility first seen here
diff --git a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr
index a210238652a..dd75f32f68f 100644
--- a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr
+++ b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr
@@ -1,10 +1,10 @@
-error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-87694-duplicated-pub.rs:1:11
    |
 LL | pub const pub fn test() {}
    |           ^^^
    |           |
-   |           expected one of `async`, `extern`, `fn`, or `unsafe`
+   |           expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
    |           help: there is already a visibility modifier, remove one
    |
 note: explicit visibility first seen here
diff --git a/tests/ui/parser/issues/issue-87694-misplaced-pub.rs b/tests/ui/parser/issues/issue-87694-misplaced-pub.rs
index 3f824617cad..b5b0bc5b2fc 100644
--- a/tests/ui/parser/issues/issue-87694-misplaced-pub.rs
+++ b/tests/ui/parser/issues/issue-87694-misplaced-pub.rs
@@ -1,5 +1,5 @@
 const pub fn test() {}
-//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
-//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe`
+//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
+//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
 //~| HELP visibility `pub` must come before `const`
 //~| SUGGESTION pub const
diff --git a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr
index 6f686a7e504..d35e09dceaf 100644
--- a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr
+++ b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr
@@ -1,10 +1,10 @@
-error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
   --> $DIR/issue-87694-misplaced-pub.rs:1:7
    |
 LL | const pub fn test() {}
    | ------^^^
    | |     |
-   | |     expected one of `async`, `extern`, `fn`, or `unsafe`
+   | |     expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
    | help: visibility `pub` must come before `const`: `pub const`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/parser/macro/macro-repeat.stderr b/tests/ui/parser/macro/macro-repeat.stderr
index ade2bbf9b0b..ba722ab6cf9 100644
--- a/tests/ui/parser/macro/macro-repeat.stderr
+++ b/tests/ui/parser/macro/macro-repeat.stderr
@@ -1,10 +1,10 @@
-error: variable 'v' is still repeating at this depth
+error: variable `v` is still repeating at this depth
   --> $DIR/macro-repeat.rs:3:9
    |
 LL |         $v
    |         ^^
 
-error: variable 'v' is still repeating at this depth
+error: variable `v` is still repeating at this depth
   --> $DIR/macro-repeat.rs:3:9
    |
 LL |         $v
diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs
index d6c578681cc..3ad9ba006d3 100644
--- a/tests/ui/parser/no-const-fn-in-extern-block.rs
+++ b/tests/ui/parser/no-const-fn-in-extern-block.rs
@@ -3,7 +3,7 @@ extern "C" {
     //~^ ERROR functions in `extern` blocks cannot have qualifiers
     const unsafe fn bar();
     //~^ ERROR functions in `extern` blocks cannot have qualifiers
-    //~| ERROR functions in `extern` blocks cannot have qualifiers
+    //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers
 }
 
 fn main() {}
diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr
index 948ce669112..892024ce893 100644
--- a/tests/ui/parser/no-const-fn-in-extern-block.stderr
+++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr
@@ -6,14 +6,14 @@ LL | extern "C" {
 LL |     const fn foo();
    |     ^^^^^ help: remove this qualifier
 
-error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/no-const-fn-in-extern-block.rs:4:11
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/no-const-fn-in-extern-block.rs:4:5
    |
 LL | extern "C" {
-   | ---------- in this `extern` block
+   | ---------- help: add unsafe to this `extern` block
 ...
 LL |     const unsafe fn bar();
-   |           ^^^^^^ help: remove this qualifier
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: functions in `extern` blocks cannot have qualifiers
   --> $DIR/no-const-fn-in-extern-block.rs:4:5
diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr
index e0ea8ec24dc..e29b6c1c666 100644
--- a/tests/ui/parser/recover/recover-range-pats.stderr
+++ b/tests/ui/parser/recover/recover-range-pats.stderr
@@ -316,9 +316,6 @@ LL |     if let X.. .0 = 0 {}
    |            |   |
    |            |   expected `u8`, found floating-point number
    |            this is of type `u8`
-   |
-   = note: expected type `u8`
-              found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:31:12
@@ -353,9 +350,6 @@ LL |     if let X..=.0 = 0 {}
    |            |   |
    |            |   expected `u8`, found floating-point number
    |            this is of type `u8`
-   |
-   = note: expected type `u8`
-              found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:52:12
@@ -390,9 +384,6 @@ LL |     if let X... .0 = 0 {}
    |            |    |
    |            |    expected `u8`, found floating-point number
    |            this is of type `u8`
-   |
-   = note: expected type `u8`
-              found type `{float}`
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:71:12
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
index a851300a982..e9c89807fa5 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
@@ -1,7 +1,8 @@
 // Regression test for issues #100790 and #106439.
 //@ run-rustfix
 
-pub struct Example(#[allow(dead_code)] usize)
+#[allow(dead_code)]
+pub struct Example(usize)
 where
     (): Sized;
 //~^^^ ERROR where clauses are not allowed before tuple struct bodies
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
index 10f435859f1..3bd0f51ec2c 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
@@ -1,10 +1,11 @@
 // Regression test for issues #100790 and #106439.
 //@ run-rustfix
 
+#[allow(dead_code)]
 pub struct Example
 where
     (): Sized,
-(#[allow(dead_code)] usize);
+(usize);
 //~^^^ ERROR where clauses are not allowed before tuple struct bodies
 
 struct _Demo
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
index ddbf237e866..77eafa6bea3 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
@@ -1,23 +1,23 @@
 error: where clauses are not allowed before tuple struct bodies
-  --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1
+  --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:6:1
    |
 LL |   pub struct Example
    |              ------- while parsing this tuple struct
 LL | / where
 LL | |     (): Sized,
    | |______________^ unexpected where clause
-LL |   (#[allow(dead_code)] usize);
-   |   --------------------------- the struct body
+LL |   (usize);
+   |   ------- the struct body
    |
 help: move the body before the where clause
    |
-LL ~ pub struct Example(#[allow(dead_code)] usize)
+LL ~ pub struct Example(usize)
 LL | where
 LL ~     (): Sized;
    |
 
 error: where clauses are not allowed before tuple struct bodies
-  --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1
+  --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:12:1
    |
 LL |   struct _Demo
    |          ----- while parsing this tuple struct
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs
index 77856fb6734..0b63a993c5b 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.rs
+++ b/tests/ui/parser/unsafe-foreign-mod-2.rs
@@ -1,8 +1,8 @@
 extern "C" unsafe {
-               //~^ ERROR expected `{`, found keyword `unsafe`
-               //~| ERROR extern block cannot be declared unsafe
+    //~^ ERROR expected `{`, found keyword `unsafe`
+    //~| ERROR extern block cannot be declared unsafe
     unsafe fn foo();
-        //~^ ERROR functions in `extern` blocks cannot have qualifiers
+    //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
 }
 
 fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr
index fc05184f018..e59352395ed 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.stderr
+++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr
@@ -10,14 +10,14 @@ error: extern block cannot be declared unsafe
 LL | extern "C" unsafe {
    |            ^^^^^^
 
-error: functions in `extern` blocks cannot have qualifiers
+error: items in unadorned `extern` blocks cannot have safety qualifiers
   --> $DIR/unsafe-foreign-mod-2.rs:4:5
    |
 LL | extern "C" unsafe {
-   | ----------------- in this `extern` block
+   | ----------------- help: add unsafe to this `extern` block
 ...
 LL |     unsafe fn foo();
-   |     ^^^^^^ help: remove this qualifier
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
deleted file mode 100644
index 15c542e6bf1..00000000000
--- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ edition: 2024
-//@ compile-flags: -Zunstable-options
-
-struct Foo(u8);
-
-fn main() {
-    let Foo(mut a) = &Foo(0);
-    a = &42;
-    //~^ ERROR: mismatched types
-
-    let Foo(mut a) = &mut Foo(0);
-    a = &mut 42;
-    //~^ ERROR: mismatched types
-}
diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
deleted file mode 100644
index 6d0a034be21..00000000000
--- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:8:9
-   |
-LL |     let Foo(mut a) = &Foo(0);
-   |             ----- expected due to the type of this binding
-LL |     a = &42;
-   |         ^^^ expected `u8`, found `&{integer}`
-   |
-help: consider removing the borrow
-   |
-LL -     a = &42;
-LL +     a = 42;
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:12:9
-   |
-LL |     let Foo(mut a) = &mut Foo(0);
-   |             ----- expected due to the type of this binding
-LL |     a = &mut 42;
-   |         ^^^^^^^ expected `u8`, found `&mut {integer}`
-   |
-help: consider removing the borrow
-   |
-LL -     a = &mut 42;
-LL +     a = 42;
-   |
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/match_ergonomics_2024.fixed b/tests/ui/pattern/match_ergonomics_2024.fixed
index d8dbcb217c0..1ec2b5a214b 100644
--- a/tests/ui/pattern/match_ergonomics_2024.fixed
+++ b/tests/ui/pattern/match_ergonomics_2024.fixed
@@ -2,7 +2,7 @@
 //@ run-rustfix
 //@ rustfix-only-machine-applicable
 //@ aux-build:match_ergonomics_2024_macros.rs
-#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 #![deny(rust_2024_incompatible_pat)]
 
diff --git a/tests/ui/pattern/match_ergonomics_2024.rs b/tests/ui/pattern/match_ergonomics_2024.rs
index 38dc0c8bebb..c9f992c12d4 100644
--- a/tests/ui/pattern/match_ergonomics_2024.rs
+++ b/tests/ui/pattern/match_ergonomics_2024.rs
@@ -2,7 +2,7 @@
 //@ run-rustfix
 //@ rustfix-only-machine-applicable
 //@ aux-build:match_ergonomics_2024_macros.rs
-#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 #![deny(rust_2024_incompatible_pat)]
 
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
index befa49fdc24..282e0ef95d2 100644
--- a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 //@ compile-flags: -Zunstable-options
-#![feature(mut_preserve_binding_mode_2024)]
+#![feature(ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features)]
 
 struct Foo(u8);
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
index 5454962e16c..19aa73573b4 100644
--- a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ edition: 2024
 //@ compile-flags: -Zunstable-options
-#![feature(mut_preserve_binding_mode_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 
 struct Foo(u8);
diff --git a/tests/ui/pattern/no_ref_mut_behind_and.rs b/tests/ui/pattern/no_ref_mut_behind_and.rs
new file mode 100644
index 00000000000..c18d64904d0
--- /dev/null
+++ b/tests/ui/pattern/no_ref_mut_behind_and.rs
@@ -0,0 +1,9 @@
+//@ edition: 2021
+//@ run-pass
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+fn main() {
+    let &[[x]] = &[&mut [42]];
+    let _: &i32 = x;
+}
diff --git a/tests/ui/polymorphization/abi_mismatch.rs b/tests/ui/polymorphization/abi_mismatch.rs
new file mode 100644
index 00000000000..22c2c162d1c
--- /dev/null
+++ b/tests/ui/polymorphization/abi_mismatch.rs
@@ -0,0 +1,20 @@
+//! This test used to ICE: #123917
+//! The reason was that while the AST knows about two fields
+//! named `ptr`, only one exists at the layout level, so accessing
+//! `_extra_field` would use an oob index
+//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on
+
+struct NonNull<T>(*mut T);
+
+struct Token<T> {
+    ptr: *mut T,
+    ptr: NonNull<T>,
+    //~^ ERROR: `ptr` is already declared
+    _extra_field: (),
+}
+
+fn tokenize<T>(item: *mut T) -> Token<T> {
+    Token { ptr: NonNull(item), _extra_field: () }
+}
+
+fn main() {}
diff --git a/tests/ui/polymorphization/abi_mismatch.stderr b/tests/ui/polymorphization/abi_mismatch.stderr
new file mode 100644
index 00000000000..e96c737f777
--- /dev/null
+++ b/tests/ui/polymorphization/abi_mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0124]: field `ptr` is already declared
+  --> $DIR/abi_mismatch.rs:11:5
+   |
+LL |     ptr: *mut T,
+   |     ----------- `ptr` first declared here
+LL |     ptr: NonNull<T>,
+   |     ^^^^^^^^^^^^^^^ field already declared
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/tests/ui/privacy/ufc-method-call.different_name.stderr b/tests/ui/privacy/ufc-method-call.different_name.stderr
new file mode 100644
index 00000000000..16496c480dd
--- /dev/null
+++ b/tests/ui/privacy/ufc-method-call.different_name.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no function or associated item named `foo` found for struct `Foo<B>` in the current scope
+  --> $DIR/ufc-method-call.rs:27:27
+   |
+LL |     pub struct Foo<T>(T);
+   |     ----------------- function or associated item `foo` not found for this struct
+...
+LL |     test::Foo::<test::B>::foo();
+   |                           ^^^ function or associated item not found in `Foo<B>`
+   |
+   = note: the function or associated item was found for
+           - `Foo<A>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/privacy/ufc-method-call.rs b/tests/ui/privacy/ufc-method-call.rs
new file mode 100644
index 00000000000..525d9a9eee9
--- /dev/null
+++ b/tests/ui/privacy/ufc-method-call.rs
@@ -0,0 +1,30 @@
+//! This test used to report that the method call cannot
+//! call the private method `Foo<A>::foo`, even though the user
+//! explicitly selected `Foo<B>::foo`. This is because we only
+//! looked for methods of the right name, without properly checking
+//! the `Self` type
+
+//@ revisions: same_name different_name
+
+pub mod test {
+    pub struct A;
+    pub struct B;
+    pub struct Foo<T>(T);
+
+    impl Foo<A> {
+        fn foo() {}
+    }
+
+    impl Foo<B> {
+        #[cfg(same_name)]
+        fn foo() {}
+        #[cfg(different_name)]
+        fn bar() {}
+    }
+}
+
+fn main() {
+    test::Foo::<test::B>::foo();
+    //[same_name]~^ ERROR associated function `foo` is private
+    //[different_name]~^^ ERROR no function or associated item named `foo` found for struct `Foo<B>`
+}
diff --git a/tests/ui/issues/issue-53498.stderr b/tests/ui/privacy/ufc-method-call.same_name.stderr
index 61a1aedf508..194ba42cbf9 100644
--- a/tests/ui/issues/issue-53498.stderr
+++ b/tests/ui/privacy/ufc-method-call.same_name.stderr
@@ -1,5 +1,5 @@
 error[E0624]: associated function `foo` is private
-  --> $DIR/issue-53498.rs:16:27
+  --> $DIR/ufc-method-call.rs:27:27
    |
 LL |         fn foo() {}
    |         -------- private associated function defined here
diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs
index cd9cce7ec3e..20467301ae1 100644
--- a/tests/ui/privacy/where-priv-type.rs
+++ b/tests/ui/privacy/where-priv-type.rs
@@ -11,55 +11,46 @@ pub struct PubTy;
 pub struct PubTyGeneric<T>(T);
 pub trait PubTr {}
 impl PubTr for PrivTy {}
-pub trait PubTrWithAssocTy { type AssocTy; }
-impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; }
-
+pub trait PubTrWithAssocTy {
+    type AssocTy;
+}
+impl PubTrWithAssocTy for PrivTy {
+    type AssocTy = PrivTy;
+}
 
 pub struct S
 //~^ WARNING type `PrivTy` is more private than the item `S`
 where
-    PrivTy:
-{}
-
+    PrivTy:, {}
 
 pub enum E
 //~^ WARNING type `PrivTy` is more private than the item `E`
 where
-    PrivTy:
-{}
-
+    PrivTy:, {}
 
 pub fn f()
 //~^ WARNING type `PrivTy` is more private than the item `f`
 where
-    PrivTy:
-{}
-
+    PrivTy:,
+{
+}
 
 impl S
 //~^ WARNING type `PrivTy` is more private than the item `S`
 where
-    PrivTy:
+    PrivTy:,
 {
     pub fn f()
     //~^ WARNING type `PrivTy` is more private than the item `S::f`
     where
-        PrivTy:
-    {}
+        PrivTy:,
+    {
+    }
 }
 
+impl PubTr for PubTy where PrivTy: {}
 
-impl PubTr for PubTy
-where
-    PrivTy:
-{}
-
-
-impl<T> PubTr for PubTyGeneric<T>
-where
-    T: PubTrWithAssocTy<AssocTy=PrivTy>
-{}
-
+impl<T> PubTr for PubTyGeneric<T> where T: PubTrWithAssocTy<AssocTy = PrivTy> {}
 
 pub struct Const<const U: u8>;
 
@@ -70,10 +61,11 @@ pub trait Trait {
 
 impl<const U: u8> Trait for Const<U>
 where
-    Const<{ my_const_fn(U) }>: ,
+    Const<{ my_const_fn(U) }>:,
 {
     type AssocTy = Const<{ my_const_fn(U) }>;
     //~^ ERROR private type
+    //~| ERROR private type
     fn assoc_fn() -> Self::AssocTy {
         Const
     }
diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr
index 126330b14a6..08963e07c35 100644
--- a/tests/ui/privacy/where-priv-type.stderr
+++ b/tests/ui/privacy/where-priv-type.stderr
@@ -1,5 +1,5 @@
 warning: type `PrivTy` is more private than the item `S`
-  --> $DIR/where-priv-type.rs:18:1
+  --> $DIR/where-priv-type.rs:21:1
    |
 LL | pub struct S
    | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub`
@@ -12,7 +12,7 @@ LL | struct PrivTy;
    = note: `#[warn(private_bounds)]` on by default
 
 warning: type `PrivTy` is more private than the item `E`
-  --> $DIR/where-priv-type.rs:25:1
+  --> $DIR/where-priv-type.rs:26:1
    |
 LL | pub enum E
    | ^^^^^^^^^^ enum `E` is reachable at visibility `pub`
@@ -24,13 +24,13 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 warning: type `PrivTy` is more private than the item `f`
-  --> $DIR/where-priv-type.rs:32:1
+  --> $DIR/where-priv-type.rs:31:1
    |
 LL | / pub fn f()
 LL | |
 LL | | where
-LL | |     PrivTy:
-   | |___________^ function `f` is reachable at visibility `pub`
+LL | |     PrivTy:,
+   | |____________^ function `f` is reachable at visibility `pub`
    |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:8:1
@@ -39,13 +39,13 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 warning: type `PrivTy` is more private than the item `S`
-  --> $DIR/where-priv-type.rs:39:1
+  --> $DIR/where-priv-type.rs:38:1
    |
 LL | / impl S
 LL | |
 LL | | where
-LL | |     PrivTy:
-   | |___________^ implementation `S` is reachable at visibility `pub`
+LL | |     PrivTy:,
+   | |____________^ implementation `S` is reachable at visibility `pub`
    |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:8:1
@@ -54,13 +54,13 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 warning: type `PrivTy` is more private than the item `S::f`
-  --> $DIR/where-priv-type.rs:44:5
+  --> $DIR/where-priv-type.rs:43:5
    |
 LL | /     pub fn f()
 LL | |
 LL | |     where
-LL | |         PrivTy:
-   | |_______________^ associated function `S::f` is reachable at visibility `pub`
+LL | |         PrivTy:,
+   | |________________^ associated function `S::f` is reachable at visibility `pub`
    |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:8:1
@@ -69,7 +69,7 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
-  --> $DIR/where-priv-type.rs:75:5
+  --> $DIR/where-priv-type.rs:66:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
    |     ^^^^^^^^^^^^ can't leak private type
@@ -77,6 +77,17 @@ LL |     type AssocTy = Const<{ my_const_fn(U) }>;
 LL | const fn my_const_fn(val: u8) -> u8 {
    | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
 
-error: aborting due to 1 previous error; 5 warnings emitted
+error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
+  --> $DIR/where-priv-type.rs:66:5
+   |
+LL |     type AssocTy = Const<{ my_const_fn(U) }>;
+   |     ^^^^^^^^^^^^ can't leak private type
+...
+LL | const fn my_const_fn(val: u8) -> u8 {
+   | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors; 5 warnings emitted
 
 For more information about this error, try `rustc --explain E0446`.
diff --git a/tests/ui/proc-macro/issue-81555.rs b/tests/ui/proc-macro/issue-81555.rs
index b337ab7ce37..7a61a31952f 100644
--- a/tests/ui/proc-macro/issue-81555.rs
+++ b/tests/ui/proc-macro/issue-81555.rs
@@ -10,5 +10,6 @@ use test_macros::identity_attr;
 fn main() {
     let _x;
     let y = ();
-    (#[identity_attr] _x) = y;
+    #[identity_attr]
+    _x = y;
 }
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
index 118882f73a3..889cd0c90eb 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
+++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
@@ -1,185 +1,6 @@
 error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
    |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: older versions of the `rental` crate no longer compile; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
 
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 8 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stdout b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout
deleted file mode 100644
index 3d793d2a014..00000000000
--- a/tests/ui/proc-macro/pretty-print-hack-show.local.stdout
+++ /dev/null
@@ -1,44 +0,0 @@
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "enum",
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
-    },
-    Ident {
-        ident: "ProceduralMasqueradeDummyType",
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
-    },
-    Group {
-        delimiter: Brace,
-        stream: TokenStream [
-            Ident {
-                ident: "Input",
-                span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
-            },
-        ],
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
-    },
-]
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "enum",
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
-    },
-    Ident {
-        ident: "ProceduralMasqueradeDummyType",
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
-    },
-    Group {
-        delimiter: Brace,
-        stream: TokenStream [
-            Ident {
-                ident: "Input",
-                span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
-            },
-        ],
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
-    },
-]
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
index 118882f73a3..889cd0c90eb 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
+++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
@@ -1,185 +1,6 @@
 error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
    |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: older versions of the `rental` crate no longer compile; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
 
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 8 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
-  --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
-   |
-LL | enum ProceduralMasqueradeDummyType {
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-   = note: `#[deny(proc_macro_back_compat)]` on by default
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout
deleted file mode 100644
index 3d793d2a014..00000000000
--- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout
+++ /dev/null
@@ -1,44 +0,0 @@
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "enum",
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
-    },
-    Ident {
-        ident: "ProceduralMasqueradeDummyType",
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
-    },
-    Group {
-        delimiter: Brace,
-        stream: TokenStream [
-            Ident {
-                ident: "Input",
-                span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
-            },
-        ],
-        span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
-    },
-]
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
-    Ident {
-        ident: "enum",
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
-    },
-    Ident {
-        ident: "ProceduralMasqueradeDummyType",
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
-    },
-    Group {
-        delimiter: Brace,
-        stream: TokenStream [
-            Ident {
-                ident: "Input",
-                span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
-            },
-        ],
-        span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
-    },
-]
diff --git a/tests/ui/pub/pub-ident-struct-4.fixed b/tests/ui/pub/pub-ident-struct-4.fixed
index 5fedbb72437..a62ece43ece 100644
--- a/tests/ui/pub/pub-ident-struct-4.fixed
+++ b/tests/ui/pub/pub-ident-struct-4.fixed
@@ -1,6 +1,7 @@
 //@ run-rustfix
 
-pub struct T(#[allow(dead_code)] String);
+#[allow(dead_code)]
+pub struct T(String);
 //~^ ERROR missing `struct` for struct definition
 
 fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.rs b/tests/ui/pub/pub-ident-struct-4.rs
index 5c721c25a78..0d56a31beaf 100644
--- a/tests/ui/pub/pub-ident-struct-4.rs
+++ b/tests/ui/pub/pub-ident-struct-4.rs
@@ -1,6 +1,7 @@
 //@ run-rustfix
 
-pub T(#[allow(dead_code)] String);
+#[allow(dead_code)]
+pub T(String);
 //~^ ERROR missing `struct` for struct definition
 
 fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr
index 5fbb02c8673..ec136783211 100644
--- a/tests/ui/pub/pub-ident-struct-4.stderr
+++ b/tests/ui/pub/pub-ident-struct-4.stderr
@@ -1,12 +1,12 @@
 error: missing `struct` for struct definition
-  --> $DIR/pub-ident-struct-4.rs:3:4
+  --> $DIR/pub-ident-struct-4.rs:4:4
    |
-LL | pub T(#[allow(dead_code)] String);
+LL | pub T(String);
    |    ^
    |
 help: add `struct` here to parse `T` as a public struct
    |
-LL | pub struct T(#[allow(dead_code)] String);
+LL | pub struct T(String);
    |     ++++++
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.rs b/tests/ui/pub/pub-reexport-priv-extern-crate.rs
index dd5cd420fa5..fb495be4001 100644
--- a/tests/ui/pub/pub-reexport-priv-extern-crate.rs
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.rs
@@ -1,5 +1,5 @@
 extern crate core;
-pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported
+pub use core as reexported_core; //~ ERROR `core` is private and cannot be re-exported
                                  //~^ WARN this was previously accepted
 
 mod foo1 {
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
index 3fa5b0f9aef..915d07fd08a 100644
--- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -22,7 +22,7 @@ note: the crate import `core` is defined here
 LL |         extern crate core;
    |         ^^^^^^^^^^^^^^^^^^
 
-error[E0365]: extern crate `core` is private, and cannot be re-exported, consider declaring with `pub`
+error[E0365]: extern crate `core` is private and cannot be re-exported
   --> $DIR/pub-reexport-priv-extern-crate.rs:2:9
    |
 LL | pub use core as reexported_core;
@@ -31,6 +31,10 @@ LL | pub use core as reexported_core;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
    = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
+help: consider making the `extern crate` item publicly accessible
+   |
+LL | pub extern crate core;
+   | +++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/regions/regions-issue-21422.rs b/tests/ui/regions/regions-issue-21422.rs
index 54beed9b3ac..67852a6f5de 100644
--- a/tests/ui/regions/regions-issue-21422.rs
+++ b/tests/ui/regions/regions-issue-21422.rs
@@ -5,6 +5,7 @@
 
 //@ pretty-expanded FIXME #23616
 
+#[allow(dead_code)]
 pub struct P<'a> {
     _ptr: *const &'a u8,
 }
diff --git a/tests/ui/resolve/filter-intrinsics.rs b/tests/ui/resolve/filter-intrinsics.rs
index c0956ef85af..8d6d22817dc 100644
--- a/tests/ui/resolve/filter-intrinsics.rs
+++ b/tests/ui/resolve/filter-intrinsics.rs
@@ -1,6 +1,6 @@
 fn main() {
-    // Should suggest only `std::mem::size_of`
-    let _ = size_of::<usize>();
+    // Should suggest only `std::mem::transmute`
+    let _ = transmute::<usize>();
     //~^ ERROR cannot find
 
     // Should suggest `std::intrinsics::fabsf64`,
diff --git a/tests/ui/resolve/filter-intrinsics.stderr b/tests/ui/resolve/filter-intrinsics.stderr
index cc1092dd0cf..9c9e92f6d4f 100644
--- a/tests/ui/resolve/filter-intrinsics.stderr
+++ b/tests/ui/resolve/filter-intrinsics.stderr
@@ -1,12 +1,12 @@
-error[E0425]: cannot find function `size_of` in this scope
+error[E0425]: cannot find function `transmute` in this scope
   --> $DIR/filter-intrinsics.rs:3:13
    |
-LL |     let _ = size_of::<usize>();
-   |             ^^^^^^^ not found in this scope
+LL |     let _ = transmute::<usize>();
+   |             ^^^^^^^^^ not found in this scope
    |
 help: consider importing this function
    |
-LL + use std::mem::size_of;
+LL + use std::mem::transmute;
    |
 
 error[E0425]: cannot find function `fabsf64` in this scope
diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr
index 9d0439d9d87..730fd6d6026 100644
--- a/tests/ui/resolve/issue-82865.stderr
+++ b/tests/ui/resolve/issue-82865.stderr
@@ -15,13 +15,6 @@ LL |     Box::z
 LL |     mac!();
    |     ------ in this macro invocation
    |
-note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
-      Box::<T>::new
-      Box::<T>::new_uninit
-      Box::<T>::new_zeroed
-      Box::<T>::try_new
-      and 18 others
-  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
    = 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
diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
index 402efaf5027..ea9d48e7859 100644
--- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
+++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs
@@ -3,8 +3,8 @@
 //@ needs-dlltool
 //@ compile-flags: --crate-type lib --emit link
 //@ normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL"
-//@ normalize-stderr-test: "[^ ]*/foo.def" -> "$$DEF_FILE"
-//@ normalize-stderr-test: "[^ ]*/foo.lib" -> "$$LIB_FILE"
+//@ normalize-stderr-test: "[^ ]*/foo.dll_imports.def" -> "$$DEF_FILE"
+//@ normalize-stderr-test: "[^ ]*/foo.dll_imports.lib" -> "$$LIB_FILE"
 //@ normalize-stderr-test: "-m [^ ]*" -> "$$TARGET_MACHINE"
 //@ normalize-stderr-test: "-f [^ ]*" -> "$$ASM_FLAGS"
 //@ normalize-stderr-test: "--temp-prefix [^ ]*/foo.dll" -> "$$TEMP_PREFIX"
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs
new file mode 100644
index 00000000000..6b5ba5bb624
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs
@@ -0,0 +1,22 @@
+//@ check-fail
+// Fixes #119830
+
+#![feature(effects)]
+#![feature(min_specialization)]
+#![feature(const_trait_impl)]
+
+trait Specialize {}
+
+trait Foo {}
+
+impl<T> const Foo for T {}
+//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
+//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207]
+
+impl<T> const Foo for T where T: const Specialize {}
+//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
+//~| error: `const` can only be applied to `#[const_trait]` traits
+//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207]
+//~| error: conflicting implementations of trait `Foo`
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr
new file mode 100644
index 00000000000..70dd0350dc4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr
@@ -0,0 +1,61 @@
+error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
+  --> $DIR/spec-effectvar-ice.rs:12:15
+   |
+LL | trait Foo {}
+   | - help: mark `Foo` as const: `#[const_trait]`
+LL |
+LL | impl<T> const Foo for T {}
+   |               ^^^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
+
+error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
+  --> $DIR/spec-effectvar-ice.rs:16:15
+   |
+LL | trait Foo {}
+   | - help: mark `Foo` as const: `#[const_trait]`
+...
+LL | impl<T> const Foo for T where T: const Specialize {}
+   |               ^^^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
+
+error: `const` can only be applied to `#[const_trait]` traits
+  --> $DIR/spec-effectvar-ice.rs:16:40
+   |
+LL | impl<T> const Foo for T where T: const Specialize {}
+   |                                        ^^^^^^^^^^
+
+error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/spec-effectvar-ice.rs:12:9
+   |
+LL | impl<T> const Foo for T {}
+   |         ^^^^^ unconstrained const parameter
+   |
+   = note: expressions using a const parameter must map each value to a distinct output value
+   = note: proving the result of expressions other than the parameter are unique is not supported
+
+error[E0119]: conflicting implementations of trait `Foo`
+  --> $DIR/spec-effectvar-ice.rs:16:1
+   |
+LL | impl<T> const Foo for T {}
+   | ----------------------- first implementation here
+...
+LL | impl<T> const Foo for T where T: const Specialize {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/spec-effectvar-ice.rs:16:9
+   |
+LL | impl<T> const Foo for T where T: const Specialize {}
+   |         ^^^^^ unconstrained const parameter
+   |
+   = note: expressions using a const parameter must map each value to a distinct output value
+   = note: proving the result of expressions other than the parameter are unique is not supported
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0119, E0207.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/rust-2018/macro-use-warned-against.rs b/tests/ui/rust-2018/macro-use-warned-against.rs
index 1e78acf201d..d6bb5150178 100644
--- a/tests/ui/rust-2018/macro-use-warned-against.rs
+++ b/tests/ui/rust-2018/macro-use-warned-against.rs
@@ -4,7 +4,7 @@
 
 #![warn(macro_use_extern_crate, unused)]
 
-#[macro_use] //~ WARN should be replaced at use sites with a `use` item
+#[macro_use] //~ WARN applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
 extern crate macro_use_warned_against;
 #[macro_use] //~ WARN unused `#[macro_use]`
 extern crate macro_use_warned_against2;
diff --git a/tests/ui/rust-2018/macro-use-warned-against.stderr b/tests/ui/rust-2018/macro-use-warned-against.stderr
index 6b46f002e32..3ac1f127051 100644
--- a/tests/ui/rust-2018/macro-use-warned-against.stderr
+++ b/tests/ui/rust-2018/macro-use-warned-against.stderr
@@ -1,9 +1,10 @@
-warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
+warning: applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
   --> $DIR/macro-use-warned-against.rs:7:1
    |
 LL | #[macro_use]
    | ^^^^^^^^^^^^
    |
+   = help: remove it and import macros at use sites with a `use` item instead
 note: the lint level is defined here
   --> $DIR/macro-use-warned-against.rs:5:9
    |
diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr
index cc40ec2e466..90c1df192aa 100644
--- a/tests/ui/rust-2024/unsafe-env.e2021.stderr
+++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr
@@ -1,5 +1,24 @@
+error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block
+  --> $DIR/unsafe-env.rs:15:9
+   |
+LL |         unsafe_fn();
+   |         ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/unsafe-env.rs:9:1
+   |
+LL | unsafe fn unsafe_fn() {
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/unsafe-env.rs:8:8
+   |
+LL | #[deny(unsafe_op_in_unsafe_fn)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-env.rs:23:5
+  --> $DIR/unsafe-env.rs:33:5
    |
 LL |     unsafe_fn();
    |     ^^^^^^^^^^^ call to unsafe function
@@ -7,17 +26,17 @@ LL |     unsafe_fn();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: unnecessary `unsafe` block
-  --> $DIR/unsafe-env.rs:26:5
+  --> $DIR/unsafe-env.rs:36:5
    |
 LL |     unsafe {
    |     ^^^^^^ unnecessary `unsafe` block
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-env.rs:11:8
+  --> $DIR/unsafe-env.rs:21:8
    |
 LL | #[deny(unused_unsafe)]
    |        ^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr
index b43f817cf72..5ecdf3cd7a7 100644
--- a/tests/ui/rust-2024/unsafe-env.e2024.stderr
+++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr
@@ -1,5 +1,42 @@
+error[E0133]: call to unsafe function `std::env::set_var` is unsafe and requires unsafe block
+  --> $DIR/unsafe-env.rs:10:5
+   |
+LL |     env::set_var("FOO", "BAR");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/unsafe-env.rs:9:1
+   |
+LL | unsafe fn unsafe_fn() {
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/unsafe-env.rs:8:8
+   |
+LL | #[deny(unsafe_op_in_unsafe_fn)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0133]: call to unsafe function `std::env::remove_var` is unsafe and requires unsafe block
+  --> $DIR/unsafe-env.rs:12:5
+   |
+LL |     env::remove_var("FOO");
+   |     ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block
+  --> $DIR/unsafe-env.rs:15:9
+   |
+LL |         unsafe_fn();
+   |         ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
 error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block
-  --> $DIR/unsafe-env.rs:13:5
+  --> $DIR/unsafe-env.rs:23:5
    |
 LL |     env::set_var("FOO", "BAR");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +44,7 @@ LL |     env::set_var("FOO", "BAR");
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block
-  --> $DIR/unsafe-env.rs:15:5
+  --> $DIR/unsafe-env.rs:25:5
    |
 LL |     env::remove_var("FOO");
    |     ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
@@ -15,7 +52,7 @@ LL |     env::remove_var("FOO");
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block
-  --> $DIR/unsafe-env.rs:23:5
+  --> $DIR/unsafe-env.rs:33:5
    |
 LL |     unsafe_fn();
    |     ^^^^^^^^^^^ call to unsafe function
@@ -23,17 +60,17 @@ LL |     unsafe_fn();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: unnecessary `unsafe` block
-  --> $DIR/unsafe-env.rs:26:5
+  --> $DIR/unsafe-env.rs:36:5
    |
 LL |     unsafe {
    |     ^^^^^^ unnecessary `unsafe` block
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-env.rs:11:8
+  --> $DIR/unsafe-env.rs:21:8
    |
 LL | #[deny(unused_unsafe)]
    |        ^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs
index a882f077b9b..601f44e1d3e 100644
--- a/tests/ui/rust-2024/unsafe-env.rs
+++ b/tests/ui/rust-2024/unsafe-env.rs
@@ -5,7 +5,17 @@
 
 use std::env;
 
-unsafe fn unsafe_fn() {}
+#[deny(unsafe_op_in_unsafe_fn)]
+unsafe fn unsafe_fn() {
+    env::set_var("FOO", "BAR");
+    //[e2024]~^ ERROR call to unsafe function `std::env::set_var` is unsafe
+    env::remove_var("FOO");
+    //[e2024]~^ ERROR call to unsafe function `std::env::remove_var` is unsafe
+    if false {
+        unsafe_fn();
+        //~^ ERROR call to unsafe function `unsafe_fn` is unsafe
+    }
+}
 fn safe_fn() {}
 
 #[deny(unused_unsafe)]
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
new file mode 100644
index 00000000000..3a99caa719b
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
+  --> $DIR/extern-items-unsafe.rs:14:5
+   |
+LL |     test1(TEST1);
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/extern-items-unsafe.rs:14:11
+   |
+LL |     test1(TEST1);
+   |           ^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
new file mode 100644
index 00000000000..fcf937b7ac5
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
+  --> $DIR/extern-items-unsafe.rs:14:5
+   |
+LL |     test1(TEST1);
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: use of extern static is unsafe and requires unsafe block
+  --> $DIR/extern-items-unsafe.rs:14:11
+   |
+LL |     test1(TEST1);
+   |           ^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
new file mode 100644
index 00000000000..ad569a256db
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
@@ -0,0 +1,25 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+
+#![feature(unsafe_extern_blocks)]
+
+unsafe extern "C" {
+    static TEST1: i32;
+    fn test1(i: i32);
+}
+
+fn test2() {
+    test1(TEST1);
+    //~^ ERROR: call to unsafe function `test1` is unsafe
+    //~| ERROR: use of extern static is unsafe
+}
+
+fn test3() {
+    unsafe {
+        test1(TEST1);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
new file mode 100644
index 00000000000..d456cfc6829
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
@@ -0,0 +1,12 @@
+error: extern blocks must be unsafe
+  --> $DIR/extern-items.rs:9:1
+   |
+LL | / extern "C" {
+LL | |
+LL | |     static TEST1: i32;
+LL | |     fn test1(i: i32);
+LL | | }
+   | |_^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
new file mode 100644
index 00000000000..16fa1bbb8a4
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
@@ -0,0 +1,20 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2021] check-pass
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+
+#![feature(unsafe_extern_blocks)]
+
+extern "C" {
+    //[edition2024]~^ ERROR extern blocks must be unsafe
+    static TEST1: i32;
+    fn test1(i: i32);
+}
+
+unsafe extern "C" {
+    static TEST2: i32;
+    fn test2(i: i32);
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
new file mode 100644
index 00000000000..74cd5621fce
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
@@ -0,0 +1,18 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+//@ check-pass
+
+#![feature(unsafe_extern_blocks)]
+
+unsafe extern "C" {
+    safe static TEST1: i32;
+    safe fn test1(i: i32);
+}
+
+fn test2() {
+    test1(TEST1);
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
new file mode 100644
index 00000000000..411cf48b486
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
@@ -0,0 +1,20 @@
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+   |
+LL | extern "C" {
+   | ---------- help: add unsafe to this `extern` block
+LL |
+LL |     safe static TEST1: i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+   |
+LL | extern "C" {
+   | ---------- help: add unsafe to this `extern` block
+...
+LL |     safe fn test1(i: i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
new file mode 100644
index 00000000000..b634adc2999
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
@@ -0,0 +1,32 @@
+error: extern blocks must be unsafe
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1
+   |
+LL | / extern "C" {
+LL | |
+LL | |     safe static TEST1: i32;
+LL | |
+LL | |     safe fn test1(i: i32);
+LL | |
+LL | | }
+   | |_^
+
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+   |
+LL | extern "C" {
+   | ---------- help: add unsafe to this `extern` block
+LL |
+LL |     safe static TEST1: i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: items in unadorned `extern` blocks cannot have safety qualifiers
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+   |
+LL | extern "C" {
+   | ---------- help: add unsafe to this `extern` block
+...
+LL |     safe fn test1(i: i32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
new file mode 100644
index 00000000000..11f55cb195f
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
@@ -0,0 +1,20 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+
+#![feature(unsafe_extern_blocks)]
+
+extern "C" {
+    //[edition2024]~^ ERROR extern blocks must be unsafe
+    safe static TEST1: i32;
+    //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
+    safe fn test1(i: i32);
+    //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
+}
+
+fn test2() {
+    test1(TEST1);
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
new file mode 100644
index 00000000000..10c19759d8a
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
@@ -0,0 +1,19 @@
+//@ run-rustfix
+
+#![feature(unsafe_extern_blocks)]
+#![deny(missing_unsafe_on_extern)]
+#![allow(unused)]
+
+unsafe extern "C" {
+    //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern]
+    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+    static TEST1: i32;
+    fn test1(i: i32);
+}
+
+unsafe extern "C" {
+    static TEST2: i32;
+    fn test2(i: i32);
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
new file mode 100644
index 00000000000..b81e52ddc58
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
@@ -0,0 +1,19 @@
+//@ run-rustfix
+
+#![feature(unsafe_extern_blocks)]
+#![deny(missing_unsafe_on_extern)]
+#![allow(unused)]
+
+extern "C" {
+    //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern]
+    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+    static TEST1: i32;
+    fn test1(i: i32);
+}
+
+unsafe extern "C" {
+    static TEST2: i32;
+    fn test2(i: i32);
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
new file mode 100644
index 00000000000..0a3c2cd25e3
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
@@ -0,0 +1,25 @@
+error: extern blocks should be unsafe
+  --> $DIR/unsafe-extern-suggestion.rs:7:1
+   |
+LL |   extern "C" {
+   |   ^
+   |   |
+   |  _help: needs `unsafe` before the extern keyword: `unsafe`
+   | |
+LL | |
+LL | |
+LL | |     static TEST1: i32;
+LL | |     fn test1(i: i32);
+LL | | }
+   | |_^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123743 <https://github.com/rust-lang/rust/issues/123743>
+note: the lint level is defined here
+  --> $DIR/unsafe-extern-suggestion.rs:4:9
+   |
+LL | #![deny(missing_unsafe_on_extern)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
new file mode 100644
index 00000000000..8bb7ffefeea
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-items.rs:20:5
+   |
+LL |     test1(TEST1);
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-items.rs:20:11
+   |
+LL |     test1(TEST1);
+   |           ^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
new file mode 100644
index 00000000000..9a30142a632
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
@@ -0,0 +1,19 @@
+error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
+  --> $DIR/unsafe-items.rs:20:5
+   |
+LL |     test1(TEST1);
+   |     ^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: use of extern static is unsafe and requires unsafe block
+  --> $DIR/unsafe-items.rs:20:11
+   |
+LL |     test1(TEST1);
+   |           ^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
new file mode 100644
index 00000000000..9066953abc6
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
@@ -0,0 +1,25 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+
+#![feature(unsafe_extern_blocks)]
+
+unsafe extern "C" {
+    unsafe static TEST1: i32;
+    unsafe fn test1(i: i32);
+}
+
+fn test2() {
+    unsafe {
+        test1(TEST1);
+    }
+}
+
+fn test3() {
+    test1(TEST1);
+    //~^ ERROR: call to unsafe function `test1` is unsafe
+    //~| ERROR: use of extern static is unsafe
+}
+
+fn main() {}
diff --git a/tests/ui/specialization/anyid-repro-125197.rs b/tests/ui/specialization/anyid-repro-125197.rs
new file mode 100644
index 00000000000..9428d8dc2d4
--- /dev/null
+++ b/tests/ui/specialization/anyid-repro-125197.rs
@@ -0,0 +1,17 @@
+//@ aux-build: anyid-repro-125197.rs
+//@ check-pass
+
+// Makes sure that we don't check `specializes(impl1, impl2)` for a pair of impls that don't
+// actually participate in specialization. Since <https://github.com/rust-lang/rust/pull/122791>,
+// we don't treat inductive cycles as errors -- so we may need to winnow more pairs of impls, and
+// we try to winnow impls in favor of other impls. However, if we're *inside* the `specializes`
+// query, then may have a query cycle if we call `specializes` again!
+
+extern crate anyid_repro_125197;
+use anyid_repro_125197::AnyId;
+
+fn main() {
+    let x = "hello, world";
+    let y: AnyId = x.into();
+    let _ = y == x;
+}
diff --git a/tests/ui/specialization/auxiliary/anyid-repro-125197.rs b/tests/ui/specialization/auxiliary/anyid-repro-125197.rs
new file mode 100644
index 00000000000..c2794959740
--- /dev/null
+++ b/tests/ui/specialization/auxiliary/anyid-repro-125197.rs
@@ -0,0 +1,26 @@
+use std::fmt::Display;
+use std::sync::Arc;
+
+pub struct AnyId(());
+
+impl PartialEq<Self> for AnyId {
+    fn eq(&self, _: &Self) -> bool {
+        todo!()
+    }
+}
+
+impl<T: Identifier> PartialEq<T> for AnyId {
+    fn eq(&self, _: &T) -> bool {
+        todo!()
+    }
+}
+
+impl<T: Identifier> From<T> for AnyId {
+    fn from(_: T) -> Self {
+        todo!()
+    }
+}
+
+pub trait Identifier: Display + 'static {}
+
+impl<T> Identifier for T where T: PartialEq + Display + 'static {}
diff --git a/tests/ui/specialization/dont-drop-upcast-candidate.rs b/tests/ui/specialization/dont-drop-upcast-candidate.rs
new file mode 100644
index 00000000000..98d8cad7c1f
--- /dev/null
+++ b/tests/ui/specialization/dont-drop-upcast-candidate.rs
@@ -0,0 +1,13 @@
+#![feature(unsize)]
+
+use std::marker::Unsize;
+use std::ops::Deref;
+
+trait Foo: Bar {}
+trait Bar {}
+
+impl<T> Bar for T where dyn Foo: Unsize<dyn Bar> {}
+impl Bar for () {}
+//~^ ERROR conflicting implementations of trait `Bar` for type `()`
+
+fn main() {}
diff --git a/tests/ui/specialization/dont-drop-upcast-candidate.stderr b/tests/ui/specialization/dont-drop-upcast-candidate.stderr
new file mode 100644
index 00000000000..dc0c54f9aa8
--- /dev/null
+++ b/tests/ui/specialization/dont-drop-upcast-candidate.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Bar` for type `()`
+  --> $DIR/dont-drop-upcast-candidate.rs:10:1
+   |
+LL | impl<T> Bar for T where dyn Foo: Unsize<dyn Bar> {}
+   | ------------------------------------------------ first implementation here
+LL | impl Bar for () {}
+   | ^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/crashes/124464.rs b/tests/ui/static/duplicated-fields-issue-124464.rs
index 471479f5cf1..60609edbfeb 100644
--- a/tests/crashes/124464.rs
+++ b/tests/ui/static/duplicated-fields-issue-124464.rs
@@ -1,12 +1,16 @@
-//@ known-bug: rust-lang/rust #124464
+// Don't const eval fields with ambiguous layout.
+// See issues #125842 and #124464.
+
 enum TestOption<T> {
     TestSome(T),
     TestSome(T),
+//~^ ERROR the name `TestSome` is defined multiple times
 }
 
 pub struct Request {
     bar: TestOption<u64>,
     bar: u8,
+//~^ ERROR field `bar` is already declared
 }
 
 fn default_instance() -> &'static Request {
diff --git a/tests/ui/static/duplicated-fields-issue-124464.stderr b/tests/ui/static/duplicated-fields-issue-124464.stderr
new file mode 100644
index 00000000000..a36192ae8d6
--- /dev/null
+++ b/tests/ui/static/duplicated-fields-issue-124464.stderr
@@ -0,0 +1,22 @@
+error[E0428]: the name `TestSome` is defined multiple times
+  --> $DIR/duplicated-fields-issue-124464.rs:6:5
+   |
+LL |     TestSome(T),
+   |     ----------- previous definition of the type `TestSome` here
+LL |     TestSome(T),
+   |     ^^^^^^^^^^^ `TestSome` redefined here
+   |
+   = note: `TestSome` must be defined only once in the type namespace of this enum
+
+error[E0124]: field `bar` is already declared
+  --> $DIR/duplicated-fields-issue-124464.rs:12:5
+   |
+LL |     bar: TestOption<u64>,
+   |     -------------------- `bar` first declared here
+LL |     bar: u8,
+   |     ^^^^^^^ field already declared
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0124, E0428.
+For more information about an error, try `rustc --explain E0124`.
diff --git a/tests/ui/static/duplicated-fields-issue-125842.rs b/tests/ui/static/duplicated-fields-issue-125842.rs
new file mode 100644
index 00000000000..580b810232e
--- /dev/null
+++ b/tests/ui/static/duplicated-fields-issue-125842.rs
@@ -0,0 +1,21 @@
+// Do not try to evaluate static initalizers that reference
+// ill-defined types. This used to be an ICE.
+// See issues #125842 and #124464.
+struct Struct {
+    field: Option<u8>,
+    field: u8,
+//~^ ERROR field `field` is already declared
+}
+
+static STATIC_A: Struct = Struct {
+    field: 1
+};
+
+static STATIC_B: Struct = {
+    let field = 1;
+    Struct {
+        field,
+    }
+};
+
+fn main() {}
diff --git a/tests/ui/static/duplicated-fields-issue-125842.stderr b/tests/ui/static/duplicated-fields-issue-125842.stderr
new file mode 100644
index 00000000000..c80bb99005e
--- /dev/null
+++ b/tests/ui/static/duplicated-fields-issue-125842.stderr
@@ -0,0 +1,11 @@
+error[E0124]: field `field` is already declared
+  --> $DIR/duplicated-fields-issue-125842.rs:6:5
+   |
+LL |     field: Option<u8>,
+   |     ----------------- `field` first declared here
+LL |     field: u8,
+   |     ^^^^^^^^^ field already declared
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
index 19672e41c9a..16439a7fedd 100644
--- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs
+++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
@@ -3,8 +3,10 @@
 #![allow(unused_variables)]
 //@ pretty-expanded FIXME #23616
 
+#[allow(dead_code)]
 pub struct Fd(u32);
 
+#[allow(dead_code)]
 fn foo(a: u32) {}
 
 impl Drop for Fd {
diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs
index 97bc7d8414e..1074dbcd6e6 100644
--- a/tests/ui/structs-enums/uninstantiable-struct.rs
+++ b/tests/ui/structs-enums/uninstantiable-struct.rs
@@ -1,4 +1,5 @@
 //@ run-pass
-pub struct Z(#[allow(dead_code)] &'static Z);
+#[allow(dead_code)]
+pub struct Z(&'static Z);
 
 pub fn main() {}
diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed
index 4dc362f9478..cf800c6e47d 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.fixed
+++ b/tests/ui/suggestions/derive-clone-for-eq.fixed
@@ -1,6 +1,7 @@
 //@ run-rustfix
 // https://github.com/rust-lang/rust/issues/79076
 
+#[allow(dead_code)]
 #[derive(Clone, Eq)] //~ ERROR [E0277]
 pub struct Struct<T: std::clone::Clone>(T);
 
diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs
index b3635000f16..84736426bac 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.rs
+++ b/tests/ui/suggestions/derive-clone-for-eq.rs
@@ -1,6 +1,7 @@
 //@ run-rustfix
 // https://github.com/rust-lang/rust/issues/79076
 
+#[allow(dead_code)]
 #[derive(Clone, Eq)] //~ ERROR [E0277]
 pub struct Struct<T>(T);
 
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
index 6fae6e1316d..54670fbffcf 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.stderr
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/derive-clone-for-eq.rs:4:17
+  --> $DIR/derive-clone-for-eq.rs:5:17
    |
 LL | #[derive(Clone, Eq)]
    |                 ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
    |
 note: required for `Struct<T>` to implement `PartialEq`
-  --> $DIR/derive-clone-for-eq.rs:7:19
+  --> $DIR/derive-clone-for-eq.rs:8:19
    |
 LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
    |         -----     ^^^^^^^^^^^^     ^^^^^^^^^
diff --git a/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.rs b/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.rs
new file mode 100644
index 00000000000..efa296db47c
--- /dev/null
+++ b/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.rs
@@ -0,0 +1,11 @@
+// Regression test for ICE #125876
+
+fn main() {
+    std::ptr::from_ref(num).cast_mut().as_deref();
+    //~^ ERROR cannot find value `num` in this scope
+    //~| ERROR no method named `as_deref` found for raw pointer `*mut _` in the current scope
+    //~| WARN type annotations needed
+    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+    //~| WARN type annotations needed
+    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+}
diff --git a/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.stderr b/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.stderr
new file mode 100644
index 00000000000..d610a3b7cad
--- /dev/null
+++ b/tests/ui/suggestions/ice-unwrap-probe-many-result-125876.stderr
@@ -0,0 +1,40 @@
+error[E0425]: cannot find value `num` in this scope
+  --> $DIR/ice-unwrap-probe-many-result-125876.rs:4:24
+   |
+LL |     std::ptr::from_ref(num).cast_mut().as_deref();
+   |                        ^^^ not found in this scope
+
+warning: type annotations needed
+  --> $DIR/ice-unwrap-probe-many-result-125876.rs:4:29
+   |
+LL |     std::ptr::from_ref(num).cast_mut().as_deref();
+   |                             ^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+   = note: `#[warn(tyvar_behind_raw_pointer)]` on by default
+
+warning: type annotations needed
+  --> $DIR/ice-unwrap-probe-many-result-125876.rs:4:40
+   |
+LL |     std::ptr::from_ref(num).cast_mut().as_deref();
+   |                                        ^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+
+error[E0599]: no method named `as_deref` found for raw pointer `*mut _` in the current scope
+  --> $DIR/ice-unwrap-probe-many-result-125876.rs:4:40
+   |
+LL |     std::ptr::from_ref(num).cast_mut().as_deref();
+   |                                        ^^^^^^^^
+   |
+help: there is a method `as_ref` with a similar name
+   |
+LL |     std::ptr::from_ref(num).cast_mut().as_ref();
+   |                                        ~~~~~~
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0425, E0599.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs
index cd7fa0c1d85..dd437fc0c0b 100644
--- a/tests/ui/suggestions/missing-lifetime-specifier.rs
+++ b/tests/ui/suggestions/missing-lifetime-specifier.rs
@@ -1,6 +1,11 @@
-// different number of duplicated diagnostics on different targets
-//@ only-x86_64
-//@ only-linux
+// The specific errors produced depend the thread-local implementation.
+// Run only on platforms with "fast" TLS.
+//@ ignore-windows FIXME(#84933)
+//@ ignore-wasm globals are used instead of thread locals
+//@ ignore-emscripten globals are used instead of thread locals
+//@ ignore-android does not use #[thread_local]
+//@ ignore-nto does not use #[thread_local]
+// Different number of duplicated diagnostics on different targets
 //@ compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![allow(bare_trait_objects)]
@@ -21,23 +26,19 @@ trait Tar<'t, 'k, I> {}
 
 thread_local! {
     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
-      //~^ ERROR missing lifetime specifiers
-      //~| ERROR missing lifetime specifiers
+    //~^ ERROR missing lifetime specifiers
 }
 thread_local! {
     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-      //~^ ERROR missing lifetime specifiers
-      //~| ERROR missing lifetime specifiers
+    //~^ ERROR missing lifetime specifiers
 }
 thread_local! {
     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
     //~^ ERROR missing lifetime specifiers
-    //~| ERROR missing lifetime specifiers
 }
 thread_local! {
     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
     //~^ ERROR missing lifetime specifiers
-    //~| ERROR missing lifetime specifiers
 }
 
 thread_local! {
@@ -47,8 +48,7 @@ thread_local! {
 thread_local! {
     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
     //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-    //~| ERROR missing lifetime
-    //~| ERROR missing lifetime
+    //~| ERROR missing lifetime specifier
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr
index 2b85cfde7b6..e0b6bb872b5 100644
--- a/tests/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr
@@ -1,5 +1,5 @@
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:23:44
+  --> $DIR/missing-lifetime-specifier.rs:28:44
    |
 LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
    |                                            ^^^ expected 2 lifetime parameters
@@ -11,20 +11,7 @@ LL |     static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefC
    |                                               ++++++++++++++++++
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:23:44
-   |
-LL | / thread_local! {
-LL | |     static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new());
-   | |                                            ^^^ expected 2 lifetime parameters
-LL | |
-LL | |
-LL | | }
-   | |_-
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
-
-error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:28:44
+  --> $DIR/missing-lifetime-specifier.rs:32:44
    |
 LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^ expected 2 lifetime parameters
@@ -38,22 +25,7 @@ LL |     static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar<'static, 'static>>>
    |                                             +++++++    ++++++++++++++++++
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:28:44
-   |
-LL | / thread_local! {
-LL | |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-   | |                                            ^^^^ expected 2 lifetime parameters
-   | |                                            |
-   | |                                            expected named lifetime parameter
-LL | |
-LL | |
-LL | | }
-   | |_-
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
-
-error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:33:47
+  --> $DIR/missing-lifetime-specifier.rs:36:47
    |
 LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
    |                                               ^ expected 2 lifetime parameters
@@ -65,20 +37,7 @@ LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> =
    |                                                +++++++++++++++++
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:33:47
-   |
-LL | / thread_local! {
-LL | |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
-   | |                                               ^ expected 2 lifetime parameters
-LL | |
-LL | |
-LL | | }
-   | |_-
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
-
-error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:38:44
+  --> $DIR/missing-lifetime-specifier.rs:40:44
    |
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^   ^ expected 2 lifetime parameters
@@ -91,23 +50,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             +++++++     +++++++++++++++++
 
-error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:38:44
-   |
-LL | / thread_local! {
-LL | |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
-   | |                                            ^   ^ expected 2 lifetime parameters
-   | |                                            |
-   | |                                            expected named lifetime parameter
-LL | |
-LL | |
-LL | | }
-   | |_-
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from
-
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:48:44
+  --> $DIR/missing-lifetime-specifier.rs:49:44
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -118,22 +62,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             +++++++
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:48:44
-   |
-LL | / thread_local! {
-LL | |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   | |                                            ^ expected named lifetime parameter
-LL | |
-LL | |
-LL | |
-LL | | }
-   | |_-
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
-
 error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:44:44
+  --> $DIR/missing-lifetime-specifier.rs:45:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^ ------- supplied 1 lifetime argument
@@ -141,7 +71,7 @@ LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell:
    |                                            expected 2 lifetime arguments
    |
 note: union defined here, with 2 lifetime parameters: `'t`, `'k`
-  --> $DIR/missing-lifetime-specifier.rs:16:11
+  --> $DIR/missing-lifetime-specifier.rs:21:11
    |
 LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
@@ -151,7 +81,7 @@ LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> =
    |                                                       +++++++++
 
 error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing-lifetime-specifier.rs:48:45
+  --> $DIR/missing-lifetime-specifier.rs:49:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^ ------- supplied 1 lifetime argument
@@ -159,7 +89,7 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell
    |                                             expected 2 lifetime arguments
    |
 note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
-  --> $DIR/missing-lifetime-specifier.rs:20:7
+  --> $DIR/missing-lifetime-specifier.rs:25:7
    |
 LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
@@ -168,7 +98,7 @@ help: add missing lifetime argument
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                                        +++++++++
 
-error: aborting due to 12 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0106, E0107.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed
index 4a5a9483c20..ef07d55871e 100644
--- a/tests/ui/suggestions/option-content-move.fixed
+++ b/tests/ui/suggestions/option-content-move.fixed
@@ -1,4 +1,5 @@
 //@ run-rustfix
+#[allow(dead_code)]
 pub struct LipogramCorpora {
     selections: Vec<(char, Option<String>)>,
 }
@@ -17,6 +18,7 @@ impl LipogramCorpora {
     }
 }
 
+#[allow(dead_code)]
 pub struct LipogramCorpora2 {
     selections: Vec<(char, Result<String, String>)>,
 }
diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs
index 90d05c74399..5be6358fd6a 100644
--- a/tests/ui/suggestions/option-content-move.rs
+++ b/tests/ui/suggestions/option-content-move.rs
@@ -1,4 +1,5 @@
 //@ run-rustfix
+#[allow(dead_code)]
 pub struct LipogramCorpora {
     selections: Vec<(char, Option<String>)>,
 }
@@ -17,6 +18,7 @@ impl LipogramCorpora {
     }
 }
 
+#[allow(dead_code)]
 pub struct LipogramCorpora2 {
     selections: Vec<(char, Result<String, String>)>,
 }
diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr
index a382a04344a..b4ec5b180d2 100644
--- a/tests/ui/suggestions/option-content-move.stderr
+++ b/tests/ui/suggestions/option-content-move.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
-  --> $DIR/option-content-move.rs:10:20
+  --> $DIR/option-content-move.rs:11:20
    |
 LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
@@ -19,7 +19,7 @@ LL |                 if selection.1.clone().unwrap().contains(selection.0) {
    |                               ++++++++
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
-  --> $DIR/option-content-move.rs:28:20
+  --> $DIR/option-content-move.rs:30:20
    |
 LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
diff --git a/tests/ui/suggestions/silenced-binding-typo.stderr b/tests/ui/suggestions/silenced-binding-typo.stderr
index c362d00c713..a1e8b9e30d4 100644
--- a/tests/ui/suggestions/silenced-binding-typo.stderr
+++ b/tests/ui/suggestions/silenced-binding-typo.stderr
@@ -1,10 +1,12 @@
 error[E0425]: cannot find value `x` in this scope
   --> $DIR/silenced-binding-typo.rs:4:14
    |
+LL |     let _x = 42;
+   |         -- `_x` defined here
 LL |     let _y = x;
    |              ^
    |
-help: a local variable with a similar name exists, consider renaming `_x` into `x`
+help: the leading underscore in `_x` marks it as unused, consider renaming it to `x`
    |
 LL |     let x = 42;
    |         ~
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
index cab484a120c..445ea2de610 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
@@ -14,14 +14,12 @@ impl<T, S> Trait<T> for i32 {
 // Should not not trigger suggestion here...
 impl<T, S> Trait<T, S> for () {}
 //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
-//~| ERROR `S` is not constrained
 
 //... but should do so in all of the below cases except the last one
 fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
 //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
 //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied
 //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied
-//~| ERROR type annotations needed
     3
 }
 
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
index 99e81a9039e..06e2fa5d4d1 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
@@ -16,14 +16,8 @@ note: trait defined here, with 1 generic parameter: `T`
 LL | pub trait Trait<T> {
    |           ^^^^^ -
 
-error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9
-   |
-LL | impl<T, S> Trait<T, S> for () {}
-   |         ^ unconstrained type parameter
-
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:12
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:12
    |
 LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
    |            ^^^^^ expected 1 generic argument
@@ -39,7 +33,7 @@ LL | fn func<T: Trait<u32, Assoc = String>>(t: T) -> impl Trait<(), i32> {
    |                       +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:46
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:46
    |
 LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
    |                                              ^^^^^ expected 1 generic argument
@@ -55,7 +49,7 @@ LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), Assoc = i32> {
    |                                                        +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:46
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:46
    |
 LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
    |                                              ^^^^^ expected 1 generic argument
@@ -71,14 +65,8 @@ help: replace the generic bound with the associated type
 LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), Assoc = i32> {
    |                                                        +++++++
 
-error[E0282]: type annotations needed
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:41
-   |
-LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
-   |                                         ^^^^^^^^^^^^^^^^^^^ cannot infer type
-
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:28:18
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:18
    |
 LL | struct Struct<T: Trait<u32, String>> {
    |                  ^^^^^ expected 1 generic argument
@@ -94,7 +82,7 @@ LL | struct Struct<T: Trait<u32, Assoc = String>> {
    |                             +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:33:23
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:31:23
    |
 LL | trait AnotherTrait<T: Trait<T, i32>> {}
    |                       ^^^^^ expected 1 generic argument
@@ -110,7 +98,7 @@ LL | trait AnotherTrait<T: Trait<T, Assoc = i32>> {}
    |                                +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:36:9
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:34:9
    |
 LL | impl<T: Trait<u32, String>> Struct<T> {}
    |         ^^^^^ expected 1 generic argument
@@ -126,7 +114,7 @@ LL | impl<T: Trait<u32, Assoc = String>> Struct<T> {}
    |                    +++++++
 
 error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:42:58
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:58
    |
 LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
    |                                                          ^^^^^^    - help: remove this generic argument
@@ -134,12 +122,12 @@ LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
    |                                                          expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:28:8
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:8
    |
 LL | struct Struct<T: Trait<u32, String>> {
    |        ^^^^^^ -
 
-error: aborting due to 11 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0107, E0207, E0282.
+Some errors have detailed explanations: E0107, E0207.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs
new file mode 100644
index 00000000000..bf1278f992b
--- /dev/null
+++ b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs
@@ -0,0 +1,27 @@
+//! This test used to ICE: #121134
+//! The issue is that we're trying to prove a projection, but there's
+//! no bound for the projection's trait, and the projection has the wrong
+//! kind of generic parameter (lifetime vs type).
+//! When actually calling the function with those broken bounds, trying to
+//! instantiate the bounds with inference vars would ICE.
+#![feature(unboxed_closures)]
+
+trait Output<'a> {
+    type Type;
+}
+
+struct Wrapper;
+
+impl Wrapper {
+    fn do_something_wrapper<O, F>(&mut self, _: F)
+    where
+        F: for<'a> FnOnce(<F as Output<i32>>::Type),
+        //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
+    {
+    }
+}
+
+fn main() {
+    let mut wrapper = Wrapper;
+    wrapper.do_something_wrapper(|value| ());
+}
diff --git a/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr
new file mode 100644
index 00000000000..acda3418894
--- /dev/null
+++ b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr
@@ -0,0 +1,19 @@
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/generic_param_mismatch_in_unsatisfied_projection.rs:18:33
+   |
+LL |         F: for<'a> FnOnce(<F as Output<i32>>::Type),
+   |                                 ^^^^^^ expected 0 generic arguments
+   |
+note: trait defined here, with 0 generic parameters
+  --> $DIR/generic_param_mismatch_in_unsatisfied_projection.rs:9:7
+   |
+LL | trait Output<'a> {
+   |       ^^^^^^
+help: replace the generic bound with the associated type
+   |
+LL |         F: for<'a> FnOnce(<F as Output<Type = i32>>::Type),
+   |                                        ++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 58a4c229e5e..cdcb0cdf259 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -55,12 +55,6 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    = help: add `#![feature(dispatch_from_dyn)]` 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[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
-  --> $DIR/issue-78372.rs:3:1
-   |
-LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/issue-78372.rs:12:17
    |
@@ -88,6 +82,12 @@ LL |     fn foo(self: Smaht<Self, T>);
    = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+  --> $DIR/issue-78372.rs:3:1
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658.
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index d08bb4745bf..50b561dfd16 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -126,14 +126,15 @@ LL |     S::B;
    |        ^ associated item not found in `S`
    |
    = help: items from traits can only be used if the trait is in scope
+help: there is a method `b` with a similar name
+  --> $DIR/item-privacy.rs:11:9
+   |
+LL |         fn b(&self) { }
+   |         ^^^^^^^^^^^
 help: trait `B` which provides `B` is implemented but not in scope; perhaps you want to import it
    |
 LL + use assoc_const::B;
    |
-help: there is a method `b` with a similar name
-   |
-LL |     S::b;
-   |        ~
 
 error[E0624]: associated constant `A` is private
   --> $DIR/item-privacy.rs:101:14
diff --git a/tests/ui/traits/next-solver/generalize/bivariant-alias.rs b/tests/ui/traits/next-solver/generalize/bivariant-alias.rs
new file mode 100644
index 00000000000..b03d547838a
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/bivariant-alias.rs
@@ -0,0 +1,20 @@
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// When generalizing an alias in a bivariant context, we have to set
+// `has_unconstrained_ty_var` as we may otherwise never check for
+// well-formedness of the generalized type, causing us to error due
+// to ambiguity.
+trait Trait {
+    type Assoc;
+}
+
+struct BivariantArg<I, T: Trait<Assoc = I>>(T);
+
+fn generalize<T: Trait>(input: BivariantArg<T::Assoc, T>) {
+    let _generalized = input;
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs
index 462b0bc5bb7..0ae562c0d30 100644
--- a/tests/ui/traits/object/generics.rs
+++ b/tests/ui/traits/object/generics.rs
@@ -7,6 +7,7 @@ pub trait Trait2<A> {
     fn doit(&self) -> A;
 }
 
+#[allow(dead_code)]
 pub struct Impl<A1, A2, A3> {
     m1: marker::PhantomData<(A1,A2,A3)>,
     /*
diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs
index 26de3f60621..b3c76815703 100644
--- a/tests/ui/traits/vtable/vtable-vacant.rs
+++ b/tests/ui/traits/vtable/vtable-vacant.rs
@@ -1,7 +1,6 @@
 //@ build-fail
 #![feature(rustc_attrs)]
 #![feature(negative_impls)]
-#![allow(where_clauses_object_safety)]
 
 // B --> A
 
diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr
index 9ce1d0b7632..f6961ca010e 100644
--- a/tests/ui/traits/vtable/vtable-vacant.stderr
+++ b/tests/ui/traits/vtable/vtable-vacant.stderr
@@ -7,7 +7,7 @@ error: vtable entries for `<S as B>`: [
            Method(<S as B>::foo_b1),
            Vacant,
        ]
-  --> $DIR/vtable-vacant.rs:15:1
+  --> $DIR/vtable-vacant.rs:14:1
    |
 LL | trait B: A {
    | ^^^^^^^^^^
diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs
index e2cec24aac1..1c0bd29d707 100644
--- a/tests/ui/transmutability/issue-101739-2.rs
+++ b/tests/ui/transmutability/issue-101739-2.rs
@@ -15,7 +15,6 @@ mod assert {
     >()
     where
         Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied
-        //~^ ERROR: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
             Src,
             ASSUME_ALIGNMENT, //~ ERROR: mismatched types
             ASSUME_LIFETIMES,
diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr
index 639b4460892..38912696c18 100644
--- a/tests/ui/transmutability/issue-101739-2.stderr
+++ b/tests/ui/transmutability/issue-101739-2.stderr
@@ -9,29 +9,13 @@ LL | |             ASSUME_VALIDITY,
 LL | |             ASSUME_VISIBILITY,
    | |_____________________________- help: remove these generic arguments
 
-error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
-  --> $DIR/issue-101739-2.rs:17:14
-   |
-LL |           Dst: BikeshedIntrinsicFrom<
-   |  ______________^
-LL | |
-LL | |             Src,
-LL | |             ASSUME_ALIGNMENT,
-...  |
-LL | |             ASSUME_VISIBILITY,
-LL | |         >,
-   | |_________^ expected `Assume`, found `bool`
-   |
-note: required by a bound in `BikeshedIntrinsicFrom`
-  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
-
 error[E0308]: mismatched types
-  --> $DIR/issue-101739-2.rs:20:13
+  --> $DIR/issue-101739-2.rs:19:13
    |
 LL |             ASSUME_ALIGNMENT,
    |             ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0107, E0308.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
index 266a532a1db..ff059bc5806 100644
--- a/tests/ui/type-alias-impl-trait/coherence.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
@@ -1,5 +1,5 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence.rs:14:1
+  --> $DIR/coherence.rs:16:1
    |
 LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr
new file mode 100644
index 00000000000..dab2786c1f0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr
@@ -0,0 +1,14 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence.rs:16:1
+   |
+LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
+   | |                                    |
+   | |                                    `AliasOfForeignType<()>` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs
index 641c0fac17a..760e5210c5b 100644
--- a/tests/ui/type-alias-impl-trait/coherence.rs
+++ b/tests/ui/type-alias-impl-trait/coherence.rs
@@ -1,4 +1,6 @@
 //@ aux-build:foreign-crate.rs
+//@ revisions: classic next
+//@[next] compile-flags: -Znext-solver
 #![feature(type_alias_impl_trait)]
 
 extern crate foreign_crate;
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
index 6a1a770228d..3b6999cabc4 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
@@ -1,5 +1,5 @@
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:7:24
+  --> $DIR/const_generic_type.rs:8:24
    |
 LL | async fn test<const N: crate::Bar>() {
    |                        ^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
index a1a69bfaca3..56a10201651 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
@@ -1,13 +1,13 @@
-error[E0283]: type annotations needed
-  --> $DIR/const_generic_type.rs:7:1
+error: unconstrained opaque type
+  --> $DIR/const_generic_type.rs:5:12
    |
-LL | async fn test<const N: crate::Bar>() {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+LL | type Bar = impl std::fmt::Display;
+   |            ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `_: std::fmt::Display`
+   = note: `Bar` must be used in combination with a concrete type within the same module
 
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:7:24
+  --> $DIR/const_generic_type.rs:8:24
    |
 LL | async fn test<const N: crate::Bar>() {
    |                        ^^^^^^^^^^
@@ -16,4 +16,3 @@ LL | async fn test<const N: crate::Bar>() {
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs
index 95a5e1c6286..bfd06826f00 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.rs
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs
@@ -3,10 +3,10 @@
 
 #![feature(type_alias_impl_trait)]
 type Bar = impl std::fmt::Display;
+//[no_infer]~^ ERROR: unconstrained opaque type
 
 async fn test<const N: crate::Bar>() {
-    //[no_infer]~^ ERROR: type annotations needed
-    //~^^ ERROR: `Bar` is forbidden as the type of a const generic parameter
+    //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
     #[cfg(infer)]
     let x: u32 = N;
 }
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 6aa032d7ed8..92c2e7b4884 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -25,6 +25,7 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
+#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 
@@ -473,8 +474,8 @@ mod items {
 
     /// ItemKind::ForeignMod
     mod item_foreign_mod {
-        extern "C++" {}
-        extern {}
+        unsafe extern "C++" {}
+        unsafe extern {}
     }
 
     /// ItemKind::GlobalAsm
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 8737063bf3c..137a8aa5510 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -26,6 +26,7 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
+#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 #[prelude_import]
@@ -82,8 +83,7 @@ mod expressions {
     fn expr_const_block() {
         const {};
         const { 1 };
-        const
-            {
+        const {
                 struct S;
             };
     }
@@ -451,8 +451,8 @@ mod items {
     mod item_mod { }
     /// ItemKind::ForeignMod
     mod item_foreign_mod {
-        extern "C++" {}
-        extern {}
+        unsafe extern "C++" {}
+        unsafe extern {}
     }
     /// ItemKind::GlobalAsm
     mod item_global_asm {
diff --git a/tests/ui/unused-crate-deps/deny-attr.rs b/tests/ui/unused-crate-deps/deny-attr.rs
index 3b2e8b5677e..71f478b6b7d 100644
--- a/tests/ui/unused-crate-deps/deny-attr.rs
+++ b/tests/ui/unused-crate-deps/deny-attr.rs
@@ -4,6 +4,6 @@
 //@ aux-crate:bar=bar.rs
 
 #![deny(unused_crate_dependencies)]
-//~^ ERROR external crate `bar` unused in
+//~^ ERROR extern crate `bar` is unused in
 
 fn main() {}
diff --git a/tests/ui/unused-crate-deps/deny-attr.stderr b/tests/ui/unused-crate-deps/deny-attr.stderr
index 89e87c9d5ac..7540d9cdc16 100644
--- a/tests/ui/unused-crate-deps/deny-attr.stderr
+++ b/tests/ui/unused-crate-deps/deny-attr.stderr
@@ -1,9 +1,10 @@
-error: external crate `bar` unused in `deny_attr`: remove the dependency or add `use bar as _;`
+error: extern crate `bar` is unused in crate `deny_attr`
   --> $DIR/deny-attr.rs:6:1
    |
 LL | #![deny(unused_crate_dependencies)]
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
 note: the lint level is defined here
   --> $DIR/deny-attr.rs:6:9
    |
diff --git a/tests/ui/unused-crate-deps/deny-cmdline.rs b/tests/ui/unused-crate-deps/deny-cmdline.rs
index d32e8e205af..890c01e0016 100644
--- a/tests/ui/unused-crate-deps/deny-cmdline.rs
+++ b/tests/ui/unused-crate-deps/deny-cmdline.rs
@@ -5,4 +5,4 @@
 //@ aux-crate:bar=bar.rs
 
 fn main() {}
-//~^ ERROR external crate `bar` unused in
+//~^ ERROR extern crate `bar` is unused in
diff --git a/tests/ui/unused-crate-deps/deny-cmdline.stderr b/tests/ui/unused-crate-deps/deny-cmdline.stderr
index fc526878ef0..b48d1ec1ba9 100644
--- a/tests/ui/unused-crate-deps/deny-cmdline.stderr
+++ b/tests/ui/unused-crate-deps/deny-cmdline.stderr
@@ -1,9 +1,10 @@
-error: external crate `bar` unused in `deny_cmdline`: remove the dependency or add `use bar as _;`
+error: extern crate `bar` is unused in crate `deny_cmdline`
   --> $DIR/deny-cmdline.rs:7:1
    |
 LL | fn main() {}
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
    = note: requested on the command line with `-D unused-crate-dependencies`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/unused-crate-deps/libfib.rs b/tests/ui/unused-crate-deps/libfib.rs
index 8a5ec758e56..d7729c9ebe7 100644
--- a/tests/ui/unused-crate-deps/libfib.rs
+++ b/tests/ui/unused-crate-deps/libfib.rs
@@ -5,7 +5,7 @@
 //@ compile-flags:--crate-type lib -Wunused-crate-dependencies
 
 pub fn fib(n: u32) -> Vec<u32> {
-//~^ WARNING external crate `bar` unused in
+//~^ WARNING extern crate `bar` is unused in
 let mut prev = 0;
     let mut cur = 1;
     let mut v = vec![];
diff --git a/tests/ui/unused-crate-deps/libfib.stderr b/tests/ui/unused-crate-deps/libfib.stderr
index 15833126bd6..da6893f5034 100644
--- a/tests/ui/unused-crate-deps/libfib.stderr
+++ b/tests/ui/unused-crate-deps/libfib.stderr
@@ -1,9 +1,10 @@
-warning: external crate `bar` unused in `libfib`: remove the dependency or add `use bar as _;`
+warning: extern crate `bar` is unused in crate `libfib`
   --> $DIR/libfib.rs:7:1
    |
 LL | pub fn fib(n: u32) -> Vec<u32> {
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
    = note: requested on the command line with `-W unused-crate-dependencies`
 
 warning: 1 warning emitted
diff --git a/tests/ui/unused-crate-deps/unused-aliases.rs b/tests/ui/unused-crate-deps/unused-aliases.rs
index f86f6bbf356..2db50cec971 100644
--- a/tests/ui/unused-crate-deps/unused-aliases.rs
+++ b/tests/ui/unused-crate-deps/unused-aliases.rs
@@ -6,7 +6,7 @@
 //@ aux-crate:barbar=bar.rs
 
 #![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `barbar` unused in
+//~^ WARNING extern crate `barbar` is unused in
 
 use bar as _;
 
diff --git a/tests/ui/unused-crate-deps/unused-aliases.stderr b/tests/ui/unused-crate-deps/unused-aliases.stderr
index c8c6c4507b0..d4093b102d5 100644
--- a/tests/ui/unused-crate-deps/unused-aliases.stderr
+++ b/tests/ui/unused-crate-deps/unused-aliases.stderr
@@ -1,9 +1,10 @@
-warning: external crate `barbar` unused in `unused_aliases`: remove the dependency or add `use barbar as _;`
+warning: extern crate `barbar` is unused in crate `unused_aliases`
   --> $DIR/unused-aliases.rs:8:1
    |
 LL | #![warn(unused_crate_dependencies)]
    | ^
    |
+   = help: remove the dependency or add `use barbar as _;` to the crate root
 note: the lint level is defined here
   --> $DIR/unused-aliases.rs:8:9
    |
diff --git a/tests/ui/unused-crate-deps/warn-attr.rs b/tests/ui/unused-crate-deps/warn-attr.rs
index b558c0678d6..c40ed001732 100644
--- a/tests/ui/unused-crate-deps/warn-attr.rs
+++ b/tests/ui/unused-crate-deps/warn-attr.rs
@@ -5,6 +5,6 @@
 //@ aux-crate:bar=bar.rs
 
 #![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
+//~^ WARNING extern crate `bar` is unused in
 
 fn main() {}
diff --git a/tests/ui/unused-crate-deps/warn-attr.stderr b/tests/ui/unused-crate-deps/warn-attr.stderr
index 0d38315704b..2c72961093c 100644
--- a/tests/ui/unused-crate-deps/warn-attr.stderr
+++ b/tests/ui/unused-crate-deps/warn-attr.stderr
@@ -1,9 +1,10 @@
-warning: external crate `bar` unused in `warn_attr`: remove the dependency or add `use bar as _;`
+warning: extern crate `bar` is unused in crate `warn_attr`
   --> $DIR/warn-attr.rs:7:1
    |
 LL | #![warn(unused_crate_dependencies)]
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
 note: the lint level is defined here
   --> $DIR/warn-attr.rs:7:9
    |
diff --git a/tests/ui/unused-crate-deps/warn-cmdline-static.rs b/tests/ui/unused-crate-deps/warn-cmdline-static.rs
index ccb404e3033..eb51543ad1a 100644
--- a/tests/ui/unused-crate-deps/warn-cmdline-static.rs
+++ b/tests/ui/unused-crate-deps/warn-cmdline-static.rs
@@ -7,4 +7,4 @@
 //@ no-prefer-dynamic
 
 fn main() {}
-//~^ WARNING external crate `bar` unused in
+//~^ WARNING extern crate `bar` is unused in
diff --git a/tests/ui/unused-crate-deps/warn-cmdline-static.stderr b/tests/ui/unused-crate-deps/warn-cmdline-static.stderr
index 65956461d64..79a3ade8719 100644
--- a/tests/ui/unused-crate-deps/warn-cmdline-static.stderr
+++ b/tests/ui/unused-crate-deps/warn-cmdline-static.stderr
@@ -1,9 +1,10 @@
-warning: external crate `bar` unused in `warn_cmdline_static`: remove the dependency or add `use bar as _;`
+warning: extern crate `bar` is unused in crate `warn_cmdline_static`
   --> $DIR/warn-cmdline-static.rs:9:1
    |
 LL | fn main() {}
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
    = note: requested on the command line with `-W unused-crate-dependencies`
 
 warning: 1 warning emitted
diff --git a/tests/ui/unused-crate-deps/warn-cmdline.rs b/tests/ui/unused-crate-deps/warn-cmdline.rs
index 8d390e02ca5..cdeff5e5f60 100644
--- a/tests/ui/unused-crate-deps/warn-cmdline.rs
+++ b/tests/ui/unused-crate-deps/warn-cmdline.rs
@@ -6,4 +6,4 @@
 //@ aux-crate:bar=bar.rs
 
 fn main() {}
-//~^ WARNING external crate `bar` unused in
+//~^ WARNING extern crate `bar` is unused in
diff --git a/tests/ui/unused-crate-deps/warn-cmdline.stderr b/tests/ui/unused-crate-deps/warn-cmdline.stderr
index ea675ba9a1e..f5df83ca884 100644
--- a/tests/ui/unused-crate-deps/warn-cmdline.stderr
+++ b/tests/ui/unused-crate-deps/warn-cmdline.stderr
@@ -1,9 +1,10 @@
-warning: external crate `bar` unused in `warn_cmdline`: remove the dependency or add `use bar as _;`
+warning: extern crate `bar` is unused in crate `warn_cmdline`
   --> $DIR/warn-cmdline.rs:8:1
    |
 LL | fn main() {}
    | ^
    |
+   = help: remove the dependency or add `use bar as _;` to the crate root
    = note: requested on the command line with `-W unused-crate-dependencies`
 
 warning: 1 warning emitted
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
index db155f4fa3c..3f43fbfc0cf 100644
--- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
@@ -1,7 +1,6 @@
 trait Trait<const N: Trait = bar> {
     //~^ ERROR cannot find value `bar` in this scope
     //~| ERROR cycle detected when computing type of `Trait::N`
-    //~| ERROR cycle detected when computing type of `Trait::N`
     //~| ERROR the trait `Trait` cannot be made into an object
     //~| ERROR the trait `Trait` cannot be made into an object
     //~| ERROR the trait `Trait` cannot be made into an object
@@ -11,20 +10,20 @@ trait Trait<const N: Trait = bar> {
     //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
     //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
     fn fnc<const N: Trait = u32>(&self) -> Trait {
-    //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters
-    //~| ERROR expected value, found builtin type `u32`
-    //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-    //~| ERROR associated item referring to unboxed trait object for its own trait
-    //~| ERROR the trait `Trait` cannot be made into an object
-    //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
-    //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
-    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-    //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
-    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-    //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
-    //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+        //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters
+        //~| ERROR expected value, found builtin type `u32`
+        //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+        //~| ERROR associated item referring to unboxed trait object for its own trait
+        //~| ERROR the trait `Trait` cannot be made into an object
+        //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
+        //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+        //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+        //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+        //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+        //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
+        //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
         bar
-    //~^ ERROR cannot find value `bar` in this scope
+        //~^ ERROR cannot find value `bar` in this scope
     }
 }
 
diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
index cf985d9d1fd..f2456f99e62 100644
--- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
+++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
@@ -1,5 +1,5 @@
 error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:18
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:18
    |
 LL | trait Trait<const N: Trait = bar> {
    |                   - first use of `N`
@@ -14,13 +14,13 @@ LL | trait Trait<const N: Trait = bar> {
    |                              ^^^ not found in this scope
 
 error[E0423]: expected value, found builtin type `u32`
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:29
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:29
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                             ^^^ not a value
 
 error[E0425]: cannot find value `bar` in this scope
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:26:9
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:25:9
    |
 LL |         bar
    |         ^^^ not found in this scope
@@ -53,28 +53,14 @@ LL | trait Trait<const N: Trait = bar> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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 `Trait::N`
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13
-   |
-LL | trait Trait<const N: Trait = bar> {
-   |             ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which immediately requires computing type of `Trait::N` again
-note: cycle used when computing explicit predicates of trait `Trait`
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
-   |
-LL | trait Trait<const N: Trait = bar> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = 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: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:12
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:12
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |            ^^^^^^^^^^^^^^^^^^^^
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                     ^^^^^
@@ -87,7 +73,7 @@ LL |     fn fnc<const N: dyn Trait = u32>(&self) -> Trait {
    |                     +++
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:44
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                                            ^^^^^
@@ -120,7 +106,7 @@ LL | trait Trait<const N: Trait = bar> {
    |                      ^^^^^ `Trait` 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-122199.rs:13:8
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8
    |
 LL | trait Trait<const N: Trait = bar> {
    |       ----- this trait cannot be made into an object...
@@ -136,7 +122,7 @@ LL | trait Trait<const N: Trait = bar> {
    |             ^^^^^^^^^^^^^^^^^^^^ `Trait` 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-122199.rs:13:8
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8
    |
 LL | trait Trait<const N: Trait = bar> {
    |       ----- this trait cannot be made into an object...
@@ -154,7 +140,7 @@ LL | trait Trait<const N: Trait = bar> {
    = note: the only supported types are integers, `bool` and `char`
 
 error: associated item referring to unboxed trait object for its own trait
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:44
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44
    |
 LL | trait Trait<const N: Trait = bar> {
    |       ----- in this trait
@@ -168,7 +154,7 @@ LL |     fn fnc<const N: Trait = u32>(&self) -> Self {
    |                                            ~~~~
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                     ^^^^^
@@ -182,13 +168,13 @@ LL |     fn fnc<const N: dyn Trait = u32>(&self) -> Trait {
    |                     +++
 
 error[E0038]: the trait `Trait` cannot be made into an object
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                     ^^^^^ `Trait` 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-122199.rs:13:8
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8
    |
 LL | trait Trait<const N: Trait = bar> {
    |       ----- this trait cannot be made into an object...
@@ -204,7 +190,7 @@ LL | trait Trait<const N: Trait = bar> {
    |             ^^^^^^^^^^^^^^^^^^^^ `Trait` 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-122199.rs:13:8
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8
    |
 LL | trait Trait<const N: Trait = bar> {
    |       ----- this trait cannot be made into an object...
@@ -215,14 +201,14 @@ LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
-  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21
    |
 LL |     fn fnc<const N: Trait = u32>(&self) -> Trait {
    |                     ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
 
-error: aborting due to 14 previous errors; 5 warnings emitted
+error: aborting due to 13 previous errors; 5 warnings emitted
 
 Some errors have detailed explanations: E0038, E0391, E0403, E0423, E0425.
 For more information about an error, try `rustc --explain E0038`.
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
index 2995f26af4a..a953f1818c5 100644
--- 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
@@ -1,15 +1,11 @@
 // 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() {
-    }
+    //~^ 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 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>> {}
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
index e6fdc440873..a0fd11de2dc 100644
--- 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
@@ -13,7 +13,7 @@ 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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
    |
 LL | trait Bar<const M: Foo<2>> {}
    |                    ^^^^^^
@@ -32,7 +32,7 @@ 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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
    |
 LL | trait Bar<const M: Foo<2>> {}
    |           ^^^^^^^^^^^^^^^
@@ -44,26 +44,6 @@ 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
    |
@@ -71,43 +51,20 @@ 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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
    |
 LL | trait Foo<const N: Bar<2>> {
    |       --- this trait cannot be made into an object...
 ...
-LL |     fn func() {
+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) {
+LL |     fn func(&self) {}
    |             +++++
 help: alternatively, consider constraining `func` so it does not apply to trait objects
    |
-LL |     fn func() where Self: Sized {
+LL |     fn func() where Self: Sized {}
    |               +++++++++++++++++
 
 error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
@@ -119,61 +76,37 @@ 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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11: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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
    |
 LL | trait Foo<const N: Bar<2>> {
    |       --- this trait cannot be made into an object...
 ...
-LL |     fn func() {
+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) {
+LL |     fn func(&self) {}
    |             +++++
 help: alternatively, consider constraining `func` so it does not apply to trait objects
    |
-LL |     fn func() where Self: Sized {
+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
+  --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11: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
+error: aborting due to 5 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/tests/ui/where-clauses/self-in-where-clause-allowed.rs b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
index fd2cfe2bf65..a4c2d82b483 100644
--- a/tests/ui/where-clauses/self-in-where-clause-allowed.rs
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
@@ -1,7 +1,6 @@
 //@ check-fail
 
 #![feature(auto_traits)]
-#![deny(where_clauses_object_safety)]
 
 auto trait AutoTrait {}
 
diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
index 7f92ac102f0..5d23c4bee00 100644
--- a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied
-  --> $DIR/self-in-where-clause-allowed.rs:22:18
+  --> $DIR/self-in-where-clause-allowed.rs:21:18
    |
 LL |     trait_object.autotrait_bound();
    |                  ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait`
    |
 note: required by a bound in `Trait::autotrait_bound`
-  --> $DIR/self-in-where-clause-allowed.rs:13:43
+  --> $DIR/self-in-where-clause-allowed.rs:12:43
    |
 LL |     fn autotrait_bound(&self) where Self: AutoTrait {}
    |                                           ^^^^^^^^^ required by this bound in `Trait::autotrait_bound`
diff --git a/triagebot.toml b/triagebot.toml
index 23e5c0a27f3..3abff0f1c78 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -330,6 +330,7 @@ trigger_files = [
     "src/tools/compiletest",
     "src/tools/tidy",
     "src/tools/rustdoc-gui-test",
+    "src/tools/libcxx-version",
 ]
 
 [autolabel."T-infra"]
@@ -428,6 +429,12 @@ trigger_files = [
     "tests/ui/stack-protector"
 ]
 
+[autolabel."A-run-make"]
+trigger_files = [
+    "tests/run-make",
+    "src/tools/run-make-support"
+]
+
 [notify-zulip."I-prioritize"]
 zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
 topic = "#{number} {title}"
@@ -683,7 +690,13 @@ message = "Some changes occurred in GUI tests."
 cc = ["@GuillaumeGomez"]
 
 [mentions."tests/run-make/"]
-message = "Some changes occurred in run-make tests."
+message = """
+This PR modifies `tests/run-make/`. If this PR is trying to port a Makefile
+run-make test to use rmake.rs, please update the
+[run-make port tracking issue](https://github.com/rust-lang/rust/issues/121876)
+so we can track our progress. You can either modify the tracking issue
+directly, or you can comment on the tracking issue and link this PR.
+"""
 cc = ["@jieyouxu"]
 
 [mentions."src/librustdoc/html/static/css/themes/ayu.css"]
@@ -1117,6 +1130,7 @@ project-exploit-mitigations = [
 "/src/tools/tidy" =                                      ["bootstrap"]
 "/src/tools/x" =                                         ["bootstrap"]
 "/src/tools/rustdoc-gui-test" =                          ["bootstrap", "@onur-ozkan"]
+"/src/tools/libcxx-version" =                            ["@onur-ozkan"]
 
 # Enable tracking of PR review assignment
 # Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html