summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs4
-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/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.rs5
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs23
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs54
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs23
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs18
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs18
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs10
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs32
-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/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs4
-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.rs80
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs2
-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_typeck/src/closure.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs10
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs21
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs3
-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/passes.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs42
-rw-r--r--compiler/rustc_lint/src/context.rs42
-rw-r--r--compiler/rustc_lint/src/errors.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs14
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs10
-rw-r--r--compiler/rustc_lint/src/levels.rs82
-rw-r--r--compiler/rustc_lint/src/methods.rs6
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs4
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs10
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs2
-rw-r--r--compiler/rustc_lint/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/unused.rs9
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs42
-rw-r--r--compiler/rustc_macros/src/extension.rs9
-rw-r--r--compiler/rustc_middle/src/mir/query.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs125
-rw-r--r--compiler/rustc_middle/src/ty/context.rs5
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs21
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs69
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs27
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs20
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs117
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs74
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs50
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs731
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs62
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs19
-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.rs2
-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/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs4
-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_transform/src/coroutine.rs4
-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/shim.rs4
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs105
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs5
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs38
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs44
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs59
-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.rs74
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs6
-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.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs95
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs58
-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.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs117
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs78
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs84
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs203
-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.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs47
-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_ty_utils/src/consts.rs33
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs3
-rw-r--r--compiler/rustc_type_ir/src/binder.rs15
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs28
-rw-r--r--compiler/rustc_type_ir/src/interner.rs7
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs2
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs10
-rw-r--r--compiler/rustc_type_ir/src/ty_kind/closure.rs696
-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--library/core/src/cell/once.rs4
-rw-r--r--library/core/src/intrinsics/mir.rs58
-rw-r--r--library/core/src/num/f32.rs55
-rw-r--r--library/core/src/num/int_macros.rs24
-rw-r--r--library/core/src/num/uint_macros.rs31
-rw-r--r--library/core/src/str/pattern.rs2
-rw-r--r--library/core/tests/num/mod.rs29
-rw-r--r--library/std/src/sync/once_lock.rs2
-rw-r--r--library/std/src/sys/pal/unix/fs.rs3
-rw-r--r--library/std/src/sys/pal/unix/thread.rs11
-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.rs81
-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/thread/local.rs12
-rw-r--r--rustfmt.toml31
-rw-r--r--src/bootstrap/src/lib.rs3
-rw-r--r--src/doc/rustc/src/SUMMARY.md18
-rw-r--r--src/doc/rustc/src/json.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.md21
-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/types.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs2
-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/unit_return_expecting_ord.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs6
-rw-r--r--src/tools/compiletest/src/errors.rs12
-rw-r--r--src/tools/compiletest/src/main.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs51
-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/run-make-support/src/cc.rs7
-rw-r--r--src/tools/run-make-support/src/lib.rs38
-rw-r--r--src/tools/run-make-support/src/run.rs4
-rw-r--r--src/tools/rust-analyzer/Cargo.lock98
-rw-r--r--src/tools/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/command.rs16
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs227
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/term_search.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs685
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs601
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs51
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs86
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs14
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt6
-rw-r--r--tests/codegen/checked_ilog.rs20
-rw-r--r--tests/codegen/simd/packed-simd-alignment.rs44
-rw-r--r--tests/codegen/simd/packed-simd.rs44
-rw-r--r--tests/crashes/119830.rs11
-rw-r--r--tests/crashes/121134.rs20
-rw-r--r--tests/crashes/123917.rs41
-rw-r--r--tests/debuginfo/unsized.rs6
-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.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/shifts.rs13
-rw-r--r--tests/mir-opt/building/storage_live_dead_in_statics.rs5
-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/enum_opt.rs62
-rw-r--r--tests/mir-opt/gvn.rs24
-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.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_91633.rs44
-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/optimizes_into_variable.rs2
-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/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/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs9
-rw-r--r--tests/run-make-fulldeps/pretty-expanded/input.rs29
-rw-r--r--tests/run-make/bare-outfile/Makefile9
-rw-r--r--tests/run-make/bare-outfile/rmake.rs15
-rw-r--r--tests/run-make/c-link-to-rust-dylib/Makefile21
-rw-r--r--tests/run-make/c-link-to-rust-dylib/rmake.rs41
-rw-r--r--tests/run-make/cdylib/Makefile23
-rw-r--r--tests/run-make/cdylib/rmake.rs36
-rw-r--r--tests/run-make/emit-named-files/Makefile33
-rw-r--r--tests/run-make/emit-named-files/rmake.rs25
-rw-r--r--tests/run-make/emit/Makefile22
-rw-r--r--tests/run-make/emit/rmake.rs19
-rw-r--r--tests/run-make/mixing-formats/Makefile75
-rw-r--r--tests/run-make/mixing-formats/rmake.rs94
-rw-r--r--tests/run-make/notify-all-emit-artifacts/lib.rs21
-rw-r--r--tests/run-make/notify-all-emit-artifacts/rmake.rs45
-rw-r--r--tests/run-make/print-check-cfg/rmake.rs164
-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/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/doc-alias.rs6
-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/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/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/unable-fulfill-trait.rs13
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.stderr31
-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/async-fn/impl-header.stderr2
-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/closures/closure-expected.stderr2
-rw-r--r--tests/ui/closures/coerce-unsafe-to-closure.stderr2
-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/generic_const_exprs/eval-privacy.rs1
-rw-r--r--tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr13
-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.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-71381.min.stderr20
-rw-r--r--tests/ui/const-generics/issues/issue-71381.rs2
-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_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/fn_trait_refs.stderr12
-rw-r--r--tests/ui/consts/unstable-const-fn-in-libcore.stderr4
-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/expr/malformed_closure/block_instead_of_closure_in_arg.stderr2
-rw-r--r--tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr2
-rw-r--r--tests/ui/extern/extern-wrong-value-type.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-vectorcall.stderr7
-rw-r--r--tests/ui/fn/fn-trait-formatting.stderr2
-rw-r--r--tests/ui/fn/issue-39259.stderr2
-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-68642-broken-llvm-ir.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-68643-broken-mir.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr4
-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/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/impl-trait/normalize-tait-in-const.stderr4
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.stderr4
-rw-r--r--tests/ui/issues/issue-22034.stderr2
-rw-r--r--tests/ui/issues/issue-23966.stderr2
-rw-r--r--tests/ui/issues/issue-50781.rs8
-rw-r--r--tests/ui/issues/issue-50781.stderr50
-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/issue-76168-hr-outlives-3.stderr10
-rw-r--r--tests/ui/lifetimes/issue-95023.stderr2
-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/macros/expand-full-no-resolution.stderr4
-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/mismatched_types/suggest-option-asderef-unfixable.stderr4
-rw-r--r--tests/ui/object-safety/issue-106247.rs2
-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/macro/mbe-dotdotdot-may-not-begin-a-type.rs11
-rw-r--r--tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs4
-rw-r--r--tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr10
-rw-r--r--tests/ui/polymorphization/abi_mismatch.rs20
-rw-r--r--tests/ui/polymorphization/abi_mismatch.stderr11
-rw-r--r--tests/ui/privacy/where-priv-type.rs1
-rw-r--r--tests/ui/privacy/where-priv-type.stderr13
-rw-r--r--tests/ui/resolve/fn-new-doesnt-exist.rs5
-rw-r--r--tests/ui/resolve/fn-new-doesnt-exist.stderr14
-rw-r--r--tests/ui/resolve/suggest-builder-fn.rs64
-rw-r--r--tests/ui/resolve/suggest-builder-fn.stderr51
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs24
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr69
-rw-r--r--tests/ui/simd/repr_packed.rs21
-rw-r--r--tests/ui/suggestions/deref-path-method.stderr2
-rw-r--r--tests/ui/suggestions/issue-109291.stderr1
-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/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/associated_type_bound/check-trait-object-bounds-2.stderr2
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs2
-rw-r--r--tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr2
-rw-r--r--tests/ui/traits/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/issue-87558.stderr2
-rw-r--r--tests/ui/traits/next-solver/fn-trait.stderr8
-rw-r--r--tests/ui/traits/suggest-dereferences/root-obligation.stderr4
-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/issue-63279.stderr4
-rw-r--r--tests/ui/ufcs/bad-builder.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr6
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr6
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr6
-rw-r--r--tests/ui/unsafe/initializing-ranged-via-ctor.stderr2
-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
528 files changed, 7427 insertions, 4399 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7c60d3b4bd8..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);
@@ -1361,7 +1361,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     match *predicate.self_ty().kind() {
                         ty::Param(param_ty) => Ok((
                             generics.type_param(param_ty, tcx),
-                            predicate.trait_ref.print_only_trait_path().to_string(),
+                            predicate.trait_ref.print_trait_sugared().to_string(),
                         )),
                         _ => Err(()),
                     }
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/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 a05fa967af0..291d2782c32 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -27,8 +27,9 @@ use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
-    self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
-    OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
+    self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
+    Dynamic, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType,
+    UserTypeAnnotationIndex,
 };
 use rustc_middle::ty::{GenericArgsRef, UserArgs};
 use rustc_middle::{bug, span_bug};
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_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_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 2155cabe171..a88d50cb434 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -5,7 +5,7 @@ use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeM
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
 use rustc_target::abi::{
     self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 10d3c0d0e74..a543ccbde0e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -31,7 +31,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{
-    self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
+    self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt,
+    Visibility,
 };
 use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::symbol::Symbol;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 4edef14422e..12f98eef97d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -12,7 +12,7 @@ use rustc_middle::{
     ty::{
         self,
         layout::{LayoutOf, TyAndLayout},
-        AdtDef, CoroutineArgs, Ty,
+        AdtDef, CoroutineArgs, CoroutineArgsExt, Ty,
     },
 };
 use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index bacd74f430f..2b00bb14593 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -10,7 +10,7 @@ use rustc_middle::{
     ty::{
         self,
         layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
-        AdtDef, CoroutineArgs, Ty, VariantDef,
+        AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef,
     },
 };
 use rustc_span::Symbol;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 3d2ce550b23..39bbf87bea7 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -482,8 +482,60 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             _ if name.as_str().starts_with("simd_") => {
+                // Unpack non-power-of-2 #[repr(packed, simd)] arguments.
+                // This gives them the expected layout of a regular #[repr(simd)] vector.
+                let mut loaded_args = Vec::new();
+                for (ty, arg) in arg_tys.iter().zip(args) {
+                    loaded_args.push(
+                        // #[repr(packed, simd)] vectors are passed like arrays (as references,
+                        // with reduced alignment and no padding) rather than as immediates.
+                        // We can use a vector load to fix the layout and turn the argument
+                        // into an immediate.
+                        if ty.is_simd()
+                            && let OperandValue::Ref(place) = arg.val
+                        {
+                            let (size, elem_ty) = ty.simd_size_and_type(self.tcx());
+                            let elem_ll_ty = match elem_ty.kind() {
+                                ty::Float(f) => self.type_float_from_ty(*f),
+                                ty::Int(i) => self.type_int_from_ty(*i),
+                                ty::Uint(u) => self.type_uint_from_ty(*u),
+                                ty::RawPtr(_, _) => self.type_ptr(),
+                                _ => unreachable!(),
+                            };
+                            let loaded =
+                                self.load_from_place(self.type_vector(elem_ll_ty, size), place);
+                            OperandRef::from_immediate_or_packed_pair(self, loaded, arg.layout)
+                        } else {
+                            *arg
+                        },
+                    );
+                }
+
+                let llret_ty = if ret_ty.is_simd()
+                    && let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi
+                {
+                    let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
+                    let elem_ll_ty = match elem_ty.kind() {
+                        ty::Float(f) => self.type_float_from_ty(*f),
+                        ty::Int(i) => self.type_int_from_ty(*i),
+                        ty::Uint(u) => self.type_uint_from_ty(*u),
+                        ty::RawPtr(_, _) => self.type_ptr(),
+                        _ => unreachable!(),
+                    };
+                    self.type_vector(elem_ll_ty, size)
+                } else {
+                    llret_ty
+                };
+
                 match generic_simd_intrinsic(
-                    self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
+                    self,
+                    name,
+                    callee_ty,
+                    fn_args,
+                    &loaded_args,
+                    ret_ty,
+                    llret_ty,
+                    span,
                 ) {
                     Ok(llval) => llval,
                     Err(()) => return Ok(()),
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 011d8ab57c7..7be941ed749 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
-use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
 use rustc_target::abi::{Abi, Align, FieldsShape};
 use rustc_target::abi::{Float, Int, Pointer};
 use rustc_target::abi::{Scalar, Size, Variants};
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/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 07473ee476b..2360cce55a9 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();
 
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_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/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 90b622cae65..feab5b929ac 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -113,7 +113,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
                         let constraint = with_no_trimmed_paths!(format!(
                             "~const {}",
-                            trait_ref.print_only_trait_path()
+                            trait_ref.print_trait_sugared(),
                         ));
                         suggest_constraining_type_param(
                             tcx,
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 224d17dbf52..67fbf9642bf 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -3,7 +3,7 @@
 use rustc_middle::mir;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
-use rustc_middle::ty::{self, ScalarInt, Ty};
+use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
 use rustc_target::abi::{self, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 use tracing::{instrument, trace};
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 08b97b4953e..627fd74c8d7 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -814,13 +814,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}="))
+                            }
                         }
                     }
                 }
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_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 2a4859a2478..8de2cdefa81 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)),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3904f14b0f6..76b6cbd6e53 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -342,7 +342,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)
@@ -1727,7 +1727,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..74dcd672578 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
@@ -2275,7 +2281,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/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/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 8f0aba1c38c..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,
@@ -554,7 +554,7 @@ fn infringing_fields_error(
                         if let ty::Param(_) = ty.kind() {
                             bounds.push((
                                 format!("{ty}"),
-                                trait_ref.print_only_trait_path().to_string(),
+                                trait_ref.print_trait_sugared().to_string(),
                                 Some(trait_ref.def_id),
                             ));
                         }
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 054a3af212a..eae41d28e89 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -12,7 +12,6 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_session::parse::feature_err;
 use rustc_span::{sym, ErrorGuaranteed};
-use rustc_trait_selection::traits;
 
 mod builtin;
 mod inherent_impls;
@@ -192,14 +191,14 @@ 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`.
                 // With the feature enabled, the trait is not implemented automatically,
                 // so this is valid.
             } else {
-                let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id);
+                let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id);
                 if supertrait_def_ids.any(|d| d == trait_def_id) {
                     let span = tcx.def_span(impl_def_id);
                     return Err(struct_span_code_err!(
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/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c677fa92261..71b08e29376 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -502,7 +502,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/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..2f54349d267 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -215,12 +215,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 +239,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>;
@@ -404,10 +404,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.
@@ -425,6 +423,7 @@ impl<'tcx> dyn HirTyLowerer<'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,11 +438,18 @@ 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();
 
+                if let Err(incorrect) = self.incorrect_args {
+                    if incorrect.invalid_args.contains(&(param.index as usize)) {
+                        return param.to_error(tcx, preceding_args);
+                    }
+                }
+
                 let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| {
                     if has_default {
                         tcx.check_optional_stability(
@@ -506,11 +512,17 @@ 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, preceding_args);
+                    }
+                }
                 match param.kind {
                     GenericParamDefKind::Lifetime => self
                         .lowerer
@@ -529,15 +541,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     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 {
@@ -557,7 +573,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         // 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 {
@@ -571,6 +587,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 }
             }
         }
+        if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
+            && generics.has_self
+            && !tcx.has_attr(def_id, sym::const_trait)
+        {
+            let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
+                span,
+                modifier: constness.as_str(),
+            });
+            self.set_tainted_by_errors(reported);
+            arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] });
+        }
 
         let mut args_ctx = GenericArgsCtxt {
             lowerer: self,
@@ -579,19 +606,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             generic_args: segment.args(),
             inferred_params: vec![],
             infer_args: segment.infer_args,
+            incorrect_args: &arg_count.correct,
         };
-        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 {
-                span,
-                modifier: constness.as_str(),
-            });
-            self.set_tainted_by_errors(e);
-            arg_count.correct =
-                Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
-        }
         let args = lower_generic_args(
             tcx,
             def_id,
@@ -1298,7 +1314,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_);
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 10101aa046e..3e15fddf559 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
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_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/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 061d9507a35..3d88c425524 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1347,6 +1347,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Some(rcvr),
                         rcvr_t,
                         segment.ident,
+                        expr.hir_id,
                         SelfSource::MethodCall(rcvr),
                         error,
                         Some(args),
@@ -3048,7 +3049,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);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index b40bb74d7be..58eb0c28179 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -832,6 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         None,
                         ty.normalized,
                         item_name,
+                        hir_id,
                         SelfSource::QPath(qself),
                         error,
                         args,
@@ -1117,7 +1118,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 {
@@ -1135,9 +1136,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.
             }
         }
 
@@ -1231,15 +1235,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,
@@ -1271,6 +1275,7 @@ 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> {
@@ -1313,7 +1318,7 @@ 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> {
@@ -1327,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // 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.
@@ -1352,7 +1357,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();
                             }
                         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 5723b73a328..caaf4142f7d 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 _;
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 9c64f9475cf..0825e661373 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -383,6 +383,7 @@ 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> {
@@ -419,7 +420,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/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 97a74b55c53..12ced49f92f 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1390,7 +1390,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 af7b68bc36b..daaaf630f2c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -191,6 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
+        expr_id: hir::HirId,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
         args: Option<&'tcx [hir::Expr<'tcx>]>,
@@ -216,6 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     rcvr_opt,
                     rcvr_ty,
                     item_name,
+                    expr_id,
                     source,
                     args,
                     sugg_span,
@@ -549,6 +551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
+        expr_id: hir::HirId,
         source: SelfSource<'tcx>,
         args: Option<&'tcx [hir::Expr<'tcx>]>,
         sugg_span: Span,
@@ -681,7 +684,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if matches!(source, SelfSource::QPath(_)) && args.is_some() {
-            self.find_builder_fn(&mut err, rcvr_ty);
+            self.find_builder_fn(&mut err, rcvr_ty, expr_id);
         }
 
         if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
@@ -1942,7 +1945,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Look at all the associated functions without receivers in the type's inherent impls
     /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
-    fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>) {
+    fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: hir::HirId) {
         let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
             return;
         };
@@ -1951,8 +1954,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut items = impls
             .iter()
             .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
-            // Only assoc fn with no receivers.
-            .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter)
+            // Only assoc fn with no receivers and only if
+            // they are resolvable
+            .filter(|item| {
+                matches!(item.kind, ty::AssocKind::Fn)
+                    && !item.fn_has_self_parameter
+                    && self
+                        .probe_for_name(
+                            Mode::Path,
+                            item.ident(self.tcx),
+                            None,
+                            IsSuggestion(true),
+                            rcvr_ty,
+                            expr_id,
+                            ProbeScope::TraitsInScope,
+                        )
+                        .is_ok()
+            })
             .filter_map(|item| {
                 // Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
                 let ret_ty = self
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/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_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..fe0a246abbc 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -425,7 +425,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,
                     })
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 3380f945241..e9a4cc3e04b 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -12,7 +12,7 @@ pub use SubregionOrigin::*;
 pub use ValuePairs::*;
 
 use crate::traits::{
-    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
+    self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
 };
 use error_reporting::TypeErrCtxt;
 use free_regions::RegionRelations;
@@ -424,8 +424,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 +587,7 @@ pub enum FixupError {
     UnresolvedFloatTy(FloatVid),
     UnresolvedTy(TyVid),
     UnresolvedConst(ConstVid),
+    UnresolvedEffect(EffectVid),
 }
 
 /// See the `region_obligations` field for more information.
@@ -614,6 +615,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 +739,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);
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/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/passes.rs b/compiler/rustc_interface/src/passes.rs
index 33995f80162..b678582766d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -832,7 +832,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/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ba42eae3441..87c433a5dc0 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1494,8 +1494,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
 
         let ty = cx.tcx.type_of(item.owner_id).skip_binder();
         if ty.has_inherent_projections() {
-            // Bounds of type aliases that contain opaque types or inherent projections are respected.
-            // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`.
+            // Bounds of type aliases that contain opaque types or inherent projections are
+            // respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X =
+            // Type::Inherent;`.
             return;
         }
 
@@ -2224,7 +2225,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                         hir_generics.span.shrink_to_hi().to(where_span)
                     };
 
-                // Due to macro expansions, the `full_where_span` might not actually contain all predicates.
+                // Due to macro expansions, the `full_where_span` might not actually contain all
+                // predicates.
                 if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) {
                     lint_spans.push(full_where_span);
                 } else {
@@ -2601,7 +2603,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                     };
                     // So we have at least one potentially inhabited variant. Might we have two?
                     let Some(second_variant) = potential_variants.next() else {
-                        // There is only one potentially inhabited variant. So we can recursively check that variant!
+                        // There is only one potentially inhabited variant. So we can recursively
+                        // check that variant!
                         return variant_find_init_error(
                             cx,
                             ty,
@@ -2611,10 +2614,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                             init,
                         );
                     };
-                    // So we have at least two potentially inhabited variants.
-                    // If we can prove that we have at least two *definitely* inhabited variants,
-                    // then we have a tag and hence leaving this uninit is definitely disallowed.
-                    // (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.)
+                    // So we have at least two potentially inhabited variants. If we can prove that
+                    // we have at least two *definitely* inhabited variants, then we have a tag and
+                    // hence leaving this uninit is definitely disallowed. (Leaving it zeroed could
+                    // be okay, depending on which variant is encoded as zero tag.)
                     if init == InitKind::Uninit {
                         let definitely_inhabited = (first_variant.1 as usize)
                             + (second_variant.1 as usize)
@@ -2825,7 +2828,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
 
                 let mut found_labels = Vec::new();
 
-                // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
+                // A semicolon might not actually be specified as a separator for all targets, but
+                // it seems like LLVM accepts it always.
                 let statements = template_str.split(|c| matches!(c, '\n' | ';'));
                 for statement in statements {
                     // If there's a comment, trim it from the statement
@@ -2838,7 +2842,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                         let mut chars = possible_label.chars();
 
                         let Some(start) = chars.next() else {
-                            // Empty string means a leading ':' in this section, which is not a label.
+                            // Empty string means a leading ':' in this section, which is not a
+                            // label.
                             break 'label_loop;
                         };
 
@@ -2855,12 +2860,15 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
 
                         // Labels continue with ASCII alphanumeric characters, _, or $
                         for c in chars {
-                            // Inside a template format arg, any character is permitted for the puproses of label detection
-                            // because we assume that it can be replaced with some other valid label string later.
-                            // `options(raw)` asm blocks cannot have format args, so they are excluded from this special case.
+                            // Inside a template format arg, any character is permitted for the
+                            // puproses of label detection because we assume that it can be
+                            // replaced with some other valid label string later. `options(raw)`
+                            // asm blocks cannot have format args, so they are excluded from this
+                            // special case.
                             if !raw && in_bracket {
                                 if c == '{' {
-                                    // Nested brackets are not allowed in format args, this cannot be a label.
+                                    // Nested brackets are not allowed in format args, this cannot
+                                    // be a label.
                                     break 'label_loop;
                                 }
 
@@ -2873,7 +2881,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                                 in_bracket = true;
                             } else {
                                 if !(c.is_ascii_alphanumeric() || matches!(c, '_' | '$')) {
-                                    // The potential label had an invalid character inside it, it cannot be a label.
+                                    // The potential label had an invalid character inside it, it
+                                    // cannot be a label.
                                     break 'label_loop;
                                 }
                             }
@@ -2892,7 +2901,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                         .into_iter()
                         .filter_map(|label| find_label_span(label))
                         .collect::<Vec<Span>>();
-                    // If there were labels but we couldn't find a span, combine the warnings and use the template span
+                    // If there were labels but we couldn't find a span, combine the warnings and
+                    // use the template span.
                     let target_spans: MultiSpan =
                         if spans.len() > 0 { spans.into() } else { (*template_span).into() };
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 56f07a2b5e9..9f0f116cbd0 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -94,7 +94,8 @@ enum TargetLint {
 
     /// A lint name that should give no warnings and have no effect.
     ///
-    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints.
+    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
+    /// them as tool lints.
     Ignored,
 }
 
@@ -126,12 +127,16 @@ pub enum CheckLintNameResult<'a> {
     Renamed(String),
     /// The lint has been removed due to the given reason.
     Removed(String),
-    /// The lint is from a tool. If the Option is None, then either
-    /// the lint does not exist in the tool or the code was not
-    /// compiled with the tool and therefore the lint was never
-    /// added to the `LintStore`. Otherwise the `LintId` will be
-    /// returned as if it where a rustc lint.
-    Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>),
+
+    /// The lint is from a tool. The `LintId` will be returned as if it were a
+    /// rustc lint. The `Option<String>` indicates if the lint has been
+    /// renamed.
+    Tool(&'a [LintId], Option<String>),
+
+    /// The lint is from a tool. Either the lint does not exist in the tool or
+    /// the code was not compiled with the tool and therefore the lint was
+    /// never added to the `LintStore`.
+    MissingTool,
 }
 
 impl LintStore {
@@ -384,14 +389,14 @@ impl LintStore {
                         } else {
                             // 2. The tool isn't currently running, so no lints will be registered.
                             // To avoid giving a false positive, ignore all unknown lints.
-                            CheckLintNameResult::Tool(Err((None, String::new())))
+                            CheckLintNameResult::MissingTool
                         };
                     }
                     Some(LintGroup { lint_ids, .. }) => {
-                        return CheckLintNameResult::Tool(Ok(lint_ids));
+                        return CheckLintNameResult::Tool(lint_ids, None);
                     }
                 },
-                Some(Id(id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
+                Some(Id(id)) => return CheckLintNameResult::Tool(slice::from_ref(id), None),
                 // If the lint was registered as removed or renamed by the lint tool, we don't need
                 // to treat tool_lints and rustc lints different and can use the code below.
                 _ => {}
@@ -411,7 +416,7 @@ impl LintStore {
                         return if *silent {
                             CheckLintNameResult::Ok(lint_ids)
                         } else {
-                            CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string())))
+                            CheckLintNameResult::Tool(lint_ids, Some((*name).to_string()))
                         };
                     }
                     CheckLintNameResult::Ok(lint_ids)
@@ -472,18 +477,17 @@ impl LintStore {
                     // Reaching this would be weird, but let's cover this case anyway
                     if let Some(LintAlias { name, silent }) = depr {
                         let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap();
-                        return if *silent {
-                            CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name)))
+                        if *silent {
+                            CheckLintNameResult::Tool(lint_ids, Some(complete_name))
                         } else {
-                            CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string())))
-                        };
+                            CheckLintNameResult::Tool(lint_ids, Some((*name).to_string()))
+                        }
+                    } else {
+                        CheckLintNameResult::Tool(lint_ids, Some(complete_name))
                     }
-                    CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name)))
                 }
             },
-            Some(Id(id)) => {
-                CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
-            }
+            Some(Id(id)) => CheckLintNameResult::Tool(slice::from_ref(id), Some(complete_name)),
             Some(other) => {
                 debug!("got renamed lint {:?}", other);
                 CheckLintNameResult::NoLint(None)
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index c23d1221bc8..46dfaf0b83f 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -16,7 +16,7 @@ pub struct OverruledAttribute<'a> {
     #[subdiagnostic]
     pub sub: OverruledAttributeSub,
 }
-//
+
 pub enum OverruledAttributeSub {
     DefaultSource { id: String },
     NodeSource { span: Span, reason: Option<Symbol> },
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 6e291a327fa..9110cccdc46 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -18,11 +18,11 @@ use rustc_span::Span;
 use tracing::debug;
 
 declare_tool_lint! {
-    /// The `default_hash_type` lint detects use of [`std::collections::HashMap`]/[`std::collections::HashSet`],
-    /// suggesting the use of `FxHashMap`/`FxHashSet`.
+    /// The `default_hash_type` lint detects use of [`std::collections::HashMap`] and
+    /// [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`.
     ///
-    /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is not
-    /// required as input is assumed to be trusted.
+    /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is
+    /// not required as input is assumed to be trusted.
     pub rustc::DEFAULT_HASH_TYPES,
     Allow,
     "forbid HashMap and HashSet and suggest the FxHash* variants",
@@ -35,7 +35,7 @@ impl LateLintPass<'_> for DefaultHashTypes {
     fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
         let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
         if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) {
-            // don't lint imports, only actual usages
+            // Don't lint imports, only actual usages.
             return;
         }
         let preferred = match cx.tcx.get_diagnostic_name(def_id) {
@@ -75,8 +75,8 @@ declare_tool_lint! {
     /// potential query instability, such as iterating over a `HashMap`.
     ///
     /// Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model,
-    /// queries must return deterministic, stable results. `HashMap` iteration order can change between compilations,
-    /// and will introduce instability if query results expose the order.
+    /// queries must return deterministic, stable results. `HashMap` iteration order can change
+    /// between compilations, and will introduce instability if query results expose the order.
     pub rustc::POTENTIAL_QUERY_INSTABILITY,
     Allow,
     "require explicit opt-in when using potentially unstable methods or functions",
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index ea82fb9f262..e6c274ec09a 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -113,11 +113,11 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
 
         let mut top_level = true;
 
-        // We recursively walk through all patterns, so that we can catch cases where the lock is nested in a pattern.
-        // For the basic `let_underscore_drop` lint, we only look at the top level, since there are many legitimate reasons
-        // to bind a sub-pattern to an `_`, if we're only interested in the rest.
-        // But with locks, we prefer having the chance of "false positives" over missing cases, since the effects can be
-        // quite catastrophic.
+        // We recursively walk through all patterns, so that we can catch cases where the lock is
+        // nested in a pattern. For the basic `let_underscore_drop` lint, we only look at the top
+        // level, since there are many legitimate reasons to bind a sub-pattern to an `_`, if we're
+        // only interested in the rest. But with locks, we prefer having the chance of "false
+        // positives" over missing cases, since the effects can be quite catastrophic.
         local.pat.walk_always(|pat| {
             let is_top_level = top_level;
             top_level = false;
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 84645e0ce7f..1317af50a4a 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -593,7 +593,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     let lint = UnknownLintFromCommandLine { name, suggestion, requested_level };
                     self.emit_lint(UNKNOWN_LINTS, lint);
                 }
-                CheckLintNameResult::Tool(Err((Some(_), ref replace))) => {
+                CheckLintNameResult::Tool(_, Some(ref replace)) => {
                     let name = lint_name.clone();
                     let requested_level = RequestedLevel { level, lint_name };
                     let lint = DeprecatedLintNameFromCommandLine { name, replace, requested_level };
@@ -750,7 +750,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
 
             let level = match Level::from_attr(attr) {
                 None => continue,
-                // This is the only lint level with a `LintExpectationId` that can be created from an attribute
+                // This is the only lint level with a `LintExpectationId` that can be created from
+                // an attribute.
                 Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => {
                     let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id else {
                         bug!("stable id Level::from_attr")
@@ -760,8 +761,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                         hir_id,
                         attr_index: attr_index.try_into().unwrap(),
                         lint_index,
-                        // we pass the previous unstable attr_id such that we can trace the ast id when building a map
-                        // to go from unstable to stable id.
+                        // We pass the previous unstable attr_id such that we can trace the ast id
+                        // when building a map to go from unstable to stable id.
                         attr_id: Some(attr_id),
                     };
 
@@ -860,13 +861,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     self.store.check_lint_name(&name, tool_name, self.registered_tools);
                 match &lint_result {
                     CheckLintNameResult::Ok(ids) => {
-                        // This checks for instances where the user writes `#[expect(unfulfilled_lint_expectations)]`
-                        // in that case we want to avoid overriding the lint level but instead add an expectation that
-                        // can't be fulfilled. The lint message will include an explanation, that the
+                        // This checks for instances where the user writes
+                        // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid
+                        // overriding the lint level but instead add an expectation that can't be
+                        // fulfilled. The lint message will include an explanation, that the
                         // `unfulfilled_lint_expectations` lint can't be expected.
                         if let Level::Expect(expect_id) = level {
-                            // The `unfulfilled_lint_expectations` lint is not part of any lint groups. Therefore. we
-                            // only need to check the slice if it contains a single lint.
+                            // The `unfulfilled_lint_expectations` lint is not part of any lint
+                            // groups. Therefore. we only need to check the slice if it contains a
+                            // single lint.
                             let is_unfulfilled_lint_expectations = match ids {
                                 [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS),
                                 _ => false,
@@ -899,32 +902,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                         }
                     }
 
-                    CheckLintNameResult::Tool(result) => {
-                        match *result {
-                            Ok(ids) => {
+                    CheckLintNameResult::Tool(ids, new_lint_name) => {
+                        let src = match new_lint_name {
+                            None => {
                                 let complete_name =
                                     &format!("{}::{}", tool_ident.unwrap().name, name);
-                                let src = LintLevelSource::Node {
+                                LintLevelSource::Node {
                                     name: Symbol::intern(complete_name),
                                     span: sp,
                                     reason,
-                                };
-                                for &id in ids {
-                                    if self.check_gated_lint(id, attr.span, false) {
-                                        self.insert_spec(id, (level, src));
-                                    }
-                                }
-                                if let Level::Expect(expect_id) = level {
-                                    self.provider.push_expectation(
-                                        expect_id,
-                                        LintExpectation::new(reason, sp, false, tool_name),
-                                    );
                                 }
                             }
-                            Err((Some(ids), ref new_lint_name)) => {
-                                let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                            Some(new_lint_name) => {
                                 self.emit_span_lint(
-                                    lint,
+                                    builtin::RENAMED_AND_REMOVED_LINTS,
                                     sp.into(),
                                     DeprecatedLintName {
                                         name,
@@ -932,29 +923,31 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                                         replace: new_lint_name,
                                     },
                                 );
-
-                                let src = LintLevelSource::Node {
+                                LintLevelSource::Node {
                                     name: Symbol::intern(new_lint_name),
                                     span: sp,
                                     reason,
-                                };
-                                for id in ids {
-                                    self.insert_spec(*id, (level, src));
-                                }
-                                if let Level::Expect(expect_id) = level {
-                                    self.provider.push_expectation(
-                                        expect_id,
-                                        LintExpectation::new(reason, sp, false, tool_name),
-                                    );
                                 }
                             }
-                            Err((None, _)) => {
-                                // If Tool(Err(None, _)) is returned, then either the lint does not
-                                // exist in the tool or the code was not compiled with the tool and
-                                // therefore the lint was never added to the `LintStore`. To detect
-                                // this is the responsibility of the lint tool.
+                        };
+                        for &id in *ids {
+                            if self.check_gated_lint(id, attr.span, false) {
+                                self.insert_spec(id, (level, src));
                             }
                         }
+                        if let Level::Expect(expect_id) = level {
+                            self.provider.push_expectation(
+                                expect_id,
+                                LintExpectation::new(reason, sp, false, tool_name),
+                            );
+                        }
+                    }
+
+                    CheckLintNameResult::MissingTool => {
+                        // If `MissingTool` is returned, then either the lint does not
+                        // exist in the tool or the code was not compiled with the tool and
+                        // therefore the lint was never added to the `LintStore`. To detect
+                        // this is the responsibility of the lint tool.
                     }
 
                     &CheckLintNameResult::NoTool => {
@@ -997,7 +990,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                 // we don't warn about the name change.
                 if let CheckLintNameResult::Renamed(new_name) = lint_result {
                     // Ignore any errors or warnings that happen because the new name is inaccurate
-                    // NOTE: `new_name` already includes the tool name, so we don't have to add it again.
+                    // NOTE: `new_name` already includes the tool name, so we don't have to add it
+                    // again.
                     let CheckLintNameResult::Ok(ids) =
                         self.store.check_lint_name(&new_name, None, self.registered_tools)
                     else {
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index b93245d58d9..7a71fec769f 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -25,9 +25,9 @@ declare_lint! {
     ///
     /// The inner pointer of a `CString` lives only as long as the `CString` it
     /// points to. Getting the inner pointer of a *temporary* `CString` allows the `CString`
-    /// to be dropped at the end of the statement, as it is not being referenced as far as the typesystem
-    /// is concerned. This means outside of the statement the pointer will point to freed memory, which
-    /// causes undefined behavior if the pointer is later dereferenced.
+    /// to be dropped at the end of the statement, as it is not being referenced as far as the
+    /// typesystem is concerned. This means outside of the statement the pointer will point to
+    /// freed memory, which causes undefined behavior if the pointer is later dereferenced.
     pub TEMPORARY_CSTRING_AS_PTR,
     Warn,
     "detects getting the inner pointer of a temporary `CString`"
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/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 5135996186a..d7ffc34d824 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -306,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
     }
 }
 
-// Detecting if the impl definition is leaking outside of it's defining scope.
+// Detecting if the impl definition is leaking outside of its defining scope.
 //
 // Rule: for each impl, instantiate all local types with inference vars and
 // then assemble candidates for that goal, if there are more than 1 (non-private
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index dbb0644cd63..d64f4447162 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -297,14 +297,14 @@ impl NonSnakeCase {
             // We cannot provide meaningful suggestions
             // if the characters are in the category of "Uppercase Letter".
             let sub = if name != sc {
-                // We have a valid span in almost all cases, but we don't have one when linting a crate
-                // name provided via the command line.
+                // We have a valid span in almost all cases, but we don't have one when linting a
+                // crate name provided via the command line.
                 if !span.is_dummy() {
                     let sc_ident = Ident::from_str_and_span(&sc, span);
                     if sc_ident.is_reserved() {
-                        // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers.
-                        // Instead, recommend renaming the identifier entirely or, if permitted,
-                        // escaping it to create a raw identifier.
+                        // We shouldn't suggest a reserved identifier to fix non-snake-case
+                        // identifiers. Instead, recommend renaming the identifier entirely or, if
+                        // permitted, escaping it to create a raw identifier.
                         if sc_ident.name.can_be_raw() {
                             NonSnakeCaseDiagSub::RenameOrConvertSuggestion {
                                 span,
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/passes.rs b/compiler/rustc_lint/src/passes.rs
index c4f5f152de5..2a843977990 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -237,5 +237,5 @@ macro_rules! declare_combined_early_lint_pass {
 }
 
 /// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
-pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>;
+pub(crate) type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
+pub(crate) type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>;
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a6993547c8f..c8da9f179e7 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -387,7 +387,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             }
         }
 
-        // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored.
+        // Returns whether further errors should be suppressed because either a lint has been
+        // emitted or the type should be ignored.
         fn check_must_use_def(
             cx: &LateContext<'_>,
             def_id: DefId,
@@ -677,7 +678,8 @@ trait UnusedDelimLint {
             return true;
         }
 
-        // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`.
+        // Check if LHS needs parens to prevent false-positives in cases like
+        // `fn x() -> u8 { ({ 0 } + 1) }`.
         //
         // FIXME: https://github.com/rust-lang/rust/issues/119426
         // The syntax tree in this code is from after macro expansion, so the
@@ -722,7 +724,8 @@ trait UnusedDelimLint {
             }
         }
 
-        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`.
+        // Check if RHS needs parens to prevent false-positives in cases like `if (() == return)
+        // {}`.
         if !followed_by_block {
             return false;
         }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 93995fe60a3..a3044489fdc 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -136,7 +136,6 @@ declare_lint_pass! {
         USELESS_DEPRECATED,
         WARNINGS,
         WASM_C_ABI,
-        WHERE_CLAUSES_OBJECT_SAFETY,
         WRITES_THROUGH_IMMUTABLE_POINTER,
         // tidy-alphabetical-end
     ]
@@ -2094,47 +2093,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.
     ///
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_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 9d70231be3b..46b38e4a6a6 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,7 +1,7 @@
 //! Values computed by queries that use MIR.
 
 use crate::mir;
-use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
+use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LocalDefId;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d72ad09f954..3c4aae73bc4 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) }
     }
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 6416bbbe889..384a4e7009d 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
 pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
 
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
+rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
 
 /// Use this rather than `ConstData`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
@@ -58,7 +58,7 @@ pub struct ConstData<'tcx> {
 }
 
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(ConstData<'_>, 40);
+rustc_data_structures::static_assert_size!(ConstData<'_>, 32);
 
 impl<'tcx> Const<'tcx> {
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index d7ae050ed4d..5f29acf5ed2 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,125 @@ 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 Iterator<Item = Const<'tcx>>,
+    ) -> Self {
+        let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
+            [func_ty.into(), func_expr.into()].into_iter().chain(arguments.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/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c2219fba023..47f66c64406 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -90,7 +90,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type AdtDef = ty::AdtDef<'tcx>;
 
     type GenericArgs = ty::GenericArgsRef<'tcx>;
-    type OwnItemArgs = &'tcx [ty::GenericArg<'tcx>];
+    type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
     type GenericArg = ty::GenericArg<'tcx>;
     type Term = ty::Term<'tcx>;
 
@@ -113,7 +113,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     type ErrorGuaranteed = ErrorGuaranteed;
     type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
-    type PolyFnSig = PolyFnSig<'tcx>;
     type AllocId = crate::mir::interpret::AllocId;
 
     type Pat = Pattern<'tcx>;
@@ -191,7 +190,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self,
         def_id: Self::DefId,
         args: Self::GenericArgs,
-    ) -> (rustc_type_ir::TraitRef<Self>, Self::OwnItemArgs) {
+    ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
         assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
         let trait_def_id = self.parent(def_id);
         assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 4de7d532c96..93a51d3a334 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -374,26 +374,7 @@ impl FlagComputation {
                 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::Expr(e) => self.add_args(e.args()),
             ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
         }
     }
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 7a516b9f2c8..c3ab755175d 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -2,9 +2,10 @@
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs};
 use crate::ty::visit::{TypeVisitable, TypeVisitor};
-use crate::ty::{self, Lift, List, Ty, TyCtxt};
+use crate::ty::{
+    self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt,
+};
 
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_ast_ir::walk_visitable_list;
@@ -56,6 +57,64 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
     ) -> ty::GenericArgsRef<'tcx> {
         ty::GenericArgs::extend_with_error(tcx, def_id, original_args)
     }
+
+    fn split_closure_args(self) -> ty::ClosureArgsParts<TyCtxt<'tcx>> {
+        match self[..] {
+            [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+                ty::ClosureArgsParts {
+                    parent_args,
+                    closure_kind_ty: closure_kind_ty.expect_ty(),
+                    closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(),
+                    tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
+                }
+            }
+            _ => bug!("closure args missing synthetics"),
+        }
+    }
+
+    fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<TyCtxt<'tcx>> {
+        match self[..] {
+            [
+                ref parent_args @ ..,
+                closure_kind_ty,
+                signature_parts_ty,
+                tupled_upvars_ty,
+                coroutine_captures_by_ref_ty,
+                coroutine_witness_ty,
+            ] => ty::CoroutineClosureArgsParts {
+                parent_args,
+                closure_kind_ty: closure_kind_ty.expect_ty(),
+                signature_parts_ty: signature_parts_ty.expect_ty(),
+                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
+                coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
+                coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
+            },
+            _ => bug!("closure args missing synthetics"),
+        }
+    }
+
+    fn split_coroutine_args(self) -> ty::CoroutineArgsParts<TyCtxt<'tcx>> {
+        match self[..] {
+            [
+                ref parent_args @ ..,
+                kind_ty,
+                resume_ty,
+                yield_ty,
+                return_ty,
+                witness,
+                tupled_upvars_ty,
+            ] => ty::CoroutineArgsParts {
+                parent_args,
+                kind_ty: kind_ty.expect_ty(),
+                resume_ty: resume_ty.expect_ty(),
+                yield_ty: yield_ty.expect_ty(),
+                return_ty: return_ty.expect_ty(),
+                witness: witness.expect_ty(),
+                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
+            },
+            _ => bug!("coroutine args missing synthetics"),
+        }
+    }
 }
 
 impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
@@ -295,7 +354,7 @@ impl<'tcx> GenericArgs<'tcx> {
     /// Closure args have a particular structure controlled by the
     /// compiler that encodes information like the signature and closure kind;
     /// see `ty::ClosureArgs` struct for more comments.
-    pub fn as_closure(&'tcx self) -> ClosureArgs<'tcx> {
+    pub fn as_closure(&'tcx self) -> ClosureArgs<TyCtxt<'tcx>> {
         ClosureArgs { args: self }
     }
 
@@ -303,7 +362,7 @@ impl<'tcx> GenericArgs<'tcx> {
     /// Coroutine-closure args have a particular structure controlled by the
     /// compiler that encodes information like the signature and closure kind;
     /// see `ty::CoroutineClosureArgs` struct for more comments.
-    pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<'tcx> {
+    pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<TyCtxt<'tcx>> {
         CoroutineClosureArgs { args: self }
     }
 
@@ -311,7 +370,7 @@ impl<'tcx> GenericArgs<'tcx> {
     /// Coroutine args have a particular structure controlled by the
     /// compiler that encodes information like the signature and coroutine kind;
     /// see `ty::CoroutineArgs` struct for more comments.
-    pub fn as_coroutine(&'tcx self) -> CoroutineArgs<'tcx> {
+    pub fn as_coroutine(&'tcx self) -> CoroutineArgs<TyCtxt<'tcx>> {
         CoroutineArgs { args: self }
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 60ce8744032..a2df90b2c0f 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt};
 use rustc_error_messages::DiagMessage;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
@@ -827,25 +827,14 @@ where
                         });
                     }
 
-                    let mk_dyn_vtable = || {
+                    let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
+                        let min_count = ty::vtable_min_entries(tcx, principal);
                         Ty::new_imm_ref(
                             tcx,
                             tcx.lifetimes.re_static,
-                            Ty::new_array(tcx, tcx.types.usize, 3),
+                            // FIXME: properly type (e.g. usize and fn pointers) the fields.
+                            Ty::new_array(tcx, tcx.types.usize, min_count.try_into().unwrap()),
                         )
-                        /* FIXME: use actual fn pointers
-                        Warning: naively computing the number of entries in the
-                        vtable by counting the methods on the trait + methods on
-                        all parent traits does not work, because some methods can
-                        be not object safe and thus excluded from the vtable.
-                        Increase this counter if you tried to implement this but
-                        failed to do it without duplicating a lot of code from
-                        other places in the compiler: 2
-                        Ty::new_tup(tcx,&[
-                            Ty::new_array(tcx,tcx.types.usize, 3),
-                            Ty::new_array(tcx,Option<fn()>),
-                        ])
-                        */
                     };
 
                     let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
@@ -864,16 +853,16 @@ where
                         // `std::mem::uninitialized::<&dyn Trait>()`, for example.
                         if let ty::Adt(def, args) = metadata.kind()
                             && Some(def.did()) == tcx.lang_items().dyn_metadata()
-                            && args.type_at(0).is_trait()
+                            && let ty::Dynamic(data, _, ty::Dyn) = args.type_at(0).kind()
                         {
-                            mk_dyn_vtable()
+                            mk_dyn_vtable(data.principal())
                         } else {
                             metadata
                         }
                     } else {
                         match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
                             ty::Slice(_) | ty::Str => tcx.types.usize,
-                            ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(),
+                            ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
                             _ => bug!("TyAndLayout::field({:?}): not applicable", this),
                         }
                     };
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 90c154233da..c6028ef74a9 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -87,7 +87,7 @@ pub use self::closure::{
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
-    Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
+    Const, ConstData, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
@@ -113,10 +113,8 @@ pub use self::region::{
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
-    ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
-    CoroutineClosureArgsParts, CoroutineClosureSignature, EarlyBinder, FnSig, GenSig,
-    InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
-    UpvarArgs, VarianceDiagInfo,
+    CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
+    ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -626,14 +624,22 @@ impl<'tcx> Term<'tcx> {
         }
     }
 
-    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(),
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 83790db9926..1b37078e703 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;
                         }
@@ -1533,8 +1533,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 +1545,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 +1580,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 +1591,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 +1603,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)?
                 }
             }
         }
@@ -1938,7 +1924,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         Ok(())
     }
 
-    fn pretty_closure_as_impl(&mut self, closure: ty::ClosureArgs<'tcx>) -> Result<(), PrintError> {
+    fn pretty_closure_as_impl(
+        &mut self,
+        closure: ty::ClosureArgs<TyCtxt<'tcx>>,
+    ) -> Result<(), PrintError> {
         let sig = closure.sig();
         let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
 
@@ -2973,7 +2962,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> {
 
 #[derive(Debug, Copy, Clone, Lift)]
 pub struct PrintClosureAsImpl<'tcx> {
-    pub closure: ty::ClosureArgs<'tcx>,
+    pub closure: ty::ClosureArgs<TyCtxt<'tcx>>,
 }
 
 macro_rules! forward_display_to_print {
@@ -3199,7 +3188,7 @@ define_print_and_forward_display! {
         if let ty::PredicatePolarity::Negative = self.0.polarity {
             p!("!")
         }
-        p!(print(self.0.trait_ref.print_only_trait_path()));
+        p!(print(self.0.trait_ref.print_trait_sugared()));
     }
 
     PrintClosureAsImpl<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index f02b4849f83..a621d255a03 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -6,8 +6,8 @@
 
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::{
-    self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg,
-    GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
+    self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind,
+    GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -665,46 +665,18 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
                 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)
-                }
+            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::ConstMismatch(expected_found(a, b))),
-            };
-            return Ok(ty::Const::new_expr(tcx, expr, a.ty()));
+            }
+
+            let args = relation.relate(ae.args(), be.args())?;
+            return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args), a.ty()));
         }
         _ => false,
     };
@@ -756,28 +728,6 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::ClosureArgs<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::ClosureArgs<'tcx>,
-        b: ty::ClosureArgs<'tcx>,
-    ) -> RelateResult<'tcx, ty::ClosureArgs<'tcx>> {
-        let args = relate_args_invariantly(relation, a.args, b.args)?;
-        Ok(ty::ClosureArgs { args })
-    }
-}
-
-impl<'tcx> Relate<'tcx> for ty::CoroutineArgs<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::CoroutineArgs<'tcx>,
-        b: ty::CoroutineArgs<'tcx>,
-    ) -> RelateResult<'tcx, ty::CoroutineArgs<'tcx>> {
-        let args = relate_args_invariantly(relation, a.args, b.args)?;
-        Ok(ty::CoroutineArgs { args })
-    }
-}
-
 impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index af3aa3b56f7..7a291b4dbff 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)
+                )
             }
         }
     }
@@ -259,18 +279,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
     }
 }
 
-impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        f.debug_tuple("Binder")
-            .field(&this.map(|data| data.as_ref().skip_binder()))
-            .field(&this.data.bound_vars())
-            .finish()
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5f7385fccc9..879396b0678 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -16,7 +16,7 @@ use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
-use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable};
+use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
@@ -30,7 +30,6 @@ use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
 
-use super::fold::FnMutDelegate;
 use super::GenericParamDefKind;
 
 // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
@@ -60,670 +59,14 @@ impl<'tcx> Article for TyKind<'tcx> {
     }
 }
 
-/// A closure can be modeled as a struct that looks like:
-/// ```ignore (illustrative)
-/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
-/// ```
-/// where:
-///
-/// - 'l0...'li and T0...Tj are the generic parameters
-///   in scope on the function that defined the closure,
-/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
-///   is rather hackily encoded via a scalar type. See
-///   `Ty::to_opt_closure_kind` for details.
-/// - CS represents the *closure signature*, representing as a `fn()`
-///   type. For example, `fn(u32, u32) -> u32` would mean that the closure
-///   implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
-///   specified above.
-/// - U is a type parameter representing the types of its upvars, tupled up
-///   (borrowed, if appropriate; that is, if a U field represents a by-ref upvar,
-///    and the up-var has the type `Foo`, then that field of U will be `&Foo`).
-///
-/// So, for example, given this function:
-/// ```ignore (illustrative)
-/// fn foo<'a, T>(data: &'a mut T) {
-///      do(|| data.count += 1)
-/// }
-/// ```
-/// the type of the closure would be something like:
-/// ```ignore (illustrative)
-/// struct Closure<'a, T, U>(...U);
-/// ```
-/// Note that the type of the upvar is not specified in the struct.
-/// You may wonder how the impl would then be able to use the upvar,
-/// if it doesn't know it's type? The answer is that the impl is
-/// (conceptually) not fully generic over Closure but rather tied to
-/// instances with the expected upvar types:
-/// ```ignore (illustrative)
-/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
-///     ...
-/// }
-/// ```
-/// You can see that the *impl* fully specified the type of the upvar
-/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
-/// (Here, I am assuming that `data` is mut-borrowed.)
-///
-/// Now, the last question you may ask is: Why include the upvar types
-/// in an extra type parameter? The reason for this design is that the
-/// upvar types can reference lifetimes that are internal to the
-/// creating function. In my example above, for example, the lifetime
-/// `'b` represents the scope of the closure itself; this is some
-/// subset of `foo`, probably just the scope of the call to the to
-/// `do()`. If we just had the lifetime/type parameters from the
-/// enclosing function, we couldn't name this lifetime `'b`. Note that
-/// there can also be lifetimes in the types of the upvars themselves,
-/// if one of them happens to be a reference to something that the
-/// creating fn owns.
-///
-/// OK, you say, so why not create a more minimal set of parameters
-/// that just includes the extra lifetime parameters? The answer is
-/// primarily that it would be hard --- we don't know at the time when
-/// we create the closure type what the full types of the upvars are,
-/// nor do we know which are borrowed and which are not. In this
-/// design, we can just supply a fresh type parameter and figure that
-/// out later.
-///
-/// All right, you say, but why include the type parameters from the
-/// original function then? The answer is that codegen may need them
-/// when monomorphizing, and they may not appear in the upvars. A
-/// closure could capture no variables but still make use of some
-/// in-scope type parameter with a bound (e.g., if our example above
-/// had an extra `U: Default`, and the closure called `U::default()`).
-///
-/// There is another reason. This design (implicitly) prohibits
-/// closures from capturing themselves (except via a trait
-/// object). This simplifies closure inference considerably, since it
-/// means that when we infer the kind of a closure or its upvars, we
-/// don't have to handle cycles where the decisions we make for
-/// closure C wind up influencing the decisions we ought to make for
-/// closure C (which would then require fixed point iteration to
-/// handle). Plus it fixes an ICE. :P
-///
-/// ## Coroutines
-///
-/// Coroutines are handled similarly in `CoroutineArgs`. The set of
-/// type parameters is similar, but `CK` and `CS` are replaced by the
-/// following type parameters:
-///
-/// * `GS`: The coroutine's "resume type", which is the type of the
-///   argument passed to `resume`, and the type of `yield` expressions
-///   inside the coroutine.
-/// * `GY`: The "yield type", which is the type of values passed to
-///   `yield` inside the coroutine.
-/// * `GR`: The "return type", which is the type of value returned upon
-///   completion of the coroutine.
-/// * `GW`: The "coroutine witness".
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
-pub struct ClosureArgs<'tcx> {
-    /// Lifetime and type parameters from the enclosing function,
-    /// concatenated with a tuple containing the types of the upvars.
-    ///
-    /// These are separated out because codegen wants to pass them around
-    /// when monomorphizing.
-    pub args: GenericArgsRef<'tcx>,
-}
-
-/// Struct returned by `split()`.
-pub struct ClosureArgsParts<'tcx> {
-    /// This is the args of the typeck root.
-    pub parent_args: &'tcx [GenericArg<'tcx>],
-    /// Represents the maximum calling capability of the closure.
-    pub closure_kind_ty: Ty<'tcx>,
-    /// Captures the closure's signature. This closure signature is "tupled", and
-    /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`.
-    pub closure_sig_as_fn_ptr_ty: Ty<'tcx>,
-    /// The upvars captured by the closure. Remains an inference variable
-    /// until the upvar analysis, which happens late in HIR typeck.
-    pub tupled_upvars_ty: Ty<'tcx>,
-}
-
-impl<'tcx> ClosureArgs<'tcx> {
-    /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
-    /// for the closure parent, alongside additional closure-specific components.
-    pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx>) -> ClosureArgs<'tcx> {
-        ClosureArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
-                parts.closure_kind_ty.into(),
-                parts.closure_sig_as_fn_ptr_ty.into(),
-                parts.tupled_upvars_ty.into(),
-            ])),
-        }
-    }
-
-    /// Divides the closure args into their respective components.
-    /// The ordering assumed here must match that used by `ClosureArgs::new` above.
-    fn split(self) -> ClosureArgsParts<'tcx> {
-        match self.args[..] {
-            [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
-                ClosureArgsParts {
-                    parent_args,
-                    closure_kind_ty: closure_kind_ty.expect_ty(),
-                    closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(),
-                    tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
-                }
-            }
-            _ => bug!("closure args missing synthetics"),
-        }
-    }
-
-    /// Returns the generic parameters of the closure's parent.
-    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_args
-    }
-
-    /// Returns an iterator over the list of types of captured paths by the closure.
-    /// In case there was a type error in figuring out the types of the captured path, an
-    /// empty iterator is returned.
-    #[inline]
-    pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
-        match *self.tupled_upvars_ty().kind() {
-            TyKind::Error(_) => ty::List::empty(),
-            TyKind::Tuple(tys) => tys,
-            TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
-            ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
-        }
-    }
-
-    /// Returns the tuple type representing the upvars for this closure.
-    #[inline]
-    pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
-        self.split().tupled_upvars_ty
-    }
-
-    /// Returns the closure kind for this closure; may return a type
-    /// variable during inference. To get the closure kind during
-    /// inference, use `infcx.closure_kind(args)`.
-    pub fn kind_ty(self) -> Ty<'tcx> {
-        self.split().closure_kind_ty
-    }
-
-    /// Returns the `fn` pointer type representing the closure signature for this
-    /// closure.
-    // FIXME(eddyb) this should be unnecessary, as the shallowly resolved
-    // type is known at the time of the creation of `ClosureArgs`,
-    // see `rustc_hir_analysis::check::closure`.
-    pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
-        self.split().closure_sig_as_fn_ptr_ty
-    }
-
-    /// Returns the closure kind for this closure; only usable outside
-    /// of an inference context, because in that context we know that
-    /// there are no type variables.
-    ///
-    /// If you have an inference context, use `infcx.closure_kind()`.
-    pub fn kind(self) -> ty::ClosureKind {
-        self.kind_ty().to_opt_closure_kind().unwrap()
-    }
-
-    /// Extracts the signature from the closure.
-    pub fn sig(self) -> ty::PolyFnSig<'tcx> {
-        match *self.sig_as_fn_ptr_ty().kind() {
-            ty::FnPtr(sig) => sig,
-            ty => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
-        }
-    }
-
-    pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> {
-        ty::print::PrintClosureAsImpl { closure: self }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
-pub struct CoroutineClosureArgs<'tcx> {
-    pub args: GenericArgsRef<'tcx>,
-}
-
-/// See docs for explanation of how each argument is used.
-///
-/// See [`CoroutineClosureSignature`] for how these arguments are put together
-/// to make a callable [`FnSig`] suitable for typeck and borrowck.
-pub struct CoroutineClosureArgsParts<'tcx> {
-    /// This is the args of the typeck root.
-    pub parent_args: &'tcx [GenericArg<'tcx>],
-    /// Represents the maximum calling capability of the closure.
-    pub closure_kind_ty: Ty<'tcx>,
-    /// Represents all of the relevant parts of the coroutine returned by this
-    /// coroutine-closure. This signature parts type will have the general
-    /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
-    /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
-    /// coroutine returned by the coroutine-closure.
-    ///
-    /// Use `coroutine_closure_sig` to break up this type rather than using it
-    /// yourself.
-    pub signature_parts_ty: Ty<'tcx>,
-    /// The upvars captured by the closure. Remains an inference variable
-    /// until the upvar analysis, which happens late in HIR typeck.
-    pub tupled_upvars_ty: Ty<'tcx>,
-    /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
-    /// This allows us to represent the binder of the self-captures of the closure.
-    ///
-    /// For example, if the coroutine returned by the closure borrows `String`
-    /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
-    /// while the `tupled_upvars_ty`, representing the by-move version of the same
-    /// captures, will be `(String,)`.
-    pub coroutine_captures_by_ref_ty: Ty<'tcx>,
-    /// Witness type returned by the generator produced by this coroutine-closure.
-    pub coroutine_witness_ty: Ty<'tcx>,
-}
-
-impl<'tcx> CoroutineClosureArgs<'tcx> {
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        parts: CoroutineClosureArgsParts<'tcx>,
-    ) -> CoroutineClosureArgs<'tcx> {
-        CoroutineClosureArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
-                parts.closure_kind_ty.into(),
-                parts.signature_parts_ty.into(),
-                parts.tupled_upvars_ty.into(),
-                parts.coroutine_captures_by_ref_ty.into(),
-                parts.coroutine_witness_ty.into(),
-            ])),
-        }
-    }
-
-    fn split(self) -> CoroutineClosureArgsParts<'tcx> {
-        match self.args[..] {
-            [
-                ref parent_args @ ..,
-                closure_kind_ty,
-                signature_parts_ty,
-                tupled_upvars_ty,
-                coroutine_captures_by_ref_ty,
-                coroutine_witness_ty,
-            ] => CoroutineClosureArgsParts {
-                parent_args,
-                closure_kind_ty: closure_kind_ty.expect_ty(),
-                signature_parts_ty: signature_parts_ty.expect_ty(),
-                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
-                coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
-                coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
-            },
-            _ => bug!("closure args missing synthetics"),
-        }
-    }
-
-    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_args
-    }
-
-    #[inline]
-    pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
-        match self.tupled_upvars_ty().kind() {
-            TyKind::Error(_) => ty::List::empty(),
-            TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
-            TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
-            ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
-        }
-    }
-
-    #[inline]
-    pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
-        self.split().tupled_upvars_ty
-    }
-
-    pub fn kind_ty(self) -> Ty<'tcx> {
-        self.split().closure_kind_ty
-    }
-
-    pub fn kind(self) -> ty::ClosureKind {
-        self.kind_ty().to_opt_closure_kind().unwrap()
-    }
-
-    pub fn signature_parts_ty(self) -> Ty<'tcx> {
-        self.split().signature_parts_ty
-    }
-
-    pub fn coroutine_closure_sig(self) -> Binder<'tcx, CoroutineClosureSignature<'tcx>> {
-        let interior = self.coroutine_witness_ty();
-        let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() };
-        sig.map_bound(|sig| {
-            let [resume_ty, tupled_inputs_ty] = *sig.inputs() else {
-                bug!();
-            };
-            let [yield_ty, return_ty] = **sig.output().tuple_fields() else { bug!() };
-            CoroutineClosureSignature {
-                interior,
-                tupled_inputs_ty,
-                resume_ty,
-                yield_ty,
-                return_ty,
-                c_variadic: sig.c_variadic,
-                safety: sig.safety,
-                abi: sig.abi,
-            }
-        })
-    }
-
-    pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> {
-        self.split().coroutine_captures_by_ref_ty
-    }
-
-    pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
-        self.split().coroutine_witness_ty
-    }
-
-    pub fn has_self_borrows(&self) -> bool {
-        match self.coroutine_captures_by_ref_ty().kind() {
-            ty::FnPtr(sig) => sig
-                .skip_binder()
-                .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
-                .is_break(),
-            ty::Error(_) => true,
-            _ => bug!(),
-        }
-    }
-}
-/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
-/// detect only regions bound *at* the debruijn index.
-struct HasRegionsBoundAt {
-    binder: ty::DebruijnIndex,
-}
-// FIXME: Could be optimized to not walk into components with no escaping bound vars.
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt {
-    type Result = ControlFlow<()>;
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> Self::Result {
-        self.binder.shift_in(1);
-        t.super_visit_with(self)?;
-        self.binder.shift_out(1);
-        ControlFlow::Continue(())
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
-        if let ty::ReBound(binder, _) = *r
-            && self.binder == binder
-        {
-            ControlFlow::Break(())
-        } else {
-            ControlFlow::Continue(())
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
-pub struct CoroutineClosureSignature<'tcx> {
-    pub interior: Ty<'tcx>,
-    pub tupled_inputs_ty: Ty<'tcx>,
-    pub resume_ty: Ty<'tcx>,
-    pub yield_ty: Ty<'tcx>,
-    pub return_ty: Ty<'tcx>,
-
-    // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
-    // never actually differ. But we save them rather than recreating them
-    // from scratch just for good measure.
-    /// Always false
-    pub c_variadic: bool,
-    /// Always [`hir::Safety::Safe`]
-    pub safety: hir::Safety,
-    /// Always [`abi::Abi::RustCall`]
-    pub abi: abi::Abi,
-}
-
-impl<'tcx> CoroutineClosureSignature<'tcx> {
-    /// Construct a coroutine from the closure signature. Since a coroutine signature
-    /// is agnostic to the type of generator that is returned (by-ref/by-move),
-    /// the caller must specify what "flavor" of generator that they'd like to
-    /// create. Additionally, they must manually compute the upvars of the closure.
-    ///
-    /// This helper is not really meant to be used directly except for early on
-    /// during typeck, when we want to put inference vars into the kind and upvars tys.
-    /// When the kind and upvars are known, use the other helper functions.
-    pub fn to_coroutine(
-        self,
-        tcx: TyCtxt<'tcx>,
-        parent_args: &'tcx [GenericArg<'tcx>],
-        coroutine_kind_ty: Ty<'tcx>,
-        coroutine_def_id: DefId,
-        tupled_upvars_ty: Ty<'tcx>,
-    ) -> Ty<'tcx> {
-        let coroutine_args = ty::CoroutineArgs::new(
-            tcx,
-            ty::CoroutineArgsParts {
-                parent_args,
-                kind_ty: coroutine_kind_ty,
-                resume_ty: self.resume_ty,
-                yield_ty: self.yield_ty,
-                return_ty: self.return_ty,
-                witness: self.interior,
-                tupled_upvars_ty,
-            },
-        );
-
-        Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args)
-    }
-
-    /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
-    /// returned by that corresponding async fn trait.
-    ///
-    /// This function expects the upvars to have been computed already, and doesn't check
-    /// that the `ClosureKind` is actually supported by the coroutine-closure.
-    pub fn to_coroutine_given_kind_and_upvars(
-        self,
-        tcx: TyCtxt<'tcx>,
-        parent_args: &'tcx [GenericArg<'tcx>],
-        coroutine_def_id: DefId,
-        goal_kind: ty::ClosureKind,
-        env_region: ty::Region<'tcx>,
-        closure_tupled_upvars_ty: Ty<'tcx>,
-        coroutine_captures_by_ref_ty: Ty<'tcx>,
-    ) -> Ty<'tcx> {
-        let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
-            tcx,
-            goal_kind,
-            self.tupled_inputs_ty,
-            closure_tupled_upvars_ty,
-            coroutine_captures_by_ref_ty,
-            env_region,
-        );
-
-        self.to_coroutine(
-            tcx,
-            parent_args,
-            Ty::from_coroutine_closure_kind(tcx, goal_kind),
-            coroutine_def_id,
-            tupled_upvars_ty,
-        )
-    }
-
-    /// Compute the tupled upvars that a coroutine-closure's output coroutine
-    /// would return for the given `ClosureKind`.
-    ///
-    /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref"
-    /// to return a set of upvars which are borrowed with the given `env_region`.
-    ///
-    /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars'
-    /// lifetimes are related to the lifetime of the borrow on the closure made for
-    /// the call. This allows borrowck to enforce the self-borrows correctly.
-    pub fn tupled_upvars_by_closure_kind(
-        tcx: TyCtxt<'tcx>,
-        kind: ty::ClosureKind,
-        tupled_inputs_ty: Ty<'tcx>,
-        closure_tupled_upvars_ty: Ty<'tcx>,
-        coroutine_captures_by_ref_ty: Ty<'tcx>,
-        env_region: ty::Region<'tcx>,
-    ) -> Ty<'tcx> {
-        match kind {
-            ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
-                let ty::FnPtr(sig) = *coroutine_captures_by_ref_ty.kind() else {
-                    bug!();
-                };
-                let coroutine_captures_by_ref_ty = tcx.replace_escaping_bound_vars_uncached(
-                    sig.output().skip_binder(),
-                    FnMutDelegate {
-                        consts: &mut |c, t| ty::Const::new_bound(tcx, ty::INNERMOST, c, t),
-                        types: &mut |t| Ty::new_bound(tcx, ty::INNERMOST, t),
-                        regions: &mut |_| env_region,
-                    },
-                );
-                Ty::new_tup_from_iter(
-                    tcx,
-                    tupled_inputs_ty
-                        .tuple_fields()
-                        .iter()
-                        .chain(coroutine_captures_by_ref_ty.tuple_fields()),
-                )
-            }
-            ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
-                tcx,
-                tupled_inputs_ty
-                    .tuple_fields()
-                    .iter()
-                    .chain(closure_tupled_upvars_ty.tuple_fields()),
-            ),
-        }
-    }
-}
-/// Similar to `ClosureArgs`; see the above documentation for more.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
-pub struct CoroutineArgs<'tcx> {
-    pub args: GenericArgsRef<'tcx>,
-}
-
-pub struct CoroutineArgsParts<'tcx> {
-    /// This is the args of the typeck root.
-    pub parent_args: &'tcx [GenericArg<'tcx>],
-
-    /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
-    /// implementations must be distinguished since the former takes the closure's
-    /// upvars by move, and the latter takes the closure's upvars by ref.
-    ///
-    /// This field distinguishes these fields so that codegen can select the right
-    /// body for the coroutine. This has the same type representation as the closure
-    /// kind: `i8`/`i16`/`i32`.
-    ///
-    /// For regular coroutines, this field will always just be `()`.
-    pub kind_ty: Ty<'tcx>,
-
-    pub resume_ty: Ty<'tcx>,
-    pub yield_ty: Ty<'tcx>,
-    pub return_ty: Ty<'tcx>,
-
-    /// The interior type of the coroutine.
-    /// Represents all types that are stored in locals
-    /// in the coroutine's body.
-    pub witness: Ty<'tcx>,
-
-    /// The upvars captured by the closure. Remains an inference variable
-    /// until the upvar analysis, which happens late in HIR typeck.
-    pub tupled_upvars_ty: Ty<'tcx>,
-}
-
-impl<'tcx> CoroutineArgs<'tcx> {
-    /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
-    /// for the coroutine parent, alongside additional coroutine-specific components.
-    pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> {
-        CoroutineArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
-                parts.kind_ty.into(),
-                parts.resume_ty.into(),
-                parts.yield_ty.into(),
-                parts.return_ty.into(),
-                parts.witness.into(),
-                parts.tupled_upvars_ty.into(),
-            ])),
-        }
-    }
-
-    /// Divides the coroutine args into their respective components.
-    /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
-    fn split(self) -> CoroutineArgsParts<'tcx> {
-        match self.args[..] {
-            [
-                ref parent_args @ ..,
-                kind_ty,
-                resume_ty,
-                yield_ty,
-                return_ty,
-                witness,
-                tupled_upvars_ty,
-            ] => CoroutineArgsParts {
-                parent_args,
-                kind_ty: kind_ty.expect_ty(),
-                resume_ty: resume_ty.expect_ty(),
-                yield_ty: yield_ty.expect_ty(),
-                return_ty: return_ty.expect_ty(),
-                witness: witness.expect_ty(),
-                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
-            },
-            _ => bug!("coroutine args missing synthetics"),
-        }
-    }
-
-    /// Returns the generic parameters of the coroutine's parent.
-    pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent_args
-    }
-
-    // Returns the kind of the coroutine. See docs on the `kind_ty` field.
-    pub fn kind_ty(self) -> Ty<'tcx> {
-        self.split().kind_ty
-    }
-
-    /// This describes the types that can be contained in a coroutine.
-    /// It will be a type variable initially and unified in the last stages of typeck of a body.
-    /// It contains a tuple of all the types that could end up on a coroutine frame.
-    /// The state transformation MIR pass may only produce layouts which mention types
-    /// in this tuple. Upvars are not counted here.
-    pub fn witness(self) -> Ty<'tcx> {
-        self.split().witness
-    }
-
-    /// Returns an iterator over the list of types of captured paths by the coroutine.
-    /// In case there was a type error in figuring out the types of the captured path, an
-    /// empty iterator is returned.
-    #[inline]
-    pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
-        match *self.tupled_upvars_ty().kind() {
-            TyKind::Error(_) => ty::List::empty(),
-            TyKind::Tuple(tys) => tys,
-            TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
-            ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
-        }
-    }
-
-    /// Returns the tuple type representing the upvars for this coroutine.
-    #[inline]
-    pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
-        self.split().tupled_upvars_ty
-    }
-
-    /// Returns the type representing the resume type of the coroutine.
-    pub fn resume_ty(self) -> Ty<'tcx> {
-        self.split().resume_ty
-    }
-
-    /// Returns the type representing the yield type of the coroutine.
-    pub fn yield_ty(self) -> Ty<'tcx> {
-        self.split().yield_ty
-    }
-
-    /// Returns the type representing the return type of the coroutine.
-    pub fn return_ty(self) -> Ty<'tcx> {
-        self.split().return_ty
-    }
-
-    /// Returns the "coroutine signature", which consists of its resume, yield
-    /// and return types.
-    pub fn sig(self) -> GenSig<'tcx> {
-        let parts = self.split();
-        ty::GenSig {
-            resume_ty: parts.resume_ty,
-            yield_ty: parts.yield_ty,
-            return_ty: parts.return_ty,
-        }
-    }
-}
-
-impl<'tcx> CoroutineArgs<'tcx> {
+#[extension(pub trait CoroutineArgsExt<'tcx>)]
+impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
     /// Coroutine has not been resumed yet.
-    pub const UNRESUMED: usize = 0;
+    const UNRESUMED: usize = 0;
     /// Coroutine has returned or is completed.
-    pub const RETURNED: usize = 1;
+    const RETURNED: usize = 1;
     /// Coroutine has been poisoned.
-    pub const POISONED: usize = 2;
+    const POISONED: usize = 2;
 
     const UNRESUMED_NAME: &'static str = "Unresumed";
     const RETURNED_NAME: &'static str = "Returned";
@@ -731,7 +74,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
 
     /// The valid variant indices of this coroutine.
     #[inline]
-    pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
+    fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
         FIRST_VARIANT
             ..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
@@ -740,7 +83,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
     /// The discriminant for the given variant. Panics if the `variant_index` is
     /// out of range.
     #[inline]
-    pub fn discriminant_for_variant(
+    fn discriminant_for_variant(
         &self,
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
@@ -755,7 +98,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
     /// The set of all discriminants for the coroutine, enumerated with their
     /// variant indices.
     #[inline]
-    pub fn discriminants(
+    fn discriminants(
         self,
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
@@ -767,7 +110,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
 
     /// Calls `f` with a reference to the name of the enumerator for the given
     /// variant `v`.
-    pub fn variant_name(v: VariantIdx) -> Cow<'static, str> {
+    fn variant_name(v: VariantIdx) -> Cow<'static, str> {
         match v.as_usize() {
             Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME),
             Self::RETURNED => Cow::from(Self::RETURNED_NAME),
@@ -778,7 +121,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
 
     /// The type of the state discriminant used in the coroutine type.
     #[inline]
-    pub fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+    fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         tcx.types.u32
     }
 
@@ -789,7 +132,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
     /// The locals are grouped by their variant number. Note that some locals may
     /// be repeated in multiple variants.
     #[inline]
-    pub fn state_tys(
+    fn state_tys(
         self,
         def_id: DefId,
         tcx: TyCtxt<'tcx>,
@@ -805,7 +148,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
     /// This is the types of the fields of a coroutine which are not stored in a
     /// variant.
     #[inline]
-    pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
+    fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
         self.upvar_tys()
     }
 }
@@ -859,7 +202,7 @@ impl<'tcx> UpvarArgs<'tcx> {
 ///
 /// When the inline const is instantiated, `R` is instantiated as the actual inferred
 /// type of the constant. The reason that `R` is represented as an extra type parameter
-/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters:
+/// is the same reason that [`ty::ClosureArgs`] have `CS` and `U` as type parameters:
 /// inline const can reference lifetimes that are internal to the creating function.
 #[derive(Copy, Clone, Debug)]
 pub struct InlineConstArgs<'tcx> {
@@ -938,13 +281,6 @@ impl BoundVariableKind {
     }
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct GenSig<'tcx> {
-    pub resume_ty: Ty<'tcx>,
-    pub yield_ty: Ty<'tcx>,
-    pub return_ty: Ty<'tcx>,
-}
-
 pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
 pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
 
@@ -1451,6 +787,41 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     ) -> Self {
         Ty::new_alias(interner, kind, alias_ty)
     }
+
+    fn new_coroutine(
+        interner: TyCtxt<'tcx>,
+        def_id: DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> Self {
+        Ty::new_coroutine(interner, def_id, args)
+    }
+
+    fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
+    where
+        It: Iterator<Item = T>,
+        T: CollectAndApply<Self, Self>,
+    {
+        Ty::new_tup_from_iter(interner, iter)
+    }
+
+    fn tuple_fields(self) -> &'tcx ty::List<Ty<'tcx>> {
+        self.tuple_fields()
+    }
+
+    fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
+        self.to_opt_closure_kind()
+    }
+
+    fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self {
+        Ty::from_closure_kind(interner, kind)
+    }
+
+    fn from_coroutine_closure_kind(
+        interner: TyCtxt<'tcx>,
+        kind: rustc_type_ir::ClosureKind,
+    ) -> Self {
+        Ty::from_coroutine_closure_kind(interner, kind)
+    }
 }
 
 /// Type utilities
@@ -2169,8 +1540,8 @@ impl<'tcx> Ty<'tcx> {
     /// }
     /// ```
     ///
-    /// After upvar analysis, you should instead use [`ClosureArgs::kind()`]
-    /// or [`CoroutineClosureArgs::kind()`] to assert that the `ClosureKind`
+    /// After upvar analysis, you should instead use [`ty::ClosureArgs::kind()`]
+    /// or [`ty::CoroutineClosureArgs::kind()`] to assert that the `ClosureKind`
     /// has been constrained instead of manually calling this method.
     ///
     /// ```rust,ignore (snippet of compiler code)
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index b8371cc2bca..dc3c84f9e43 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -3,6 +3,8 @@ use std::fmt;
 use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
 use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
 use rustc_ast::Mutability;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 
 #[derive(Clone, Copy, PartialEq, HashStable)]
@@ -40,12 +42,69 @@ impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
 impl<'tcx> TyCtxt<'tcx> {
     pub const COMMON_VTABLE_ENTRIES: &'tcx [VtblEntry<'tcx>] =
         &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign];
+
+    pub fn supertrait_def_ids(self, trait_def_id: DefId) -> SupertraitDefIds<'tcx> {
+        SupertraitDefIds {
+            tcx: self,
+            stack: vec![trait_def_id],
+            visited: Some(trait_def_id).into_iter().collect(),
+        }
+    }
 }
 
 pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
 pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1;
 pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
 
+pub struct SupertraitDefIds<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    stack: Vec<DefId>,
+    visited: FxHashSet<DefId>,
+}
+
+impl Iterator for SupertraitDefIds<'_> {
+    type Item = DefId;
+
+    fn next(&mut self) -> Option<DefId> {
+        let def_id = self.stack.pop()?;
+        let predicates = self.tcx.super_predicates_of(def_id);
+        let visited = &mut self.visited;
+        self.stack.extend(
+            predicates
+                .predicates
+                .iter()
+                .filter_map(|(pred, _)| pred.as_trait_clause())
+                .map(|trait_ref| trait_ref.def_id())
+                .filter(|&super_def_id| visited.insert(super_def_id)),
+        );
+        Some(def_id)
+    }
+}
+
+// Note that we don't have access to a self type here, this has to be purely based on the trait (and
+// supertrait) definitions. That means we can't call into the same vtable_entries code since that
+// returns a specific instantiation (e.g., with Vacant slots when bounds aren't satisfied). The goal
+// here is to do a best-effort approximation without duplicating a lot of code.
+//
+// This function is used in layout computation for e.g. &dyn Trait, so it's critical that this
+// function is an accurate approximation. We verify this when actually computing the vtable below.
+pub(crate) fn vtable_min_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+) -> usize {
+    let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len();
+    let Some(trait_ref) = trait_ref else {
+        return count;
+    };
+
+    // This includes self in supertraits.
+    for def_id in tcx.supertrait_def_ids(trait_ref.def_id()) {
+        count += tcx.own_existential_vtable_entries(def_id).len();
+    }
+
+    count
+}
+
 /// Retrieves an allocation that represents the contents of a vtable.
 /// Since this is a query, allocations are cached and not duplicated.
 pub(super) fn vtable_allocation_provider<'tcx>(
@@ -63,6 +122,9 @@ pub(super) fn vtable_allocation_provider<'tcx>(
         TyCtxt::COMMON_VTABLE_ENTRIES
     };
 
+    // This confirms that the layout computation for &dyn Trait has an accurate sizing.
+    assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref));
+
     let layout = tcx
         .layout_of(ty::ParamEnv::reveal_all().and(ty))
         .expect("failed to build vtable representation");
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a9421aacff8..58f69d772ec 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -222,24 +222,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 | 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::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/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..f7229326c54 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -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>,
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/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..659ae172460 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -597,7 +597,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 +737,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_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index a3e6e5a5a91..84512e81637 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -69,7 +69,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::CoroutineArgs;
 use rustc_middle::ty::InstanceDef;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
@@ -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/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/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index dcf54ad2cfc..d03c2d18c0c 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -4,7 +4,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
@@ -634,7 +634,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         dest: Place<'tcx>,
         src: Place<'tcx>,
         coroutine_def_id: DefId,
-        args: CoroutineArgs<'tcx>,
+        args: CoroutineArgs<TyCtxt<'tcx>>,
     ) {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
         let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 851e1655958..3b4d4c93877 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -8,7 +8,10 @@ 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::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
+use rustc_middle::ty::adjustment::PointerCoercion;
+use rustc_middle::ty::{
+    self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{Size, FIRST_VARIANT};
 use rustc_target::spec::abi::Abi;
@@ -1132,9 +1135,76 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         // FIXME(dyn-star): make sure nothing needs to be done here.
                     }
                     // FIXME: Add Checks for these
-                    CastKind::PointerWithExposedProvenance
-                    | CastKind::PointerExposeProvenance
-                    | CastKind::PointerCoercion(_) => {}
+                    CastKind::PointerWithExposedProvenance | CastKind::PointerExposeProvenance => {}
+                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
+                        // FIXME: check signature compatibility.
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a fn item, not {:?}",
+                            ty::FnDef(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a fn pointer, not {:?}",
+                            ty::FnPtr(..)
+                        );
+                    }
+                    CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
+                        // FIXME: check safety and signature compatibility.
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a fn pointer, not {:?}",
+                            ty::FnPtr(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a fn pointer, not {:?}",
+                            ty::FnPtr(..)
+                        );
+                    }
+                    CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..)) => {
+                        // FIXME: check safety, captures, and signature compatibility.
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a closure, not {:?}",
+                            ty::Closure(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a fn pointer, not {:?}",
+                            ty::FnPtr(..)
+                        );
+                    }
+                    CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
+                        // FIXME: check same pointee?
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a raw mut pointer, not {:?}",
+                            ty::RawPtr(_, Mutability::Mut)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a raw const pointer, not {:?}",
+                            ty::RawPtr(_, Mutability::Not)
+                        );
+                    }
+                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
+                        // FIXME: Check pointee types
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a raw pointer, not {:?}",
+                            ty::RawPtr(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a raw pointer, not {:?}",
+                            ty::RawPtr(..)
+                        );
+                    }
+                    CastKind::PointerCoercion(PointerCoercion::Unsize) => {
+                        // This is used for all `CoerceUnsized` types,
+                        // not just pointers/references, so is hard to check.
+                    }
                     CastKind::IntToInt | CastKind::IntToFloat => {
                         let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
                         let target_valid = target_type.is_numeric() || target_type.is_char();
@@ -1145,10 +1215,29 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             );
                         }
                     }
-                    CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
-                        if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
-                            self.fail(location, "Can't cast {op_ty} into 'Ptr'");
-                        }
+                    CastKind::FnPtrToPtr => {
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a fn pointer, not {:?}",
+                            ty::FnPtr(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a raw pointer, not {:?}",
+                            ty::RawPtr(..)
+                        );
+                    }
+                    CastKind::PtrToPtr => {
+                        check_kinds!(
+                            op_ty,
+                            "CastKind::{kind:?} input must be a raw pointer, not {:?}",
+                            ty::RawPtr(..)
+                        );
+                        check_kinds!(
+                            target_type,
+                            "CastKind::{kind:?} output must be a raw pointer, not {:?}",
+                            ty::RawPtr(..)
+                        );
                     }
                     CastKind::FloatToFloat | CastKind::FloatToInt => {
                         if !op_ty.is_floating_point() || !target_type.is_numeric() {
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 619c4c63e51..a0b704aeea5 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -47,7 +47,7 @@ impl<'a> Parser<'a> {
                 token.can_begin_expr()
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Let)
-                && (token.span.edition().at_least_rust_2024() || !token.is_keyword(kw::Const))
+                && (!token.is_keyword(kw::Const) || token.span.edition().at_least_rust_2024())
             }
             NonterminalKind::Ty => token.can_begin_type(),
             NonterminalKind::Ident => get_macro_ident(token).is_some(),
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 2df8f58507b..2033f387887 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -194,7 +194,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
-            AllowCVariadic::Yes,
+            AllowCVariadic::No,
             RecoverQPath::Yes,
             RecoverReturnSign::OnlyFatArrow,
             None,
@@ -344,8 +344,9 @@ impl<'a> Parser<'a> {
             match allow_c_variadic {
                 AllowCVariadic::Yes => TyKind::CVarArgs,
                 AllowCVariadic::No => {
-                    // FIXME(Centril): Should we just allow `...` syntactically
+                    // FIXME(c_variadic): Should we just allow `...` syntactically
                     // anywhere in a type and use semantic restrictions instead?
+                    // NOTE: This may regress certain MBE calls if done incorrectly.
                     let guar = self
                         .dcx()
                         .emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 4fe84b91b8b..39cb48c1af3 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2321,7 +2321,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/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_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_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_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 6ec710f97d1..edfd48ed43b 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,23 +246,10 @@ 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::Unevaluated(uneval, ty) => {
@@ -392,7 +386,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..9822ed79e2b 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;
@@ -360,7 +360,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 +377,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 +398,45 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             )));
         }
 
-        Ok(ty::Const::zero_sized(tables.tcx, ty_internal).stable(&mut *tables))
+        Ok(mir::Const::Ty(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 +481,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 +502,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..1c87293209c 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(c) => MirConst::new(
+                stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
+                c.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..1f3356f579f 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,8 +409,50 @@ 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(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_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() {
@@ -425,30 +466,27 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
                 let ty = tables.tcx.lift(self.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_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/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 08796ef3109..98f98d9992d 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -554,8 +554,8 @@ fn coroutine_closure_to_certain_coroutine<'tcx>(
     goal_kind: ty::ClosureKind,
     goal_region: ty::Region<'tcx>,
     def_id: DefId,
-    args: ty::CoroutineClosureArgs<'tcx>,
-    sig: ty::CoroutineClosureSignature<'tcx>,
+    args: ty::CoroutineClosureArgs<TyCtxt<'tcx>>,
+    sig: ty::CoroutineClosureSignature<TyCtxt<'tcx>>,
 ) -> Ty<'tcx> {
     sig.to_coroutine_given_kind_and_upvars(
         tcx,
@@ -578,8 +578,8 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
     goal_kind: ty::ClosureKind,
     goal_region: ty::Region<'tcx>,
     def_id: DefId,
-    args: ty::CoroutineClosureArgs<'tcx>,
-    sig: ty::CoroutineClosureSignature<'tcx>,
+    args: ty::CoroutineClosureArgs<TyCtxt<'tcx>>,
+    sig: ty::CoroutineClosureSignature<TyCtxt<'tcx>>,
 ) -> Ty<'tcx> {
     let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
     let tupled_upvars_ty = Ty::new_projection(
@@ -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/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/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index f9febd290fe..68a4831c335 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)
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 5d5161e092e..c60d1aed415 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;
@@ -102,7 +111,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
         &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();
@@ -142,8 +151,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
@@ -243,7 +255,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 +264,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/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 67dd3fa85fa..a741f488901 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -1,7 +1,5 @@
 //! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
 
-use crate::traits::supertrait_def_ids;
-
 use super::assembly::structural_traits::AsyncCallableRelevantTypes;
 use super::assembly::{self, structural_traits, Candidate};
 use super::{EvalCtxt, GoalSource, SolverMode};
@@ -791,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);
         }
 
@@ -837,7 +835,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         let a_auto_traits: FxIndexSet<DefId> = a_data
             .auto_traits()
             .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
-                supertrait_def_ids(self.interner(), principal_def_id)
+                self.interner()
+                    .supertrait_def_ids(principal_def_id)
                     .filter(|def_id| self.interner().trait_is_auto(*def_id))
             }))
             .collect();
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 1ea207cc375..6623a86e69f 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
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index ebdb032dc0e..7723f2229bf 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.
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 8dcbac88880..6a96a03e047 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -29,10 +29,11 @@ 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::print::PrintPolyTraitRefExt;
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
-    InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitableExt, TypeckResults, Upcast,
+    InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
@@ -219,15 +220,15 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
             (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)),
             (None, Some((ident, []))) => (
                 ident.span.shrink_to_hi(),
-                format!(": {}", trait_pred.print_modifiers_and_trait_path()),
+                format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
             ),
             (_, Some((_, [.., bounds]))) => (
                 bounds.span().shrink_to_hi(),
-                format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
+                format!(" + {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
             ),
             (Some(_), Some((_, []))) => (
                 hir_generics.span.shrink_to_hi(),
-                format!(": {}", trait_pred.print_modifiers_and_trait_path()),
+                format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()),
             ),
         };
 
@@ -1111,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 {
@@ -1128,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 {
@@ -1156,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 {
@@ -3839,7 +3840,7 @@ 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 {
                         expected: where_pred
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..9a0929baeaf 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
@@ -996,12 +995,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 +1007,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 +1017,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         }
 
-        trait_predicate
+        applied_do_not_recommend
     }
 
     fn emit_specialized_closure_kind_error(
@@ -1521,6 +1517,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..a26288efc96 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![])
@@ -840,13 +850,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 ab4d06f2660..d918945dbed 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;
@@ -65,14 +66,85 @@ pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
-pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
-    SupertraitDefIds,
-};
+pub use self::util::{supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item};
 pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
 
 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
@@ -410,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);
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 f4051561dae..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,9 +23,9 @@ 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;
 use smallvec::SmallVec;
 
 use std::iter;
@@ -44,7 +44,8 @@ pub fn hir_ty_lowering_object_safety_violations(
     trait_def_id: DefId,
 ) -> Vec<ObjectSafetyViolation> {
     debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    let violations = traits::supertrait_def_ids(tcx, trait_def_id)
+    let violations = tcx
+        .supertrait_def_ids(trait_def_id)
         .map(|def_id| predicates_reference_self(tcx, def_id, true))
         .filter(|spans| !spans.is_empty())
         .map(ObjectSafetyViolation::SupertraitSelf)
@@ -58,50 +59,19 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object
     debug!("object_safety_violations: {:?}", trait_def_id);
 
     tcx.arena.alloc_from_iter(
-        traits::supertrait_def_ids(tcx, trait_def_id)
+        tcx.supertrait_def_ids(trait_def_id)
             .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id)),
     )
 }
 
-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);
@@ -110,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(
@@ -145,6 +113,14 @@ fn object_safety_violations_for_trait(
         violations.push(ObjectSafetyViolation::SupertraitNonLifetimeBinder(spans));
     }
 
+    if violations.is_empty() {
+        for item in tcx.associated_items(trait_def_id).in_definition_order() {
+            if let ty::AssocKind::Fn = item.kind {
+                check_receiver_correct(tcx, trait_def_id, *item);
+            }
+        }
+    }
+
     debug!(
         "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
         trait_def_id, violations
@@ -153,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>,
@@ -493,59 +428,8 @@ fn virtual_call_violations_for_method<'tcx>(
             };
             errors.push(MethodViolationCode::UndispatchableReceiver(span));
         } else {
-            // Do sanity check to make sure the receiver actually has the layout of a pointer.
-
-            use rustc_target::abi::Abi;
-
-            let param_env = tcx.param_env(method.def_id);
-
-            let abi_of_ty = |ty: Ty<'tcx>| -> Option<Abi> {
-                match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => Some(layout.abi),
-                    Err(err) => {
-                        // #78372
-                        tcx.dcx().span_delayed_bug(
-                            tcx.def_span(method.def_id),
-                            format!("error: {err}\n while computing layout for type {ty:?}"),
-                        );
-                        None
-                    }
-                }
-            };
-
-            // e.g., `Rc<()>`
-            let unit_receiver_ty =
-                receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method.def_id);
-
-            match abi_of_ty(unit_receiver_ty) {
-                Some(Abi::Scalar(..)) => (),
-                abi => {
-                    tcx.dcx().span_delayed_bug(
-                        tcx.def_span(method.def_id),
-                        format!(
-                            "receiver when `Self = ()` should have a Scalar ABI; found {abi:?}"
-                        ),
-                    );
-                }
-            }
-
-            let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
-
-            // e.g., `Rc<dyn Trait>`
-            let trait_object_receiver =
-                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
-
-            match abi_of_ty(trait_object_receiver) {
-                Some(Abi::ScalarPair(..)) => (),
-                abi => {
-                    tcx.dcx().span_delayed_bug(
-                        tcx.def_span(method.def_id),
-                        format!(
-                            "receiver when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
-                        ),
-                    );
-                }
-            }
+            // We confirm that the `receiver_is_dispatchable` is accurate later,
+            // see `check_receiver_correct`. It should be kept in sync with this code.
         }
     }
 
@@ -606,6 +490,55 @@ fn virtual_call_violations_for_method<'tcx>(
     errors
 }
 
+/// This code checks that `receiver_is_dispatchable` is correctly implemented.
+///
+/// This check is outlined from the object safety check to avoid cycles with
+/// layout computation, which relies on knowing whether methods are object safe.
+pub fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) {
+    if !is_vtable_safe_method(tcx, trait_def_id, method) {
+        return;
+    }
+
+    let method_def_id = method.def_id;
+    let sig = tcx.fn_sig(method_def_id).instantiate_identity();
+    let param_env = tcx.param_env(method_def_id);
+    let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0));
+
+    if receiver_ty == tcx.types.self_param {
+        // Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable.
+        return;
+    }
+
+    // e.g., `Rc<()>`
+    let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id);
+    match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.abi) {
+        Ok(Abi::Scalar(..)) => (),
+        abi => {
+            tcx.dcx().span_delayed_bug(
+                tcx.def_span(method_def_id),
+                format!("receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}"),
+            );
+        }
+    }
+
+    let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
+
+    // e.g., `Rc<dyn Trait>`
+    let trait_object_receiver =
+        receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id);
+    match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.abi) {
+        Ok(Abi::ScalarPair(..)) => (),
+        abi => {
+            tcx.dcx().span_delayed_bug(
+                tcx.def_span(method_def_id),
+                format!(
+                    "receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
+                ),
+            );
+        }
+    }
+}
+
 /// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
 /// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
 fn receiver_for_self_ty<'tcx>(
@@ -921,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/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 fd7c47ad6fb..4d3aa067c6c 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;
@@ -946,7 +946,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 }
@@ -1004,7 +1004,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let a_auto_traits: FxIndexSet<DefId> = a_data
                         .auto_traits()
                         .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| {
-                            util::supertrait_def_ids(self.tcx(), principal_def_id)
+                            self.tcx()
+                                .supertrait_def_ids(principal_def_id)
                                 .filter(|def_id| self.tcx().trait_is_auto(*def_id))
                         }))
                         .collect();
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index c684f087d32..ef0d8735d35 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1222,7 +1222,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 92c0c37d0c3..2489b8916d1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -798,7 +798,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)
@@ -2591,8 +2591,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         let a_auto_traits: FxIndexSet<DefId> = a_data
             .auto_traits()
             .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
-                util::supertrait_def_ids(tcx, principal_def_id)
-                    .filter(|def_id| tcx.trait_is_auto(*def_id))
+                tcx.supertrait_def_ids(principal_def_id).filter(|def_id| tcx.trait_is_auto(*def_id))
             }))
             .collect();
 
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 445fa1761b9..5d5a22e189c 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
 
 use super::NormalizeExt;
 use super::{ObligationCause, PredicateObligation, SelectionContext};
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Diag;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{InferCtxt, InferOk};
@@ -162,43 +162,6 @@ impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Iterator over def-IDs of supertraits
-///////////////////////////////////////////////////////////////////////////
-
-pub struct SupertraitDefIds<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<DefId>,
-    visited: FxHashSet<DefId>,
-}
-
-pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
-    SupertraitDefIds {
-        tcx,
-        stack: vec![trait_def_id],
-        visited: Some(trait_def_id).into_iter().collect(),
-    }
-}
-
-impl Iterator for SupertraitDefIds<'_> {
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<DefId> {
-        let def_id = self.stack.pop()?;
-        let predicates = self.tcx.super_predicates_of(def_id);
-        let visited = &mut self.visited;
-        self.stack.extend(
-            predicates
-                .predicates
-                .iter()
-                .filter_map(|(pred, _)| pred.as_trait_clause())
-                .map(|trait_ref| trait_ref.def_id())
-                .filter(|&super_def_id| visited.insert(super_def_id)),
-        );
-        Some(def_id)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
 // Other
 ///////////////////////////////////////////////////////////////////////////
 
@@ -295,7 +258,7 @@ pub fn coroutine_trait_ref_and_outputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_trait_def_id: DefId,
     self_ty: Ty<'tcx>,
-    sig: ty::GenSig<'tcx>,
+    sig: ty::GenSig<TyCtxt<'tcx>>,
 ) -> (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>) {
     assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, sig.resume_ty]);
@@ -306,7 +269,7 @@ pub fn future_trait_ref_and_outputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_trait_def_id: DefId,
     self_ty: Ty<'tcx>,
-    sig: ty::GenSig<'tcx>,
+    sig: ty::GenSig<TyCtxt<'tcx>>,
 ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
     assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty]);
@@ -317,7 +280,7 @@ pub fn iterator_trait_ref_and_outputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     iterator_def_id: DefId,
     self_ty: Ty<'tcx>,
-    sig: ty::GenSig<'tcx>,
+    sig: ty::GenSig<TyCtxt<'tcx>>,
 ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
     assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = ty::TraitRef::new(tcx, iterator_def_id, [self_ty]);
@@ -328,7 +291,7 @@ pub fn async_iterator_trait_ref_and_outputs<'tcx>(
     tcx: TyCtxt<'tcx>,
     async_iterator_def_id: DefId,
     self_ty: Ty<'tcx>,
-    sig: ty::GenSig<'tcx>,
+    sig: ty::GenSig<TyCtxt<'tcx>>,
 ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
     assert!(!self_ty.has_escaping_bound_vars());
     let trait_ref = ty::TraitRef::new(tcx, async_iterator_def_id, [self_ty]);
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_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index e9112d232cb..8a42298f216 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -148,17 +148,24 @@ fn recurse_build<'tcx>(
             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.into_iter()),
+                node.ty,
+            )
         }
         &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
             let lhs = recurse_build(tcx, body, lhs, root_span)?;
             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),
+                node.ty,
+            )
         }
         &ExprKind::Unary { op, arg } if check_unop(op) => {
             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), node.ty)
         }
         // This is necessary so that the following compiles:
         //
@@ -178,12 +185,22 @@ 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),
+                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),
+                node.ty,
+            )
         }
         ExprKind::Borrow { arg, .. } => {
             let arg_node = &body.exprs[*arg];
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 1dee14fae57..6045abc50a9 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -10,7 +10,8 @@ use rustc_middle::ty::layout::{
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, AdtDef, EarlyBinder, FieldDef, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt,
+    self, AdtDef, CoroutineArgsExt, EarlyBinder, FieldDef, GenericArgsRef, Ty, TyCtxt,
+    TypeVisitableExt,
 };
 use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
 use rustc_span::sym;
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index e50d59ba5f0..9a2c9059967 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -8,11 +8,12 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use rustc_serialize::Decodable;
 use tracing::debug;
 
+use crate::debug::{DebugWithInfcx, WithInfcx};
 use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::inherent::*;
 use crate::lift::Lift;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-use crate::{self as ty, Interner, SsoHashSet};
+use crate::{self as ty, InferCtxtLike, Interner, SsoHashSet};
 
 /// Binder is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
@@ -55,6 +56,18 @@ where
     }
 }
 
+impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for ty::Binder<I, T> {
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        f.debug_tuple("Binder")
+            .field(&this.map(|data| data.as_ref().skip_binder()))
+            .field(&this.data.bound_vars())
+            .finish()
+    }
+}
+
 macro_rules! impl_binder_encode_decode {
     ($($t:ty),+ $(,)?) => {
         $(
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 7b1dfecfee2..f305ed9b5d7 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -9,7 +9,7 @@ use std::ops::Deref;
 
 use crate::fold::{TypeFoldable, TypeSuperFoldable};
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{self as ty, DebugWithInfcx, Interner, UpcastFrom};
+use crate::{self as ty, CollectAndApply, DebugWithInfcx, Interner, UpcastFrom};
 
 pub trait Ty<I: Interner<Ty = Self>>:
     Copy
@@ -34,6 +34,21 @@ pub trait Ty<I: Interner<Ty = Self>>:
     fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
 
     fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
+
+    fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
+    where
+        It: Iterator<Item = T>,
+        T: CollectAndApply<Self, Self>;
+
+    fn tuple_fields(self) -> I::Tys;
+
+    fn to_opt_closure_kind(self) -> Option<ty::ClosureKind>;
+
+    fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
+
+    fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
 }
 
 pub trait Tys<I: Interner<Tys = Self>>:
@@ -43,17 +58,18 @@ pub trait Tys<I: Interner<Tys = Self>>:
     + Eq
     + IntoIterator<Item = I::Ty>
     + Deref<Target: Deref<Target = [I::Ty]>>
-    + TypeVisitable<I>
+    + TypeFoldable<I>
+    + Default
 {
     fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty);
 }
 
-pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
+pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + TypeVisitable<I> {
     /// Whether this ABI is `extern "Rust"`.
     fn is_rust(self) -> bool;
 }
 
-pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
+pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + TypeVisitable<I> {
     fn is_safe(self) -> bool;
 
     fn prefix_str(self) -> &'static str;
@@ -129,6 +145,10 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
         def_id: I::DefId,
         original_args: &[I::GenericArg],
     ) -> I::GenericArgs;
+
+    fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
+    fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
+    fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
 }
 
 pub trait Predicate<I: Interner<Predicate = Self>>:
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 2a228c973d3..6ebb434299b 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -29,9 +29,7 @@ pub trait Interner:
     type AdtDef: Copy + Debug + Hash + Eq;
 
     type GenericArgs: GenericArgs<Self>;
-    /// The slice of args for a specific item. For a GAT like `type Foo<'a>`, it will be `['a]`,
-    /// not including the args from the parent item (trait or impl).
-    type OwnItemArgs: Copy + Debug + Hash + Eq;
+    type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref<Target = [Self::GenericArg]>;
     type GenericArg: Copy
         + DebugWithInfcx<Self>
         + Hash
@@ -69,7 +67,6 @@ pub trait Interner:
     // Things stored inside of tys
     type ErrorGuaranteed: Copy + Debug + Hash + Eq;
     type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Eq;
-    type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type AllocId: Copy + Debug + Hash + Eq;
     type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx<Self>;
     type Safety: Safety<Self>;
@@ -112,7 +109,7 @@ pub trait Interner:
         self,
         def_id: Self::DefId,
         args: Self::GenericArgs,
-    ) -> (ty::TraitRef<Self>, Self::OwnItemArgs);
+    ) -> (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;
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 48a6f79993c..e7039583c91 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -604,7 +604,7 @@ impl<I: Interner> AliasTerm<I> {
     /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
     /// then this function would return a `T: StreamingIterator` trait reference and
     /// `['a]` as the own args.
-    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::OwnItemArgs) {
+    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
         interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
     }
 
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index ddff3a24784..71f3862226d 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -7,13 +7,15 @@ use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEn
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
+pub use self::closure::*;
+use self::TyKind::*;
 use crate::inherent::*;
 use crate::{self as ty, DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
 
-use self::TyKind::*;
-
 use rustc_ast_ir::Mutability;
 
+mod closure;
+
 /// Specifies how a trait object is represented.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
@@ -141,7 +143,7 @@ pub enum TyKind<I: Interner> {
     /// fn foo() -> i32 { 1 }
     /// let bar: fn() -> i32 = foo;
     /// ```
-    FnPtr(I::PolyFnSig),
+    FnPtr(ty::Binder<I, FnSig<I>>),
 
     /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
     Dynamic(I::BoundExistentialPredicates, I::Region, DynKind),
@@ -514,7 +516,7 @@ impl<I: Interner> AliasTy<I> {
     /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
     /// then this function would return a `T: StreamingIterator` trait reference and
     /// `['a]` as the own args.
-    pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef<I>, I::OwnItemArgs) {
+    pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef<I>, I::GenericArgsSlice) {
         debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
         interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
     }
diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs
new file mode 100644
index 00000000000..97752934632
--- /dev/null
+++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs
@@ -0,0 +1,696 @@
+use std::ops::ControlFlow;
+
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
+
+use crate::fold::{shift_region, TypeFoldable, TypeFolder, TypeSuperFoldable};
+use crate::inherent::*;
+use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use crate::{self as ty, Interner};
+
+/// A closure can be modeled as a struct that looks like:
+/// ```ignore (illustrative)
+/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
+/// ```
+/// where:
+///
+/// - 'l0...'li and T0...Tj are the generic parameters
+///   in scope on the function that defined the closure,
+/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This
+///   is rather hackily encoded via a scalar type. See
+///   `Ty::to_opt_closure_kind` for details.
+/// - CS represents the *closure signature*, representing as a `fn()`
+///   type. For example, `fn(u32, u32) -> u32` would mean that the closure
+///   implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
+///   specified above.
+/// - U is a type parameter representing the types of its upvars, tupled up
+///   (borrowed, if appropriate; that is, if a U field represents a by-ref upvar,
+///    and the up-var has the type `Foo`, then that field of U will be `&Foo`).
+///
+/// So, for example, given this function:
+/// ```ignore (illustrative)
+/// fn foo<'a, T>(data: &'a mut T) {
+///      do(|| data.count += 1)
+/// }
+/// ```
+/// the type of the closure would be something like:
+/// ```ignore (illustrative)
+/// struct Closure<'a, T, U>(...U);
+/// ```
+/// Note that the type of the upvar is not specified in the struct.
+/// You may wonder how the impl would then be able to use the upvar,
+/// if it doesn't know it's type? The answer is that the impl is
+/// (conceptually) not fully generic over Closure but rather tied to
+/// instances with the expected upvar types:
+/// ```ignore (illustrative)
+/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> {
+///     ...
+/// }
+/// ```
+/// You can see that the *impl* fully specified the type of the upvar
+/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
+/// (Here, I am assuming that `data` is mut-borrowed.)
+///
+/// Now, the last question you may ask is: Why include the upvar types
+/// in an extra type parameter? The reason for this design is that the
+/// upvar types can reference lifetimes that are internal to the
+/// creating function. In my example above, for example, the lifetime
+/// `'b` represents the scope of the closure itself; this is some
+/// subset of `foo`, probably just the scope of the call to the to
+/// `do()`. If we just had the lifetime/type parameters from the
+/// enclosing function, we couldn't name this lifetime `'b`. Note that
+/// there can also be lifetimes in the types of the upvars themselves,
+/// if one of them happens to be a reference to something that the
+/// creating fn owns.
+///
+/// OK, you say, so why not create a more minimal set of parameters
+/// that just includes the extra lifetime parameters? The answer is
+/// primarily that it would be hard --- we don't know at the time when
+/// we create the closure type what the full types of the upvars are,
+/// nor do we know which are borrowed and which are not. In this
+/// design, we can just supply a fresh type parameter and figure that
+/// out later.
+///
+/// All right, you say, but why include the type parameters from the
+/// original function then? The answer is that codegen may need them
+/// when monomorphizing, and they may not appear in the upvars. A
+/// closure could capture no variables but still make use of some
+/// in-scope type parameter with a bound (e.g., if our example above
+/// had an extra `U: Default`, and the closure called `U::default()`).
+///
+/// There is another reason. This design (implicitly) prohibits
+/// closures from capturing themselves (except via a trait
+/// object). This simplifies closure inference considerably, since it
+/// means that when we infer the kind of a closure or its upvars, we
+/// don't have to handle cycles where the decisions we make for
+/// closure C wind up influencing the decisions we ought to make for
+/// closure C (which would then require fixed point iteration to
+/// handle). Plus it fixes an ICE. :P
+///
+/// ## Coroutines
+///
+/// Coroutines are handled similarly in `CoroutineArgs`. The set of
+/// type parameters is similar, but `CK` and `CS` are replaced by the
+/// following type parameters:
+///
+/// * `GS`: The coroutine's "resume type", which is the type of the
+///   argument passed to `resume`, and the type of `yield` expressions
+///   inside the coroutine.
+/// * `GY`: The "yield type", which is the type of values passed to
+///   `yield` inside the coroutine.
+/// * `GR`: The "return type", which is the type of value returned upon
+///   completion of the coroutine.
+/// * `GW`: The "coroutine witness".
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+pub struct ClosureArgs<I: Interner> {
+    /// Lifetime and type parameters from the enclosing function,
+    /// concatenated with a tuple containing the types of the upvars.
+    ///
+    /// These are separated out because codegen wants to pass them around
+    /// when monomorphizing.
+    pub args: I::GenericArgs,
+}
+
+/// Struct returned by `split()`.
+pub struct ClosureArgsParts<I: Interner> {
+    /// This is the args of the typeck root.
+    pub parent_args: I::GenericArgsSlice,
+    /// Represents the maximum calling capability of the closure.
+    pub closure_kind_ty: I::Ty,
+    /// Captures the closure's signature. This closure signature is "tupled", and
+    /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`.
+    pub closure_sig_as_fn_ptr_ty: I::Ty,
+    /// The upvars captured by the closure. Remains an inference variable
+    /// until the upvar analysis, which happens late in HIR typeck.
+    pub tupled_upvars_ty: I::Ty,
+}
+
+impl<I: Interner> ClosureArgs<I> {
+    /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
+    /// for the closure parent, alongside additional closure-specific components.
+    pub fn new(tcx: I, parts: ClosureArgsParts<I>) -> ClosureArgs<I> {
+        ClosureArgs {
+            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
+                parts.closure_kind_ty.into(),
+                parts.closure_sig_as_fn_ptr_ty.into(),
+                parts.tupled_upvars_ty.into(),
+            ])),
+        }
+    }
+
+    /// Divides the closure args into their respective components.
+    /// The ordering assumed here must match that used by `ClosureArgs::new` above.
+    fn split(self) -> ClosureArgsParts<I> {
+        self.args.split_closure_args()
+    }
+
+    /// Returns the generic parameters of the closure's parent.
+    pub fn parent_args(self) -> I::GenericArgsSlice {
+        self.split().parent_args
+    }
+
+    /// Returns an iterator over the list of types of captured paths by the closure.
+    /// In case there was a type error in figuring out the types of the captured path, an
+    /// empty iterator is returned.
+    #[inline]
+    pub fn upvar_tys(self) -> I::Tys {
+        match self.tupled_upvars_ty().kind() {
+            ty::Error(_) => Default::default(),
+            ty::Tuple(tys) => tys,
+            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
+            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
+        }
+    }
+
+    /// Returns the tuple type representing the upvars for this closure.
+    #[inline]
+    pub fn tupled_upvars_ty(self) -> I::Ty {
+        self.split().tupled_upvars_ty
+    }
+
+    /// Returns the closure kind for this closure; may return a type
+    /// variable during inference. To get the closure kind during
+    /// inference, use `infcx.closure_kind(args)`.
+    pub fn kind_ty(self) -> I::Ty {
+        self.split().closure_kind_ty
+    }
+
+    /// Returns the `fn` pointer type representing the closure signature for this
+    /// closure.
+    // FIXME(eddyb) this should be unnecessary, as the shallowly resolved
+    // type is known at the time of the creation of `ClosureArgs`,
+    // see `rustc_hir_analysis::check::closure`.
+    pub fn sig_as_fn_ptr_ty(self) -> I::Ty {
+        self.split().closure_sig_as_fn_ptr_ty
+    }
+
+    /// Returns the closure kind for this closure; only usable outside
+    /// of an inference context, because in that context we know that
+    /// there are no type variables.
+    ///
+    /// If you have an inference context, use `infcx.closure_kind()`.
+    pub fn kind(self) -> ty::ClosureKind {
+        self.kind_ty().to_opt_closure_kind().unwrap()
+    }
+
+    /// Extracts the signature from the closure.
+    pub fn sig(self) -> ty::Binder<I, ty::FnSig<I>> {
+        match self.sig_as_fn_ptr_ty().kind() {
+            ty::FnPtr(sig) => sig,
+            ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
+        }
+    }
+}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+pub struct CoroutineClosureArgs<I: Interner> {
+    pub args: I::GenericArgs,
+}
+
+/// See docs for explanation of how each argument is used.
+///
+/// See [`CoroutineClosureSignature`] for how these arguments are put together
+/// to make a callable [`ty::FnSig`] suitable for typeck and borrowck.
+pub struct CoroutineClosureArgsParts<I: Interner> {
+    /// This is the args of the typeck root.
+    pub parent_args: I::GenericArgsSlice,
+    /// Represents the maximum calling capability of the closure.
+    pub closure_kind_ty: I::Ty,
+    /// Represents all of the relevant parts of the coroutine returned by this
+    /// coroutine-closure. This signature parts type will have the general
+    /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where
+    /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the
+    /// coroutine returned by the coroutine-closure.
+    ///
+    /// Use `coroutine_closure_sig` to break up this type rather than using it
+    /// yourself.
+    pub signature_parts_ty: I::Ty,
+    /// The upvars captured by the closure. Remains an inference variable
+    /// until the upvar analysis, which happens late in HIR typeck.
+    pub tupled_upvars_ty: I::Ty,
+    /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`.
+    /// This allows us to represent the binder of the self-captures of the closure.
+    ///
+    /// For example, if the coroutine returned by the closure borrows `String`
+    /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`,
+    /// while the `tupled_upvars_ty`, representing the by-move version of the same
+    /// captures, will be `(String,)`.
+    pub coroutine_captures_by_ref_ty: I::Ty,
+    /// Witness type returned by the generator produced by this coroutine-closure.
+    pub coroutine_witness_ty: I::Ty,
+}
+
+impl<I: Interner> CoroutineClosureArgs<I> {
+    pub fn new(tcx: I, parts: CoroutineClosureArgsParts<I>) -> CoroutineClosureArgs<I> {
+        CoroutineClosureArgs {
+            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
+                parts.closure_kind_ty.into(),
+                parts.signature_parts_ty.into(),
+                parts.tupled_upvars_ty.into(),
+                parts.coroutine_captures_by_ref_ty.into(),
+                parts.coroutine_witness_ty.into(),
+            ])),
+        }
+    }
+
+    fn split(self) -> CoroutineClosureArgsParts<I> {
+        self.args.split_coroutine_closure_args()
+    }
+
+    pub fn parent_args(self) -> I::GenericArgsSlice {
+        self.split().parent_args
+    }
+
+    #[inline]
+    pub fn upvar_tys(self) -> I::Tys {
+        match self.tupled_upvars_ty().kind() {
+            ty::Error(_) => Default::default(),
+            ty::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
+            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
+            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
+        }
+    }
+
+    #[inline]
+    pub fn tupled_upvars_ty(self) -> I::Ty {
+        self.split().tupled_upvars_ty
+    }
+
+    pub fn kind_ty(self) -> I::Ty {
+        self.split().closure_kind_ty
+    }
+
+    pub fn kind(self) -> ty::ClosureKind {
+        self.kind_ty().to_opt_closure_kind().unwrap()
+    }
+
+    pub fn signature_parts_ty(self) -> I::Ty {
+        self.split().signature_parts_ty
+    }
+
+    pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> {
+        let interior = self.coroutine_witness_ty();
+        let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { panic!() };
+        sig.map_bound(|sig| {
+            let [resume_ty, tupled_inputs_ty] = *sig.inputs() else {
+                panic!();
+            };
+            let [yield_ty, return_ty] = **sig.output().tuple_fields() else { panic!() };
+            CoroutineClosureSignature {
+                interior,
+                tupled_inputs_ty,
+                resume_ty,
+                yield_ty,
+                return_ty,
+                c_variadic: sig.c_variadic,
+                safety: sig.safety,
+                abi: sig.abi,
+            }
+        })
+    }
+
+    pub fn coroutine_captures_by_ref_ty(self) -> I::Ty {
+        self.split().coroutine_captures_by_ref_ty
+    }
+
+    pub fn coroutine_witness_ty(self) -> I::Ty {
+        self.split().coroutine_witness_ty
+    }
+
+    pub fn has_self_borrows(&self) -> bool {
+        match self.coroutine_captures_by_ref_ty().kind() {
+            ty::FnPtr(sig) => sig
+                .skip_binder()
+                .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
+                .is_break(),
+            ty::Error(_) => true,
+            _ => panic!(),
+        }
+    }
+}
+
+/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
+/// detect only regions bound *at* the debruijn index.
+struct HasRegionsBoundAt {
+    binder: ty::DebruijnIndex,
+}
+// FIXME: Could be optimized to not walk into components with no escaping bound vars.
+impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
+    type Result = ControlFlow<()>;
+    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
+        self.binder.shift_in(1);
+        t.super_visit_with(self)?;
+        self.binder.shift_out(1);
+        ControlFlow::Continue(())
+    }
+
+    fn visit_region(&mut self, r: I::Region) -> Self::Result {
+        if matches!(r.kind(), ty::ReBound(binder, _) if self.binder == binder) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
+        }
+    }
+}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
+pub struct CoroutineClosureSignature<I: Interner> {
+    pub interior: I::Ty,
+    pub tupled_inputs_ty: I::Ty,
+    pub resume_ty: I::Ty,
+    pub yield_ty: I::Ty,
+    pub return_ty: I::Ty,
+
+    // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
+    // never actually differ. But we save them rather than recreating them
+    // from scratch just for good measure.
+    /// Always false
+    pub c_variadic: bool,
+    /// Always `Normal` (safe)
+    pub safety: I::Safety,
+    /// Always `RustCall`
+    pub abi: I::Abi,
+}
+
+impl<I: Interner> CoroutineClosureSignature<I> {
+    /// Construct a coroutine from the closure signature. Since a coroutine signature
+    /// is agnostic to the type of generator that is returned (by-ref/by-move),
+    /// the caller must specify what "flavor" of generator that they'd like to
+    /// create. Additionally, they must manually compute the upvars of the closure.
+    ///
+    /// This helper is not really meant to be used directly except for early on
+    /// during typeck, when we want to put inference vars into the kind and upvars tys.
+    /// When the kind and upvars are known, use the other helper functions.
+    pub fn to_coroutine(
+        self,
+        tcx: I,
+        parent_args: I::GenericArgsSlice,
+        coroutine_kind_ty: I::Ty,
+        coroutine_def_id: I::DefId,
+        tupled_upvars_ty: I::Ty,
+    ) -> I::Ty {
+        let coroutine_args = ty::CoroutineArgs::new(
+            tcx,
+            ty::CoroutineArgsParts {
+                parent_args,
+                kind_ty: coroutine_kind_ty,
+                resume_ty: self.resume_ty,
+                yield_ty: self.yield_ty,
+                return_ty: self.return_ty,
+                witness: self.interior,
+                tupled_upvars_ty,
+            },
+        );
+
+        Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args)
+    }
+
+    /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
+    /// returned by that corresponding async fn trait.
+    ///
+    /// This function expects the upvars to have been computed already, and doesn't check
+    /// that the `ClosureKind` is actually supported by the coroutine-closure.
+    pub fn to_coroutine_given_kind_and_upvars(
+        self,
+        tcx: I,
+        parent_args: I::GenericArgsSlice,
+        coroutine_def_id: I::DefId,
+        goal_kind: ty::ClosureKind,
+        env_region: I::Region,
+        closure_tupled_upvars_ty: I::Ty,
+        coroutine_captures_by_ref_ty: I::Ty,
+    ) -> I::Ty {
+        let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
+            tcx,
+            goal_kind,
+            self.tupled_inputs_ty,
+            closure_tupled_upvars_ty,
+            coroutine_captures_by_ref_ty,
+            env_region,
+        );
+
+        self.to_coroutine(
+            tcx,
+            parent_args,
+            Ty::from_coroutine_closure_kind(tcx, goal_kind),
+            coroutine_def_id,
+            tupled_upvars_ty,
+        )
+    }
+
+    /// Compute the tupled upvars that a coroutine-closure's output coroutine
+    /// would return for the given `ClosureKind`.
+    ///
+    /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref"
+    /// to return a set of upvars which are borrowed with the given `env_region`.
+    ///
+    /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars'
+    /// lifetimes are related to the lifetime of the borrow on the closure made for
+    /// the call. This allows borrowck to enforce the self-borrows correctly.
+    pub fn tupled_upvars_by_closure_kind(
+        tcx: I,
+        kind: ty::ClosureKind,
+        tupled_inputs_ty: I::Ty,
+        closure_tupled_upvars_ty: I::Ty,
+        coroutine_captures_by_ref_ty: I::Ty,
+        env_region: I::Region,
+    ) -> I::Ty {
+        match kind {
+            ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
+                let ty::FnPtr(sig) = coroutine_captures_by_ref_ty.kind() else {
+                    panic!();
+                };
+                let coroutine_captures_by_ref_ty =
+                    sig.output().skip_binder().fold_with(&mut FoldEscapingRegions {
+                        interner: tcx,
+                        region: env_region,
+                        debruijn: ty::INNERMOST,
+                    });
+                Ty::new_tup_from_iter(
+                    tcx,
+                    tupled_inputs_ty
+                        .tuple_fields()
+                        .into_iter()
+                        .chain(coroutine_captures_by_ref_ty.tuple_fields()),
+                )
+            }
+            ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
+                tcx,
+                tupled_inputs_ty
+                    .tuple_fields()
+                    .into_iter()
+                    .chain(closure_tupled_upvars_ty.tuple_fields()),
+            ),
+        }
+    }
+}
+
+/// Instantiates a `for<'env> ...` binder with a specific region.
+// FIXME(async_closures): Get rid of this in favor of `BoundVarReplacerDelegate`
+// when that is uplifted.
+struct FoldEscapingRegions<I: Interner> {
+    interner: I,
+    debruijn: ty::DebruijnIndex,
+    region: I::Region,
+}
+
+impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<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.debruijn.shift_in(1);
+        let result = t.super_fold_with(self);
+        self.debruijn.shift_out(1);
+        result
+    }
+
+    fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
+        if let ty::ReBound(debruijn, _) = r.kind() {
+            assert!(
+                debruijn <= self.debruijn,
+                "cannot instantiate binder with escaping bound vars"
+            );
+            if self.debruijn == debruijn {
+                shift_region(self.interner, self.region, self.debruijn.as_u32())
+            } else {
+                r
+            }
+        } else {
+            r
+        }
+    }
+}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
+pub struct GenSig<I: Interner> {
+    pub resume_ty: I::Ty,
+    pub yield_ty: I::Ty,
+    pub return_ty: I::Ty,
+}
+
+/// Similar to `ClosureArgs`; see the above documentation for more.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = ""),
+    Debug(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+pub struct CoroutineArgs<I: Interner> {
+    pub args: I::GenericArgs,
+}
+
+pub struct CoroutineArgsParts<I: Interner> {
+    /// This is the args of the typeck root.
+    pub parent_args: I::GenericArgsSlice,
+
+    /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut`
+    /// implementations must be distinguished since the former takes the closure's
+    /// upvars by move, and the latter takes the closure's upvars by ref.
+    ///
+    /// This field distinguishes these fields so that codegen can select the right
+    /// body for the coroutine. This has the same type representation as the closure
+    /// kind: `i8`/`i16`/`i32`.
+    ///
+    /// For regular coroutines, this field will always just be `()`.
+    pub kind_ty: I::Ty,
+
+    pub resume_ty: I::Ty,
+    pub yield_ty: I::Ty,
+    pub return_ty: I::Ty,
+
+    /// The interior type of the coroutine.
+    /// Represents all types that are stored in locals
+    /// in the coroutine's body.
+    pub witness: I::Ty,
+
+    /// The upvars captured by the closure. Remains an inference variable
+    /// until the upvar analysis, which happens late in HIR typeck.
+    pub tupled_upvars_ty: I::Ty,
+}
+
+impl<I: Interner> CoroutineArgs<I> {
+    /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
+    /// for the coroutine parent, alongside additional coroutine-specific components.
+    pub fn new(tcx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
+        CoroutineArgs {
+            args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
+                parts.kind_ty.into(),
+                parts.resume_ty.into(),
+                parts.yield_ty.into(),
+                parts.return_ty.into(),
+                parts.witness.into(),
+                parts.tupled_upvars_ty.into(),
+            ])),
+        }
+    }
+
+    /// Divides the coroutine args into their respective components.
+    /// The ordering assumed here must match that used by `CoroutineArgs::new` above.
+    fn split(self) -> CoroutineArgsParts<I> {
+        self.args.split_coroutine_args()
+    }
+
+    /// Returns the generic parameters of the coroutine's parent.
+    pub fn parent_args(self) -> I::GenericArgsSlice {
+        self.split().parent_args
+    }
+
+    // Returns the kind of the coroutine. See docs on the `kind_ty` field.
+    pub fn kind_ty(self) -> I::Ty {
+        self.split().kind_ty
+    }
+
+    /// This describes the types that can be contained in a coroutine.
+    /// It will be a type variable initially and unified in the last stages of typeck of a body.
+    /// It contains a tuple of all the types that could end up on a coroutine frame.
+    /// The state transformation MIR pass may only produce layouts which mention types
+    /// in this tuple. Upvars are not counted here.
+    pub fn witness(self) -> I::Ty {
+        self.split().witness
+    }
+
+    /// Returns an iterator over the list of types of captured paths by the coroutine.
+    /// In case there was a type error in figuring out the types of the captured path, an
+    /// empty iterator is returned.
+    #[inline]
+    pub fn upvar_tys(self) -> I::Tys {
+        match self.tupled_upvars_ty().kind() {
+            ty::Error(_) => Default::default(),
+            ty::Tuple(tys) => tys,
+            ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"),
+            ty => panic!("Unexpected representation of upvar types tuple {:?}", ty),
+        }
+    }
+
+    /// Returns the tuple type representing the upvars for this coroutine.
+    #[inline]
+    pub fn tupled_upvars_ty(self) -> I::Ty {
+        self.split().tupled_upvars_ty
+    }
+
+    /// Returns the type representing the resume type of the coroutine.
+    pub fn resume_ty(self) -> I::Ty {
+        self.split().resume_ty
+    }
+
+    /// Returns the type representing the yield type of the coroutine.
+    pub fn yield_ty(self) -> I::Ty {
+        self.split().yield_ty
+    }
+
+    /// Returns the type representing the return type of the coroutine.
+    pub fn return_ty(self) -> I::Ty {
+        self.split().return_ty
+    }
+
+    /// Returns the "coroutine signature", which consists of its resume, yield
+    /// and return types.
+    pub fn sig(self) -> GenSig<I> {
+        let parts = self.split();
+        GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty }
+    }
+}
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/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/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/num/f32.rs b/library/core/src/num/f32.rs
index 19fc4489618..22b24937cbc 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1030,25 +1030,42 @@ impl f32 {
     /// ```
     #[unstable(feature = "num_midpoint", issue = "110840")]
     pub fn midpoint(self, other: f32) -> f32 {
-        const LO: f32 = f32::MIN_POSITIVE * 2.;
-        const HI: f32 = f32::MAX / 2.;
-
-        let (a, b) = (self, other);
-        let abs_a = a.abs_private();
-        let abs_b = b.abs_private();
-
-        if abs_a <= HI && abs_b <= HI {
-            // Overflow is impossible
-            (a + b) / 2.
-        } else if abs_a < LO {
-            // Not safe to halve a
-            a + (b / 2.)
-        } else if abs_b < LO {
-            // Not safe to halve b
-            (a / 2.) + b
-        } else {
-            // Not safe to halve a and b
-            (a / 2.) + (b / 2.)
+        cfg_if! {
+            if #[cfg(any(
+                    target_arch = "x86_64",
+                    target_arch = "aarch64",
+                    all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"),
+                    all(target_arch = "arm", target_feature="vfp2"),
+                    target_arch = "wasm32",
+                    target_arch = "wasm64",
+                ))] {
+                // whitelist the faster implementation to targets that have known good 64-bit float
+                // implementations. Falling back to the branchy code on targets that don't have
+                // 64-bit hardware floats or buggy implementations.
+                // see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114
+                ((f64::from(self) + f64::from(other)) / 2.0) as f32
+            } else {
+                const LO: f32 = f32::MIN_POSITIVE * 2.;
+                const HI: f32 = f32::MAX / 2.;
+
+                let (a, b) = (self, other);
+                let abs_a = a.abs_private();
+                let abs_b = b.abs_private();
+
+                if abs_a <= HI && abs_b <= HI {
+                    // Overflow is impossible
+                    (a + b) / 2.
+                } else if abs_a < LO {
+                    // Not safe to halve a
+                    a + (b / 2.)
+                } else if abs_b < LO {
+                    // Not safe to halve b
+                    (a / 2.) + b
+                } else {
+                    // Not safe to halve a and b
+                    (a / 2.) + (b / 2.)
+                }
+            }
         }
     }
 
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index c9c6e34eaad..96510ee4dca 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -183,6 +183,30 @@ macro_rules! int_impl {
             (self as $UnsignedT).trailing_ones()
         }
 
+        /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
+        ///
+        /// This produces the same result as an `as` cast, but ensures that the bit-width remains
+        /// the same.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(integer_sign_cast)]
+        ///
+        #[doc = concat!("let n = -1", stringify!($SelfT), ";")]
+        ///
+        #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")]
+        /// ```
+        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        pub const fn cast_unsigned(self) -> $UnsignedT {
+            self as $UnsignedT
+        }
+
         /// Shifts the bits to the left by a specified amount, `n`,
         /// wrapping the truncated bits to the end of the resulting integer.
         ///
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index f70c34199ac..1491c27372b 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -184,6 +184,30 @@ macro_rules! uint_impl {
             (!self).trailing_zeros()
         }
 
+        /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size.
+        ///
+        /// This produces the same result as an `as` cast, but ensures that the bit-width remains
+        /// the same.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(integer_sign_cast)]
+        ///
+        #[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")]
+        ///
+        #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")]
+        /// ```
+        #[unstable(feature = "integer_sign_cast", issue = "125882")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        pub const fn cast_signed(self) -> $SignedT {
+            self as $SignedT
+        }
+
         /// Shifts the bits to the left by a specified amount, `n`,
         /// wrapping the truncated bits to the end of the resulting integer.
         ///
@@ -1148,9 +1172,12 @@ macro_rules! uint_impl {
         pub const fn checked_ilog(self, base: Self) -> Option<u32> {
             if self <= 0 || base <= 1 {
                 None
+            } else if self < base {
+                Some(0)
             } else {
-                let mut n = 0;
-                let mut r = 1;
+                // Since base >= self, n >= 1
+                let mut n = 1;
+                let mut r = base;
 
                 // Optimization for 128 bit wide integers.
                 if Self::BITS == 128 {
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index cc66da25795..8988229be2e 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -342,7 +342,7 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
 ///
 /// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
 /// the pattern `"aa"` in the haystack `"aaa"` matches as either
-/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched.
+/// `"[aa]a"` or `"a[aa]"`, depending on which side it is searched.
 pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 0fed854318d..9d2912c4b22 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -729,7 +729,7 @@ assume_usize_width! {
 }
 
 macro_rules! test_float {
-    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
+    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
         mod $modname {
             #[test]
             fn min() {
@@ -880,6 +880,27 @@ macro_rules! test_float {
                 assert!(($nan as $fty).midpoint(1.0).is_nan());
                 assert!((1.0 as $fty).midpoint($nan).is_nan());
                 assert!(($nan as $fty).midpoint($nan).is_nan());
+
+                // test if large differences in magnitude are still correctly computed.
+                // NOTE: that because of how small x and y are, x + y can never overflow
+                // so (x + y) / 2.0 is always correct
+                // in particular, `2.pow(i)` will  never be at the max exponent, so it could
+                // be safely doubled, while j is significantly smaller.
+                for i in $max_exp.saturating_sub(64)..$max_exp {
+                    for j in 0..64u8 {
+                        let large = <$fty>::from(2.0f32).powi(i);
+                        // a much smaller number, such that there is no chance of overflow to test
+                        // potential double rounding in midpoint's implementation.
+                        let small = <$fty>::from(2.0f32).powi($max_exp - 1)
+                            * <$fty>::EPSILON
+                            * <$fty>::from(j);
+
+                        let naive = (large + small) / 2.0;
+                        let midpoint = large.midpoint(small);
+
+                        assert_eq!(naive, midpoint);
+                    }
+                }
             }
             #[test]
             fn rem_euclid() {
@@ -912,7 +933,8 @@ test_float!(
     f32::NAN,
     f32::MIN,
     f32::MAX,
-    f32::MIN_POSITIVE
+    f32::MIN_POSITIVE,
+    f32::MAX_EXP
 );
 test_float!(
     f64,
@@ -922,5 +944,6 @@ test_float!(
     f64::NAN,
     f64::MIN,
     f64::MAX,
-    f64::MIN_POSITIVE
+    f64::MIN_POSITIVE,
+    f64::MAX_EXP
 );
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index fc830bacced..6b9f70da854 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -5,7 +5,7 @@ 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.
 ///
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index fbbd40bfb79..a79a232e3d5 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -1910,8 +1910,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/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 853ef8736de..1ab54ec57c3 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -717,5 +717,14 @@ unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
 
 #[cfg(target_os = "netbsd")]
 unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
-    2048 // just a guess
+    static STACK: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new();
+
+    *STACK.get_or_init(|| {
+        let mut stack = unsafe { libc::sysconf(libc::_SC_THREAD_STACK_MIN) };
+        if stack < 0 {
+            stack = 2048; // just a guess
+        }
+
+        stack as usize
+    })
 }
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 25379071cb7..575d60de4ee 100644
--- a/library/std/src/sys/thread_local/fast_local/mod.rs
+++ b/library/std/src/sys/thread_local/fast_local/mod.rs
@@ -1,7 +1,7 @@
 //! Thread local support for platforms with native TLS.
 //!
 //! To achieve the best performance, we choose from four different types for
-//! the TLS variable, depending from the method of initialization used (`const`
+//! the TLS variable, depending on the method of initialization used (`const`
 //! or lazy) and the drop requirements of the stored type:
 //!
 //! |         | `Drop`               | `!Drop`             |
@@ -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/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/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/src/lib.rs b/src/bootstrap/src/lib.rs
index 8312885915c..cde090637e0 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -469,7 +469,8 @@ impl Build {
 
             // Make sure we update these before gathering metadata so we don't get an error about missing
             // Cargo.toml files.
-            let rust_submodules = ["src/tools/cargo", "library/backtrace", "library/stdarch"];
+            let rust_submodules =
+                ["src/tools/cargo", "src/doc/book", "library/backtrace", "library/stdarch"];
             for s in rust_submodules {
                 build.update_submodule(Path::new(s));
             }
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/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/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..ab8b4caaadf 100644
--- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md
@@ -1,16 +1,13 @@
-# 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
 
@@ -23,6 +20,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/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/types.rs b/src/librustdoc/clean/types.rs
index 3f84da310dd..b387809cc71 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -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)
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index b58018ca035..48c4c4206fe 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -10,7 +10,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
     self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty,
-    TypeVisitableExt, TypeckResults,
+    TypeVisitableExt, TypeckResults, TyCtxt,
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
@@ -240,7 +240,7 @@ fn check_inputs(
         })
 }
 
-fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: FnSig<'_>) -> bool {
+fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<TyCtxt<'tcx>>, call_sig: FnSig<'_>) -> bool {
     call_sig.safety == Safety::Safe
         && !has_late_bound_to_non_late_bound_regions(
             cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder(),
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/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 2091e74665f..57e0a7aa2c7 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -253,7 +253,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
     // fill the set with current and super traits
     fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) {
         if set.insert(traitt) {
-            for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) {
+            for supertrait in cx.tcx.supertrait_def_ids(traitt) {
                 fill_trait_set(supertrait, set, cx);
             }
         }
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/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_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 3414b5ef680..f0dac6f5d9c 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -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();
             },
             _ => (),
         }
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index c11d3da13a8..7a5abc51d04 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -57,6 +57,18 @@ pub struct Error {
     pub msg: String,
 }
 
+impl Error {
+    pub fn render_for_expected(&self) -> String {
+        use colored::Colorize;
+        format!(
+            "{: <10}line {: >3}: {}",
+            self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
+            self.line_num,
+            self.msg.cyan(),
+        )
+    }
+}
+
 #[derive(PartialEq, Debug)]
 enum WhichLine {
     ThisLine,
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 42c751bb6be..1ec3f0a0552 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,10 +1,18 @@
-use std::{env, sync::Arc};
+use std::{env, io::IsTerminal, sync::Arc};
 
 use compiletest::{common::Mode, log_config, parse_config, run_tests};
 
 fn main() {
     tracing_subscriber::fmt::init();
 
+    // colored checks stdout by default, but for some reason only stderr is a terminal.
+    // compiletest *does* print many things to stdout, but it doesn't really matter.
+    if std::io::stderr().is_terminal()
+        && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
+    {
+        colored::control::set_override(true);
+    }
+
     let config = Arc::new(parse_config(env::args().collect()));
 
     if config.valgrind_path.is_none() && config.force_valgrind {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 79e158992d4..9bd0002a3d9 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -17,10 +17,10 @@ use crate::json;
 use crate::read2::{read2_abbreviated, Truncated};
 use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt};
 use crate::ColorConfig;
+use colored::Colorize;
 use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
 use regex::{Captures, Regex};
 use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
-
 use std::collections::{HashMap, HashSet};
 use std::env;
 use std::ffi::{OsStr, OsString};
@@ -1493,14 +1493,22 @@ impl<'test> TestCx<'test> {
                 unexpected.len(),
                 not_found.len()
             ));
-            println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline);
+            println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
             if !unexpected.is_empty() {
-                println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
+                println!("{}", "--- unexpected errors (from JSON output) ---".green());
+                for error in &unexpected {
+                    println!("{}", error.render_for_expected());
+                }
+                println!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                println!("not found errors (from test file): {:#?}\n", not_found);
+                println!("{}", "--- not found errors (from test file) ---".red());
+                for error in &not_found {
+                    println!("{}", error.render_for_expected());
+                }
+                println!("{}", "---\n".red());
             }
-            panic!();
+            panic!("errors differ from expected");
         }
     }
 
@@ -3431,11 +3439,23 @@ impl<'test> TestCx<'test> {
         let build_root = self.config.build_base.parent().unwrap().parent().unwrap();
         let build_root = cwd.join(&build_root);
 
-        let tmpdir = cwd.join(self.output_base_name());
-        if tmpdir.exists() {
-            self.aggressive_rm_rf(&tmpdir).unwrap();
+        // We construct the following directory tree for each rmake.rs test:
+        // ```
+        // base_dir/
+        //     rmake.exe
+        //     rmake_out/
+        // ```
+        // having the executable separate from the output artifacts directory allows the recipes to
+        // `remove_dir_all($TMPDIR)` without running into permission denied issues because
+        // the executable is not under the `rmake_out/` directory.
+        //
+        // This setup intentionally diverges from legacy Makefile run-make tests.
+        let base_dir = cwd.join(self.output_base_name());
+        if base_dir.exists() {
+            self.aggressive_rm_rf(&base_dir).unwrap();
         }
-        create_dir_all(&tmpdir).unwrap();
+        let rmake_out_dir = base_dir.join("rmake_out");
+        create_dir_all(&rmake_out_dir).unwrap();
 
         // HACK: assume stageN-target, we only want stageN.
         let stage = self.config.stage_id.split('-').next().unwrap();
@@ -3452,8 +3472,11 @@ impl<'test> TestCx<'test> {
         stage_std_path.push("lib");
 
         // Then, we need to build the recipe `rmake.rs` and link in the support library.
-        let recipe_bin =
-            tmpdir.join(if self.config.target.contains("windows") { "rmake.exe" } else { "rmake" });
+        let recipe_bin = base_dir.join(if self.config.target.contains("windows") {
+            "rmake.exe"
+        } else {
+            "rmake"
+        });
 
         let mut support_lib_deps = PathBuf::new();
         support_lib_deps.push(&build_root);
@@ -3494,7 +3517,7 @@ impl<'test> TestCx<'test> {
             .env("S", &src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &tmpdir)
+            .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))
@@ -3530,7 +3553,7 @@ impl<'test> TestCx<'test> {
         let dylib_env_paths = env::join_paths(dylib_env_paths).unwrap();
 
         let mut target_rpath_env_path = Vec::new();
-        target_rpath_env_path.push(&tmpdir);
+        target_rpath_env_path.push(&rmake_out_dir);
         target_rpath_env_path.extend(&orig_dylib_env_paths);
         let target_rpath_env_path = env::join_paths(target_rpath_env_path).unwrap();
 
@@ -3546,7 +3569,7 @@ impl<'test> TestCx<'test> {
             .env("S", &src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &tmpdir)
+            .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)
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/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index 799c36b1049..0012e7b66af 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -80,6 +80,13 @@ impl Cc {
         self
     }
 
+    /// Specify path of the output binary.
+    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-o");
+        self.cmd.arg(path.as_ref());
+        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/lib.rs b/src/tools/run-make-support/src/lib.rs
index 0cf64db6ac9..323fc40e648 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -123,12 +123,23 @@ pub fn dynamic_lib_name(name: &str) -> String {
     // ```
     assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
 
+    let extension = dynamic_lib_extension();
     if is_darwin() {
-        format!("lib{name}.dylib")
+        format!("lib{name}.{extension}")
     } else if is_windows() {
-        format!("{name}.dll")
+        format!("{name}.{extension}")
     } else {
-        format!("lib{name}.so")
+        format!("lib{name}.{extension}")
+    }
+}
+
+pub fn dynamic_lib_extension() -> &'static str {
+    if is_darwin() {
+        "dylib"
+    } else if is_windows() {
+        "dll"
+    } else {
+        "so"
     }
 }
 
@@ -249,16 +260,13 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
     }
 
     let dir2 = dir2.as_ref();
-    for entry in fs::read_dir(dir1).unwrap() {
-        let entry = entry.unwrap();
-        let entry_name = entry.file_name();
-        let path = entry.path();
-
-        if path.is_dir() {
-            recursive_diff(&path, &dir2.join(entry_name));
+    read_dir(dir1, |entry_path| {
+        let entry_name = entry_path.file_name().unwrap();
+        if entry_path.is_dir() {
+            recursive_diff(&entry_path, &dir2.join(entry_name));
         } else {
             let path2 = dir2.join(entry_name);
-            let file1 = read_file(&path);
+            let file1 = read_file(&entry_path);
             let file2 = read_file(&path2);
 
             // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
@@ -267,10 +275,16 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
             assert!(
                 file1 == file2,
                 "`{}` and `{}` have different content",
-                path.display(),
+                entry_path.display(),
                 path2.display(),
             );
         }
+    });
+}
+
+pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
+    for entry in fs::read_dir(dir).unwrap() {
+        callback(&entry.unwrap().path());
     }
 }
 
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 9aad91f1b46..da4f265efc3 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -4,12 +4,12 @@ use std::process::{Command, Output};
 
 use crate::is_windows;
 
-use super::{bin_name, handle_failed_output};
+use super::handle_failed_output;
 
 fn run_common(name: &str) -> (Command, Output) {
     let mut bin_path = PathBuf::new();
     bin_path.push(env::var("TMPDIR").unwrap());
-    bin_path.push(&bin_name(name));
+    bin_path.push(name);
     let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
     let mut cmd = Command::new(bin_path);
     cmd.env(&ld_lib_path_envvar, {
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 8eb872514a5..3558c39bb32 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -217,16 +217,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "command-group"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916"
-dependencies = [
- "nix 0.26.4",
- "winapi",
-]
-
-[[package]]
 name = "countme"
 version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -292,7 +282,7 @@ version = "3.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
 dependencies = [
- "nix 0.28.0",
+ "nix",
  "windows-sys 0.52.0",
 ]
 
@@ -432,9 +422,9 @@ name = "flycheck"
 version = "0.0.0"
 dependencies = [
  "cargo_metadata",
- "command-group",
  "crossbeam-channel",
  "paths",
+ "process-wrap",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -1123,17 +1113,6 @@ dependencies = [
 
 [[package]]
 name = "nix"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
-dependencies = [
- "bitflags 1.3.2",
- "cfg-if",
- "libc",
-]
-
-[[package]]
-name = "nix"
 version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
@@ -1398,6 +1377,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "process-wrap"
+version = "8.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38ee68ae331824036479c84060534b18254c864fa73366c58d86db3b7b811619"
+dependencies = [
+ "indexmap",
+ "nix",
+ "tracing",
+ "windows",
+]
+
+[[package]]
 name = "profile"
 version = "0.0.0"
 dependencies = [
@@ -2375,35 +2366,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
-name = "winapi"
-version = "0.3.9"
+name = "winapi-util"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "windows"
+version = "0.56.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
 dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
+ "windows-core",
+ "windows-targets 0.52.5",
 ]
 
 [[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
+name = "windows-core"
+version = "0.56.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-targets 0.52.5",
+]
 
 [[package]]
-name = "winapi-util"
-version = "0.1.8"
+name = "windows-implement"
+version = "0.56.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
 dependencies = [
- "windows-sys 0.52.0",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
+name = "windows-interface"
+version = "0.56.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
+dependencies = [
+ "windows-targets 0.52.5",
+]
 
 [[package]]
 name = "windows-sys"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 3108c1b3dfe..ccc27e21333 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -111,7 +111,6 @@ chalk-solve = { version = "0.97.0", default-features = false }
 chalk-ir = "0.97.0"
 chalk-recursive = { version = "0.97.0", default-features = false }
 chalk-derive = "0.97.0"
-command-group = "2.0.1"
 crossbeam-channel = "0.5.8"
 dissimilar = "1.0.7"
 dot = "0.1.4"
@@ -132,6 +131,7 @@ object = { version = "0.33.0", default-features = false, features = [
     "macho",
     "pe",
 ] }
+process-wrap = { version = "8.0.2", features = ["std"] }
 pulldown-cmark-to-cmark = "10.0.4"
 pulldown-cmark = { version = "0.9.0", default-features = false }
 rayon = "1.8.0"
diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
index b8c10da1b6e..d81a5fe3400 100644
--- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
@@ -18,7 +18,7 @@ tracing.workspace = true
 rustc-hash.workspace = true
 serde_json.workspace = true
 serde.workspace = true
-command-group.workspace = true
+process-wrap.workspace = true
 
 # local deps
 paths.workspace = true
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/command.rs b/src/tools/rust-analyzer/crates/flycheck/src/command.rs
index 8ba7018316a..38c7c81f57a 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/command.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/command.rs
@@ -9,8 +9,8 @@ use std::{
     process::{ChildStderr, ChildStdout, Command, Stdio},
 };
 
-use command_group::{CommandGroup, GroupChild};
 use crossbeam_channel::Sender;
+use process_wrap::std::{StdChildWrapper, StdCommandWrap};
 use stdx::process::streaming_output;
 
 /// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of
@@ -85,7 +85,7 @@ impl<T: ParseFromLine> CargoActor<T> {
     }
 }
 
-struct JodGroupChild(GroupChild);
+struct JodGroupChild(Box<dyn StdChildWrapper>);
 
 impl Drop for JodGroupChild {
     fn drop(&mut self) {
@@ -119,14 +119,20 @@ impl<T> fmt::Debug for CommandHandle<T> {
 impl<T: ParseFromLine> CommandHandle<T> {
     pub(crate) fn spawn(mut command: Command, sender: Sender<T>) -> std::io::Result<Self> {
         command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
-        let mut child = command.group_spawn().map(JodGroupChild)?;
 
         let program = command.get_program().into();
         let arguments = command.get_args().map(|arg| arg.into()).collect::<Vec<OsString>>();
         let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf());
 
-        let stdout = child.0.inner().stdout.take().unwrap();
-        let stderr = child.0.inner().stderr.take().unwrap();
+        let mut child = StdCommandWrap::from(command);
+        #[cfg(unix)]
+        child.wrap(process_wrap::std::ProcessSession);
+        #[cfg(windows)]
+        child.wrap(process_wrap::std::JobObject);
+        let mut child = child.spawn().map(JodGroupChild)?;
+
+        let stdout = child.0.stdout().take().unwrap();
+        let stderr = child.0.stderr().take().unwrap();
 
         let actor = CargoActor::<T>::new(sender, stdout, stderr);
         let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index 6d5ca8321e5..afdc3e389b3 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -163,6 +163,9 @@ pub enum Message {
     /// Request adding a diagnostic with fixes included to a file
     AddDiagnostic { id: usize, workspace_root: AbsPathBuf, diagnostic: Diagnostic },
 
+    /// Request clearing all previous diagnostics
+    ClearDiagnostics { id: usize },
+
     /// Request check progress notification to client
     Progress {
         /// Flycheck instance ID
@@ -180,6 +183,9 @@ impl fmt::Debug for Message {
                 .field("workspace_root", workspace_root)
                 .field("diagnostic_code", &diagnostic.code.as_ref().map(|it| &it.code))
                 .finish(),
+            Message::ClearDiagnostics { id } => {
+                f.debug_struct("ClearDiagnostics").field("id", id).finish()
+            }
             Message::Progress { id, progress } => {
                 f.debug_struct("Progress").field("id", id).field("progress", progress).finish()
             }
@@ -220,6 +226,8 @@ struct FlycheckActor {
     command_handle: Option<CommandHandle<CargoCheckMessage>>,
     /// The receiver side of the channel mentioned above.
     command_receiver: Option<Receiver<CargoCheckMessage>>,
+
+    status: FlycheckStatus,
 }
 
 enum Event {
@@ -227,6 +235,13 @@ enum Event {
     CheckEvent(Option<CargoCheckMessage>),
 }
 
+#[derive(PartialEq)]
+enum FlycheckStatus {
+    Started,
+    DiagnosticSent,
+    Finished,
+}
+
 const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
 
 impl FlycheckActor {
@@ -248,6 +263,7 @@ impl FlycheckActor {
             manifest_path,
             command_handle: None,
             command_receiver: None,
+            status: FlycheckStatus::Finished,
         }
     }
 
@@ -298,12 +314,14 @@ impl FlycheckActor {
                             self.command_handle = Some(command_handle);
                             self.command_receiver = Some(receiver);
                             self.report_progress(Progress::DidStart);
+                            self.status = FlycheckStatus::Started;
                         }
                         Err(error) => {
                             self.report_progress(Progress::DidFailToRestart(format!(
                                 "Failed to run the following command: {} error={}",
                                 formatted_command, error
                             )));
+                            self.status = FlycheckStatus::Finished;
                         }
                     }
                 }
@@ -323,7 +341,11 @@ impl FlycheckActor {
                             error
                         );
                     }
+                    if self.status == FlycheckStatus::Started {
+                        self.send(Message::ClearDiagnostics { id: self.id });
+                    }
                     self.report_progress(Progress::DidFinish(res));
+                    self.status = FlycheckStatus::Finished;
                 }
                 Event::CheckEvent(Some(message)) => match message {
                     CargoCheckMessage::CompilerArtifact(msg) => {
@@ -341,11 +363,15 @@ impl FlycheckActor {
                             message = msg.message,
                             "diagnostic received"
                         );
+                        if self.status == FlycheckStatus::Started {
+                            self.send(Message::ClearDiagnostics { id: self.id });
+                        }
                         self.send(Message::AddDiagnostic {
                             id: self.id,
                             workspace_root: self.root.clone(),
                             diagnostic: msg,
                         });
+                        self.status = FlycheckStatus::DiagnosticSent;
                     }
                 },
             }
@@ -362,6 +388,7 @@ impl FlycheckActor {
             );
             command_handle.cancel();
             self.report_progress(Progress::DidCancel);
+            self.status = FlycheckStatus::Finished;
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index 2e5fa6131a7..12421bbe702 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -298,7 +298,7 @@ pub fn expand_speculative(
             // prefer tokens of the same kind and text
             // Note the inversion of the score here, as we want to prefer the first token in case
             // of all tokens having the same score
-            (t.kind() != token_to_map.kind()) as u8 + (t.text() != token_to_map.text()) as u8
+            (t.kind() != token_to_map.kind()) as u8 + 2 * ((t.text() != token_to_map.text()) as u8)
         })?;
     Some((node.syntax_node(), token))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 04a4851ddb7..1ba85c5c7ea 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -153,24 +153,20 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
 // region:specific impls
 
 impl InFile<&SyntaxNode> {
-    /// Skips the attributed item that caused the macro invocation we are climbing up
-    pub fn ancestors_with_macros_skip_attr_item(
+    /// Traverse up macro calls and skips the macro invocation node
+    pub fn ancestors_with_macros(
         self,
         db: &dyn db::ExpandDatabase,
     ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
         let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
             Some(parent) => Some(node.with_value(parent)),
-            None => {
-                let macro_file_id = node.file_id.macro_file()?;
-                let parent_node = macro_file_id.call_node(db);
-                if macro_file_id.is_attr_macro(db) {
-                    // macro call was an attributed item, skip it
-                    // FIXME: does this fail if this is a direct expansion of another macro?
-                    parent_node.map(|node| node.parent()).transpose()
-                } else {
-                    Some(parent_node)
-                }
-            }
+            None => db
+                .lookup_intern_macro_call(node.file_id.macro_file()?.macro_call_id)
+                .to_node_item(db)
+                .syntax()
+                .cloned()
+                .map(|node| node.parent())
+                .transpose(),
         };
         iter::successors(succ(&self.cloned()), succ)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 4ab989bec2f..83e92565f4d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -33,8 +33,8 @@ use std::{fmt, hash::Hash};
 use base_db::{salsa::impl_intern_value_trivial, CrateId, FileId};
 use either::Either;
 use span::{
-    Edition, ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData,
-    SyntaxContextId,
+    Edition, ErasedFileAstId, FileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor,
+    SyntaxContextData, SyntaxContextId,
 };
 use syntax::{
     ast::{self, AstNode},
@@ -546,6 +546,18 @@ impl MacroCallLoc {
         }
     }
 
+    pub fn to_node_item(&self, db: &dyn ExpandDatabase) -> InFile<ast::Item> {
+        match self.kind {
+            MacroCallKind::FnLike { ast_id, .. } => {
+                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
+            }
+            MacroCallKind::Derive { ast_id, .. } => {
+                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
+            }
+            MacroCallKind::Attr { ast_id, .. } => InFile::new(ast_id.file_id, ast_id.to_node(db)),
+        }
+    }
+
     fn expand_to(&self) -> ExpandTo {
         match self.kind {
             MacroCallKind::FnLike { expand_to, .. } => expand_to,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 6c70cc4baf0..43de2a6ee7d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -380,6 +380,27 @@ impl<'db> SemanticsImpl<'db> {
         self.with_ctx(|ctx| ctx.has_derives(adt))
     }
 
+    pub fn derive_helper(&self, attr: &ast::Attr) -> Option<Vec<(Macro, MacroFileId)>> {
+        let adt = attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it {
+            ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+            ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+            ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+            _ => None,
+        })?;
+        let attr_name = attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
+        let sa = self.analyze_no_infer(adt.syntax())?;
+        let id = self.db.ast_id_map(sa.file_id).ast_id(&adt);
+        let res: Vec<_> = sa
+            .resolver
+            .def_map()
+            .derive_helpers_in_scope(InFile::new(sa.file_id, id))?
+            .iter()
+            .filter(|&(name, _, _)| *name == attr_name)
+            .map(|&(_, macro_, call)| (macro_.into(), call.as_macro_file()))
+            .collect();
+        res.is_empty().not().then_some(res)
+    }
+
     pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
         let file_id = self.find_file(item.syntax()).file_id;
         let src = InFile::new(file_id, item.clone());
@@ -409,6 +430,20 @@ impl<'db> SemanticsImpl<'db> {
         )
     }
 
+    pub fn speculative_expand_raw(
+        &self,
+        macro_file: MacroFileId,
+        speculative_args: &SyntaxNode,
+        token_to_map: SyntaxToken,
+    ) -> Option<(SyntaxNode, SyntaxToken)> {
+        hir_expand::db::expand_speculative(
+            self.db.upcast(),
+            macro_file.macro_call_id,
+            speculative_args,
+            token_to_map,
+        )
+    }
+
     /// Expand the macro call with a different item as the input, mapping the `token_to_map` down into the
     /// expansion. `token_to_map` should be a token from the `speculative args` node.
     pub fn speculative_expand_attr_macro(
@@ -826,107 +861,109 @@ impl<'db> SemanticsImpl<'db> {
 
                     // Then check for token trees, that means we are either in a function-like macro or
                     // secondary attribute inputs
-                    let tt = token.parent_ancestors().map_while(ast::TokenTree::cast).last()?;
-                    let parent = tt.syntax().parent()?;
-
-                    if tt.left_delimiter_token().map_or(false, |it| it == token) {
-                        return None;
-                    }
-                    if tt.right_delimiter_token().map_or(false, |it| it == token) {
-                        return None;
-                    }
-
-                    if let Some(macro_call) = ast::MacroCall::cast(parent.clone()) {
-                        let mcall: hir_expand::files::InFileWrapper<HirFileId, ast::MacroCall> =
-                            InFile::new(file_id, macro_call);
-                        let file_id = match mcache.get(&mcall) {
-                            Some(&it) => it,
-                            None => {
-                                let it = sa.expand(self.db, mcall.as_ref())?;
-                                mcache.insert(mcall, it);
-                                it
+                    let tt = token
+                        .parent_ancestors()
+                        .map_while(Either::<ast::TokenTree, ast::Meta>::cast)
+                        .last()?;
+                    match tt {
+                        Either::Left(tt) => {
+                            if tt.left_delimiter_token().map_or(false, |it| it == token) {
+                                return None;
                             }
-                        };
-                        let text_range = tt.syntax().text_range();
-                        // remove any other token in this macro input, all their mappings are the
-                        // same as this one
-                        tokens.retain(|t| !text_range.contains_range(t.text_range()));
-
-                        process_expansion_for_token(&mut stack, file_id).or(file_id
-                            .eager_arg(self.db.upcast())
-                            .and_then(|arg| {
-                                // also descend into eager expansions
-                                process_expansion_for_token(&mut stack, arg.as_macro_file())
-                            }))
-                    } else if let Some(meta) = ast::Meta::cast(parent) {
-                        // attribute we failed expansion for earlier, this might be a derive invocation
-                        // or derive helper attribute
-                        let attr = meta.parent_attr()?;
-
-                        let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast)
-                        {
-                            // this might be a derive, or a derive helper on an ADT
-                            let derive_call = self.with_ctx(|ctx| {
-                                // so try downmapping the token into the pseudo derive expansion
-                                // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works
-                                ctx.attr_to_derive_macro_call(
-                                    InFile::new(file_id, &adt),
-                                    InFile::new(file_id, attr.clone()),
-                                )
-                                .map(|(_, call_id, _)| call_id)
-                            });
-
-                            match derive_call {
-                                Some(call_id) => {
-                                    // resolved to a derive
-                                    let file_id = call_id.as_macro_file();
-                                    let text_range = attr.syntax().text_range();
-                                    // remove any other token in this macro input, all their mappings are the
-                                    // same as this one
-                                    tokens.retain(|t| !text_range.contains_range(t.text_range()));
-                                    return process_expansion_for_token(&mut stack, file_id);
+                            if tt.right_delimiter_token().map_or(false, |it| it == token) {
+                                return None;
+                            }
+                            let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?;
+                            let mcall: hir_expand::files::InFileWrapper<HirFileId, ast::MacroCall> =
+                                InFile::new(file_id, macro_call);
+                            let file_id = match mcache.get(&mcall) {
+                                Some(&it) => it,
+                                None => {
+                                    let it = sa.expand(self.db, mcall.as_ref())?;
+                                    mcache.insert(mcall, it);
+                                    it
+                                }
+                            };
+                            let text_range = tt.syntax().text_range();
+                            // remove any other token in this macro input, all their mappings are the
+                            // same as this one
+                            tokens.retain(|t| !text_range.contains_range(t.text_range()));
+
+                            process_expansion_for_token(&mut stack, file_id).or(file_id
+                                .eager_arg(self.db.upcast())
+                                .and_then(|arg| {
+                                    // also descend into eager expansions
+                                    process_expansion_for_token(&mut stack, arg.as_macro_file())
+                                }))
+                        }
+                        Either::Right(meta) => {
+                            // attribute we failed expansion for earlier, this might be a derive invocation
+                            // or derive helper attribute
+                            let attr = meta.parent_attr()?;
+                            let adt = match attr.syntax().parent().and_then(ast::Adt::cast) {
+                                Some(adt) => {
+                                    // this might be a derive on an ADT
+                                    let derive_call = self.with_ctx(|ctx| {
+                                        // so try downmapping the token into the pseudo derive expansion
+                                        // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works
+                                        ctx.attr_to_derive_macro_call(
+                                            InFile::new(file_id, &adt),
+                                            InFile::new(file_id, attr.clone()),
+                                        )
+                                        .map(|(_, call_id, _)| call_id)
+                                    });
+
+                                    match derive_call {
+                                        Some(call_id) => {
+                                            // resolved to a derive
+                                            let file_id = call_id.as_macro_file();
+                                            let text_range = attr.syntax().text_range();
+                                            // remove any other token in this macro input, all their mappings are the
+                                            // same as this
+                                            tokens.retain(|t| {
+                                                !text_range.contains_range(t.text_range())
+                                            });
+                                            return process_expansion_for_token(
+                                                &mut stack, file_id,
+                                            );
+                                        }
+                                        None => Some(adt),
+                                    }
+                                }
+                                None => {
+                                    // Otherwise this could be a derive helper on a variant or field
+                                    attr.syntax().ancestors().find_map(ast::Item::cast).and_then(
+                                        |it| match it {
+                                            ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+                                            ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+                                            ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+                                            _ => None,
+                                        },
+                                    )
                                 }
-                                None => Some(adt),
+                            }?;
+                            if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) {
+                                return None;
                             }
-                        } else {
-                            // Otherwise this could be a derive helper on a variant or field
-                            if let Some(field) =
-                                attr.syntax().parent().and_then(ast::RecordField::cast)
+                            let attr_name =
+                                attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
+                            // Not an attribute, nor a derive, so it's either a builtin or a derive helper
+                            // Try to resolve to a derive helper and downmap
+                            let id = self.db.ast_id_map(file_id).ast_id(&adt);
+                            let helpers =
+                                def_map.derive_helpers_in_scope(InFile::new(file_id, id))?;
+
+                            let mut res = None;
+                            for (.., derive) in
+                                helpers.iter().filter(|(helper, ..)| *helper == attr_name)
                             {
-                                field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
-                            } else if let Some(field) =
-                                attr.syntax().parent().and_then(ast::TupleField::cast)
-                            {
-                                field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
-                            } else if let Some(variant) =
-                                attr.syntax().parent().and_then(ast::Variant::cast)
-                            {
-                                variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast)
-                            } else {
-                                None
+                                res = res.or(process_expansion_for_token(
+                                    &mut stack,
+                                    derive.as_macro_file(),
+                                ));
                             }
-                        }?;
-                        if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) {
-                            return None;
-                        }
-                        // Not an attribute, nor a derive, so it's either a builtin or a derive helper
-                        // Try to resolve to a derive helper and downmap
-                        let attr_name =
-                            attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
-                        let id = self.db.ast_id_map(file_id).ast_id(&adt);
-                        let helpers = def_map.derive_helpers_in_scope(InFile::new(file_id, id))?;
-                        let mut res = None;
-                        for (.., derive) in
-                            helpers.iter().filter(|(helper, ..)| *helper == attr_name)
-                        {
-                            res = res.or(process_expansion_for_token(
-                                &mut stack,
-                                derive.as_macro_file(),
-                            ));
+                            res
                         }
-                        res
-                    } else {
-                        None
                     }
                 })()
                 .is_none();
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index d2bd8b0e799..77e7cdb58ab 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -139,7 +139,7 @@ impl SourceToDefCtx<'_, '_> {
         let _p = tracing::span!(tracing::Level::INFO, "module_to_def").entered();
         let parent_declaration = src
             .syntax()
-            .ancestors_with_macros_skip_attr_item(self.db.upcast())
+            .ancestors_with_macros(self.db.upcast())
             .find_map(|it| it.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose())
             .map(|it| it.transpose());
 
@@ -366,7 +366,7 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
-        for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) {
+        for container in src.ancestors_with_macros(self.db.upcast()) {
             if let Some(res) = self.container_to_def(container) {
                 return Some(res);
             }
@@ -420,7 +420,7 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
-        let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
+        let ancestors = src.ancestors_with_macros(self.db.upcast());
         for InFile { file_id, value } in ancestors {
             let item = match ast::Item::cast(value) {
                 Some(it) => it,
@@ -429,6 +429,7 @@ impl SourceToDefCtx<'_, '_> {
             let res: GenericDefId = match item {
                 ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(),
+                ast::Item::Union(it) => self.union_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::TraitAlias(it) => {
@@ -446,11 +447,18 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
-        let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
+        let ancestors = src.ancestors_with_macros(self.db.upcast());
         for InFile { file_id, value } in ancestors {
-            let item = match ast::Item::cast(value) {
+            let item = match ast::Item::cast(value.clone()) {
                 Some(it) => it,
-                None => continue,
+                None => {
+                    if let Some(variant) = ast::Variant::cast(value.clone()) {
+                        return self
+                            .enum_variant_to_def(InFile::new(file_id, variant))
+                            .map(Into::into);
+                    }
+                    continue;
+                }
             };
             let res: DefWithBodyId = match item {
                 ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(),
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search.rs b/src/tools/rust-analyzer/crates/hir/src/term_search.rs
index 5c5ddae19e2..7b70cdf4599 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search.rs
@@ -329,7 +329,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
     while should_continue() {
         lookup.new_round();
 
-        solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup, should_continue));
+        solutions.extend(tactics::data_constructor(ctx, &defs, &mut lookup, should_continue));
         solutions.extend(tactics::free_function(ctx, &defs, &mut lookup, should_continue));
         solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup, should_continue));
         solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup, should_continue));
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
index a26728272dc..f95ff1dc0fa 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
@@ -87,9 +87,9 @@ pub(super) fn trivial<'a, DB: HirDatabase>(
     })
 }
 
-/// # Type constructor tactic
+/// # Data constructor tactic
 ///
-/// Attempts different type constructors for enums and structs in scope
+/// Attempts different data constructors for enums and structs in scope
 ///
 /// Updates lookup by new types reached and returns iterator that yields
 /// elements that unify with `goal`.
@@ -99,7 +99,7 @@ pub(super) fn trivial<'a, DB: HirDatabase>(
 /// * `defs` - Set of items in scope at term search target location
 /// * `lookup` - Lookup table for types
 /// * `should_continue` - Function that indicates when to stop iterating
-pub(super) fn type_constructor<'a, DB: HirDatabase>(
+pub(super) fn data_constructor<'a, DB: HirDatabase>(
     ctx: &'a TermSearchCtx<'a, DB>,
     defs: &'a FxHashSet<ScopeDef>,
     lookup: &'a mut LookupTable,
@@ -308,7 +308,9 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
                         // Early exit if some param cannot be filled from lookup
                         let param_exprs: Vec<Vec<Expr>> = fields
                             .into_iter()
-                            .map(|field| lookup.find(db, &field.ty(db)))
+                            .map(|field| {
+                                lookup.find(db, &field.ty_with_args(db, generics.iter().cloned()))
+                            })
                             .collect::<Option<_>>()?;
 
                         // Note that we need special case for 0 param constructors because of multi cartesian
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
new file mode 100644
index 00000000000..953119fd1ff
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
@@ -0,0 +1,685 @@
+use itertools::Itertools;
+use syntax::{
+    ast::{self, edit::IndentLevel, Comment, CommentPlacement, Whitespace},
+    AstToken, Direction, SyntaxElement, TextRange,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: comment_to_doc
+//
+// Converts comments to documentation.
+//
+// ```
+// // Wow what $0a nice module
+// // I sure hope this shows up when I hover over it
+// ```
+// ->
+// ```
+// //! Wow what a nice module
+// //! I sure hope this shows up when I hover over it
+// ```
+pub(crate) fn convert_comment_from_or_to_doc(
+    acc: &mut Assists,
+    ctx: &AssistContext<'_>,
+) -> Option<()> {
+    let comment = ctx.find_token_at_offset::<ast::Comment>()?;
+
+    match comment.kind().doc {
+        Some(_) => doc_to_comment(acc, comment),
+        None => can_be_doc_comment(&comment).and_then(|style| comment_to_doc(acc, comment, style)),
+    }
+}
+
+fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
+    let target = if comment.kind().shape.is_line() {
+        line_comments_text_range(&comment)?
+    } else {
+        comment.syntax().text_range()
+    };
+
+    acc.add(
+        AssistId("doc_to_comment", AssistKind::RefactorRewrite),
+        "Replace comment with doc comment",
+        target,
+        |edit| {
+            // We need to either replace the first occurrence of /* with /***, or we need to replace
+            // the occurrences // at the start of each line with ///
+            let output = match comment.kind().shape {
+                ast::CommentShape::Line => {
+                    let indentation = IndentLevel::from_token(comment.syntax());
+                    let line_start = comment.prefix();
+                    let prefix = format!("{indentation}//");
+                    relevant_line_comments(&comment)
+                        .iter()
+                        .map(|comment| comment.text())
+                        .flat_map(|text| text.lines())
+                        .map(|line| line.replacen(line_start, &prefix, 1))
+                        .join("\n")
+                }
+                ast::CommentShape::Block => {
+                    let block_start = comment.prefix();
+                    comment
+                        .text()
+                        .lines()
+                        .enumerate()
+                        .map(|(idx, line)| {
+                            if idx == 0 {
+                                line.replacen(block_start, "/*", 1)
+                            } else {
+                                line.replacen("*  ", "* ", 1)
+                            }
+                        })
+                        .join("\n")
+                }
+            };
+            edit.replace(target, output)
+        },
+    )
+}
+
+fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacement) -> Option<()> {
+    let target = if comment.kind().shape.is_line() {
+        line_comments_text_range(&comment)?
+    } else {
+        comment.syntax().text_range()
+    };
+
+    acc.add(
+        AssistId("comment_to_doc", AssistKind::RefactorRewrite),
+        "Replace doc comment with comment",
+        target,
+        |edit| {
+            // We need to either replace the first occurrence of /* with /***, or we need to replace
+            // the occurrences // at the start of each line with ///
+            let output = match comment.kind().shape {
+                ast::CommentShape::Line => {
+                    let indentation = IndentLevel::from_token(comment.syntax());
+                    let line_start = match style {
+                        CommentPlacement::Inner => format!("{indentation}//!"),
+                        CommentPlacement::Outer => format!("{indentation}///"),
+                    };
+                    relevant_line_comments(&comment)
+                        .iter()
+                        .map(|comment| comment.text())
+                        .flat_map(|text| text.lines())
+                        .map(|line| line.replacen("//", &line_start, 1))
+                        .join("\n")
+                }
+                ast::CommentShape::Block => {
+                    let block_start = match style {
+                        CommentPlacement::Inner => "/*!",
+                        CommentPlacement::Outer => "/**",
+                    };
+                    comment
+                        .text()
+                        .lines()
+                        .enumerate()
+                        .map(|(idx, line)| {
+                            if idx == 0 {
+                                // On the first line we replace the comment start with a doc comment
+                                // start.
+                                line.replacen("/*", block_start, 1)
+                            } else {
+                                // put one extra space after each * since we moved the first line to
+                                // the right by one column as well.
+                                line.replacen("* ", "*  ", 1)
+                            }
+                        })
+                        .join("\n")
+                }
+            };
+            edit.replace(target, output)
+        },
+    )
+}
+
+/// Not all comments are valid candidates for conversion into doc comments. For example, the
+/// comments in the code:
+/// ```rust
+/// // Brilliant module right here
+///
+/// // Really good right
+/// fn good_function(foo: Foo) -> Bar {
+///     foo.into_bar()
+/// }
+///
+/// // So nice
+/// mod nice_module {}
+/// ```
+/// can be converted to doc comments. However, the comments in this example:
+/// ```rust
+/// fn foo_bar(foo: Foo /* not bar yet */) -> Bar {
+///     foo.into_bar()
+///     // Nicely done
+/// }
+/// // end of function
+///
+/// struct S {
+///     // The S struct
+/// }
+/// ```
+/// are not allowed to become doc comments. Moreover, some comments _are_ allowed, but aren't common
+/// style in Rust. For example, the following comments are allowed to be doc comments, but it is not
+/// common style for them to be:
+/// ```rust
+/// fn foo_bar(foo: Foo) -> Bar {
+///     // this could be an inner comment with //!
+///     foo.into_bar()
+/// }
+///
+/// trait T {
+///     // The T struct could also be documented from within
+/// }
+///
+/// mod mymod {
+///     // Modules only normally get inner documentation when they are defined as a separate file.
+/// }
+/// ```
+fn can_be_doc_comment(comment: &ast::Comment) -> Option<CommentPlacement> {
+    use syntax::SyntaxKind::*;
+
+    // if the comment is not on its own line, then we do not propose anything.
+    match comment.syntax().prev_token() {
+        Some(prev) => {
+            // There was a previous token, now check if it was a newline
+            Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?;
+        }
+        // There is no previous token, this is the start of the file.
+        None => return Some(CommentPlacement::Inner),
+    }
+
+    // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`,
+    // `use` or `const`.
+    let parent = comment.syntax().parent();
+    let par_kind = parent.as_ref().map(|parent| parent.kind());
+    matches!(par_kind, Some(STRUCT | TRAIT | MODULE | FN | TYPE_ALIAS | EXTERN_CRATE | USE | CONST))
+        .then_some(CommentPlacement::Outer)
+}
+
+/// The line -> block assist can  be invoked from anywhere within a sequence of line comments.
+/// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will
+/// be joined.
+pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
+    // The prefix identifies the kind of comment we're dealing with
+    let prefix = comment.prefix();
+    let same_prefix = |c: &ast::Comment| c.prefix() == prefix;
+
+    // These tokens are allowed to exist between comments
+    let skippable = |not: &SyntaxElement| {
+        not.clone()
+            .into_token()
+            .and_then(Whitespace::cast)
+            .map(|w| !w.spans_multiple_lines())
+            .unwrap_or(false)
+    };
+
+    // Find all preceding comments (in reverse order) that have the same prefix
+    let prev_comments = comment
+        .syntax()
+        .siblings_with_tokens(Direction::Prev)
+        .filter(|s| !skippable(s))
+        .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
+        .take_while(|opt_com| opt_com.is_some())
+        .flatten()
+        .skip(1); // skip the first element so we don't duplicate it in next_comments
+
+    let next_comments = comment
+        .syntax()
+        .siblings_with_tokens(Direction::Next)
+        .filter(|s| !skippable(s))
+        .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
+        .take_while(|opt_com| opt_com.is_some())
+        .flatten();
+
+    let mut comments: Vec<_> = prev_comments.collect();
+    comments.reverse();
+    comments.extend(next_comments);
+    comments
+}
+
+fn line_comments_text_range(comment: &ast::Comment) -> Option<TextRange> {
+    let comments = relevant_line_comments(comment);
+    let first = comments.first()?;
+    let indentation = IndentLevel::from_token(first.syntax());
+    let start =
+        first.syntax().text_range().start().checked_sub((indentation.0 as u32 * 4).into())?;
+    let end = comments.last()?.syntax().text_range().end();
+    Some(TextRange::new(start, end))
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::{check_assist, check_assist_not_applicable};
+
+    use super::*;
+
+    #[test]
+    fn module_comment_to_doc() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            // such a nice module$0
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+            //! such a nice module
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_line_comment_to_doc() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            // unseen$0 docs
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /// unseen docs
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_line_comment_to_doc() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            // unseen$0 docs
+            // make me seen!
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /// unseen docs
+            /// make me seen!
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_line_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /// visible$0 docs
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            // visible docs
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_line_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /// visible$0 docs
+            /// Hide me!
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            // visible docs
+            // Hide me!
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_line_block_comment_to_doc() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /* unseen$0 docs */
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /** unseen docs */
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_line_block_comment_to_doc() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /* unseen$0 docs
+            *  make me seen!
+            */
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /** unseen docs
+            *   make me seen!
+            */
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_line_block_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /** visible$0 docs */
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /* visible docs */
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_line_block_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+
+            /** visible$0 docs
+            *   Hide me!
+            */
+            fn main() {
+                foo();
+            }
+            "#,
+            r#"
+
+            /* visible docs
+            *  Hide me!
+            */
+            fn main() {
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_inner_line_comment_to_doc() {
+        check_assist_not_applicable(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                // unseen$0 docs
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_inner_line_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                //! visible$0 docs
+                foo();
+            }
+            "#,
+            r#"
+            mod mymod {
+                // visible docs
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_inner_line_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                //! visible$0 docs
+                //! Hide me!
+                foo();
+            }
+            "#,
+            r#"
+            mod mymod {
+                // visible docs
+                // Hide me!
+                foo();
+            }
+            "#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                /// visible$0 docs
+                /// Hide me!
+                foo();
+            }
+            "#,
+            r#"
+            mod mymod {
+                // visible docs
+                // Hide me!
+                foo();
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn single_inner_line_block_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                /*! visible$0 docs */
+                type Int = i32;
+            }
+            "#,
+            r#"
+            mod mymod {
+                /* visible docs */
+                type Int = i32;
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn multi_inner_line_block_doc_to_comment() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                /*! visible$0 docs
+                *   Hide me!
+                */
+                type Int = i32;
+            }
+            "#,
+            r#"
+            mod mymod {
+                /* visible docs
+                *  Hide me!
+                */
+                type Int = i32;
+            }
+            "#,
+        );
+    }
+
+    #[test]
+    fn not_overeager() {
+        check_assist_not_applicable(
+            convert_comment_from_or_to_doc,
+            r#"
+            fn main() {
+                foo();
+                // $0well that settles main
+            }
+            // $1 nicely done
+            "#,
+        );
+    }
+
+    #[test]
+    fn all_possible_items() {
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice struct$0 */
+                struct S {}
+            }"#,
+            r#"mod m {
+                /** Nice struct */
+                struct S {}
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice trait$0 */
+                trait T {}
+            }"#,
+            r#"mod m {
+                /** Nice trait */
+                trait T {}
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice module$0 */
+                mod module {}
+            }"#,
+            r#"mod m {
+                /** Nice module */
+                mod module {}
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice function$0 */
+                fn function() {}
+            }"#,
+            r#"mod m {
+                /** Nice function */
+                fn function() {}
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice type$0 */
+                type Type Int = i32;
+            }"#,
+            r#"mod m {
+                /** Nice type */
+                type Type Int = i32;
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice crate$0 */
+                extern crate rust_analyzer;
+            }"#,
+            r#"mod m {
+                /** Nice crate */
+                extern crate rust_analyzer;
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice import$0 */
+                use ide_assists::convert_comment_from_or_to_doc::tests
+            }"#,
+            r#"mod m {
+                /** Nice import */
+                use ide_assists::convert_comment_from_or_to_doc::tests
+            }"#,
+        );
+        check_assist(
+            convert_comment_from_or_to_doc,
+            r#"mod m {
+                /* Nice constant$0 */
+                const CONST: &str = "very const";
+            }"#,
+            r#"mod m {
+                /** Nice constant */
+                const CONST: &str = "very const";
+            }"#,
+        );
+    }
+
+    #[test]
+    fn no_inner_comments() {
+        check_assist_not_applicable(
+            convert_comment_from_or_to_doc,
+            r#"
+            mod mymod {
+                // aaa$0aa
+            }
+            "#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
index ffd1508ccbd..94e0519cba0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
@@ -278,4 +278,16 @@ fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = todo$0!(); }"#,
             r#"fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = (a, (a, b)); }"#,
         )
     }
+
+    #[test]
+    fn test_tuple_struct_with_generics() {
+        check_assist(
+            term_search,
+            r#"//- minicore: todo, unimplemented
+struct Foo<T>(T);
+fn f() { let a = 1; let b: Foo<i32> = todo$0!(); }"#,
+            r#"struct Foo<T>(T);
+fn f() { let a = 1; let b: Foo<i32> = Foo(a); }"#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs
new file mode 100644
index 00000000000..30e09648ea1
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs
@@ -0,0 +1,601 @@
+use hir::{ImportPathConfig, ModuleDef};
+use ide_db::{
+    assists::{AssistId, AssistKind},
+    famous_defs::FamousDefs,
+};
+use syntax::{
+    ast::{self, HasVisibility},
+    AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange,
+};
+
+use crate::{AssistContext, Assists};
+
+// Assist: sugar_impl_future_into_async
+//
+// Rewrites asynchronous function from `-> impl Future` into `async fn`.
+// This action does not touch the function body and therefore `async { 0 }`
+// block does not transform to just `0`.
+//
+// ```
+// # //- minicore: future
+// pub fn foo() -> impl core::future::F$0uture<Output = usize> {
+//     async { 0 }
+// }
+// ```
+// ->
+// ```
+// pub async fn foo() -> usize {
+//     async { 0 }
+// }
+// ```
+pub(crate) fn sugar_impl_future_into_async(
+    acc: &mut Assists,
+    ctx: &AssistContext<'_>,
+) -> Option<()> {
+    let ret_type: ast::RetType = ctx.find_node_at_offset()?;
+    let function = ret_type.syntax().parent().and_then(ast::Fn::cast)?;
+
+    if function.async_token().is_some() || function.const_token().is_some() {
+        return None;
+    }
+
+    let ast::Type::ImplTraitType(return_impl_trait) = ret_type.ty()? else {
+        return None;
+    };
+
+    let main_trait_path = return_impl_trait
+        .type_bound_list()?
+        .bounds()
+        .filter_map(|bound| match bound.ty() {
+            Some(ast::Type::PathType(trait_path)) => trait_path.path(),
+            _ => None,
+        })
+        .next()?;
+
+    let trait_type = ctx.sema.resolve_trait(&main_trait_path)?;
+    let scope = ctx.sema.scope(main_trait_path.syntax())?;
+    if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_future_Future()? {
+        return None;
+    }
+    let future_output = unwrap_future_output(main_trait_path)?;
+
+    acc.add(
+        AssistId("sugar_impl_future_into_async", AssistKind::RefactorRewrite),
+        "Convert `impl Future` into async",
+        function.syntax().text_range(),
+        |builder| {
+            match future_output {
+                // Empty tuple
+                ast::Type::TupleType(t) if t.fields().next().is_none() => {
+                    let mut ret_type_range = ret_type.syntax().text_range();
+
+                    // find leftover whitespace
+                    let whitespace_range = function
+                        .param_list()
+                        .as_ref()
+                        .map(|params| NodeOrToken::Node(params.syntax()))
+                        .and_then(following_whitespace);
+
+                    if let Some(whitespace_range) = whitespace_range {
+                        ret_type_range =
+                            TextRange::new(whitespace_range.start(), ret_type_range.end());
+                    }
+
+                    builder.delete(ret_type_range);
+                }
+                _ => {
+                    builder.replace(
+                        return_impl_trait.syntax().text_range(),
+                        future_output.syntax().text(),
+                    );
+                }
+            }
+
+            let (place_for_async, async_kw) = match function.visibility() {
+                Some(vis) => (vis.syntax().text_range().end(), " async"),
+                None => (function.syntax().text_range().start(), "async "),
+            };
+            builder.insert(place_for_async, async_kw);
+        },
+    )
+}
+
+// Assist: desugar_async_into_impl_future
+//
+// Rewrites asynchronous function from `async fn` into `-> impl Future`.
+// This action does not touch the function body and therefore `0`
+// block does not transform to `async { 0 }`.
+//
+// ```
+// # //- minicore: future
+// pub as$0ync fn foo() -> usize {
+//     0
+// }
+// ```
+// ->
+// ```
+// pub fn foo() -> impl core::future::Future<Output = usize> {
+//     0
+// }
+// ```
+pub(crate) fn desugar_async_into_impl_future(
+    acc: &mut Assists,
+    ctx: &AssistContext<'_>,
+) -> Option<()> {
+    let async_token = ctx.find_token_syntax_at_offset(SyntaxKind::ASYNC_KW)?;
+    let function = async_token.parent().and_then(ast::Fn::cast)?;
+
+    let rparen = function.param_list()?.r_paren_token()?;
+    let return_type = match function.ret_type() {
+        // unable to get a `ty` makes the action unapplicable
+        Some(ret_type) => Some(ret_type.ty()?),
+        // No type means `-> ()`
+        None => None,
+    };
+
+    let scope = ctx.sema.scope(function.syntax())?;
+    let module = scope.module();
+    let future_trait = FamousDefs(&ctx.sema, scope.krate()).core_future_Future()?;
+    let trait_path = module.find_path(
+        ctx.db(),
+        ModuleDef::Trait(future_trait),
+        ImportPathConfig {
+            prefer_no_std: ctx.config.prefer_no_std,
+            prefer_prelude: ctx.config.prefer_prelude,
+        },
+    )?;
+    let trait_path = trait_path.display(ctx.db());
+
+    acc.add(
+        AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite),
+        "Convert async into `impl Future`",
+        function.syntax().text_range(),
+        |builder| {
+            let mut async_range = async_token.text_range();
+
+            if let Some(whitespace_range) = following_whitespace(NodeOrToken::Token(async_token)) {
+                async_range = TextRange::new(async_range.start(), whitespace_range.end());
+            }
+            builder.delete(async_range);
+
+            match return_type {
+                Some(ret_type) => builder.replace(
+                    ret_type.syntax().text_range(),
+                    format!("impl {trait_path}<Output = {ret_type}>"),
+                ),
+                None => builder.insert(
+                    rparen.text_range().end(),
+                    format!(" -> impl {trait_path}<Output = ()>"),
+                ),
+            }
+        },
+    )
+}
+
+fn unwrap_future_output(path: ast::Path) -> Option<ast::Type> {
+    let future_trait = path.segments().last()?;
+    let assoc_list = future_trait.generic_arg_list()?;
+    let future_assoc = assoc_list.generic_args().next()?;
+    match future_assoc {
+        ast::GenericArg::AssocTypeArg(output_type) => output_type.ty(),
+        _ => None,
+    }
+}
+
+fn following_whitespace(nt: NodeOrToken<&SyntaxNode, SyntaxToken>) -> Option<TextRange> {
+    let next_token = match nt {
+        NodeOrToken::Node(node) => node.next_sibling_or_token(),
+        NodeOrToken::Token(token) => token.next_sibling_or_token(),
+    }?;
+    (next_token.kind() == SyntaxKind::WHITESPACE).then_some(next_token.text_range())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::tests::{check_assist, check_assist_not_applicable};
+
+    #[test]
+    fn sugar_with_use() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    fn foo() -> impl F$0uture<Output = ()> {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future::Future;
+    async fn foo() {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    fn foo() -> impl F$0uture<Output = usize> {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future::Future;
+    async fn foo() -> usize {
+        todo!()
+    }
+    "#,
+        );
+    }
+
+    #[test]
+    fn desugar_with_use() {
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    as$0ync fn foo() {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future::Future;
+    fn foo() -> impl Future<Output = ()> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    use core::future;
+    as$0ync fn foo() {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future;
+    fn foo() -> impl future::Future<Output = ()> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    as$0ync fn foo() -> usize {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future::Future;
+    fn foo() -> impl Future<Output = usize> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    as$0ync fn foo() -> impl Future<Output = usize> {
+        todo!()
+    }
+    "#,
+            r#"
+    use core::future::Future;
+    fn foo() -> impl Future<Output = impl Future<Output = usize>> {
+        todo!()
+    }
+    "#,
+        );
+    }
+
+    #[test]
+    fn sugar_without_use() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = ()> {
+        todo!()
+    }
+    "#,
+            r#"
+    async fn foo() {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = usize> {
+        todo!()
+    }
+    "#,
+            r#"
+    async fn foo() -> usize {
+        todo!()
+    }
+    "#,
+        );
+    }
+
+    #[test]
+    fn desugar_without_use() {
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    as$0ync fn foo() {
+        todo!()
+    }
+    "#,
+            r#"
+    fn foo() -> impl core::future::Future<Output = ()> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist(
+            desugar_async_into_impl_future,
+            r#"
+    //- minicore: future
+    as$0ync fn foo() -> usize {
+        todo!()
+    }
+    "#,
+            r#"
+    fn foo() -> impl core::future::Future<Output = usize> {
+        todo!()
+    }
+    "#,
+        );
+    }
+
+    #[test]
+    fn not_applicable() {
+        check_assist_not_applicable(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    trait Future {
+        type Output;
+    }
+    fn foo() -> impl F$0uture<Output = ()> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist_not_applicable(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    trait Future {
+        type Output;
+    }
+    fn foo() -> impl F$0uture<Output = usize> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist_not_applicable(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    f$0n foo() -> impl core::future::Future<Output = usize> {
+        todo!()
+    }
+    "#,
+        );
+
+        check_assist_not_applicable(
+            desugar_async_into_impl_future,
+            r#"
+    async f$0n foo() {
+        todo!()
+    }
+    "#,
+        );
+    }
+
+    #[test]
+    fn sugar_definition_with_use() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    fn foo() -> impl F$0uture<Output = ()>;
+    "#,
+            r#"
+    use core::future::Future;
+    async fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    use core::future::Future;
+    fn foo() -> impl F$0uture<Output = usize>;
+    "#,
+            r#"
+    use core::future::Future;
+    async fn foo() -> usize;
+    "#,
+        );
+    }
+
+    #[test]
+    fn sugar_definition_without_use() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = ()>;
+    "#,
+            r#"
+    async fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = usize>;
+    "#,
+            r#"
+    async fn foo() -> usize;
+    "#,
+        );
+    }
+
+    #[test]
+    fn sugar_more_types() {
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = ()> + Send + Sync;
+    "#,
+            r#"
+    async fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = usize> + Debug;
+    "#,
+            r#"
+    async fn foo() -> usize;
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = (usize)> + Debug;
+    "#,
+            r#"
+    async fn foo() -> (usize);
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::F$0uture<Output = (usize, usize)> + Debug;
+    "#,
+            r#"
+    async fn foo() -> (usize, usize);
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo() -> impl core::future::Future<Output = impl core::future::F$0uture<Output = ()> + Send>;
+    "#,
+            r#"
+    async fn foo() -> impl core::future::Future<Output = ()> + Send;
+    "#,
+        );
+    }
+
+    #[test]
+    fn sugar_with_modifiers() {
+        check_assist_not_applicable(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    const fn foo() -> impl core::future::F$0uture<Output = ()>;
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+            //- minicore: future
+            pub(crate) unsafe fn foo() -> impl core::future::F$0uture<Output = usize>;
+        "#,
+            r#"
+            pub(crate) async unsafe fn foo() -> usize;
+        "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    unsafe fn foo() -> impl core::future::F$0uture<Output = ()>;
+    "#,
+            r#"
+    async unsafe fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    unsafe extern "C" fn foo() -> impl core::future::F$0uture<Output = ()>;
+    "#,
+            r#"
+    async unsafe extern "C" fn foo();
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo<T>() -> impl core::future::F$0uture<Output = T>;
+    "#,
+            r#"
+    async fn foo<T>() -> T;
+    "#,
+        );
+
+        check_assist(
+            sugar_impl_future_into_async,
+            r#"
+    //- minicore: future
+    fn foo<T>() -> impl core::future::F$0uture<Output = T>
+    where
+        T: Sized;
+    "#,
+            r#"
+    async fn foo<T>() -> T
+    where
+        T: Sized;
+    "#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 0df5e913a57..abebdec1d18 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -116,6 +116,7 @@ mod handlers {
     mod change_visibility;
     mod convert_bool_then;
     mod convert_comment_block;
+    mod convert_comment_from_or_to_doc;
     mod convert_from_to_tryfrom;
     mod convert_integer_literal;
     mod convert_into_to_from;
@@ -209,6 +210,7 @@ mod handlers {
     mod sort_items;
     mod split_import;
     mod term_search;
+    mod toggle_async_sugar;
     mod toggle_ignore;
     mod unmerge_match_arm;
     mod unmerge_use;
@@ -238,7 +240,10 @@ mod handlers {
             change_visibility::change_visibility,
             convert_bool_then::convert_bool_then_to_if,
             convert_bool_then::convert_if_to_bool_then,
+            toggle_async_sugar::desugar_async_into_impl_future,
+            toggle_async_sugar::sugar_impl_future_into_async,
             convert_comment_block::convert_comment_block,
+            convert_comment_from_or_to_doc::convert_comment_from_or_to_doc,
             convert_from_to_tryfrom::convert_from_to_tryfrom,
             convert_integer_literal::convert_integer_literal,
             convert_into_to_from::convert_into_to_from,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 937e78f8d7d..eec1087e2df 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -346,6 +346,21 @@ pub(crate) fn frobnicate() {}
 }
 
 #[test]
+fn doctest_comment_to_doc() {
+    check_doc_test(
+        "comment_to_doc",
+        r#####"
+// Wow what $0a nice module
+// I sure hope this shows up when I hover over it
+"#####,
+        r#####"
+//! Wow what a nice module
+//! I sure hope this shows up when I hover over it
+"#####,
+    )
+}
+
+#[test]
 fn doctest_convert_bool_then_to_if() {
     check_doc_test(
         "convert_bool_then_to_if",
@@ -801,6 +816,24 @@ fn main() {
 }
 
 #[test]
+fn doctest_desugar_async_into_impl_future() {
+    check_doc_test(
+        "desugar_async_into_impl_future",
+        r#####"
+//- minicore: future
+pub as$0ync fn foo() -> usize {
+    0
+}
+"#####,
+        r#####"
+pub fn foo() -> impl core::future::Future<Output = usize> {
+    0
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_desugar_doc_comment() {
     check_doc_test(
         "desugar_doc_comment",
@@ -3021,6 +3054,24 @@ use std::{collections::HashMap};
 }
 
 #[test]
+fn doctest_sugar_impl_future_into_async() {
+    check_doc_test(
+        "sugar_impl_future_into_async",
+        r#####"
+//- minicore: future
+pub fn foo() -> impl core::future::F$0uture<Output = usize> {
+    async { 0 }
+}
+"#####,
+        r#####"
+pub async fn foo() -> usize {
+    async { 0 }
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_toggle_ignore() {
     check_doc_test(
         "toggle_ignore",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 79c503e0a10..f0c6e7a63b0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -3,8 +3,9 @@ use std::iter;
 
 use hir::{Semantics, Type, TypeInfo, Variant};
 use ide_db::{active_parameter::ActiveParameter, RootDatabase};
+use itertools::Either;
 use syntax::{
-    algo::{find_node_at_offset, non_trivia_sibling},
+    algo::{ancestors_at_offset, find_node_at_offset, non_trivia_sibling},
     ast::{self, AttrKind, HasArgList, HasGenericParams, HasLoopBody, HasName, NameOrNameRef},
     match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
     SyntaxToken, TextRange, TextSize, T,
@@ -119,20 +120,45 @@ fn expand(
         }
 
         // No attributes have been expanded, so look for macro_call! token trees or derive token trees
-        let orig_tt = match find_node_at_offset::<ast::TokenTree>(&original_file, offset) {
+        let orig_tt = match ancestors_at_offset(&original_file, offset)
+            .map_while(Either::<ast::TokenTree, ast::Meta>::cast)
+            .last()
+        {
             Some(it) => it,
             None => break 'expansion,
         };
-        let spec_tt = match find_node_at_offset::<ast::TokenTree>(&speculative_file, offset) {
+        let spec_tt = match ancestors_at_offset(&speculative_file, offset)
+            .map_while(Either::<ast::TokenTree, ast::Meta>::cast)
+            .last()
+        {
             Some(it) => it,
             None => break 'expansion,
         };
 
-        // Expand pseudo-derive expansion
-        if let (Some(orig_attr), Some(spec_attr)) = (
-            orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
-            spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
-        ) {
+        let (tts, attrs) = match (orig_tt, spec_tt) {
+            (Either::Left(orig_tt), Either::Left(spec_tt)) => {
+                let attrs = orig_tt
+                    .syntax()
+                    .parent()
+                    .and_then(ast::Meta::cast)
+                    .and_then(|it| it.parent_attr())
+                    .zip(
+                        spec_tt
+                            .syntax()
+                            .parent()
+                            .and_then(ast::Meta::cast)
+                            .and_then(|it| it.parent_attr()),
+                    );
+                (Some((orig_tt, spec_tt)), attrs)
+            }
+            (Either::Right(orig_path), Either::Right(spec_path)) => {
+                (None, orig_path.parent_attr().zip(spec_path.parent_attr()))
+            }
+            _ => break 'expansion,
+        };
+
+        // Expand pseudo-derive expansion aka `derive(Debug$0)`
+        if let Some((orig_attr, spec_attr)) = attrs {
             if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = (
                 sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
                 sema.speculative_expand_derive_as_pseudo_attr_macro(
@@ -147,15 +173,54 @@ fn expand(
                     fake_mapped_token.text_range().start(),
                     orig_attr,
                 ));
+                break 'expansion;
+            }
+
+            if let Some(spec_adt) =
+                spec_attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it {
+                    ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+                    ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+                    ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+                    _ => None,
+                })
+            {
+                // might be the path of derive helper or a token tree inside of one
+                if let Some(helpers) = sema.derive_helper(&orig_attr) {
+                    for (_mac, file) in helpers {
+                        if let Some((fake_expansion, fake_mapped_token)) = sema
+                            .speculative_expand_raw(
+                                file,
+                                spec_adt.syntax(),
+                                fake_ident_token.clone(),
+                            )
+                        {
+                            // we are inside a derive helper token tree, treat this as being inside
+                            // the derive expansion
+                            let actual_expansion = sema.parse_or_expand(file.into());
+                            let new_offset = fake_mapped_token.text_range().start();
+                            if new_offset + relative_offset > actual_expansion.text_range().end() {
+                                // offset outside of bounds from the original expansion,
+                                // stop here to prevent problems from happening
+                                break 'expansion;
+                            }
+                            original_file = actual_expansion;
+                            speculative_file = fake_expansion;
+                            fake_ident_token = fake_mapped_token;
+                            offset = new_offset;
+                            continue 'expansion;
+                        }
+                    }
+                }
             }
             // at this point we won't have any more successful expansions, so stop
             break 'expansion;
         }
 
         // Expand fn-like macro calls
+        let Some((orig_tt, spec_tt)) = tts else { break 'expansion };
         if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = (
-            orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
-            spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
+            orig_tt.syntax().parent().and_then(ast::MacroCall::cast),
+            spec_tt.syntax().parent().and_then(ast::MacroCall::cast),
         ) {
             let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text());
             let mac_call_path1 =
@@ -201,6 +266,7 @@ fn expand(
         // none of our states have changed so stop the loop
         break 'expansion;
     }
+
     ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
index 3106772e63b..e445e9fb68d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
@@ -106,6 +106,10 @@ impl FamousDefs<'_, '_> {
         self.find_trait("core:marker:Copy")
     }
 
+    pub fn core_future_Future(&self) -> Option<Trait> {
+        self.find_trait("core:future:Future")
+    }
+
     pub fn core_macros_builtin_derive(&self) -> Option<Macro> {
         self.find_macro("core:macros:builtin:derive")
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
index fab62e95d19..c19f19803f1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
@@ -16,7 +16,7 @@ use crate::{
 //
 // This is the same as `Go to Definition` with the following exceptions:
 // - outline modules will navigate to the `mod name;` item declaration
-// - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl
+// - trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl
 // - fields in patterns will navigate to the field declaration of the struct, union or variant
 pub(crate) fn goto_declaration(
     db: &RootDatabase,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 79b87ecd58f..f64e66183d1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -87,7 +87,6 @@ pub(crate) struct GlobalState {
     pub(crate) flycheck_sender: Sender<flycheck::Message>,
     pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
     pub(crate) last_flycheck_error: Option<String>,
-    pub(crate) diagnostics_received: bool,
 
     // Test explorer
     pub(crate) test_run_session: Option<Vec<flycheck::CargoTestHandle>>,
@@ -225,7 +224,6 @@ impl GlobalState {
             flycheck_sender,
             flycheck_receiver,
             last_flycheck_error: None,
-            diagnostics_received: false,
 
             test_run_session: None,
             test_run_sender,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 7acd302867c..193b3fdd4a8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -804,10 +804,6 @@ impl GlobalState {
     fn handle_flycheck_msg(&mut self, message: flycheck::Message) {
         match message {
             flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => {
-                if !self.diagnostics_received {
-                    self.diagnostics.clear_check(id);
-                    self.diagnostics_received = true;
-                }
                 let snap = self.snapshot();
                 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
                     &self.config.diagnostics_map(),
@@ -833,12 +829,11 @@ impl GlobalState {
                 }
             }
 
+            flycheck::Message::ClearDiagnostics { id } => self.diagnostics.clear_check(id),
+
             flycheck::Message::Progress { id, progress } => {
                 let (state, message) = match progress {
-                    flycheck::Progress::DidStart => {
-                        self.diagnostics_received = false;
-                        (Progress::Begin, None)
-                    }
+                    flycheck::Progress::DidStart => (Progress::Begin, None),
                     flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
                     flycheck::Progress::DidCancel => {
                         self.last_flycheck_error = None;
@@ -852,9 +847,6 @@ impl GlobalState {
                     flycheck::Progress::DidFinish(result) => {
                         self.last_flycheck_error =
                             result.err().map(|err| format!("cargo check failed to start: {err}"));
-                        if !self.diagnostics_received {
-                            self.diagnostics.clear_check(id);
-                        }
                         (Progress::End, None)
                     }
                 };
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 009200aca15..600ca06fcdf 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -2,11 +2,9 @@ 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
-run-make/c-link-to-rust-dylib/Makefile
 run-make/c-static-dylib/Makefile
 run-make/c-static-rlib/Makefile
 run-make/c-unwind-abi-catch-lib-panic/Makefile
@@ -14,7 +12,6 @@ run-make/c-unwind-abi-catch-panic/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
 run-make/cdylib-fewer-symbols/Makefile
-run-make/cdylib/Makefile
 run-make/codegen-options-parsing/Makefile
 run-make/comment-section/Makefile
 run-make/compiler-lookup-paths-2/Makefile
@@ -38,12 +35,10 @@ run-make/dump-ice-to-disk/Makefile
 run-make/dump-mono-stats/Makefile
 run-make/duplicate-output-flavors/Makefile
 run-make/dylib-chain/Makefile
-run-make/emit-named-files/Makefile
 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
@@ -150,7 +145,6 @@ 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
diff --git a/tests/codegen/checked_ilog.rs b/tests/codegen/checked_ilog.rs
new file mode 100644
index 00000000000..8f3c07119fe
--- /dev/null
+++ b/tests/codegen/checked_ilog.rs
@@ -0,0 +1,20 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+// Ensure that when val < base, we do not divide or multiply.
+
+// CHECK-LABEL: @checked_ilog
+// CHECK-SAME: (i16 noundef %val, i16 noundef %base)
+#[no_mangle]
+pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
+    // CHECK-NOT: udiv
+    // CHECK-NOT: mul
+    // CHECK: %[[IS_LESS:.+]] = icmp ult i16 %val, %base
+    // CHECK-NEXT: br i1 %[[IS_LESS]], label %[[TRUE:.+]], label %[[FALSE:.+]]
+    // CHECK: [[TRUE]]:
+    // CHECK-NOT: udiv
+    // CHECK-NOT: mul
+    // CHECK: ret { i32, i32 }
+    val.checked_ilog(base)
+}
diff --git a/tests/codegen/simd/packed-simd-alignment.rs b/tests/codegen/simd/packed-simd-alignment.rs
new file mode 100644
index 00000000000..53e88d8e5cf
--- /dev/null
+++ b/tests/codegen/simd/packed-simd-alignment.rs
@@ -0,0 +1,44 @@
+//@ compile-flags: -Cno-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(repr_simd, core_intrinsics)]
+// make sure that codegen emits correctly-aligned loads and stores for repr(packed, simd) types
+// the alignment of a load should be no less than T, and no more than the size of the vector type
+use std::intrinsics::simd as intrinsics;
+
+#[derive(Copy, Clone)]
+#[repr(packed, simd)]
+struct f32x3([f32; 3]);
+
+#[derive(Copy, Clone)]
+#[repr(packed, simd)]
+struct f32x4([f32; 4]);
+
+// CHECK-LABEL: load_f32x3
+#[no_mangle]
+pub fn load_f32x3(floats: &f32x3) -> f32x3 {
+    // FIXME: Is a memcpy really the best we can do?
+    // CHECK: @llvm.memcpy.{{.*}}ptr align 4 {{.*}}ptr align 4
+    *floats
+}
+
+// CHECK-LABEL: load_f32x4
+#[no_mangle]
+pub fn load_f32x4(floats: &f32x4) -> f32x4 {
+    // CHECK: load <4 x float>, ptr %{{[a-z0-9_]*}}, align {{4|8|16}}
+    *floats
+}
+
+// CHECK-LABEL: add_f32x3
+#[no_mangle]
+pub fn add_f32x3(x: f32x3, y: f32x3) -> f32x3 {
+    // CHECK: load <3 x float>, ptr %{{[a-z0-9_]*}}, align 4
+    unsafe { intrinsics::simd_add(x, y) }
+}
+
+// CHECK-LABEL: add_f32x4
+#[no_mangle]
+pub fn add_f32x4(x: f32x4, y: f32x4) -> f32x4 {
+    // CHECK: load <4 x float>, ptr %{{[a-z0-9_]*}}, align {{4|8|16}}
+    unsafe { intrinsics::simd_add(x, y) }
+}
diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs
new file mode 100644
index 00000000000..f0911b6e360
--- /dev/null
+++ b/tests/codegen/simd/packed-simd.rs
@@ -0,0 +1,44 @@
+//@ revisions:opt3 noopt
+//@[opt3] compile-flags: -Copt-level=3
+//@[noopt] compile-flags: -Cno-prepopulate-passes
+
+#![crate_type = "lib"]
+#![no_std]
+#![feature(repr_simd, core_intrinsics)]
+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.
+
+#[repr(simd, packed)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct FullSimd<T, const N: usize>([T; N]);
+
+// non-powers-of-two have padding and need to be expanded to full vectors
+fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
+    unsafe {
+        let mut tmp = mem::MaybeUninit::<FullSimd<T, N>>::uninit();
+        ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
+        tmp.assume_init()
+    }
+}
+
+// CHECK-LABEL: square_packed
+// 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> {
+    // CHECK-NEXT: start
+    // noopt: alloca [[RET_TYPE]], [[RET_ALIGN]]
+    // CHECK: load <3 x float>
+    let x = load(x);
+    // CHECK: [[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/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/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/debuginfo/unsized.rs b/tests/debuginfo/unsized.rs
index f76376de383..982ab003a2a 100644
--- a/tests/debuginfo/unsized.rs
+++ b/tests/debuginfo/unsized.rs
@@ -46,13 +46,13 @@
 // cdb-command:dx c
 // cdb-check:c                [Type: ref$<unsized::Foo<dyn$<core::fmt::Debug> > >]
 // cdb-check:    [+0x000] pointer          : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
-// cdb-check:    [...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
+// cdb-check:    [...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
 
 // cdb-command:dx _box
 // cdb-check:
 // cdb-check:_box             [Type: alloc::boxed::Box<unsized::Foo<dyn$<core::fmt::Debug> >,alloc::alloc::Global>]
 // cdb-check:[+0x000] pointer          : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
-// cdb-check:[...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
+// cdb-check:[...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
 
 // cdb-command:dx tuple_slice
 // cdb-check:tuple_slice      [Type: ref$<tuple$<i32,i32,slice2$<i32> > >]
@@ -62,7 +62,7 @@
 // cdb-command:dx tuple_dyn
 // cdb-check:tuple_dyn        [Type: ref$<tuple$<i32,i32,dyn$<core::fmt::Debug> > >]
 // cdb-check:    [+0x000] pointer          : 0x[...] [Type: tuple$<i32,i32,dyn$<core::fmt::Debug> > *]
-// cdb-check:    [...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[3]]
+// cdb-check:    [...] vtable           : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
 
 #![feature(unsized_tuple_coercion)]
 #![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.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/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_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/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.rs b/tests/mir-opt/gvn.rs
index 9be30515283..315377e4356 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,7 @@ fn non_freeze<T: Copy>(x: T) {
         ret = {
             Return()
         }
-    )
+    }
 }
 
 fn main() {
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.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_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/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/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/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/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/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 28a1e27cccc..07466440aab 100644
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -27,7 +27,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 +64,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() {
diff --git a/tests/run-make-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs
index 02b235068a1..64ed97572ee 100644
--- a/tests/run-make-fulldeps/pretty-expanded/input.rs
+++ b/tests/run-make-fulldeps/pretty-expanded/input.rs
@@ -1,8 +1,25 @@
 // #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) }
+#[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/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..82d0fab5073
--- /dev/null
+++ b/tests/run-make/bare-outfile/rmake.rs
@@ -0,0 +1,15 @@
+// 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, tmp_dir};
+use std::env;
+use std::fs;
+
+fn main() {
+    fs::copy("foo.rs", tmp_dir().join("foo.rs")).unwrap();
+    env::set_current_dir(tmp_dir());
+    rustc().output("foo").input("foo.rs").run();
+    run("foo");
+}
diff --git a/tests/run-make/c-link-to-rust-dylib/Makefile b/tests/run-make/c-link-to-rust-dylib/Makefile
deleted file mode 100644
index 201f717ece4..00000000000
--- a/tests/run-make/c-link-to-rust-dylib/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# This test checks that C linking with Rust does not encounter any errors, with dynamic libraries.
-# See https://github.com/rust-lang/rust/issues/10434
-
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(TMPDIR)/$(call BIN,bar)
-	$(call RUN,bar)
-	$(call REMOVE_DYLIBS,foo)
-	$(call FAIL,bar)
-
-ifdef IS_MSVC
-$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
-	$(CC) bar.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,bar)
-else
-$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
-	$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR)
-endif
-
-$(call DYLIB,foo): foo.rs
-	$(RUSTC) foo.rs
diff --git a/tests/run-make/c-link-to-rust-dylib/rmake.rs b/tests/run-make/c-link-to-rust-dylib/rmake.rs
new file mode 100644
index 00000000000..5c4b6d78649
--- /dev/null
+++ b/tests/run-make/c-link-to-rust-dylib/rmake.rs
@@ -0,0 +1,41 @@
+// This test checks that C linking with Rust does not encounter any errors, with dynamic libraries.
+// See <https://github.com/rust-lang/rust/issues/10434>.
+
+//@ ignore-cross-compile
+
+use std::fs::remove_file;
+
+use run_make_support::{
+    cc, dynamic_lib_extension, is_msvc, read_dir, run, run_fail, rustc, tmp_dir,
+};
+
+fn main() {
+    rustc().input("foo.rs").run();
+
+    if is_msvc() {
+        let lib = tmp_dir().join("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();
+    }
+
+    run("bar");
+
+    let expected_extension = dynamic_lib_extension();
+    read_dir(tmp_dir(), |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| {
+                name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib")
+            })
+        {
+            remove_file(path).unwrap();
+        }
+    });
+    run_fail("bar");
+}
diff --git a/tests/run-make/cdylib/Makefile b/tests/run-make/cdylib/Makefile
deleted file mode 100644
index 2c6414c3255..00000000000
--- a/tests/run-make/cdylib/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# When the cdylib crate type was added as a variation of dylib, it needed a test to check its function.
-# See https://github.com/rust-lang/rust/pull/33553
-
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call RUN_BINFILE,foo)
-	$(call RUN,foo)
-	rm $(call DYLIB,foo)
-	$(RUSTC) foo.rs -C lto
-	$(call RUN,foo)
-
-ifdef IS_MSVC
-$(call RUN_BINFILE,foo): $(call DYLIB,foo)
-	$(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,foo)
-else
-$(call RUN_BINFILE,foo): $(call DYLIB,foo)
-	$(CC) $(CFLAGS) foo.c -lfoo -o $(call RUN_BINFILE,foo) -L $(TMPDIR)
-endif
-
-$(call DYLIB,foo):
-	$(RUSTC) bar.rs
-	$(RUSTC) foo.rs
diff --git a/tests/run-make/cdylib/rmake.rs b/tests/run-make/cdylib/rmake.rs
new file mode 100644
index 00000000000..fcb4f56621f
--- /dev/null
+++ b/tests/run-make/cdylib/rmake.rs
@@ -0,0 +1,36 @@
+// This test tries to check that basic cdylib libraries can be compiled and linked successfully
+// with C code, that the cdylib itself can depend on another rlib, and that the library can be built
+// with LTO.
+//
+// - `bar.rs` is a rlib
+// - `foo.rs` is a cdylib that relies on an extern crate `bar` and defines two `extern "C"`
+//   functions:
+//     - `foo()` which calls `bar::bar()`.
+//     - `bar()` which implements basic addition.
+
+//@ ignore-cross-compile
+
+use std::fs::remove_file;
+
+use run_make_support::{cc, dynamic_lib, is_msvc, run, rustc, tmp_dir};
+
+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();
+    } else {
+        cc().input("foo.c")
+            .arg("-lfoo")
+            .output(tmp_dir().join("foo"))
+            .library_search_path(tmp_dir())
+            .run();
+    }
+
+    run("foo");
+    remove_file(dynamic_lib("foo")).unwrap();
+
+    rustc().input("foo.rs").arg("-Clto").run();
+    run("foo");
+}
diff --git a/tests/run-make/emit-named-files/Makefile b/tests/run-make/emit-named-files/Makefile
deleted file mode 100644
index 2b97b841fc0..00000000000
--- a/tests/run-make/emit-named-files/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-include ../tools.mk
-
-OUT=$(TMPDIR)/emit
-
-all: asm llvm-bc llvm-ir obj metadata link dep-info mir
-
-asm: $(OUT)
-	$(RUSTC) --emit asm=$(OUT)/libfoo.s foo.rs
-	test -f $(OUT)/libfoo.s
-llvm-bc: $(OUT)
-	$(RUSTC) --emit llvm-bc=$(OUT)/libfoo.bc foo.rs
-	test -f $(OUT)/libfoo.bc
-llvm-ir: $(OUT)
-	$(RUSTC) --emit llvm-ir=$(OUT)/libfoo.ll foo.rs
-	test -f $(OUT)/libfoo.ll
-obj: $(OUT)
-	$(RUSTC) --emit obj=$(OUT)/libfoo.o foo.rs
-	test -f $(OUT)/libfoo.o
-metadata: $(OUT)
-	$(RUSTC) --emit metadata=$(OUT)/libfoo.rmeta foo.rs
-	test -f $(OUT)/libfoo.rmeta
-link: $(OUT)
-	$(RUSTC) --emit link=$(OUT)/libfoo.rlib foo.rs
-	test -f $(OUT)/libfoo.rlib
-dep-info: $(OUT)
-	$(RUSTC) --emit dep-info=$(OUT)/libfoo.d foo.rs
-	test -f $(OUT)/libfoo.d
-mir: $(OUT)
-	$(RUSTC) --emit mir=$(OUT)/libfoo.mir foo.rs
-	test -f $(OUT)/libfoo.mir
-
-$(OUT):
-	mkdir -p $(OUT)
diff --git a/tests/run-make/emit-named-files/rmake.rs b/tests/run-make/emit-named-files/rmake.rs
new file mode 100644
index 00000000000..068f9796d0e
--- /dev/null
+++ b/tests/run-make/emit-named-files/rmake.rs
@@ -0,0 +1,25 @@
+use std::fs::create_dir;
+use std::path::Path;
+
+use run_make_support::{rustc, tmp_dir};
+
+fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) {
+    let out_file = out_dir.join(out_file);
+    rustc().input("foo.rs").emit(&format!("{format}={}", out_file.display())).run();
+    assert!(out_file.is_file());
+}
+
+fn main() {
+    let out_dir = tmp_dir().join("emit");
+
+    create_dir(&out_dir).unwrap();
+
+    emit_and_check(&out_dir, "libfoo.s", "asm");
+    emit_and_check(&out_dir, "libfoo.bc", "llvm-bc");
+    emit_and_check(&out_dir, "libfoo.ll", "llvm-ir");
+    emit_and_check(&out_dir, "libfoo.o", "obj");
+    emit_and_check(&out_dir, "libfoo.rmeta", "metadata");
+    emit_and_check(&out_dir, "libfoo.rlib", "link");
+    emit_and_check(&out_dir, "libfoo.d", "dep-info");
+    emit_and_check(&out_dir, "libfoo.mir", "mir");
+}
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/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..0d40b0325f7
--- /dev/null
+++ b/tests/run-make/mixing-formats/rmake.rs
@@ -0,0 +1,94 @@
+// 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::{rustc, tmp_dir};
+use std::fs;
+
+fn test_with_teardown(rustc_calls: impl Fn()) {
+    rustc_calls();
+    //FIXME(Oneirical): This should be replaced with the run-make-support fs wrappers.
+    fs::remove_dir_all(tmp_dir()).unwrap();
+    fs::create_dir(tmp_dir()).unwrap();
+}
+
+fn main() {
+    test_with_teardown(|| {
+        // 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();
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        // 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);
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        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();
+    });
+    test_with_teardown(|| {
+        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/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..c866d9179f9
--- /dev/null
+++ b/tests/run-make/notify-all-emit-artifacts/rmake.rs
@@ -0,0 +1,45 @@
+// 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::{rustc, tmp_dir};
+
+fn main() {
+    let inc_dir = tmp_dir();
+
+    // 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(&inc_dir)
+            .run();
+        let stderr = String::from_utf8_lossy(&output.stderr);
+        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(&inc_dir)
+            .run();
+        let stderr = String::from_utf8_lossy(&output.stderr);
+        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/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs
index f7f5fcf2340..a0aa95c8abc 100644
--- a/tests/run-make/print-check-cfg/rmake.rs
+++ b/tests/run-make/print-check-cfg/rmake.rs
@@ -8,61 +8,84 @@ use std::ops::Deref;
 
 use run_make_support::rustc;
 
+struct CheckCfg {
+    args: &'static [&'static str],
+    contains: Contains,
+}
+
+enum Contains {
+    Some { contains: &'static [&'static str], doesnt_contain: &'static [&'static str] },
+    Only(&'static str),
+}
+
 fn main() {
-    check(
-        /*args*/ &[],
-        /*has_any*/ false,
-        /*has_any_any*/ true,
-        /*contains*/ &[],
-    );
-    check(
-        /*args*/ &["--check-cfg=cfg()"],
-        /*has_any*/ false,
-        /*has_any_any*/ false,
-        /*contains*/ &["unix", "miri"],
-    );
-    check(
-        /*args*/ &["--check-cfg=cfg(any())"],
-        /*has_any*/ true,
-        /*has_any_any*/ false,
-        /*contains*/ &["windows", "test"],
-    );
-    check(
-        /*args*/ &["--check-cfg=cfg(feature)"],
-        /*has_any*/ false,
-        /*has_any_any*/ false,
-        /*contains*/ &["unix", "miri", "feature"],
-    );
-    check(
-        /*args*/ &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#],
-        /*has_any*/ false,
-        /*has_any_any*/ false,
-        /*contains*/ &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""],
-    );
-    check(
-        /*args*/
-        &[
+    check(CheckCfg { args: &[], contains: Contains::Only("any()=any()") });
+    check(CheckCfg {
+        args: &["--check-cfg=cfg()"],
+        contains: Contains::Some {
+            contains: &["unix", "miri"],
+            doesnt_contain: &["any()", "any()=any()"],
+        },
+    });
+    check(CheckCfg {
+        args: &["--check-cfg=cfg(any())"],
+        contains: Contains::Some {
+            contains: &["any()", "unix", r#"target_feature="crt-static""#],
+            doesnt_contain: &["any()=any()"],
+        },
+    });
+    check(CheckCfg {
+        args: &["--check-cfg=cfg(feature)"],
+        contains: Contains::Some {
+            contains: &["unix", "miri", "feature"],
+            doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
+        },
+    });
+    check(CheckCfg {
+        args: &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#],
+        contains: Contains::Some {
+            contains: &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""],
+            doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="],
+        },
+    });
+    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"))"#,
         ],
-        /*has_any*/ false,
-        /*has_any_any*/ false,
-        /*contains*/ &["unix", "miri", "feature=any()"],
-    );
-    check(
-        /*args*/
-        &[
+        contains: Contains::Some {
+            contains: &["unix", "miri", "feature=any()"],
+            doesnt_contain: &["any()", "any()=any()", "feature", "feature=", "feature=\"tmp\""],
+        },
+    });
+    check(CheckCfg {
+        args: &[
             r#"--check-cfg=cfg(has_foo, has_bar)"#,
             r#"--check-cfg=cfg(feature, values("tmp"))"#,
             r#"--check-cfg=cfg(feature, values("tmp"))"#,
         ],
-        /*has_any*/ false,
-        /*has_any_any*/ false,
-        /*contains*/ &["has_foo", "has_bar", "feature=\"tmp\""],
-    );
+        contains: Contains::Some {
+            contains: &["has_foo", "has_bar", "feature=\"tmp\""],
+            doesnt_contain: &["any()", "any()=any()", "feature"],
+        },
+    });
 }
 
-fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) {
+fn check(CheckCfg { args, contains }: CheckCfg) {
     let output = rustc()
         .input("lib.rs")
         .arg("-Zunstable-options")
@@ -72,18 +95,11 @@ fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) {
 
     let stdout = String::from_utf8(output.stdout).unwrap();
 
-    let mut found_any = false;
-    let mut found_any_any = false;
     let mut found = HashSet::<String>::new();
-    let mut recorded = HashSet::<String>::new();
 
     for l in stdout.lines() {
         assert!(l == l.trim());
-        if l == "any()" {
-            found_any = true;
-        } else if l == "any()=any()" {
-            found_any_any = true;
-        } else if let Some((left, right)) = l.split_once('=') {
+        if let Some((left, right)) = l.split_once('=') {
             if right != "any()" && right != "" {
                 assert!(right.starts_with("\""));
                 assert!(right.ends_with("\""));
@@ -92,17 +108,37 @@ fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) {
         } else {
             assert!(!l.contains("\""));
         }
-        assert!(recorded.insert(l.to_string()), "{}", &l);
-        if contains.contains(&l) {
-            assert!(found.insert(l.to_string()), "{}", &l);
-        }
+        assert!(found.insert(l.to_string()), "{}", &l);
     }
 
-    let should_found = HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
-    let diff: Vec<_> = should_found.difference(&found).collect();
-
-    assert_eq!(found_any, has_any);
-    assert_eq!(found_any_any, has_any_any);
-    assert_eq!(found_any_any, recorded.len() == 1);
-    assert!(diff.is_empty(), "{:?} != {:?} (~ {:?})", &should_found, &found, &diff);
+    match contains {
+        Contains::Some { contains, doesnt_contain } => {
+            {
+                let should_found =
+                    HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
+                let diff: Vec<_> = should_found.difference(&found).collect();
+                assert!(
+                    diff.is_empty(),
+                    "should found: {:?}, didn't found {:?}",
+                    &should_found,
+                    &diff
+                );
+            }
+            {
+                let should_not_find =
+                    HashSet::<String>::from_iter(doesnt_contain.iter().map(|s| s.to_string()));
+                let diff: Vec<_> = should_not_find.intersection(&found).collect();
+                assert!(
+                    diff.is_empty(),
+                    "should not find {:?}, did found {:?}",
+                    &should_not_find,
+                    &diff
+                );
+            }
+        }
+        Contains::Only(only) => {
+            assert!(found.contains(&only.to_string()), "{:?} != {:?}", &only, &found);
+            assert!(found.len() == 1, "len: {}, instead of 1", found.len());
+        }
+    }
 }
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/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/doc-alias.rs b/tests/rustdoc-js/doc-alias.rs
index 750b7b757bc..453b55c956c 100644
--- a/tests/rustdoc-js/doc-alias.rs
+++ b/tests/rustdoc-js/doc-alias.rs
@@ -16,7 +16,9 @@ impl Trait for Struct {
     const AssociatedConst: i32 = 12;
 
     #[doc(alias = "ImplTraitFunction")]
-    fn function() -> Self::Target { 0 }
+    fn function() -> Self::Target {
+        0
+    }
 }
 
 #[doc(alias = "EnumItem")]
@@ -71,5 +73,5 @@ impl Union {
 #[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/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/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/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/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/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr
index 2fb862af04e..64a98aab17b 100644
--- a/tests/ui/async-await/async-fn/impl-header.stderr
+++ b/tests/ui/async-await/async-fn/impl-header.stderr
@@ -28,7 +28,7 @@ error[E0277]: expected a `FnMut()` closure, found `F`
 LL | impl async Fn<()> for F {}
    |                       ^ expected an `FnMut()` closure, found `F`
    |
-   = help: the trait `FnMut<()>` is not implemented for `F`
+   = help: the trait `FnMut()` is not implemented for `F`
    = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
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/closures/closure-expected.stderr b/tests/ui/closures/closure-expected.stderr
index 6b309d70bdf..53a93e1e84d 100644
--- a/tests/ui/closures/closure-expected.stderr
+++ b/tests/ui/closures/closure-expected.stderr
@@ -6,7 +6,7 @@ LL |     let y = x.or_else(4);
    |               |
    |               required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
+   = help: the trait `FnOnce()` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Option::<T>::or_else`
   --> $SRC_DIR/core/src/option.rs:LL:COL
diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr
index 4841ff32e70..cb718ca160f 100644
--- a/tests/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr
@@ -6,7 +6,7 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    |                                        |
    |                                        required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
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/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
index 8023b998a40..af17a37bf23 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
@@ -15,6 +15,7 @@ where
 {
     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..df0d43bef87 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
@@ -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:16: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..b6460e0017f 100644
--- a/tests/ui/const-generics/issues/issue-71381.full.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.full.stderr
@@ -7,7 +7,7 @@ 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:23:40
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr
index 5d780074696..e16d3b7a8a4 100644
--- a/tests/ui/const-generics/issues/issue-71381.min.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.min.stderr
@@ -7,13 +7,29 @@ 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:23: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:23:19
+   |
+LL |         const FN: unsafe extern "C" fn(Args),
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs
index 7f2e14944e2..e472ef31fcd 100644
--- a/tests/ui/const-generics/issues/issue-71381.rs
+++ b/tests/ui/const-generics/issues/issue-71381.rs
@@ -13,6 +13,7 @@ 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 _
     }
 
@@ -21,6 +22,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_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/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index aad0ae64e85..4fb82c0683d 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -107,8 +107,8 @@ LL |     f()
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL |     T: ~const Fn<()> + ~const Destruct + ~const std::ops::Fn<()>,
-   |                                        +++++++++++++++++++++++++
+LL |     T: ~const Fn<()> + ~const Destruct + ~const Fn(),
+   |                                        +++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
@@ -132,8 +132,8 @@ LL |     f()
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL |     T: ~const FnMut<()> + ~const Destruct + ~const std::ops::FnMut<()>,
-   |                                           ++++++++++++++++++++++++++++
+LL |     T: ~const FnMut<()> + ~const Destruct + ~const FnMut(),
+   |                                           ++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
@@ -157,8 +157,8 @@ LL |     f()
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL |     T: ~const FnOnce<()> + ~const std::ops::FnOnce<()>,
-   |                          +++++++++++++++++++++++++++++
+LL |     T: ~const FnOnce<()> + ~const FnOnce(),
+   |                          +++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
index 9590b3372e3..6c83eff4de0 100644
--- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr
+++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -13,8 +13,8 @@ LL |             Opt::None => f(),
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
-   |                                                     +++++++++++++++++++++++++++++
+LL |     const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const FnOnce()>(self, f: F) -> T {
+   |                                                     +++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
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/expr/malformed_closure/block_instead_of_closure_in_arg.stderr b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr
index 1264d969342..c4c1c830afa 100644
--- a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr
+++ b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr
@@ -14,7 +14,7 @@ LL | ||         }
 LL | |      });
    | |______^ expected an `FnOnce(&bool)` closure, found `bool`
    |
-   = help: the trait `for<'a> FnOnce<(&'a bool,)>` is not implemented for `bool`
+   = help: the trait `for<'a> FnOnce(&'a bool)` is not implemented for `bool`
 note: required by a bound in `Option::<T>::filter`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: you might have meant to create the closure instead of a block
diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr
index a7ed9f5880b..54d3c6727f7 100644
--- a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr
+++ b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr
@@ -11,7 +11,7 @@ LL | |         Some(x * 2)
 LL | |     });
    | |_____^ expected an `FnOnce({integer})` closure, found `Option<usize>`
    |
-   = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<usize>`
+   = help: the trait `FnOnce({integer})` is not implemented for `Option<usize>`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: you might have meant to open the closure body instead of placing a closure within a block
diff --git a/tests/ui/extern/extern-wrong-value-type.stderr b/tests/ui/extern/extern-wrong-value-type.stderr
index 1c08aa1717f..692a6601171 100644
--- a/tests/ui/extern/extern-wrong-value-type.stderr
+++ b/tests/ui/extern/extern-wrong-value-type.stderr
@@ -6,7 +6,7 @@ LL |     is_fn(f);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}`
+   = help: the trait `Fn()` is not implemented for fn item `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `is_fn`
   --> $DIR/extern-wrong-value-type.rs:4:28
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index ed9ecc732b5..1b9febd431d 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -80,7 +80,7 @@ error[E0277]: expected a `FnMut()` closure, found `Foo`
 LL | impl Fn<()> for Foo {
    |                 ^^^ expected an `FnMut()` closure, found `Foo`
    |
-   = help: the trait `FnMut<()>` is not implemented for `Foo`
+   = help: the trait `FnMut()` is not implemented for `Foo`
    = note: wrap the `Foo` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -149,7 +149,7 @@ error[E0277]: expected a `FnOnce()` closure, found `Bar`
 LL | impl FnMut<()> for Bar {
    |                    ^^^ expected an `FnOnce()` closure, found `Bar`
    |
-   = help: the trait `FnOnce<()>` is not implemented for `Bar`
+   = help: the trait `FnOnce()` is not implemented for `Bar`
    = note: wrap the `Bar` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
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/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr
index c5e2f41691f..9fdef49c5ef 100644
--- a/tests/ui/fn/fn-trait-formatting.stderr
+++ b/tests/ui/fn/fn-trait-formatting.stderr
@@ -47,7 +47,7 @@ LL |     needs_fn(1);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
+   = help: the trait `Fn(isize)` is not implemented for `{integer}`
 note: required by a bound in `needs_fn`
   --> $DIR/fn-trait-formatting.rs:1:31
    |
diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr
index 095a5c47231..a923d7b26ef 100644
--- a/tests/ui/fn/issue-39259.stderr
+++ b/tests/ui/fn/issue-39259.stderr
@@ -16,7 +16,7 @@ error[E0277]: expected a `FnMut(u32)` closure, found `S`
 LL | impl Fn(u32) -> u32 for S {
    |                         ^ expected an `FnMut(u32)` closure, found `S`
    |
-   = help: the trait `FnMut<(u32,)>` is not implemented for `S`
+   = help: the trait `FnMut(u32)` is not implemented for `S`
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
 
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-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
index 6bf832bb9e2..3929e66a25a 100644
--- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
+++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
@@ -12,8 +12,8 @@ LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
 help: consider restricting type parameter `T`
    |
-LL | impl<T: std::ops::Fn<()>> Fun for T {
-   |       ++++++++++++++++++
+LL | impl<T: Fn()> Fun for T {
+   |       ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
index d9f26ee6c29..662726b8993 100644
--- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
+++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr
@@ -12,8 +12,8 @@ LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
 help: consider restricting type parameter `T`
    |
-LL | impl<T: std::ops::Fn<()>> Fun for T {
-   |       ++++++++++++++++++
+LL | impl<T: Fn()> Fun for T {
+   |       ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
index 3dc9ff10243..34278249e35 100644
--- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
+++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr
@@ -12,8 +12,8 @@ LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
 help: consider restricting type parameter `T`
    |
-LL | impl<T: std::ops::Fn<()>> Fun for T {
-   |       ++++++++++++++++++
+LL | impl<T: Fn()> Fun for T {
+   |       ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
index 45fb65f6cf1..dafe1c1d395 100644
--- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
+++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
@@ -12,8 +12,8 @@ LL |     type F<'a>: Fn() -> u32;
    |                 ^^^^^^^^^^^ required by this bound in `Fun::F`
 help: consider restricting type parameter `T`
    |
-LL | impl<T: std::ops::Fn<()>> Fun for T {
-   |       ++++++++++++++++++
+LL | impl<T: Fn()> Fun for T {
+   |       ++++++
 
 error: aborting due to 1 previous error
 
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/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/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index fbd41b61730..9ea4ff7cc70 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -13,8 +13,8 @@ LL |     fun(filter_positive());
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) {
-   |                                                                              ++++++++++++++++++++++++++++++++++++
+LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&Alias<'_>)>(fun: F) {
+   |                                                                              +++++++++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr
index 85e22178c4a..50092edda4f 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.stderr
+++ b/tests/ui/intrinsics/const-eval-select-bad.stderr
@@ -24,7 +24,7 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
+   = help: the trait `FnOnce()` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
@@ -37,7 +37,7 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
+   = help: the trait `FnOnce()` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
   --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr
index 75ddcd47899..68202085e77 100644
--- a/tests/ui/issues/issue-22034.stderr
+++ b/tests/ui/issues/issue-22034.stderr
@@ -4,7 +4,7 @@ error[E0277]: expected a `Fn()` closure, found `()`
 LL |         &mut *(ptr as *mut dyn Fn())
    |                ^^^ expected an `Fn()` closure, found `()`
    |
-   = help: the trait `Fn<()>` is not implemented for `()`
+   = help: the trait `Fn()` is not implemented for `()`
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
    = note: required for the cast from `*mut ()` to `*mut dyn Fn()`
 
diff --git a/tests/ui/issues/issue-23966.stderr b/tests/ui/issues/issue-23966.stderr
index c29e8861444..3f7a4fa312f 100644
--- a/tests/ui/issues/issue-23966.stderr
+++ b/tests/ui/issues/issue-23966.stderr
@@ -6,7 +6,7 @@ LL |     "".chars().fold(|_, _| (), ());
    |                |
    |                required by a bound introduced by this call
    |
-   = help: the trait `FnMut<(_, char)>` is not implemented for `()`
+   = help: the trait `FnMut(_, char)` is not implemented for `()`
 note: required by a bound in `fold`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
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/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/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
index e9f97d1d93b..e8c3ab00226 100644
--- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
+++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
@@ -10,7 +10,7 @@ LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
    | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32`
 
 error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:10
@@ -18,7 +18,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
 LL | async fn wrapper<F>(f: F)
    |          ^^^^^^^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32`
 
 error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:1
@@ -32,7 +32,7 @@ LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
    | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32`
 
 error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:1
@@ -46,7 +46,7 @@ LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
    | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
@@ -59,7 +59,7 @@ LL | |     &mut i;
 LL | | }
    | |_^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr
index feec4f83f78..310dee51406 100644
--- a/tests/ui/lifetimes/issue-95023.stderr
+++ b/tests/ui/lifetimes/issue-95023.stderr
@@ -38,7 +38,7 @@ error[E0277]: expected a `FnMut(&isize)` closure, found `Error`
 LL | impl Fn(&isize) for Error {
    |                     ^^^^^ expected an `FnMut(&isize)` closure, found `Error`
    |
-   = help: the trait `FnMut<(&isize,)>` is not implemented for `Error`
+   = help: the trait `FnMut(&isize)` is not implemented for `Error`
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
 
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/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/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/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
index 99c9028ae1e..a657a65c426 100644
--- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
+++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr
@@ -26,7 +26,7 @@ LL |     let _ = produces_string().and_then(takes_str_but_wrong_abi);
    |                               |
    |                               required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
+   = help: the trait `FnOnce(String)` is not implemented for fn item `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
@@ -38,7 +38,7 @@ LL |     let _ = produces_string().and_then(takes_str_but_unsafe);
    |                               |
    |                               required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
+   = help: the trait `FnOnce(String)` is not implemented for fn item `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::and_then`
   --> $SRC_DIR/core/src/option.rs:LL:COL
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/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/macro/mbe-dotdotdot-may-not-begin-a-type.rs b/tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs
new file mode 100644
index 00000000000..8be99f22d2e
--- /dev/null
+++ b/tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs
@@ -0,0 +1,11 @@
+// A bare `...` represents `CVarArgs` (`VaListImpl<'_>`) in function argument type
+// position without being a proper type syntactically.
+// This test ensures that we do not regress certain MBE calls would we ever promote
+// `...` to a proper type syntactically.
+
+//@ check-pass
+
+macro_rules! ck { ($ty:ty) => { compile_error!(""); }; (...) => {}; }
+ck!(...);
+
+fn main() {}
diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
index 4da9ad84bab..d9d3f9227a9 100644
--- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
+++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs
@@ -4,6 +4,10 @@ fn f1<'a>(x: u8, y: &'a ...) {}
 fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
 //~^ ERROR C-variadic type `...` may not be nested inside another type
 
+// Regression test for issue #125847.
+fn f3() where for<> ...: {}
+//~^ ERROR C-variadic type `...` may not be nested inside another type
+
 fn main() {
     let _recovery_witness: () = 0;
     //~^ ERROR: mismatched types
diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
index 8b9d676a45d..38833d6555b 100644
--- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
+++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr
@@ -10,15 +10,21 @@ error[E0743]: C-variadic type `...` may not be nested inside another type
 LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {}
    |                             ^^^
 
+error[E0743]: C-variadic type `...` may not be nested inside another type
+  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:21
+   |
+LL | fn f3() where for<> ...: {}
+   |                     ^^^
+
 error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33
+  --> $DIR/variadic-ffi-nested-syntactic-fail.rs:12:33
    |
 LL |     let _recovery_witness: () = 0;
    |                            --   ^ expected `()`, found integer
    |                            |
    |                            expected due to this
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0743.
 For more information about an error, try `rustc --explain E0308`.
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/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs
index cd9cce7ec3e..a62feace2da 100644
--- a/tests/ui/privacy/where-priv-type.rs
+++ b/tests/ui/privacy/where-priv-type.rs
@@ -74,6 +74,7 @@ where
 {
     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..8ea2e17c436 100644
--- a/tests/ui/privacy/where-priv-type.stderr
+++ b/tests/ui/privacy/where-priv-type.stderr
@@ -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:75: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/resolve/fn-new-doesnt-exist.rs b/tests/ui/resolve/fn-new-doesnt-exist.rs
deleted file mode 100644
index 4f6290808fc..00000000000
--- a/tests/ui/resolve/fn-new-doesnt-exist.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-use std::net::TcpStream;
-
-fn main() {
-   let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found
-}
diff --git a/tests/ui/resolve/fn-new-doesnt-exist.stderr b/tests/ui/resolve/fn-new-doesnt-exist.stderr
deleted file mode 100644
index 418dd9ea6b8..00000000000
--- a/tests/ui/resolve/fn-new-doesnt-exist.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
-  --> $DIR/fn-new-doesnt-exist.rs:4:28
-   |
-LL |    let stream = TcpStream::new();
-   |                            ^^^ function or associated item not found in `TcpStream`
-   |
-note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
-      TcpStream::connect
-      TcpStream::connect_timeout
-  --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/suggest-builder-fn.rs b/tests/ui/resolve/suggest-builder-fn.rs
new file mode 100644
index 00000000000..0d9b35549a4
--- /dev/null
+++ b/tests/ui/resolve/suggest-builder-fn.rs
@@ -0,0 +1,64 @@
+// Tests that we suggest the right alternatives when
+// a builder method cannot be resolved
+
+use std::net::TcpStream;
+
+trait SomeTrait {}
+
+struct Foo<T> {
+    v : T
+}
+
+impl<T: SomeTrait + Default> Foo<T> {
+    // Should not be suggested if constraint on the impl not met
+    fn new() -> Self {
+        Self { v: T::default() }
+    }
+}
+
+struct Bar;
+
+impl Bar {
+    // Should be suggested
+    fn build() -> Self {
+        Self {}
+    }
+
+    // Method with self can't be a builder.
+    // Should not be suggested
+    fn build_with_self(&self) -> Self {
+        Self {}
+    }
+}
+
+mod SomeMod {
+    use Bar;
+
+    impl Bar {
+        // Public method. Should be suggested
+        pub fn build_public() -> Self {
+            Self {}
+        }
+
+        // Private method. Should not be suggested
+        fn build_private() -> Self {
+            Self {}
+        }
+    }
+}
+
+fn main() {
+   // `new` not found on `TcpStream` and `connect` should be suggested
+   let _stream = TcpStream::new();
+   //~^ ERROR no function or associated item named `new` found
+
+    // Although `new` is found on `<impl Foo<T>>` it should not be
+    // suggested because `u8` does not meet the `T: SomeTrait` constraint
+    let _foo = Foo::<u8>::new();
+   //~^ ERROR the function or associated item `new` exists for struct `Foo<u8>`, but its trait bounds were not satisfied
+
+   // Should suggest only `<impl Bar>::build()` and `SomeMod::<impl Bar>::build_public()`.
+   // Other methods should not suggested because they are private or are not a builder
+    let _bar = Bar::new();
+   //~^ ERROR no function or associated item named `new` found
+}
diff --git a/tests/ui/resolve/suggest-builder-fn.stderr b/tests/ui/resolve/suggest-builder-fn.stderr
new file mode 100644
index 00000000000..9c5eed35ccf
--- /dev/null
+++ b/tests/ui/resolve/suggest-builder-fn.stderr
@@ -0,0 +1,51 @@
+error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
+  --> $DIR/suggest-builder-fn.rs:52:29
+   |
+LL |    let _stream = TcpStream::new();
+   |                             ^^^ function or associated item not found in `TcpStream`
+   |
+note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
+      TcpStream::connect
+      TcpStream::connect_timeout
+  --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
+
+error[E0599]: the function or associated item `new` exists for struct `Foo<u8>`, but its trait bounds were not satisfied
+  --> $DIR/suggest-builder-fn.rs:57:27
+   |
+LL | struct Foo<T> {
+   | ------------- function or associated item `new` not found for this struct
+...
+LL |     let _foo = Foo::<u8>::new();
+   |                           ^^^ function or associated item cannot be called on `Foo<u8>` due to unsatisfied trait bounds
+   |
+note: trait bound `u8: SomeTrait` was not satisfied
+  --> $DIR/suggest-builder-fn.rs:12:9
+   |
+LL | impl<T: SomeTrait + Default> Foo<T> {
+   |         ^^^^^^^^^            ------
+   |         |
+   |         unsatisfied trait bound introduced here
+
+error[E0599]: no function or associated item named `new` found for struct `Bar` in the current scope
+  --> $DIR/suggest-builder-fn.rs:62:21
+   |
+LL | struct Bar;
+   | ---------- function or associated item `new` not found for this struct
+...
+LL |     let _bar = Bar::new();
+   |                     ^^^ function or associated item not found in `Bar`
+   |
+note: if you're trying to build a new `Bar` consider using one of the following associated functions:
+      Bar::build
+      SomeMod::<impl Bar>::build_public
+  --> $DIR/suggest-builder-fn.rs:23:5
+   |
+LL |     fn build() -> Self {
+   |     ^^^^^^^^^^^^^^^^^^
+...
+LL |         pub fn build_public() -> Self {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
index 67bfaa4c98c..4c07f4d6b99 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -6,7 +6,7 @@ LL |     call(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
+   = help: the trait `Fn()` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call`
@@ -23,7 +23,7 @@ LL |     call_mut(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
+   = help: the trait `FnMut()` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_mut`
@@ -40,7 +40,7 @@ LL |     call_once(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
+   = help: the trait `FnOnce()` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_once`
@@ -57,7 +57,7 @@ LL |     call(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+   = help: the trait `Fn()` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: unsafe function cannot be called generically without an unsafe block
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
@@ -75,7 +75,7 @@ LL |     call_mut(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnMut()` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: unsafe function cannot be called generically without an unsafe block
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
@@ -93,7 +93,7 @@ LL |     call_once(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnOnce()` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: unsafe function cannot be called generically without an unsafe block
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
index 151bd6facf7..fb2e66db1d4 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr
@@ -13,8 +13,8 @@ LL |     x(())
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
-   |                                                         ++++++++++++++++++++++++++++++++
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 {
+   |                                                         +++++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr
index e2b3e352701..dede411e69c 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr
@@ -13,8 +13,8 @@ LL |     x(())
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
-   |                                                         ++++++++++++++++++++++++++++++++
+LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 {
+   |                                                         +++++++++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr
index e5a773123e9..a0f05325389 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr
@@ -31,8 +31,8 @@ LL |     f() + f()
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
-   |                                      +++++++++++++++++++++++++
+LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 {
+   |                                      +++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
@@ -47,8 +47,8 @@ LL |     f() + f()
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
-   |                                      +++++++++++++++++++++++++
+LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 {
+   |                                      +++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
@@ -63,8 +63,8 @@ LL |     f() * 7
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 help: consider further restricting this bound
    |
-LL |         F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>,
-   |                                  +++++++++++++++++++++++++
+LL |         F: ~const FnOnce() -> u8 + ~const Fn(),
+   |                                  +++++++++++++
 help: add `#![feature(effects)]` to the crate attributes to enable
    |
 LL + #![feature(effects)]
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..9778217d462
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs
@@ -0,0 +1,24 @@
+//@ 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: specialization impl does not specialize any associated items
+//~| error: could not resolve generic parameters on overridden impl
+
+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..d18063f8d3d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr
@@ -0,0 +1,69 @@
+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[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: specialization impl does not specialize any associated items
+  --> $DIR/spec-effectvar-ice.rs:16:1
+   |
+LL | impl<T> const Foo for T where T: const Specialize {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: impl is a specialization of this impl
+  --> $DIR/spec-effectvar-ice.rs:12:1
+   |
+LL | impl<T> const Foo for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: could not resolve generic parameters on overridden impl
+  --> $DIR/spec-effectvar-ice.rs:16:1
+   |
+LL | impl<T> const Foo for T where T: const Specialize {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs
index 411bba3454e..1ba15bda98d 100644
--- a/tests/ui/simd/repr_packed.rs
+++ b/tests/ui/simd/repr_packed.rs
@@ -6,9 +6,6 @@
 #[repr(simd, packed)]
 struct Simd<T, const N: usize>([T; N]);
 
-#[repr(simd)]
-struct FullSimd<T, const N: usize>([T; N]);
-
 fn check_size_align<T, const N: usize>() {
     use std::mem;
     assert_eq!(mem::size_of::<Simd<T, N>>(), mem::size_of::<[T; N]>());
@@ -39,21 +36,15 @@ fn main() {
     check_ty::<f64>();
 
     unsafe {
-        // powers-of-two have no padding and work as usual
+        // powers-of-two have no padding and have the same layout as #[repr(simd)]
         let x: Simd<f64, 4> =
             simd_add(Simd::<f64, 4>([0., 1., 2., 3.]), Simd::<f64, 4>([2., 2., 2., 2.]));
         assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]);
 
-        // non-powers-of-two have padding and need to be expanded to full vectors
-        fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
-            unsafe {
-                let mut tmp = core::mem::MaybeUninit::<FullSimd<T, N>>::uninit();
-                std::ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
-                tmp.assume_init()
-            }
-        }
-        let x: FullSimd<f64, 3> =
-            simd_add(load(Simd::<f64, 3>([0., 1., 2.])), load(Simd::<f64, 3>([2., 2., 2.])));
-        assert_eq!(x.0, [2., 3., 4.]);
+        // non-powers-of-two should have padding (which is removed by #[repr(packed)]),
+        // but the intrinsic handles it
+        let x: Simd<f64, 3> = simd_add(Simd::<f64, 3>([0., 1., 2.]), Simd::<f64, 3>([2., 2., 2.]));
+        let arr: [f64; 3] = x.0;
+        assert_eq!(arr, [2., 3., 4.]);
     }
 }
diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr
index bfcc2307fd7..b27d9aef066 100644
--- a/tests/ui/suggestions/deref-path-method.stderr
+++ b/tests/ui/suggestions/deref-path-method.stderr
@@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll
       Vec::<T>::with_capacity
       Vec::<T>::try_with_capacity
       Vec::<T>::from_raw_parts
-      and 6 others
+      and 4 others
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: the function `contains` is implemented on `[_]`
    |
diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr
index a173bbbb490..d4a9351af3a 100644
--- a/tests/ui/suggestions/issue-109291.stderr
+++ b/tests/ui/suggestions/issue-109291.stderr
@@ -8,7 +8,6 @@ note: if you're trying to build a new `Backtrace` consider using one of the foll
       Backtrace::capture
       Backtrace::force_capture
       Backtrace::disabled
-      Backtrace::create
   --> $SRC_DIR/std/src/backtrace.rs:LL:COL
 help: there is an associated function `force_capture` with a similar name
    |
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/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/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
index b7a7784755e..ebd45b9dd96 100644
--- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce(&i32)` closure, found `i32`
 LL |     f::<dyn for<'x> X<'x, F = i32>>();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce(&i32)` closure, found `i32`
    |
-   = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32`
+   = help: the trait `for<'a> FnOnce(&'a i32)` is not implemented for `i32`
 note: required by a bound in `f`
   --> $DIR/check-trait-object-bounds-2.rs:8:9
    |
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
index f8e3f8e968e..98825bd536e 100644
--- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs
@@ -2,7 +2,7 @@ fn strip_lf(s: &str) -> &str {
     s.strip_suffix(b'\n').unwrap_or(s)
     //~^ ERROR expected a `FnMut(char)` closure, found `u8`
     //~| NOTE expected an `FnMut(char)` closure, found `u8`
-    //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8`
+    //~| HELP the trait `FnMut(char)` is not implemented for `u8`
     //~| HELP the following other types implement trait `Pattern<'a>`:
     //~| NOTE required for `u8` to implement `Pattern<'_>`
 
diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
index 27006f59b90..49272e7d357 100644
--- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
+++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -4,7 +4,7 @@ error[E0277]: expected a `FnMut(char)` closure, found `u8`
 LL |     s.strip_suffix(b'\n').unwrap_or(s)
    |       ^^^^^^^^^^^^ expected an `FnMut(char)` closure, found `u8`
    |
-   = help: the trait `FnMut<(char,)>` is not implemented for `u8`, which is required by `u8: Pattern<'_>`
+   = help: the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern<'_>`
    = help: the following other types implement trait `Pattern<'a>`:
              &'b String
              &'b [char; N]
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/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr
index 21d8fc0f567..4cc3ec2ea8b 100644
--- a/tests/ui/traits/issue-87558.stderr
+++ b/tests/ui/traits/issue-87558.stderr
@@ -30,7 +30,7 @@ error[E0277]: expected a `FnMut(&isize)` closure, found `Error`
 LL | impl Fn(&isize) for Error {
    |                     ^^^^^ expected an `FnMut(&isize)` closure, found `Error`
    |
-   = help: the trait `FnMut<(&isize,)>` is not implemented for `Error`
+   = help: the trait `FnMut(&isize)` is not implemented for `Error`
 note: required by a bound in `Fn`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
 
diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr
index e33487235e6..86d97cb16b3 100644
--- a/tests/ui/traits/next-solver/fn-trait.stderr
+++ b/tests/ui/traits/next-solver/fn-trait.stderr
@@ -6,7 +6,7 @@ LL |     require_fn(f as unsafe fn() -> i32);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `unsafe fn() -> i32`
+   = help: the trait `Fn()` is not implemented for `unsafe fn() -> i32`
    = note: unsafe function cannot be called generically without an unsafe block
    = note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `require_fn`
@@ -37,7 +37,7 @@ LL |     require_fn(g);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() -> i32 {g}`
+   = help: the trait `Fn()` is not implemented for fn item `extern "C" fn() -> i32 {g}`
    = note: wrap the `extern "C" fn() -> i32 {g}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `require_fn`
   --> $DIR/fn-trait.rs:3:23
@@ -67,7 +67,7 @@ LL |     require_fn(g as extern "C" fn() -> i32);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `extern "C" fn() -> i32`
+   = help: the trait `Fn()` is not implemented for `extern "C" fn() -> i32`
    = note: wrap the `extern "C" fn() -> i32` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `require_fn`
   --> $DIR/fn-trait.rs:3:23
@@ -97,7 +97,7 @@ LL |     require_fn(h);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() -> i32 {h}`
+   = help: the trait `Fn()` is not implemented for fn item `unsafe fn() -> i32 {h}`
    = note: unsafe function cannot be called generically without an unsafe block
    = note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `require_fn`
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
index 56f95e20715..14b2ecbb9f2 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
@@ -2,11 +2,11 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
   --> $DIR/root-obligation.rs:6:38
    |
 LL |         .filter(|c| "aeiou".contains(c))
-   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
+   |                             -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
    |                             |
    |                             required by a bound introduced by this call
    |
-   = note: required for `&char` to implement `FnOnce<(char,)>`
+   = note: required for `&char` to implement `FnOnce(char)`
    = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
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/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr
index 58cafd21ca8..97158ee297d 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr
@@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce()` closure, found `()`
 LL | fn c() -> Closure {
    |           ^^^^^^^ expected an `FnOnce()` closure, found `()`
    |
-   = help: the trait `FnOnce<()>` is not implemented for `()`
+   = help: the trait `FnOnce()` is not implemented for `()`
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0277]: expected a `FnOnce()` closure, found `()`
@@ -13,7 +13,7 @@ error[E0277]: expected a `FnOnce()` closure, found `()`
 LL |     || -> Closure { || () }
    |           ^^^^^^^ expected an `FnOnce()` closure, found `()`
    |
-   = help: the trait `FnOnce<()>` is not implemented for `()`
+   = help: the trait `FnOnce()` is not implemented for `()`
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr
index e466f94d0d8..9cfeb7a5d09 100644
--- a/tests/ui/ufcs/bad-builder.stderr
+++ b/tests/ui/ufcs/bad-builder.stderr
@@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<Q>` consider using one of the followi
       Vec::<T>::with_capacity
       Vec::<T>::try_with_capacity
       Vec::<T>::from_raw_parts
-      and 6 others
+      and 4 others
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: there is an associated function `new` with a similar name
    |
diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
index 795bd0a0d18..9c5d824185b 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&S, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `Fn<(isize,)>` is not implemented for `S`
+   = help: the trait `Fn(isize)` is not implemented for `S`
    = note: `S` implements `FnMut`, but it must implement `Fn`, which is more general
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14
diff --git a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index d836af2b014..dfdb3ea19c3 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
index c0dcf83a5bb..b4521cc6890 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-abi.rs:9:15
    |
@@ -21,7 +21,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-abi.rs:12:19
    |
@@ -36,7 +36,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
+   = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-abi.rs:15:20
    |
diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index d261c38f50c..5519bb33ebc 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr
index 56b112867cf..040c1d5bcbe 100644
--- a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr
+++ b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr
@@ -6,7 +6,7 @@ LL |     println!("{:?}", Some(1).map(NonZeroAndOneU8).unwrap());
    |                              |
    |                              required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<({integer},)>` is not implemented for fn item `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
+   = help: the trait `FnOnce({integer})` is not implemented for fn item `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
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`