about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/dependencies.yml10
-rw-r--r--.gitignore1
-rw-r--r--.reuse/dep5124
-rw-r--r--Cargo.lock445
-rw-r--r--Cargo.toml14
-rw-r--r--LICENSES/CC-BY-3.0.txt319
-rw-r--r--LICENSES/CC0-1.0.txt121
-rw-r--r--REUSE.toml170
-rw-r--r--compiler/rustc_ast_passes/messages.ftl6
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs8
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs14
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs16
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs30
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs15
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs11
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/cmdline_attrs.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs39
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs41
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs30
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs48
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0120.md24
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0373.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0378.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0626.md32
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0771.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0798.md39
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_errors/src/lib.rs1
-rw-r--r--compiler/rustc_errors/src/markdown/parse.rs62
-rw-r--r--compiler/rustc_errors/src/markdown/tests/parse.rs65
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs8
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs16
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs93
-rw-r--r--compiler/rustc_feature/src/unstable.rs8
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl26
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/entry.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs43
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs130
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs49
-rw-r--r--compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs156
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs48
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs60
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs128
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs3
-rw-r--r--compiler/rustc_infer/messages.ftl392
-rw-r--r--compiler/rustc_infer/src/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs1623
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs139
-rw-r--r--compiler/rustc_infer/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs204
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs1
-rw-r--r--compiler/rustc_lint/messages.ftl5
-rw-r--r--compiler/rustc_lint/src/builtin.rs57
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs12
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs93
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs4
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs114
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs39
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs385
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs22
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs36
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs2
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs4
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs39
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs37
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs22
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs34
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs214
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs8
-rw-r--r--compiler/rustc_parse/src/parser/item.rs124
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs18
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs2
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs48
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs12
-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_pattern_analysis/src/constructor.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs13
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs8
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs180
-rw-r--r--compiler/rustc_resolve/messages.ftl2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs14
-rw-r--r--compiler/rustc_resolve/src/errors.rs9
-rw-r--r--compiler/rustc_resolve/src/imports.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs2
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs28
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs95
-rw-r--r--compiler/rustc_span/src/symbol.rs5
-rw-r--r--compiler/rustc_target/src/spec/mod.rs13
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs29
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs32
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs29
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs36
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs36
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs33
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs35
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs43
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs26
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs29
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs27
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs32
-rw-r--r--compiler/rustc_target/src/target_features.rs12
-rw-r--r--compiler/rustc_trait_selection/messages.ftl391
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/mod.rs)120
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs (renamed from compiler/rustc_infer/src/infer/need_type_info.rs)51
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs)2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/note.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs)8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/region.rs)39
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs)0
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs (renamed from compiler/rustc_infer/src/error_reporting/infer/suggest.rs)3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/mod.rs72
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs16
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs283
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs244
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs214
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs16
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs123
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs1639
-rw-r--r--compiler/rustc_trait_selection/src/errors/note_and_explain.rs (renamed from compiler/rustc_infer/src/errors/note_and_explain.rs)2
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs111
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs20
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs2
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs10
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs2
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs16
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs10
-rw-r--r--config.example.toml1
-rw-r--r--library/alloc/src/boxed.rs83
-rw-r--r--library/core/src/fmt/builders.rs2
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/marker.rs56
-rw-r--r--library/core/src/mem/transmutability.rs6
-rw-r--r--library/core/src/num/mod.rs1
-rw-r--r--library/core/src/num/nonzero.rs60
-rw-r--r--library/core/src/num/uint_macros.rs47
-rw-r--r--library/core/src/option.rs1
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/tuple.rs14
-rw-r--r--library/core/tests/future.rs2
-rw-r--r--library/panic_unwind/src/seh.rs6
-rw-r--r--library/proc_macro/src/lib.rs4
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/fs/tests.rs2
-rw-r--r--library/std/src/io/error.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/horizon/mod.rs1
-rw-r--r--library/std/src/os/horizon/raw.rs1
-rw-r--r--library/std/src/os/solid/io.rs1
-rw-r--r--library/std/src/os/solid/mod.rs1
-rw-r--r--library/std/src/os/windows/fs.rs10
-rw-r--r--library/std/src/sys/backtrace.rs118
-rw-r--r--library/std/src/sys/pal/common/alloc.rs19
-rw-r--r--library/std/src/sys/pal/solid/mod.rs2
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs199
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs1
-rw-r--r--library/std/src/sys/pal/uefi/process.rs689
-rw-r--r--library/std/src/sys/pal/unix/alloc.rs2
-rw-r--r--library/std/src/sys/pal/unix/net.rs5
-rw-r--r--library/std/src/sys/pal/unix/process/process_unsupported.rs1
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs85
-rw-r--r--library/std/src/sys/pal/windows/c.rs97
-rw-r--r--library/std/src/sys/pal/windows/c/bindings.txt1
-rw-r--r--library/std/src/sys/pal/windows/c/windows_sys.rs8
-rw-r--r--library/std/src/sys/pal/windows/fs.rs11
-rw-r--r--library/std/src/sys/pal/windows/net.rs112
-rw-r--r--library/std/src/sys/path/unsupported_backslash.rs1
-rw-r--r--library/std/src/sys/sync/mutex/itron.rs1
-rw-r--r--library/std/src/sys/sync/rwlock/solid.rs1
-rw-r--r--library/std/src/sys/thread_local/guard/windows.rs13
-rw-r--r--library/std/src/thread/mod.rs74
-rw-r--r--src/bootstrap/mk/Makefile.in1
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs7
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs35
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs77
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs59
-rw-r--r--src/bootstrap/src/core/build_steps/vendor.rs7
-rw-r--r--src/bootstrap/src/core/builder.rs3
-rw-r--r--src/bootstrap/src/core/config/config.rs36
-rw-r--r--src/bootstrap/src/lib.rs15
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/helpers.rs28
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in2
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt136
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile4
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh4
-rw-r--r--src/ci/github-actions/jobs.yml1
-rwxr-xr-xsrc/ci/run.sh2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md12
-rw-r--r--src/doc/rustc/src/platform-support/nuttx.md60
-rw-r--r--src/doc/rustdoc/src/advanced-features.md27
-rwxr-xr-xsrc/etc/htmldocck.py1
-rw-r--r--src/etc/test-float-parse/Cargo.toml9
-rw-r--r--src/etc/test-float-parse/README.md55
-rwxr-xr-xsrc/etc/test-float-parse/runtests.py394
-rw-r--r--src/etc/test-float-parse/src/bin/few-ones.rs15
-rw-r--r--src/etc/test-float-parse/src/bin/huge-pow10.rs9
-rw-r--r--src/etc/test-float-parse/src/bin/long-fractions.rs15
-rw-r--r--src/etc/test-float-parse/src/bin/many-digits.rs25
-rw-r--r--src/etc/test-float-parse/src/bin/rand-f64.rs18
-rw-r--r--src/etc/test-float-parse/src/bin/short-decimals.rs17
-rw-r--r--src/etc/test-float-parse/src/bin/subnorm.rs11
-rw-r--r--src/etc/test-float-parse/src/bin/tiny-pow10.rs9
-rw-r--r--src/etc/test-float-parse/src/bin/u32-small.rs7
-rw-r--r--src/etc/test-float-parse/src/bin/u64-pow2.rs15
-rw-r--r--src/etc/test-float-parse/src/gen/exhaustive.rs43
-rw-r--r--src/etc/test-float-parse/src/gen/exponents.rs95
-rw-r--r--src/etc/test-float-parse/src/gen/fuzz.rs88
-rw-r--r--src/etc/test-float-parse/src/gen/integers.rs104
-rw-r--r--src/etc/test-float-parse/src/gen/long_fractions.rs58
-rw-r--r--src/etc/test-float-parse/src/gen/many_digits.rs84
-rw-r--r--src/etc/test-float-parse/src/gen/sparse.rs100
-rw-r--r--src/etc/test-float-parse/src/gen/spot_checks.rs101
-rw-r--r--src/etc/test-float-parse/src/gen/subnorm.rs103
-rw-r--r--src/etc/test-float-parse/src/lib.rs540
-rw-r--r--src/etc/test-float-parse/src/main.rs129
-rw-r--r--src/etc/test-float-parse/src/traits.rs202
-rw-r--r--src/etc/test-float-parse/src/ui.rs132
-rw-r--r--src/etc/test-float-parse/src/validate.rs364
-rw-r--r--src/etc/test-float-parse/src/validate/tests.rs149
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/mod.rs34
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/render/context.rs2
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs27
-rw-r--r--src/librustdoc/html/render/sidebar.rs2
-rw-r--r--src/librustdoc/html/render/type_layout.rs2
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css7
-rw-r--r--src/librustdoc/html/static/js/main.js8
-rw-r--r--src/librustdoc/html/templates/STYLE.md20
-rw-r--r--src/librustdoc/rinja.toml (renamed from src/librustdoc/askama.toml)0
-rw-r--r--src/tools/build-manifest/src/main.rs1
-rw-r--r--src/tools/build_helper/src/git.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs3
-rw-r--r--src/tools/clippy/tests/ui/track-diagnostics.stderr2
-rw-r--r--src/tools/collect-license-metadata/src/main.rs10
-rw-r--r--src/tools/collect-license-metadata/src/path_tree.rs52
-rw-r--r--src/tools/compiletest/src/common.rs10
-rw-r--r--src/tools/compiletest/src/header.rs31
-rw-r--r--src/tools/compiletest/src/runtest.rs286
-rw-r--r--src/tools/generate-copyright/src/main.rs38
-rw-r--r--src/tools/jsondocck/src/main.rs67
-rw-r--r--src/tools/lint-docs/src/groups.rs1
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs10
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr4
-rw-r--r--src/tools/miri/tests/fail/extern_static.rs2
-rw-r--r--src/tools/miri/tests/fail/extern_static.stderr4
-rw-r--r--src/tools/miri/tests/pass/static_mut.rs2
-rw-r--r--src/tools/run-make-support/src/artifact_names.rs36
-rw-r--r--src/tools/run-make-support/src/external_deps/llvm.rs2
-rw-r--r--src/tools/run-make-support/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/panic_context.rs1
-rw-r--r--src/tools/rustbook/Cargo.lock1762
-rw-r--r--src/tools/rustbook/Cargo.toml2
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt31
-rw-r--r--src/tools/tidy/src/deps.rs10
-rw-r--r--src/tools/tier-check/src/main.rs10
-rw-r--r--src/version2
-rw-r--r--tests/assembly/targets/targets-elf.rs36
-rw-r--r--tests/codegen/generic-debug.rs1
-rw-r--r--tests/codegen/issues/issue-58881.rs1
-rw-r--r--tests/codegen/mainsubprogram.rs1
-rw-r--r--tests/codegen/mainsubprogramstart.rs1
-rw-r--r--tests/codegen/nounwind.rs1
-rw-r--r--tests/crashes/119299.rs25
-rw-r--r--tests/crashes/127009.rs11
-rw-r--r--tests/crashes/127351.rs17
-rw-r--r--tests/crashes/127353.rs18
-rw-r--r--tests/crashes/127628.rs14
-rw-r--r--tests/crashes/127643.rs18
-rw-r--r--tests/crashes/127676.rs8
-rw-r--r--tests/crashes/127737.rs21
-rw-r--r--tests/crashes/127742.rs11
-rw-r--r--tests/crashes/127880.rs5
-rw-r--r--tests/crashes/127916.rs16
-rw-r--r--tests/crashes/127972.rs6
-rw-r--r--tests/crashes/128016.rs10
-rw-r--r--tests/mir-opt/const_prop/invalid_constant.rs2
-rw-r--r--tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff6
-rw-r--r--tests/mir-opt/dataflow-const-prop/aggregate_copy.rs1
-rw-r--r--tests/mir-opt/issue_99325.rs2
-rw-r--r--tests/run-make/archive-duplicate-names/Makefile16
-rw-r--r--tests/run-make/archive-duplicate-names/rmake.rs37
-rw-r--r--tests/run-make/c-static-dylib/Makefile13
-rw-r--r--tests/run-make/c-static-dylib/rmake.rs20
-rw-r--r--tests/run-make/c-static-rlib/Makefile12
-rw-r--r--tests/run-make/c-static-rlib/rmake.rs17
-rw-r--r--tests/run-make/c-unwind-abi-catch-panic/Makefile10
-rw-r--r--tests/run-make/c-unwind-abi-catch-panic/rmake.rs18
-rw-r--r--tests/run-make/compiler-lookup-paths-2/Makefile11
-rw-r--r--tests/run-make/compiler-lookup-paths-2/rmake.rs20
-rw-r--r--tests/run-make/crate-hash-rustc-version/Makefile38
-rw-r--r--tests/run-make/crate-hash-rustc-version/rmake.rs57
-rw-r--r--tests/run-make/extern-fn-generic/Makefile7
-rw-r--r--tests/run-make/extern-fn-generic/rmake.rs16
-rw-r--r--tests/run-make/extern-fn-with-union/Makefile7
-rw-r--r--tests/run-make/extern-fn-with-union/rmake.rs16
-rw-r--r--tests/run-make/invalid-symlink-search-path/in/bar/lib.rs5
-rw-r--r--tests/run-make/invalid-symlink-search-path/in/foo/lib.rs3
-rw-r--r--tests/run-make/invalid-symlink-search-path/rmake.rs33
-rw-r--r--tests/run-make/invalid-tmpdir-env-var/foo.rs (renamed from tests/run-make/issue-14698/foo.rs)0
-rw-r--r--tests/run-make/invalid-tmpdir-env-var/rmake.rs20
-rw-r--r--tests/run-make/issue-107094/Makefile7
-rw-r--r--tests/run-make/issue-14698/Makefile4
-rw-r--r--tests/run-make/issue-15460/Makefile7
-rw-r--r--tests/run-make/issue-22131/Makefile8
-rw-r--r--tests/run-make/issue-26006/Makefile17
-rw-r--r--tests/run-make/issue-26006/in/libc/lib.rs3
-rw-r--r--tests/run-make/issue-26006/in/time/lib.rs4
-rw-r--r--tests/run-make/issue-28595/Makefile7
-rw-r--r--tests/run-make/issue-33329/Makefile5
-rw-r--r--tests/run-make/issue-33329/main.rs1
-rw-r--r--tests/run-make/issue-97463-abi-param-passing/Makefile15
-rw-r--r--tests/run-make/link-framework/Makefile23
-rw-r--r--tests/run-make/link-framework/rmake.rs38
-rw-r--r--tests/run-make/link-native-static-lib-to-dylib/bar.rs (renamed from tests/run-make/issue-15460/bar.rs)0
-rw-r--r--tests/run-make/link-native-static-lib-to-dylib/foo.c (renamed from tests/run-make/issue-15460/foo.c)0
-rw-r--r--tests/run-make/link-native-static-lib-to-dylib/foo.rs (renamed from tests/run-make/issue-15460/foo.rs)0
-rw-r--r--tests/run-make/link-native-static-lib-to-dylib/rmake.rs14
-rw-r--r--tests/run-make/link-path-order/Makefile19
-rw-r--r--tests/run-make/link-path-order/rmake.rs33
-rw-r--r--tests/run-make/linkage-attr-on-static/Makefile6
-rw-r--r--tests/run-make/linkage-attr-on-static/rmake.rs15
-rw-r--r--tests/run-make/lto-linkage-used-attr/Makefile8
-rw-r--r--tests/run-make/lto-linkage-used-attr/rmake.rs15
-rw-r--r--tests/run-make/lto-no-link-whole-rlib/Makefile9
-rw-r--r--tests/run-make/lto-no-link-whole-rlib/rmake.rs18
-rw-r--r--tests/run-make/lto-smoke-c/Makefile12
-rw-r--r--tests/run-make/lto-smoke-c/rmake.rs20
-rw-r--r--tests/run-make/macos-fat-archive/Makefile10
-rw-r--r--tests/run-make/macos-fat-archive/rmake.rs20
-rw-r--r--tests/run-make/manual-link/Makefile7
-rw-r--r--tests/run-make/manual-link/rmake.rs16
-rw-r--r--tests/run-make/native-lib-load-order/a.c (renamed from tests/run-make/issue-28595/a.c)0
-rw-r--r--tests/run-make/native-lib-load-order/a.rs (renamed from tests/run-make/issue-28595/a.rs)0
-rw-r--r--tests/run-make/native-lib-load-order/b.c (renamed from tests/run-make/issue-28595/b.c)0
-rw-r--r--tests/run-make/native-lib-load-order/b.rs (renamed from tests/run-make/issue-28595/b.rs)0
-rw-r--r--tests/run-make/native-lib-load-order/rmake.rs16
-rw-r--r--tests/run-make/no-duplicate-libs/Makefile11
-rw-r--r--tests/run-make/no-duplicate-libs/rmake.rs22
-rw-r--r--tests/run-make/pass-non-c-like-enum-to-c/Makefile6
-rw-r--r--tests/run-make/pass-non-c-like-enum-to-c/rmake.rs19
-rw-r--r--tests/run-make/pgo-gen-no-imp-symbols/Makefile11
-rw-r--r--tests/run-make/pgo-gen-no-imp-symbols/rmake.rs27
-rw-r--r--tests/run-make/return-non-c-like-enum-from-c/Makefile6
-rw-r--r--tests/run-make/return-non-c-like-enum-from-c/rmake.rs17
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/Makefile35
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs84
-rw-r--r--tests/run-make/rustdoc-cfgspec-parsing/foo.rs (renamed from tests/run-make/issue-22131/foo.rs)0
-rw-r--r--tests/run-make/rustdoc-cfgspec-parsing/rmake.rs21
-rw-r--r--tests/run-make/split-debuginfo/Makefile2
-rw-r--r--tests/run-make/staticlib-blank-lib/Makefile6
-rw-r--r--tests/run-make/staticlib-blank-lib/rmake.rs13
-rw-r--r--tests/run-make/test-benches/Makefile12
-rw-r--r--tests/run-make/test-benches/rmake.rs22
-rw-r--r--tests/run-make/version-verbose-commit-hash/rmake.rs20
-rw-r--r--tests/run-make/wasm-panic-small/rmake.rs9
-rw-r--r--tests/run-make/wasm-stringify-ints-small/rmake.rs8
-rw-r--r--tests/run-make/zero-extend-abi-param-passing/bad.c (renamed from tests/run-make/issue-97463-abi-param-passing/bad.c)0
-rw-r--r--tests/run-make/zero-extend-abi-param-passing/param_passing.rs (renamed from tests/run-make/issue-97463-abi-param-passing/param_passing.rs)0
-rw-r--r--tests/run-make/zero-extend-abi-param-passing/rmake.rs25
-rw-r--r--tests/rustdoc-gui/item-name-wrap.goml23
-rw-r--r--tests/rustdoc-gui/sidebar.goml4
-rw-r--r--tests/rustdoc-gui/source-code-page-code-scroll.goml4
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs22
-rw-r--r--tests/rustdoc-gui/stab-in-doc.goml9
-rw-r--r--tests/rustdoc-gui/trait-with-bounds.goml35
-rw-r--r--tests/rustdoc-gui/type-declation-overflow.goml22
-rw-r--r--tests/rustdoc-json/assoc_items.rs24
-rw-r--r--tests/rustdoc-json/assoc_type.rs8
-rw-r--r--tests/rustdoc-json/blanket_impls.rs6
-rw-r--r--tests/rustdoc-json/doc_hidden_failure.rs4
-rw-r--r--tests/rustdoc-json/enums/discriminant/basic.rs12
-rw-r--r--tests/rustdoc-json/enums/discriminant/expr.rs36
-rw-r--r--tests/rustdoc-json/enums/discriminant/limits.rs32
-rw-r--r--tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs16
-rw-r--r--tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs8
-rw-r--r--tests/rustdoc-json/enums/discriminant/struct.rs14
-rw-r--r--tests/rustdoc-json/enums/discriminant/tuple.rs14
-rw-r--r--tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs6
-rw-r--r--tests/rustdoc-json/enums/field_hidden.rs8
-rw-r--r--tests/rustdoc-json/enums/field_order.rs40
-rw-r--r--tests/rustdoc-json/enums/kind.rs38
-rw-r--r--tests/rustdoc-json/enums/struct_field_hidden.rs12
-rw-r--r--tests/rustdoc-json/enums/tuple_fields_hidden.rs124
-rw-r--r--tests/rustdoc-json/enums/use_glob.rs10
-rw-r--r--tests/rustdoc-json/enums/use_variant.rs12
-rw-r--r--tests/rustdoc-json/enums/use_variant_foreign.rs6
-rw-r--r--tests/rustdoc-json/enums/variant_order.rs40
-rw-r--r--tests/rustdoc-json/enums/variant_struct.rs14
-rw-r--r--tests/rustdoc-json/enums/variant_tuple_struct.rs14
-rw-r--r--tests/rustdoc-json/fn_pointer/abi.rs14
-rw-r--r--tests/rustdoc-json/fn_pointer/generics.rs14
-rw-r--r--tests/rustdoc-json/fn_pointer/qualifiers.rs12
-rw-r--r--tests/rustdoc-json/fns/abi.rs14
-rw-r--r--tests/rustdoc-json/fns/async_return.rs24
-rw-r--r--tests/rustdoc-json/fns/extern_c_variadic.rs4
-rw-r--r--tests/rustdoc-json/fns/generic_args.rs88
-rw-r--r--tests/rustdoc-json/fns/generic_returns.rs10
-rw-r--r--tests/rustdoc-json/fns/generics.rs30
-rw-r--r--tests/rustdoc-json/fns/pattern_arg.rs4
-rw-r--r--tests/rustdoc-json/fns/qualifiers.rs36
-rw-r--r--tests/rustdoc-json/fns/return_type_alias.rs4
-rw-r--r--tests/rustdoc-json/generic-associated-types/gats.rs34
-rw-r--r--tests/rustdoc-json/generic_impl.rs6
-rw-r--r--tests/rustdoc-json/glob_import.rs4
-rw-r--r--tests/rustdoc-json/impl-trait-precise-capturing.rs6
-rw-r--r--tests/rustdoc-json/impls/auto.rs4
-rw-r--r--tests/rustdoc-json/impls/blanket_with_local.rs8
-rw-r--r--tests/rustdoc-json/impls/foreign_for_local.rs12
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility.rs6
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs6
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_private.rs6
-rw-r--r--tests/rustdoc-json/impls/import_from_private.rs16
-rw-r--r--tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs10
-rw-r--r--tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs6
-rw-r--r--tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs10
-rw-r--r--tests/rustdoc-json/impls/local_for_foreign.rs12
-rw-r--r--tests/rustdoc-json/impls/local_for_local.rs14
-rw-r--r--tests/rustdoc-json/impls/local_for_local_primitive.rs12
-rw-r--r--tests/rustdoc-json/impls/local_for_primitive.rs6
-rw-r--r--tests/rustdoc-json/intra-doc-links/foreign_variant.rs6
-rw-r--r--tests/rustdoc-json/intra-doc-links/non_page.rs20
-rw-r--r--tests/rustdoc-json/intra-doc-links/user_written.rs4
-rw-r--r--tests/rustdoc-json/keyword.rs8
-rw-r--r--tests/rustdoc-json/keyword_private.rs16
-rw-r--r--tests/rustdoc-json/lifetime/longest.rs34
-rw-r--r--tests/rustdoc-json/lifetime/outlives.rs30
-rw-r--r--tests/rustdoc-json/lifetime/outlives_in_param.rs10
-rw-r--r--tests/rustdoc-json/lifetime/outlives_in_where.rs22
-rw-r--r--tests/rustdoc-json/methods/abi.rs30
-rw-r--r--tests/rustdoc-json/methods/qualifiers.rs36
-rw-r--r--tests/rustdoc-json/nested.rs40
-rw-r--r--tests/rustdoc-json/non_lifetime_binders.rs10
-rw-r--r--tests/rustdoc-json/output_generics.rs10
-rw-r--r--tests/rustdoc-json/primitives/local_primitive.rs10
-rw-r--r--tests/rustdoc-json/primitives/primitive_impls.rs18
-rw-r--r--tests/rustdoc-json/primitives/primitive_overloading.rs4
-rw-r--r--tests/rustdoc-json/primitives/primitive_type.rs12
-rw-r--r--tests/rustdoc-json/primitives/use_primitive.rs16
-rw-r--r--tests/rustdoc-json/reexport/doc_inline_external_crate.rs8
-rw-r--r--tests/rustdoc-json/reexport/export_extern_crate_as_self.rs2
-rw-r--r--tests/rustdoc-json/reexport/extern_crate_glob.rs8
-rw-r--r--tests/rustdoc-json/reexport/glob_collision.rs26
-rw-r--r--tests/rustdoc-json/reexport/glob_empty_mod.rs6
-rw-r--r--tests/rustdoc-json/reexport/glob_extern.rs18
-rw-r--r--tests/rustdoc-json/reexport/glob_private.rs26
-rw-r--r--tests/rustdoc-json/reexport/in_root_and_mod.rs8
-rw-r--r--tests/rustdoc-json/reexport/in_root_and_mod_pub.rs16
-rw-r--r--tests/rustdoc-json/reexport/macro.rs6
-rw-r--r--tests/rustdoc-json/reexport/mod_not_included.rs6
-rw-r--r--tests/rustdoc-json/reexport/private_twice_one_inline.rs16
-rw-r--r--tests/rustdoc-json/reexport/private_two_names.rs18
-rw-r--r--tests/rustdoc-json/reexport/pub_use_doc_hidden.rs4
-rw-r--r--tests/rustdoc-json/reexport/reexport_method_from_private_module.rs12
-rw-r--r--tests/rustdoc-json/reexport/reexport_of_hidden.rs4
-rw-r--r--tests/rustdoc-json/reexport/rename_private.rs6
-rw-r--r--tests/rustdoc-json/reexport/rename_public.rs14
-rw-r--r--tests/rustdoc-json/reexport/same_name_different_types.rs12
-rw-r--r--tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs12
-rw-r--r--tests/rustdoc-json/reexport/simple_private.rs12
-rw-r--r--tests/rustdoc-json/reexport/simple_public.rs12
-rw-r--r--tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs2
-rw-r--r--tests/rustdoc-json/return_private.rs4
-rw-r--r--tests/rustdoc-json/stripped_modules.rs10
-rw-r--r--tests/rustdoc-json/structs/field_order.rs40
-rw-r--r--tests/rustdoc-json/structs/plain_all_pub.rs12
-rw-r--r--tests/rustdoc-json/structs/plain_doc_hidden.rs10
-rw-r--r--tests/rustdoc-json/structs/plain_empty.rs8
-rw-r--r--tests/rustdoc-json/structs/plain_pub_priv.rs8
-rw-r--r--tests/rustdoc-json/structs/tuple.rs6
-rw-r--r--tests/rustdoc-json/structs/tuple_empty.rs2
-rw-r--r--tests/rustdoc-json/structs/tuple_pub_priv.rs10
-rw-r--r--tests/rustdoc-json/structs/unit.rs6
-rw-r--r--tests/rustdoc-json/structs/with_generics.rs16
-rw-r--r--tests/rustdoc-json/structs/with_primitives.rs12
-rw-r--r--tests/rustdoc-json/trait_alias.rs12
-rw-r--r--tests/rustdoc-json/traits/has_body.rs16
-rw-r--r--tests/rustdoc-json/traits/implementors.rs14
-rw-r--r--tests/rustdoc-json/traits/is_object_safe.rs12
-rw-r--r--tests/rustdoc-json/traits/private_supertrait.rs8
-rw-r--r--tests/rustdoc-json/traits/supertrait.rs22
-rw-r--r--tests/rustdoc-json/traits/trait_alias.rs22
-rw-r--r--tests/rustdoc-json/traits/uses_extern_trait.rs4
-rw-r--r--tests/rustdoc-json/type/dyn.rs74
-rw-r--r--tests/rustdoc-json/type/extern.rs4
-rw-r--r--tests/rustdoc-json/type/fn_lifetime.rs38
-rw-r--r--tests/rustdoc-json/type/generic_default.rs46
-rw-r--r--tests/rustdoc-json/type/hrtb.rs16
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type.rs16
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_bound.rs18
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_projections.rs26
-rw-r--r--tests/rustdoc-json/type_alias.rs12
-rw-r--r--tests/rustdoc-json/unions/field_order.rs40
-rw-r--r--tests/rustdoc-json/unions/impl.rs10
-rw-r--r--tests/rustdoc-json/unions/union.rs12
-rw-r--r--tests/rustdoc-ui/track-diagnostics.stderr2
-rw-r--r--tests/rustdoc/anchor-id-duplicate-method-name-25001.rs4
-rw-r--r--tests/rustdoc/auxiliary/precise-capturing.rs7
-rw-r--r--tests/rustdoc/const-generics/const-impl.rs2
-rw-r--r--tests/rustdoc/impl-trait-precise-capturing.rs13
-rw-r--r--tests/ui/asm/binary_asm_labels.stderr20
-rw-r--r--tests/ui/asm/binary_asm_labels_allowed.rs17
-rw-r--r--tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.rs15
-rw-r--r--tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr25
-rw-r--r--tests/ui/cfg/diagnostics-cross-crate.rs3
-rw-r--r--tests/ui/cfg/diagnostics-cross-crate.stderr27
-rw-r--r--tests/ui/cfg/diagnostics-reexport.rs8
-rw-r--r--tests/ui/cfg/diagnostics-reexport.stderr20
-rw-r--r--tests/ui/cfg/diagnostics-same-crate.rs9
-rw-r--r--tests/ui/cfg/diagnostics-same-crate.stderr48
-rw-r--r--tests/ui/check-cfg/mix.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr6
-rw-r--r--tests/ui/closures/binder/const-bound.rs3
-rw-r--r--tests/ui/closures/binder/const-bound.stderr8
-rw-r--r--tests/ui/closures/closure-no-fn-3.stderr6
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs21
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr47
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs24
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs27
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr4
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs23
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr43
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs54
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr84
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs53
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/README.md22
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs21
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs22
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs30
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs30
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs20
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs23
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs63
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs28
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs25
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs26
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs34
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs34
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs24
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs27
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs68
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs32
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs25
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs26
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs34
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs34
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs24
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs27
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs68
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs32
-rw-r--r--tests/ui/coherence/negative-coherence/regions-in-canonical.rs5
-rw-r--r--tests/ui/coherence/negative-coherence/regions-in-canonical.stderr8
-rw-r--r--tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs3
-rw-r--r--tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr12
-rw-r--r--tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs1
-rw-r--r--tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr11
-rw-r--r--tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs7
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs14
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr42
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr8
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs8
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr24
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_good.rs13
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs10
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr20
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs10
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr32
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs9
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr16
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs12
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr33
-rw-r--r--tests/ui/const-generics/adt_const_params/index-oob-ice-83993.rs24
-rw-r--r--tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr17
-rw-r--r--tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs9
-rw-r--r--tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr84
-rw-r--r--tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs11
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr9
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs27
-rw-r--r--tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr9
-rw-r--r--tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs5
-rw-r--r--tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr36
-rw-r--r--tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs13
-rw-r--r--tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr8
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-1.rs20
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-1.stderr36
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-2.rs14
-rw-r--r--tests/ui/const-generics/adt_const_params/unsized_field-2.stderr28
-rw-r--r--tests/ui/const-generics/const-param-elided-lifetime.min.stderr20
-rw-r--r--tests/ui/const-generics/const-param-elided-lifetime.rs6
-rw-r--r--tests/ui/const-generics/const-param-with-additional-obligations.rs6
-rw-r--r--tests/ui/const-generics/float-generic.adt_const_params.stderr2
-rw-r--r--tests/ui/const-generics/float-generic.full.stderr9
-rw-r--r--tests/ui/const-generics/float-generic.rs4
-rw-r--r--tests/ui/const-generics/float-generic.simple.stderr2
-rw-r--r--tests/ui/const-generics/fn-const-param-call.adt_const_params.stderr15
-rw-r--r--tests/ui/const-generics/fn-const-param-call.full.stderr4
-rw-r--r--tests/ui/const-generics/fn-const-param-call.min.stderr4
-rw-r--r--tests/ui/const-generics/fn-const-param-call.rs8
-rw-r--r--tests/ui/const-generics/fn-const-param-infer.adt_const_params.stderr30
-rw-r--r--tests/ui/const-generics/fn-const-param-infer.full.stderr10
-rw-r--r--tests/ui/const-generics/fn-const-param-infer.min.stderr10
-rw-r--r--tests/ui/const-generics/fn-const-param-infer.rs32
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-100360.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-89851.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs8
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr14
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr14
-rw-r--r--tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr8
-rw-r--r--tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr12
-rw-r--r--tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs7
-rw-r--r--tests/ui/const-generics/issue-66451.rs22
-rw-r--r--tests/ui/const-generics/issue-66451.stderr16
-rw-r--r--tests/ui/const-generics/issue-70408.rs2
-rw-r--r--tests/ui/const-generics/issue-80471.rs1
-rw-r--r--tests/ui/const-generics/issue-80471.stderr13
-rw-r--r--tests/ui/const-generics/issues/issue-100313.rs6
-rw-r--r--tests/ui/const-generics/issues/issue-105821.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-56445-1.min.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-56445-1.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs3
-rw-r--r--tests/ui/const-generics/issues/issue-71547.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs4
-rw-r--r--tests/ui/const-generics/issues/issue-86535-2.rs11
-rw-r--r--tests/ui/const-generics/issues/issue-86535.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-90455.fixed2
-rw-r--r--tests/ui/const-generics/issues/issue-90455.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-99641.stderr4
-rw-r--r--tests/ui/const-generics/min_const_generics/complex-types.stderr4
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param-deref.adt_const_params.stderr15
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr4
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr4
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param-deref.rs15
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param.adt_const_params.stderr21
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param.full.stderr4
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param.min.stderr4
-rw-r--r--tests/ui/const-generics/raw-ptr-const-param.rs6
-rw-r--r--tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr49
-rw-r--r--tests/ui/const-generics/slice-const-param-mismatch.full.stderr6
-rw-r--r--tests/ui/const-generics/slice-const-param-mismatch.min.stderr18
-rw-r--r--tests/ui/const-generics/slice-const-param-mismatch.rs11
-rw-r--r--tests/ui/const-generics/slice-const-param.rs7
-rw-r--r--tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr9
-rw-r--r--tests/ui/const-generics/transmute-const-param-static-reference.min.stderr6
-rw-r--r--tests/ui/const-generics/transmute-const-param-static-reference.rs13
-rw-r--r--tests/ui/const-generics/type-dependent/issue-71348.min.stderr8
-rw-r--r--tests/ui/const-generics/type-dependent/issue-71348.rs2
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.32bit.stderr42
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.64bit.stderr42
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.rs6
-rw-r--r--tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr40
-rw-r--r--tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr40
-rw-r--r--tests/ui/consts/const-eval/ub-incorrect-vtable.rs8
-rw-r--r--tests/ui/consts/const-eval/ub-wide-ptr.rs34
-rw-r--r--tests/ui/consts/const-eval/ub-wide-ptr.stderr83
-rw-r--r--tests/ui/consts/const_refs_to_static.rs2
-rw-r--r--tests/ui/consts/mut-ptr-to-static.rs9
-rw-r--r--tests/ui/consts/refs_check_const_eq-issue-88384.rs17
-rw-r--r--tests/ui/consts/refs_check_const_eq-issue-88384.stderr12
-rw-r--r--tests/ui/consts/refs_check_const_value_eq-issue-88876.rs2
-rw-r--r--tests/ui/coroutine/coroutine-with-nll.stderr8
-rw-r--r--tests/ui/coroutine/issue-48048.stderr8
-rw-r--r--tests/ui/coroutine/pattern-borrow.stderr7
-rw-r--r--tests/ui/coroutine/self_referential_gen_block.stderr3
-rw-r--r--tests/ui/coroutine/yield-in-args.stderr8
-rw-r--r--tests/ui/coroutine/yield-while-iterating.stderr7
-rw-r--r--tests/ui/coroutine/yield-while-local-borrowed.stderr15
-rw-r--r--tests/ui/empty/empty-struct-braces-expr.stderr37
-rw-r--r--tests/ui/enum/error-variant-with-turbofishes.stderr5
-rw-r--r--tests/ui/error-codes/E0746.stderr9
-rw-r--r--tests/ui/error-codes/E0771.rs4
-rw-r--r--tests/ui/error-codes/E0771.stderr8
-rw-r--r--tests/ui/errors/wrong-target-spec.rs8
-rw-r--r--tests/ui/errors/wrong-target-spec.stderr2
-rw-r--r--tests/ui/expr/issue-22933-2.stderr10
-rw-r--r--tests/ui/feature-gates/feature-gate-adt_const_params.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized-const-params.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized-const-params.stderr18
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.base.stderr6
-rw-r--r--tests/ui/generic-associated-types/issue-79422.base.stderr4
-rw-r--r--tests/ui/generic-const-items/elided-lifetimes.stderr4
-rw-r--r--tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr38
-rw-r--r--tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr5
-rw-r--r--tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr13
-rw-r--r--tests/ui/impl-trait/static-lifetime-return-position-impl-trait.rs2
-rw-r--r--tests/ui/inference/ice-cannot-relate-region-109178.rs2
-rw-r--r--tests/ui/issues/issue-18107.stderr4
-rw-r--r--tests/ui/issues/issue-23217.stderr10
-rw-r--r--tests/ui/issues/issue-28971.stderr10
-rw-r--r--tests/ui/issues/issue-34209.stderr7
-rw-r--r--tests/ui/issues/issue-4736.stderr4
-rw-r--r--tests/ui/issues/issue-80607.stderr4
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr23
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.rs4
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr4
-rw-r--r--tests/ui/lto/debuginfo-lto-alloc.rs3
-rw-r--r--tests/ui/macros/builtin-std-paths-fail.stderr2
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/repetitions.rs18
-rw-r--r--tests/ui/macros/macro-outer-attributes.stderr11
-rw-r--r--tests/ui/mir/ice-mir-const-qualif-125837.rs17
-rw-r--r--tests/ui/mir/ice-mir-const-qualif-125837.stderr41
-rw-r--r--tests/ui/nll/issue-55850.stderr8
-rw-r--r--tests/ui/numeric/numeric-fields.stderr4
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.rs5
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.stderr14
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-issue-126311.rs5
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-issue-126311.stderr14
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.rs11
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr17
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.rs6
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.stderr8
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.rs4
-rw-r--r--tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.stderr8
-rw-r--r--tests/ui/parser/struct-literal-variant-in-if.stderr5
-rw-r--r--tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr9
-rw-r--r--tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr1
-rw-r--r--tests/ui/resolve/issue-18252.stderr5
-rw-r--r--tests/ui/resolve/issue-19452.stderr10
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr20
-rw-r--r--tests/ui/rust-2024/safe-outside-extern.gated.stderr8
-rw-r--r--tests/ui/rust-2024/safe-outside-extern.rs3
-rw-r--r--tests/ui/rust-2024/safe-outside-extern.ungated.stderr8
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.fixed2
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.rs2
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.stderr4
-rw-r--r--tests/ui/sanitizer/cfi-supertraits.rs6
-rw-r--r--tests/ui/simd/intrinsic/generic-elements.rs20
-rw-r--r--tests/ui/simd/intrinsic/generic-elements.stderr42
-rw-r--r--tests/ui/simd/monomorphize-shuffle-index.rs2
-rw-r--r--tests/ui/static/raw-ref-deref-with-unsafe.rs16
-rw-r--r--tests/ui/static/raw-ref-deref-without-unsafe.rs18
-rw-r--r--tests/ui/static/raw-ref-deref-without-unsafe.stderr19
-rw-r--r--tests/ui/static/raw-ref-extern-static.rs27
-rw-r--r--tests/ui/static/raw-ref-static-mut.rs17
-rw-r--r--tests/ui/statics/const_generics.rs2
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr5
-rw-r--r--tests/ui/suggestions/incorrect-variant-literal.rs55
-rw-r--r--tests/ui/suggestions/incorrect-variant-literal.svg1028
-rw-r--r--tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr32
-rw-r--r--tests/ui/suggestions/suggest-variants.stderr34
-rw-r--r--tests/ui/symbol-names/const-generics-str-demangling.rs2
-rw-r--r--tests/ui/symbol-names/const-generics-structural-demangling.rs26
-rw-r--r--tests/ui/target-feature/gate.rs1
-rw-r--r--tests/ui/target-feature/gate.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs3
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr8
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs5
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr12
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs5
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr8
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr17
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr16
-rw-r--r--tests/ui/try-trait/option-to-result.stderr8
-rw-r--r--tests/ui/try-trait/try-on-option.stderr4
-rw-r--r--tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr5
-rw-r--r--tests/ui/typeck/ice-unexpected-region-123863.stderr8
-rw-r--r--tests/ui/unsized/box-instead-of-dyn-fn.stderr4
-rw-r--r--tests/ui/unsized/issue-91801.stderr10
-rw-r--r--tests/ui/unsized/issue-91803.stderr4
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr4
-rw-r--r--triagebot.toml2
870 files changed, 18508 insertions, 8717 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index 03584aed08d..b137497594f 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -64,11 +64,17 @@ jobs:
       - name: cargo update
         # Remove first line that always just says "Updating crates.io index"
         run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
+      - name: cargo update rustbook
+        run: |
+          echo -e "\nrustbook dependencies:" >> cargo_update.log
+          cargo update --manifest-path src/tools/rustbook 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
       - name: upload Cargo.lock artifact for use in PR
         uses: actions/upload-artifact@v4
         with:
           name: Cargo-lock
-          path: Cargo.lock
+          path: |
+            Cargo.lock
+            src/tools/rustbook/Cargo.lock
           retention-days: 1
       - name: upload cargo-update log artifact for use in PR
         uses: actions/upload-artifact@v4
@@ -113,7 +119,7 @@ jobs:
           git config user.name github-actions
           git config user.email github-actions@github.com
           git switch --force-create cargo_update
-          git add ./Cargo.lock
+          git add ./Cargo.lock ./src/tools/rustbook/Cargo.lock
           git commit --no-verify --file=commit.txt
 
       - name: push
diff --git a/.gitignore b/.gitignore
index f1ca6a79b5c..87d02563ed0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,6 @@ build/
 /target
 /src/bootstrap/target
 /src/tools/x/target
-/inc-fat/
 # Created by default with `src/ci/docker/run.sh`
 /obj/
 /rustc-ice*
diff --git a/.reuse/dep5 b/.reuse/dep5
deleted file mode 100644
index 5706ea0b204..00000000000
--- a/.reuse/dep5
+++ /dev/null
@@ -1,124 +0,0 @@
-# WARNING: this metadata is currently incomplete, do not rely on it yet.
-
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-
-# Note that we're explicitly listing the individual files at the root of the
-# repository rather than just having `Files: *`. This is explicitly done to
-# help downstream forks of the Rust compiler: this way, the files they add
-# won't be automatically marked as authored by the Rust project.
-Files: compiler/*
-       library/*
-       tests/*
-       src/*
-       .github/*
-       Cargo.lock
-       Cargo.toml
-       CODE_OF_CONDUCT.md
-       config.example.toml
-       configure
-       CONTRIBUTING.md
-       COPYRIGHT
-       INSTALL.md
-       LICENSE-APACHE
-       LICENSE-MIT
-       README.md
-       RELEASES.md
-       rustfmt.toml
-       rust-bors.toml
-       triagebot.toml
-       x
-       x.ps1
-       x.py
-       .clang-format
-       .editorconfig
-       .git-blame-ignore-revs
-       .gitattributes
-       .gitignore
-       .gitmodules
-       .mailmap
-       .ignore
-Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT or Apache-2.0
-
-Files: compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
-Copyright: 2003-2019 University of Illinois at Urbana-Champaign.
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: Apache-2.0 WITH LLVM-exception AND (Apache-2.0 OR MIT)
-
-Files: library/core/src/unicode/unicode_data.rs
-Copyright: 1991-2022 Unicode, Inc. All rights reserved.
-License: Unicode-DFS-2016
-
-Files: library/std/src/sync/mpmc/*
-Copyright: 2019 The Crossbeam Project Developers
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT OR Apache-2.0
-
-Files: library/std/src/sys/sync/mutex/fuchsia.rs
-Copyright: 2016 The Fuchsia Authors
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: BSD-2-Clause AND (MIT OR Apache-2.0)
-
-Files: src/test/rustdoc/auxiliary/enum-primitive.rs
-Copyright: 2015 Anders Kaseorg <andersk@mit.edu>
-License: MIT
-
-Files: src/librustdoc/html/static/fonts/FiraSans*
-Copyright: 2014, Mozilla Foundation
-           2014, Telefonica S.A.
-License: OFL-1.1
-
-Files: src/librustdoc/html/static/fonts/NanumBarun*
-Copyright: 2010 NAVER Corporation
-License: OFL-1.1
-
-Files: src/librustdoc/html/static/fonts/SourceCodePro*
-       src/librustdoc/html/static/fonts/SourceSerif4*
-Copyright: 2010, 2012, 2014-2023, Adobe Systems Incorporated
-License: OFL-1.1
-
-Files: src/librustdoc/html/static/css/normalize.css
-Copyright: Nicolas Gallagher and Jonathan Neal
-License: MIT
-
-Files: src/librustdoc/html/static/css/rustdoc.css
-Copyright: 2016 Ike Ku, Jessica Stokes and Leon Guan
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT OR Apache-2.0
-
-Files: src/doc/rustc-dev-guide/mermaid.min.js
-Copyright: 2014-2021 Knut Sveidqvist
-License: MIT
-
-Files: library/backtrace/*
-Copyright: 2014 Alex Crichton
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT OR Apache-2.0
-
-Files: src/doc/embedded-book/*
-Copyright: Rust on Embedded Devices Working Group
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT OR Apache-2.0 OR CC-BY-SA-4.0
-
-Files: src/doc/rust-by-example/*
-Copyright: 2014 Jorge Aparicio
-           The Rust Project Developers (see https://thanks.rust-lang.org)
-License: MIT OR Apache-2.0
-
-# Reuse cannot process the LLVM source tree, and so the copyrights for the LLVM
-# submodule are written out here manually. The collect-licence-metadata tool
-# has a specific exception coded within it to ignore ./src/llvm-project so
-# any time LLVM is updated, please revisit this section. The copyrights are
-# taken from the relevant LLVM sub-folders: llvm, lld, lldb, compiler-rt and libunwind.
-#
-# The git hash for the CREDITS.TXT file is taken from the current git submodule
-# commit for ./src/llvm-project.
-#
-# The copyright years were compiled by looking at all the relevant
-# ./src/llvm-project/*/LICENSE.txt files
-
-Files: src/llvm-project/*
-Copyright: 2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)
-           2010 Apple Inc
-           2003-2019 University of Illinois at Urbana-Champaign.
-License: NCSA AND Apache-2.0 WITH LLVM-exception
diff --git a/Cargo.lock b/Cargo.lock
index 1c1607e4c1a..146070cf167 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -51,6 +51,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
 dependencies = [
  "cfg-if",
+ "getrandom",
  "once_cell",
  "version_check",
  "zerocopy",
@@ -244,62 +245,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
 
 [[package]]
-name = "askama"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
-dependencies = [
- "askama_derive",
- "askama_escape",
-]
-
-[[package]]
-name = "askama_derive"
-version = "0.12.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
-dependencies = [
- "askama_parser",
- "basic-toml",
- "mime",
- "mime_guess",
- "proc-macro2",
- "quote",
- "serde",
- "syn 2.0.67",
-]
-
-[[package]]
-name = "askama_escape"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
-
-[[package]]
-name = "askama_parser"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "assert_cmd"
-version = "2.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8"
-dependencies = [
- "anstyle",
- "bstr",
- "doc-comment",
- "predicates",
- "predicates-core",
- "predicates-tree",
- "wait-timeout",
-]
-
-[[package]]
 name = "autocfg"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1112,12 +1057,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
 
 [[package]]
-name = "difflib"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
-
-[[package]]
 name = "digest"
 version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1209,12 +1148,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
-[[package]]
 name = "either"
 version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2204,21 +2137,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "line-wrap"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e"
-
-[[package]]
-name = "linereader"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d921fea6860357575519aca014c6e22470585accdd543b370c404a8a72d0dd1d"
-dependencies = [
- "memchr",
-]
-
-[[package]]
 name = "linkchecker"
 version = "0.1.0"
 dependencies = [
@@ -2227,12 +2145,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "linked-hash-map"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
-
-[[package]]
 name = "lint-docs"
 version = "0.1.0"
 dependencies = [
@@ -2369,52 +2281,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "mdbook-i18n-helpers"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c8f972ab672d366c3dad77ea5aa7bae68db2d25fbeb889849f97469d7b658e4"
-dependencies = [
- "anyhow",
- "chrono",
- "mdbook",
- "polib",
- "pulldown-cmark 0.10.3",
- "pulldown-cmark-to-cmark",
- "regex",
- "semver",
- "serde_json",
- "syntect",
- "textwrap",
-]
-
-[[package]]
-name = "mdbook-trpl-listing"
-version = "0.1.0"
-dependencies = [
- "assert_cmd",
- "clap",
- "mdbook",
- "pulldown-cmark 0.10.3",
- "pulldown-cmark-to-cmark",
- "serde_json",
- "thiserror",
- "toml 0.8.14",
- "xmlparser",
-]
-
-[[package]]
-name = "mdbook-trpl-note"
-version = "1.0.0"
-dependencies = [
- "assert_cmd",
- "clap",
- "mdbook",
- "pulldown-cmark 0.10.3",
- "pulldown-cmark-to-cmark",
- "serde_json",
-]
-
-[[package]]
 name = "measureme"
 version = "11.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2599,12 +2465,76 @@ dependencies = [
 ]
 
 [[package]]
+name = "num"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-integer",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
 name = "num-conv"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
 
 [[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
+dependencies = [
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
 name = "num-traits"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2692,25 +2622,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
-name = "onig"
-version = "6.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
-dependencies = [
- "bitflags 1.3.2",
- "libc",
- "once_cell",
- "onig_sys",
-]
-
-[[package]]
-name = "onig_sys"
-version = "69.8.1"
+name = "once_map"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
+checksum = "aa7085055bbe9c8edbd982048dbcf8181794d4a81cb04a11931673e63cc18dc6"
 dependencies = [
- "cc",
- "pkg-config",
+ "ahash",
+ "hashbrown",
+ "parking_lot",
+ "stable_deref_trait",
 ]
 
 [[package]]
@@ -3013,29 +2933,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
 
 [[package]]
-name = "plist"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9"
-dependencies = [
- "base64",
- "indexmap",
- "line-wrap",
- "quick-xml",
- "serde",
- "time",
-]
-
-[[package]]
-name = "polib"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b393b155cf9be86249cba1b56cc81be0e6212c66d94ac0d76d37a1761f3bb1b"
-dependencies = [
- "linereader",
-]
-
-[[package]]
 name = "polonius-engine"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3071,33 +2968,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
-name = "predicates"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8"
-dependencies = [
- "anstyle",
- "difflib",
- "predicates-core",
-]
-
-[[package]]
-name = "predicates-core"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
-
-[[package]]
-name = "predicates-tree"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
-dependencies = [
- "predicates-core",
- "termtree",
-]
-
-[[package]]
 name = "prettydiff"
 version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3166,7 +3036,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
 dependencies = [
  "bitflags 2.5.0",
- "getopts",
  "memchr",
  "pulldown-cmark-escape 0.10.1",
  "unicase",
@@ -3197,30 +3066,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
 
 [[package]]
-name = "pulldown-cmark-to-cmark"
-version = "13.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b"
-dependencies = [
- "pulldown-cmark 0.10.3",
-]
-
-[[package]]
 name = "punycode"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"
 
 [[package]]
-name = "quick-xml"
-version = "0.31.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
-dependencies = [
- "memchr",
-]
-
-[[package]]
 name = "quine-mc_cluskey"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3435,6 +3286,41 @@ dependencies = [
 ]
 
 [[package]]
+name = "rinja"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2d47a46d7729e891c8accf260e9daa02ae6d570aa2a94fb1fb27eb5364a2323"
+dependencies = [
+ "rinja_derive",
+]
+
+[[package]]
+name = "rinja_derive"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44dae9afe59d58ed8d988d67d1945f3638125d2fd2104058399382e11bd3ea2a"
+dependencies = [
+ "basic-toml",
+ "mime",
+ "mime_guess",
+ "once_map",
+ "proc-macro2",
+ "quote",
+ "rinja_parser",
+ "serde",
+ "syn 2.0.67",
+]
+
+[[package]]
+name = "rinja_parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1771c78cd5d3b1646ef8d8f2ed100db936e8b291d3cc06e92a339ff346858c"
+dependencies = [
+ "nom",
+]
+
+[[package]]
 name = "rls"
 version = "2.0.0"
 dependencies = [
@@ -3455,18 +3341,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustbook"
-version = "0.1.0"
-dependencies = [
- "clap",
- "env_logger",
- "mdbook",
- "mdbook-i18n-helpers",
- "mdbook-trpl-listing",
- "mdbook-trpl-note",
-]
-
-[[package]]
 name = "rustc-build-sysroot"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4932,7 +4806,6 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "arrayvec",
- "askama",
  "base64",
  "expect-test",
  "indexmap",
@@ -4940,6 +4813,7 @@ dependencies = [
  "minifier",
  "pulldown-cmark 0.9.6",
  "regex",
+ "rinja",
  "rustdoc-json-types",
  "serde",
  "serde_json",
@@ -5486,28 +5360,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "syntect"
-version = "5.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
-dependencies = [
- "bincode",
- "bitflags 1.3.2",
- "flate2",
- "fnv",
- "once_cell",
- "onig",
- "plist",
- "regex-syntax 0.8.4",
- "serde",
- "serde_derive",
- "serde_json",
- "thiserror",
- "walkdir",
- "yaml-rust",
-]
-
-[[package]]
 name = "sysinfo"
 version = "0.30.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5615,12 +5467,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "termtree"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
-
-[[package]]
 name = "test"
 version = "0.0.0"
 dependencies = [
@@ -5631,10 +5477,15 @@ dependencies = [
 ]
 
 [[package]]
-name = "textwrap"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+name = "test-float-parse"
+version = "0.1.0"
+dependencies = [
+ "indicatif",
+ "num",
+ "rand",
+ "rand_chacha",
+ "rayon",
+]
 
 [[package]]
 name = "thin-vec"
@@ -5799,19 +5650,7 @@ dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "toml_edit 0.19.15",
-]
-
-[[package]]
-name = "toml"
-version = "0.8.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
-dependencies = [
- "serde",
- "serde_spanned",
- "toml_datetime",
- "toml_edit 0.22.14",
+ "toml_edit",
 ]
 
 [[package]]
@@ -5833,20 +5672,7 @@ dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "winnow 0.5.40",
-]
-
-[[package]]
-name = "toml_edit"
-version = "0.22.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
-dependencies = [
- "indexmap",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "winnow 0.6.13",
+ "winnow",
 ]
 
 [[package]]
@@ -6257,15 +6083,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
-name = "wait-timeout"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
-dependencies = [
- "libc",
-]
-
-[[package]]
 name = "walkdir"
 version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6670,15 +6487,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "winnow"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
-dependencies = [
- "memchr",
-]
-
-[[package]]
 name = "wit-component"
 version = "0.210.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6733,12 +6541,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "xmlparser"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
-
-[[package]]
 name = "xz2"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6748,15 +6550,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "yaml-rust"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
-dependencies = [
- "linked-hash-map",
-]
-
-[[package]]
 name = "yansi-term"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index ce87a8c20b7..178a5ab9408 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ members = [
   "compiler/rustc",
   "library/std",
   "library/sysroot",
+  "src/etc/test-float-parse",
   "src/rustdoc-json-types",
   "src/tools/build_helper",
   "src/tools/cargotest",
@@ -15,7 +16,6 @@ members = [
   "src/tools/linkchecker",
   "src/tools/lint-docs",
   "src/tools/miropt-test-tools",
-  "src/tools/rustbook",
   "src/tools/unstable-book-gen",
   "src/tools/tidy",
   "src/tools/tier-check",
@@ -109,6 +109,18 @@ strip = true
 debug = 0
 strip = true
 
+# Bigint libraries are slow without optimization, speed up testing
+[profile.dev.package.test-float-parse]
+opt-level = 3
+
+# Speed up the binary as much as possible
+[profile.release.package.test-float-parse]
+opt-level = 3
+codegen-units = 1
+# FIXME: LTO cannot be enabled for binaries in a workspace
+# <https://github.com/rust-lang/cargo/issues/9330>
+# lto = true
+
 [patch.crates-io]
 # See comments in `library/rustc-std-workspace-core/README.md` for what's going on
 # here
diff --git a/LICENSES/CC-BY-3.0.txt b/LICENSES/CC-BY-3.0.txt
deleted file mode 100644
index bd32fa8477b..00000000000
--- a/LICENSES/CC-BY-3.0.txt
+++ /dev/null
@@ -1,319 +0,0 @@
-Creative Commons Legal Code
-
-Attribution 3.0 Unported
-
-    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
-    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
-    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
-    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
-    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
-    DAMAGES RESULTING FROM ITS USE.
-
-License
-
-THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
-COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
-COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
-AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
-
-BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
-TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
-BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
-CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
-CONDITIONS.
-
-1. Definitions
-
- a. "Adaptation" means a work based upon the Work, or upon the Work and
-    other pre-existing works, such as a translation, adaptation,
-    derivative work, arrangement of music or other alterations of a
-    literary or artistic work, or phonogram or performance and includes
-    cinematographic adaptations or any other form in which the Work may be
-    recast, transformed, or adapted including in any form recognizably
-    derived from the original, except that a work that constitutes a
-    Collection will not be considered an Adaptation for the purpose of
-    this License. For the avoidance of doubt, where the Work is a musical
-    work, performance or phonogram, the synchronization of the Work in
-    timed-relation with a moving image ("synching") will be considered an
-    Adaptation for the purpose of this License.
- b. "Collection" means a collection of literary or artistic works, such as
-    encyclopedias and anthologies, or performances, phonograms or
-    broadcasts, or other works or subject matter other than works listed
-    in Section 1(f) below, which, by reason of the selection and
-    arrangement of their contents, constitute intellectual creations, in
-    which the Work is included in its entirety in unmodified form along
-    with one or more other contributions, each constituting separate and
-    independent works in themselves, which together are assembled into a
-    collective whole. A work that constitutes a Collection will not be
-    considered an Adaptation (as defined above) for the purposes of this
-    License.
- c. "Distribute" means to make available to the public the original and
-    copies of the Work or Adaptation, as appropriate, through sale or
-    other transfer of ownership.
- d. "Licensor" means the individual, individuals, entity or entities that
-    offer(s) the Work under the terms of this License.
- e. "Original Author" means, in the case of a literary or artistic work,
-    the individual, individuals, entity or entities who created the Work
-    or if no individual or entity can be identified, the publisher; and in
-    addition (i) in the case of a performance the actors, singers,
-    musicians, dancers, and other persons who act, sing, deliver, declaim,
-    play in, interpret or otherwise perform literary or artistic works or
-    expressions of folklore; (ii) in the case of a phonogram the producer
-    being the person or legal entity who first fixes the sounds of a
-    performance or other sounds; and, (iii) in the case of broadcasts, the
-    organization that transmits the broadcast.
- f. "Work" means the literary and/or artistic work offered under the terms
-    of this License including without limitation any production in the
-    literary, scientific and artistic domain, whatever may be the mode or
-    form of its expression including digital form, such as a book,
-    pamphlet and other writing; a lecture, address, sermon or other work
-    of the same nature; a dramatic or dramatico-musical work; a
-    choreographic work or entertainment in dumb show; a musical
-    composition with or without words; a cinematographic work to which are
-    assimilated works expressed by a process analogous to cinematography;
-    a work of drawing, painting, architecture, sculpture, engraving or
-    lithography; a photographic work to which are assimilated works
-    expressed by a process analogous to photography; a work of applied
-    art; an illustration, map, plan, sketch or three-dimensional work
-    relative to geography, topography, architecture or science; a
-    performance; a broadcast; a phonogram; a compilation of data to the
-    extent it is protected as a copyrightable work; or a work performed by
-    a variety or circus performer to the extent it is not otherwise
-    considered a literary or artistic work.
- g. "You" means an individual or entity exercising rights under this
-    License who has not previously violated the terms of this License with
-    respect to the Work, or who has received express permission from the
-    Licensor to exercise rights under this License despite a previous
-    violation.
- h. "Publicly Perform" means to perform public recitations of the Work and
-    to communicate to the public those public recitations, by any means or
-    process, including by wire or wireless means or public digital
-    performances; to make available to the public Works in such a way that
-    members of the public may access these Works from a place and at a
-    place individually chosen by them; to perform the Work to the public
-    by any means or process and the communication to the public of the
-    performances of the Work, including by public digital performance; to
-    broadcast and rebroadcast the Work by any means including signs,
-    sounds or images.
- i. "Reproduce" means to make copies of the Work by any means including
-    without limitation by sound or visual recordings and the right of
-    fixation and reproducing fixations of the Work, including storage of a
-    protected performance or phonogram in digital form or other electronic
-    medium.
-
-2. Fair Dealing Rights. Nothing in this License is intended to reduce,
-limit, or restrict any uses free from copyright or rights arising from
-limitations or exceptions that are provided for in connection with the
-copyright protection under copyright law or other applicable laws.
-
-3. License Grant. Subject to the terms and conditions of this License,
-Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
-perpetual (for the duration of the applicable copyright) license to
-exercise the rights in the Work as stated below:
-
- a. to Reproduce the Work, to incorporate the Work into one or more
-    Collections, and to Reproduce the Work as incorporated in the
-    Collections;
- b. to create and Reproduce Adaptations provided that any such Adaptation,
-    including any translation in any medium, takes reasonable steps to
-    clearly label, demarcate or otherwise identify that changes were made
-    to the original Work. For example, a translation could be marked "The
-    original work was translated from English to Spanish," or a
-    modification could indicate "The original work has been modified.";
- c. to Distribute and Publicly Perform the Work including as incorporated
-    in Collections; and,
- d. to Distribute and Publicly Perform Adaptations.
- e. For the avoidance of doubt:
-
-     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
-        which the right to collect royalties through any statutory or
-        compulsory licensing scheme cannot be waived, the Licensor
-        reserves the exclusive right to collect such royalties for any
-        exercise by You of the rights granted under this License;
-    ii. Waivable Compulsory License Schemes. In those jurisdictions in
-        which the right to collect royalties through any statutory or
-        compulsory licensing scheme can be waived, the Licensor waives the
-        exclusive right to collect such royalties for any exercise by You
-        of the rights granted under this License; and,
-   iii. Voluntary License Schemes. The Licensor waives the right to
-        collect royalties, whether individually or, in the event that the
-        Licensor is a member of a collecting society that administers
-        voluntary licensing schemes, via that society, from any exercise
-        by You of the rights granted under this License.
-
-The above rights may be exercised in all media and formats whether now
-known or hereafter devised. The above rights include the right to make
-such modifications as are technically necessary to exercise the rights in
-other media and formats. Subject to Section 8(f), all rights not expressly
-granted by Licensor are hereby reserved.
-
-4. Restrictions. The license granted in Section 3 above is expressly made
-subject to and limited by the following restrictions:
-
- a. You may Distribute or Publicly Perform the Work only under the terms
-    of this License. You must include a copy of, or the Uniform Resource
-    Identifier (URI) for, this License with every copy of the Work You
-    Distribute or Publicly Perform. You may not offer or impose any terms
-    on the Work that restrict the terms of this License or the ability of
-    the recipient of the Work to exercise the rights granted to that
-    recipient under the terms of the License. You may not sublicense the
-    Work. You must keep intact all notices that refer to this License and
-    to the disclaimer of warranties with every copy of the Work You
-    Distribute or Publicly Perform. When You Distribute or Publicly
-    Perform the Work, You may not impose any effective technological
-    measures on the Work that restrict the ability of a recipient of the
-    Work from You to exercise the rights granted to that recipient under
-    the terms of the License. This Section 4(a) applies to the Work as
-    incorporated in a Collection, but this does not require the Collection
-    apart from the Work itself to be made subject to the terms of this
-    License. If You create a Collection, upon notice from any Licensor You
-    must, to the extent practicable, remove from the Collection any credit
-    as required by Section 4(b), as requested. If You create an
-    Adaptation, upon notice from any Licensor You must, to the extent
-    practicable, remove from the Adaptation any credit as required by
-    Section 4(b), as requested.
- b. If You Distribute, or Publicly Perform the Work or any Adaptations or
-    Collections, You must, unless a request has been made pursuant to
-    Section 4(a), keep intact all copyright notices for the Work and
-    provide, reasonable to the medium or means You are utilizing: (i) the
-    name of the Original Author (or pseudonym, if applicable) if supplied,
-    and/or if the Original Author and/or Licensor designate another party
-    or parties (e.g., a sponsor institute, publishing entity, journal) for
-    attribution ("Attribution Parties") in Licensor's copyright notice,
-    terms of service or by other reasonable means, the name of such party
-    or parties; (ii) the title of the Work if supplied; (iii) to the
-    extent reasonably practicable, the URI, if any, that Licensor
-    specifies to be associated with the Work, unless such URI does not
-    refer to the copyright notice or licensing information for the Work;
-    and (iv) , consistent with Section 3(b), in the case of an Adaptation,
-    a credit identifying the use of the Work in the Adaptation (e.g.,
-    "French translation of the Work by Original Author," or "Screenplay
-    based on original Work by Original Author"). The credit required by
-    this Section 4 (b) may be implemented in any reasonable manner;
-    provided, however, that in the case of a Adaptation or Collection, at
-    a minimum such credit will appear, if a credit for all contributing
-    authors of the Adaptation or Collection appears, then as part of these
-    credits and in a manner at least as prominent as the credits for the
-    other contributing authors. For the avoidance of doubt, You may only
-    use the credit required by this Section for the purpose of attribution
-    in the manner set out above and, by exercising Your rights under this
-    License, You may not implicitly or explicitly assert or imply any
-    connection with, sponsorship or endorsement by the Original Author,
-    Licensor and/or Attribution Parties, as appropriate, of You or Your
-    use of the Work, without the separate, express prior written
-    permission of the Original Author, Licensor and/or Attribution
-    Parties.
- c. Except as otherwise agreed in writing by the Licensor or as may be
-    otherwise permitted by applicable law, if You Reproduce, Distribute or
-    Publicly Perform the Work either by itself or as part of any
-    Adaptations or Collections, You must not distort, mutilate, modify or
-    take other derogatory action in relation to the Work which would be
-    prejudicial to the Original Author's honor or reputation. Licensor
-    agrees that in those jurisdictions (e.g. Japan), in which any exercise
-    of the right granted in Section 3(b) of this License (the right to
-    make Adaptations) would be deemed to be a distortion, mutilation,
-    modification or other derogatory action prejudicial to the Original
-    Author's honor and reputation, the Licensor will waive or not assert,
-    as appropriate, this Section, to the fullest extent permitted by the
-    applicable national law, to enable You to reasonably exercise Your
-    right under Section 3(b) of this License (right to make Adaptations)
-    but not otherwise.
-
-5. Representations, Warranties and Disclaimer
-
-UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
-OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
-KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
-INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
-FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
-LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
-WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
-OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
-
-6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
-LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
-ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
-ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
-BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-7. Termination
-
- a. This License and the rights granted hereunder will terminate
-    automatically upon any breach by You of the terms of this License.
-    Individuals or entities who have received Adaptations or Collections
-    from You under this License, however, will not have their licenses
-    terminated provided such individuals or entities remain in full
-    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
-    survive any termination of this License.
- b. Subject to the above terms and conditions, the license granted here is
-    perpetual (for the duration of the applicable copyright in the Work).
-    Notwithstanding the above, Licensor reserves the right to release the
-    Work under different license terms or to stop distributing the Work at
-    any time; provided, however that any such election will not serve to
-    withdraw this License (or any other license that has been, or is
-    required to be, granted under the terms of this License), and this
-    License will continue in full force and effect unless terminated as
-    stated above.
-
-8. Miscellaneous
-
- a. Each time You Distribute or Publicly Perform the Work or a Collection,
-    the Licensor offers to the recipient a license to the Work on the same
-    terms and conditions as the license granted to You under this License.
- b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
-    offers to the recipient a license to the original Work on the same
-    terms and conditions as the license granted to You under this License.
- c. If any provision of this License is invalid or unenforceable under
-    applicable law, it shall not affect the validity or enforceability of
-    the remainder of the terms of this License, and without further action
-    by the parties to this agreement, such provision shall be reformed to
-    the minimum extent necessary to make such provision valid and
-    enforceable.
- d. No term or provision of this License shall be deemed waived and no
-    breach consented to unless such waiver or consent shall be in writing
-    and signed by the party to be charged with such waiver or consent.
- e. This License constitutes the entire agreement between the parties with
-    respect to the Work licensed here. There are no understandings,
-    agreements or representations with respect to the Work not specified
-    here. Licensor shall not be bound by any additional provisions that
-    may appear in any communication from You. This License may not be
-    modified without the mutual written agreement of the Licensor and You.
- f. The rights granted under, and the subject matter referenced, in this
-    License were drafted utilizing the terminology of the Berne Convention
-    for the Protection of Literary and Artistic Works (as amended on
-    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
-    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
-    and the Universal Copyright Convention (as revised on July 24, 1971).
-    These rights and subject matter take effect in the relevant
-    jurisdiction in which the License terms are sought to be enforced
-    according to the corresponding provisions of the implementation of
-    those treaty provisions in the applicable national law. If the
-    standard suite of rights granted under applicable copyright law
-    includes additional rights not granted under this License, such
-    additional rights are deemed to be included in the License; this
-    License is not intended to restrict the license of any rights under
-    applicable law.
-
-
-Creative Commons Notice
-
-    Creative Commons is not a party to this License, and makes no warranty
-    whatsoever in connection with the Work. Creative Commons will not be
-    liable to You or any party on any legal theory for any damages
-    whatsoever, including without limitation any general, special,
-    incidental or consequential damages arising in connection to this
-    license. Notwithstanding the foregoing two (2) sentences, if Creative
-    Commons has expressly identified itself as the Licensor hereunder, it
-    shall have all rights and obligations of Licensor.
-
-    Except for the limited purpose of indicating to the public that the
-    Work is licensed under the CCPL, Creative Commons does not authorize
-    the use by either party of the trademark "Creative Commons" or any
-    related trademark or logo of Creative Commons without the prior
-    written consent of Creative Commons. Any permitted use will be in
-    compliance with Creative Commons' then-current trademark usage
-    guidelines, as may be published on its website or otherwise made
-    available upon request from time to time. For the avoidance of doubt,
-    this trademark restriction does not form part of this License.
-
-    Creative Commons may be contacted at https://creativecommons.org/.
\ No newline at end of file
diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt
deleted file mode 100644
index 0e259d42c99..00000000000
--- a/LICENSES/CC0-1.0.txt
+++ /dev/null
@@ -1,121 +0,0 @@
-Creative Commons Legal Code
-
-CC0 1.0 Universal
-
-    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
-    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
-    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
-    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
-    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
-    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
-    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
-    HEREUNDER.
-
-Statement of Purpose
-
-The laws of most jurisdictions throughout the world automatically confer
-exclusive Copyright and Related Rights (defined below) upon the creator
-and subsequent owner(s) (each and all, an "owner") of an original work of
-authorship and/or a database (each, a "Work").
-
-Certain owners wish to permanently relinquish those rights to a Work for
-the purpose of contributing to a commons of creative, cultural and
-scientific works ("Commons") that the public can reliably and without fear
-of later claims of infringement build upon, modify, incorporate in other
-works, reuse and redistribute as freely as possible in any form whatsoever
-and for any purposes, including without limitation commercial purposes.
-These owners may contribute to the Commons to promote the ideal of a free
-culture and the further production of creative, cultural and scientific
-works, or to gain reputation or greater distribution for their Work in
-part through the use and efforts of others.
-
-For these and/or other purposes and motivations, and without any
-expectation of additional consideration or compensation, the person
-associating CC0 with a Work (the "Affirmer"), to the extent that he or she
-is an owner of Copyright and Related Rights in the Work, voluntarily
-elects to apply CC0 to the Work and publicly distribute the Work under its
-terms, with knowledge of his or her Copyright and Related Rights in the
-Work and the meaning and intended legal effect of CC0 on those rights.
-
-1. Copyright and Related Rights. A Work made available under CC0 may be
-protected by copyright and related or neighboring rights ("Copyright and
-Related Rights"). Copyright and Related Rights include, but are not
-limited to, the following:
-
-  i. the right to reproduce, adapt, distribute, perform, display,
-     communicate, and translate a Work;
- ii. moral rights retained by the original author(s) and/or performer(s);
-iii. publicity and privacy rights pertaining to a person's image or
-     likeness depicted in a Work;
- iv. rights protecting against unfair competition in regards to a Work,
-     subject to the limitations in paragraph 4(a), below;
-  v. rights protecting the extraction, dissemination, use and reuse of data
-     in a Work;
- vi. database rights (such as those arising under Directive 96/9/EC of the
-     European Parliament and of the Council of 11 March 1996 on the legal
-     protection of databases, and under any national implementation
-     thereof, including any amended or successor version of such
-     directive); and
-vii. other similar, equivalent or corresponding rights throughout the
-     world based on applicable law or treaty, and any national
-     implementations thereof.
-
-2. Waiver. To the greatest extent permitted by, but not in contravention
-of, applicable law, Affirmer hereby overtly, fully, permanently,
-irrevocably and unconditionally waives, abandons, and surrenders all of
-Affirmer's Copyright and Related Rights and associated claims and causes
-of action, whether now known or unknown (including existing as well as
-future claims and causes of action), in the Work (i) in all territories
-worldwide, (ii) for the maximum duration provided by applicable law or
-treaty (including future time extensions), (iii) in any current or future
-medium and for any number of copies, and (iv) for any purpose whatsoever,
-including without limitation commercial, advertising or promotional
-purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
-member of the public at large and to the detriment of Affirmer's heirs and
-successors, fully intending that such Waiver shall not be subject to
-revocation, rescission, cancellation, termination, or any other legal or
-equitable action to disrupt the quiet enjoyment of the Work by the public
-as contemplated by Affirmer's express Statement of Purpose.
-
-3. Public License Fallback. Should any part of the Waiver for any reason
-be judged legally invalid or ineffective under applicable law, then the
-Waiver shall be preserved to the maximum extent permitted taking into
-account Affirmer's express Statement of Purpose. In addition, to the
-extent the Waiver is so judged Affirmer hereby grants to each affected
-person a royalty-free, non transferable, non sublicensable, non exclusive,
-irrevocable and unconditional license to exercise Affirmer's Copyright and
-Related Rights in the Work (i) in all territories worldwide, (ii) for the
-maximum duration provided by applicable law or treaty (including future
-time extensions), (iii) in any current or future medium and for any number
-of copies, and (iv) for any purpose whatsoever, including without
-limitation commercial, advertising or promotional purposes (the
-"License"). The License shall be deemed effective as of the date CC0 was
-applied by Affirmer to the Work. Should any part of the License for any
-reason be judged legally invalid or ineffective under applicable law, such
-partial invalidity or ineffectiveness shall not invalidate the remainder
-of the License, and in such case Affirmer hereby affirms that he or she
-will not (i) exercise any of his or her remaining Copyright and Related
-Rights in the Work or (ii) assert any associated claims and causes of
-action with respect to the Work, in either case contrary to Affirmer's
-express Statement of Purpose.
-
-4. Limitations and Disclaimers.
-
- a. No trademark or patent rights held by Affirmer are waived, abandoned,
-    surrendered, licensed or otherwise affected by this document.
- b. Affirmer offers the Work as-is and makes no representations or
-    warranties of any kind concerning the Work, express, implied,
-    statutory or otherwise, including without limitation warranties of
-    title, merchantability, fitness for a particular purpose, non
-    infringement, or the absence of latent or other defects, accuracy, or
-    the present or absence of errors, whether or not discoverable, all to
-    the greatest extent permissible under applicable law.
- c. Affirmer disclaims responsibility for clearing rights of other persons
-    that may apply to the Work or any use thereof, including without
-    limitation any person's Copyright and Related Rights in the Work.
-    Further, Affirmer disclaims responsibility for obtaining any necessary
-    consents, permissions or other rights required for any use of the
-    Work.
- d. Affirmer understands and acknowledges that Creative Commons is not a
-    party to this document and has no duty or obligation with respect to
-    this CC0 or use of the Work.
diff --git a/REUSE.toml b/REUSE.toml
new file mode 100644
index 00000000000..1a30d8016c9
--- /dev/null
+++ b/REUSE.toml
@@ -0,0 +1,170 @@
+version = 1
+
+# Reuse annotations file.
+#
+# This file controls how reuse-tool finds copyright and license notices within
+# source files. As the tool has a habit of picking up random uses of the word
+# 'Copyright' within source code, and because it will complain that other files
+# do not contain any specific copyright and license notifications, we usually
+# just set a blanket license and copyright notice for a whole sub-tree at a
+# time.
+#
+# See https://reuse.software and https://github.com/fsfe/reuse-tool for more
+# details. We currently use reuse-tool version 4.0.3.
+
+[[annotations]]
+path = [
+    "compiler/**",
+    "library/**",
+    "tests/**",
+    "src/**",
+    ".github/**",
+    "Cargo.lock",
+    "Cargo.toml",
+    "CODE_OF_CONDUCT.md",
+    "config.example.toml",
+    "configure",
+    "CONTRIBUTING.md",
+    "COPYRIGHT",
+    "INSTALL.md",
+    "LICENSE-APACHE",
+    "LICENSE-MIT",
+    "README.md",
+    "RELEASES.md",
+    "REUSE.toml",
+    "rustfmt.toml",
+    "rust-bors.toml",
+    "triagebot.toml",
+    "x",
+    "x.ps1",
+    "x.py",
+    ".clang-format",
+    ".editorconfig",
+    ".git-blame-ignore-revs",
+    ".gitattributes",
+    ".gitignore",
+    ".gitmodules",
+    ".mailmap",
+    ".ignore",
+]
+precedence = "override"
+SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)"
+SPDX-License-Identifier = "MIT or Apache-2.0"
+
+[[annotations]]
+path = "compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2003-2019 University of Illinois at Urbana-Champaign.",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "Apache-2.0 WITH LLVM-exception AND (Apache-2.0 OR MIT)"
+
+[[annotations]]
+path = "library/core/src/unicode/unicode_data.rs"
+precedence = "override"
+SPDX-FileCopyrightText = "1991-2022 Unicode, Inc. All rights reserved."
+SPDX-License-Identifier = "Unicode-DFS-2016"
+
+[[annotations]]
+path = "library/std/src/sync/mpmc/**"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2019 The Crossbeam Project Developers",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "MIT OR Apache-2.0"
+
+[[annotations]]
+path = "library/std/src/sys/sync/mutex/fuchsia.rs"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2016 The Fuchsia Authors",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "BSD-2-Clause AND (MIT OR Apache-2.0)"
+
+[[annotations]]
+path = "src/test/rustdoc/auxiliary/enum-primitive.rs"
+precedence = "override"
+SPDX-FileCopyrightText = "2015 Anders Kaseorg <andersk@mit.edu>"
+SPDX-License-Identifier = "MIT"
+
+[[annotations]]
+path = "src/librustdoc/html/static/fonts/FiraSans**"
+precedence = "override"
+SPDX-FileCopyrightText = ["2014, Mozilla Foundation", "2014, Telefonica S.A."]
+SPDX-License-Identifier = "OFL-1.1"
+
+[[annotations]]
+path = "src/librustdoc/html/static/fonts/NanumBarun**"
+precedence = "override"
+SPDX-FileCopyrightText = "2010 NAVER Corporation"
+SPDX-License-Identifier = "OFL-1.1"
+
+[[annotations]]
+path = [
+    "src/librustdoc/html/static/fonts/SourceCodePro**",
+    "src/librustdoc/html/static/fonts/SourceSerif4**",
+]
+precedence = "override"
+SPDX-FileCopyrightText = "2010, 2012, 2014-2023, Adobe Systems Incorporated"
+SPDX-License-Identifier = "OFL-1.1"
+
+[[annotations]]
+path = "src/librustdoc/html/static/css/normalize.css"
+precedence = "override"
+SPDX-FileCopyrightText = "Nicolas Gallagher and Jonathan Neal"
+SPDX-License-Identifier = "MIT"
+
+[[annotations]]
+path = "src/librustdoc/html/static/css/rustdoc.css"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2016 Ike Ku, Jessica Stokes and Leon Guan",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "MIT OR Apache-2.0"
+
+[[annotations]]
+path = "src/doc/rustc-dev-guide/mermaid.min.js"
+precedence = "override"
+SPDX-FileCopyrightText = "2014-2021 Knut Sveidqvist"
+SPDX-License-Identifier = "MIT"
+
+[[annotations]]
+path = "library/backtrace/**"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2014 Alex Crichton",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "MIT OR Apache-2.0"
+
+[[annotations]]
+path = "src/doc/embedded-book/**"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "Rust on Embedded Devices Working Group",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "MIT OR Apache-2.0 OR CC-BY-SA-4.0"
+
+[[annotations]]
+path = "src/doc/rust-by-example/**"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2014 Jorge Aparicio",
+    "The Rust Project Developers (see https://thanks.rust-lang.org)",
+]
+SPDX-License-Identifier = "MIT OR Apache-2.0"
+
+[[annotations]]
+path = "src/llvm-project/**"
+precedence = "override"
+SPDX-FileCopyrightText = [
+    "2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
+    "2010 Apple Inc",
+    "2003-2019 University of Illinois at Urbana-Champaign.",
+]
+SPDX-License-Identifier = "NCSA AND Apache-2.0 WITH LLVM-exception"
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 02bdff96aa6..ca0b7f2ac3a 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -120,6 +120,9 @@ ast_passes_fn_without_body =
 ast_passes_forbidden_bound =
     bounds cannot be used in this context
 
+ast_passes_forbidden_const_param =
+    late-bound const parameters cannot be used currently
+
 ast_passes_forbidden_default =
     `default` is only allowed on items in trait impls
     .label = `default` because of this
@@ -269,6 +272,9 @@ ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
     .negative = negative because of this
     .unsafe = unsafe because of this
 
+ast_passes_unsafe_static =
+    static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+
 ast_passes_visibility_not_permitted =
     visibility qualifiers are not permitted here
     .enum_variant = enum variants and their fields always share the visibility of the enum they are in
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 83249dea82a..34aac6e4473 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -438,6 +438,11 @@ impl<'a> AstValidator<'a> {
         }
     }
 
+    /// This ensures that items can only be `unsafe` (or unmarked) outside of extern
+    /// blocks.
+    ///
+    /// This additionally ensures that within extern blocks, items can only be
+    /// `safe`/`unsafe` inside of a `unsafe`-adorned extern block.
     fn check_item_safety(&self, span: Span, safety: Safety) {
         match self.extern_mod_safety {
             Some(extern_safety) => {
@@ -1177,6 +1182,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::Static(box StaticItem { expr, safety, .. }) => {
                 self.check_item_safety(item.span, *safety);
+                if matches!(safety, Safety::Unsafe(_)) {
+                    self.dcx().emit_err(errors::UnsafeStatic { span: item.span });
+                }
 
                 if expr.is_none() {
                     self.dcx().emit_err(errors::StaticWithoutBody {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 460da254653..215ccd2ab4d 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -70,6 +70,13 @@ pub struct ForbiddenBound {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_const_param)]
+pub struct ForbiddenConstParam {
+    #[primary_span]
+    pub const_param_spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_fn_param_too_many)]
 pub struct FnParamTooMany {
     #[primary_span]
@@ -225,6 +232,13 @@ pub struct InvalidSafetyOnBareFn {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_unsafe_static)]
+pub struct UnsafeStatic {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_bound_in_context)]
 pub struct BoundInContext<'a> {
     #[primary_span]
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 2178b65727d..e91dfb27766 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -162,6 +162,22 @@ impl<'a> PostExpansionVisitor<'a> {
             crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
         );
 
+        // FIXME(non_lifetime_binders): Const bound params are pretty broken.
+        // Let's keep users from using this feature accidentally.
+        if self.features.non_lifetime_binders {
+            let const_param_spans: Vec<_> = params
+                .iter()
+                .filter_map(|param| match param.kind {
+                    ast::GenericParamKind::Const { .. } => Some(param.ident.span),
+                    _ => None,
+                })
+                .collect();
+
+            if !const_param_spans.is_empty() {
+                self.sess.dcx().emit_err(errors::ForbiddenConstParam { const_param_spans });
+            }
+        }
+
         for param in params {
             if !param.bounds.is_empty() {
                 let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 8eb44458137..80deea14685 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,7 +1,9 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 
+use rustc_errors::Applicability;
 use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
+use rustc_hir as hir;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -382,13 +384,35 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
         yield_span: Span,
     ) -> Diag<'infcx> {
         let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
-        struct_span_code_err!(
+        let mut diag = struct_span_code_err!(
             self.dcx(),
             span,
             E0626,
             "borrow may still be in use when {coroutine_kind:#} yields",
-        )
-        .with_span_label(yield_span, "possible yield occurs here")
+        );
+        diag.span_label(
+            self.infcx.tcx.def_span(self.body.source.def_id()),
+            format!("within this {coroutine_kind:#}"),
+        );
+        diag.span_label(yield_span, "possible yield occurs here");
+        if matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) {
+            let hir::Closure { capture_clause, fn_decl_span, .. } = self
+                .infcx
+                .tcx
+                .hir_node_by_def_id(self.body.source.def_id().expect_local())
+                .expect_closure();
+            let span = match capture_clause {
+                rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
+                rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
+            };
+            diag.span_suggestion_verbose(
+                span,
+                "add `static` to mark this coroutine as unmovable",
+                "static ",
+                Applicability::MaybeIncorrect,
+            );
+        }
+        diag
     }
 
     pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 4cd0d9cb294..cbee01f2e2d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -1,6 +1,5 @@
 use rustc_errors::Diag;
 use rustc_hir::def_id::LocalDefId;
-use rustc_infer::error_reporting::infer::nice_region_error::NiceRegionError;
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::region_constraints::Constraint;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
@@ -14,6 +13,8 @@ use rustc_middle::ty::RegionVid;
 use rustc_middle::ty::UniverseIndex;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
+use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::query::type_op;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f7e4bba3712..b147567001d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -35,8 +35,8 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, Symbol};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
 use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
 use std::iter;
@@ -456,10 +456,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 if let Some(def_id) = def_id
                     && self.infcx.tcx.def_kind(def_id).is_fn_like()
                     && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
-                    && let ty::Param(_) =
-                        self.infcx.tcx.fn_sig(def_id).skip_binder().skip_binder().inputs()
-                            [pos + offset]
-                            .kind()
+                    && let Some(arg) = self
+                        .infcx
+                        .tcx
+                        .fn_sig(def_id)
+                        .skip_binder()
+                        .skip_binder()
+                        .inputs()
+                        .get(pos + offset)
+                    && let ty::Param(_) = arg.kind()
                 {
                     let place = &self.move_data.move_paths[mpi].place;
                     let ty = place.ty(self.body, self.infcx.tcx).ty;
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index f97459d16ba..d505d9c004e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -27,7 +27,7 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Spanned;
 use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{
     type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 26b0d23b166..a7bf6d636c1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -16,7 +16,7 @@ use rustc_middle::{
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{sym, BytePos, DesugaringKind, Span};
 use rustc_target::abi::FieldIdx;
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits;
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 6cf797b4761..6b7bd7dc0d8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -10,11 +10,6 @@ use rustc_hir::GenericBound::Trait;
 use rustc_hir::QPath::Resolved;
 use rustc_hir::WherePredicate::BoundPredicate;
 use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
-use rustc_infer::error_reporting::infer::nice_region_error::{
-    self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
-    HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
-};
-use rustc_infer::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
 use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
 use rustc_middle::bug;
 use rustc_middle::hir::place::PlaceBase;
@@ -25,6 +20,12 @@ use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_middle::ty::{Region, TyCtxt};
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
+use rustc_trait_selection::error_reporting::infer::nice_region_error::{
+    self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
+    HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
+};
+use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 356416d1a75..6443c5e92e8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -14,6 +14,7 @@ use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 
 use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
 
@@ -457,8 +458,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
     ) -> RegionNameHighlight {
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
-        let type_name =
-            self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name;
+        let type_name = self
+            .infcx
+            .err_ctxt()
+            .extract_inference_diagnostics_data(ty.into(), Some(highlight))
+            .name;
 
         debug!(
             "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -872,8 +876,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
 
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
-        let type_name =
-            self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name;
+        let type_name = self
+            .infcx
+            .err_ctxt()
+            .extract_inference_diagnostics_data(yield_ty.into(), Some(highlight))
+            .name;
 
         let yield_span = match tcx.hir_node(self.mir_hir_id()) {
             hir::Node::Expr(hir::Expr {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index c0e91ce32e3..cf28ba224d6 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_span::Span;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 
 use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 431a704687d..e4c2e0fced7 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -11,7 +11,7 @@ use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
 use rustc_span::{ErrorGuaranteed, Span};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::solve::deeply_normalize;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index 58928815e89..bffd5672b9b 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -4,6 +4,7 @@ use crate::errors;
 use rustc_ast::attr::mk_attr;
 use rustc_ast::token;
 use rustc_ast::{self as ast, AttrItem, AttrStyle};
+use rustc_parse::parser::ForceCollect;
 use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
 use rustc_session::parse::ParseSess;
 use rustc_span::FileName;
@@ -17,13 +18,14 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
         ));
 
         let start_span = parser.token.span;
-        let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
-            Ok(ai) => ai,
-            Err(err) => {
-                err.emit();
-                continue;
-            }
-        };
+        let AttrItem { unsafety, path, args, tokens: _ } =
+            match parser.parse_attr_item(ForceCollect::No) {
+                Ok(ai) => ai,
+                Err(err) => {
+                    err.emit();
+                    continue;
+                }
+            };
         let end_span = parser.token.span;
         if parser.token != token::Eof {
             psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 97e2344ff30..f6b54335829 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -38,7 +38,44 @@ pub(crate) fn expand_deriving_const_param_ty(
 ) {
     let trait_def = TraitDef {
         span,
-        path: path_std!(marker::ConstParamTy),
+        path: path_std!(marker::ConstParamTy_),
+        skip_path_as_bound: false,
+        needs_copy_as_bound_if_packed: false,
+        additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
+        supports_unions: false,
+        methods: Vec::new(),
+        associated_types: Vec::new(),
+        is_const,
+    };
+
+    trait_def.expand(cx, mitem, item, push);
+
+    let trait_def = TraitDef {
+        span,
+        path: path_std!(marker::UnsizedConstParamTy),
+        skip_path_as_bound: false,
+        needs_copy_as_bound_if_packed: false,
+        additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
+        supports_unions: false,
+        methods: Vec::new(),
+        associated_types: Vec::new(),
+        is_const,
+    };
+
+    trait_def.expand(cx, mitem, item, push);
+}
+
+pub(crate) fn expand_deriving_unsized_const_param_ty(
+    cx: &ExtCtxt<'_>,
+    span: Span,
+    mitem: &MetaItem,
+    item: &Annotatable,
+    push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
+) {
+    let trait_def = TraitDef {
+        span,
+        path: path_std!(marker::UnsizedConstParamTy),
         skip_path_as_bound: false,
         needs_copy_as_bound_if_packed: false,
         additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index f8d93666145..c77ff9eb13c 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -118,6 +118,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         Clone: clone::expand_deriving_clone,
         Copy: bounds::expand_deriving_copy,
         ConstParamTy: bounds::expand_deriving_const_param_ty,
+        UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
         Debug: debug::expand_deriving_debug,
         Default: default::expand_deriving_default,
         Eq: eq::expand_deriving_eq,
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index eb21e027dd0..3b3c86a1bd1 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
 |FreeBSD|✅[^no-rustup]|❓|❓|❓|
 |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
 |Other unixes|❓|❓|❓|❓|
-|macOS|✅|✅[^no-rustup]|N/A|N/A|
+|macOS|✅|✅|N/A|N/A|
 |Windows|✅[^no-rustup]|❌|N/A|N/A|
 
 ✅: Fully supported and tested
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index fa0de6f9de5..24cf3f061a5 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -10,12 +10,12 @@ use std::mem;
 use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
 use cranelift_codegen::isa::CallConv;
 use cranelift_module::ModuleError;
+use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::TypeVisitableExt;
-use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_target::abi::call::{Conv, FnAbi, PassMode};
@@ -505,7 +505,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
                 let nop_inst = fx.bcx.ins().nop();
                 fx.add_comment(
                     nop_inst,
-                    format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]),
+                    format!("virtual call; self arg pass mode: {:?}", fn_abi.args[0]),
                 );
             }
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 5adbbb09ac8..9bc7b57c537 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -5,13 +5,13 @@ use cranelift_codegen::CodegenError;
 use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_module::ModuleError;
 use rustc_ast::InlineAsmOptions;
+use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_index::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::TypeVisitableExt;
-use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 
 use crate::constant::ConstantCx;
 use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 192e6c91ea3..8d3d5ac98e1 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -24,7 +24,6 @@ extern crate rustc_hir;
 extern crate rustc_incremental;
 extern crate rustc_index;
 extern crate rustc_metadata;
-extern crate rustc_monomorphize;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index e7669470026..3877460fcdb 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -271,6 +271,17 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
     Some(sspattr.create_attr(cx.llcx))
 }
 
+fn backchain_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
+    if cx.sess().target.arch != "s390x" {
+        return None;
+    }
+
+    let requested_features = cx.sess().opts.cg.target_feature.split(',');
+    let found_positive = requested_features.clone().any(|r| r == "+backchain");
+
+    if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None }
+}
+
 pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute {
     let target_cpu = llvm_util::target_cpu(cx.tcx.sess);
     llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu)
@@ -447,6 +458,9 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     if let Some(align) = codegen_fn_attrs.alignment {
         llvm::set_alignment(llfn, align);
     }
+    if let Some(backchain) = backchain_attr(cx) {
+        to_add.push(backchain);
+    }
     to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
     to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index a2314f4850c..164d1681a36 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
             }
 
             // Wasm statics with custom link sections get special treatment as they
-            // go into custom sections of the wasm executable.
-            if self.tcx.sess.target.is_like_wasm {
+            // go into custom sections of the wasm executable. The exception to this
+            // is the `.init_array` section which are treated specially by the wasm linker.
+            if self.tcx.sess.target.is_like_wasm
+                && attrs
+                    .link_section
+                    .map(|link_section| !link_section.as_str().starts_with(".init_array"))
+                    .unwrap_or(true)
+            {
                 if let Some(section) = attrs.link_section {
                     let section = llvm::LLVMMDStringInContext2(
                         self.llcx,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 98dc8ac86d2..4d56d1d3b1a 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -14,7 +14,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
-use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
+use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
 
 use std::ffi::{c_char, c_void, CStr, CString};
 use std::fmt::Write;
@@ -321,6 +321,10 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
             }
         })
         .filter(|feature| {
+            // skip checking special features, as LLVM may not understands them
+            if RUSTC_SPECIAL_FEATURES.contains(feature) {
+                return true;
+            }
             // check that all features in a given smallvec are enabled
             for llvm_feature in to_llvm_features(sess, feature) {
                 let cstr = SmallCStr::new(llvm_feature);
@@ -546,6 +550,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
 
     // -Ctarget-features
     let supported_features = sess.target.supported_target_features();
+    let (llvm_major, _, _) = get_version();
     let mut featsmap = FxHashMap::default();
     let feats = sess
         .opts
@@ -604,6 +609,13 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
             if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
                 return None;
             }
+
+            // if the target-feature is "backchain" and LLVM version is greater than 18
+            // then we also need to add "+backchain" to the target-features attribute.
+            // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
+            if feature == "backchain" && llvm_major < 18 {
+                return None;
+            }
             // ... otherwise though we run through `to_llvm_features` when
             // passing requests down to LLVM. This means that all in-language
             // features also work on the command line instead of having two
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8e07d128dbd..8c582fac0d8 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -759,7 +759,7 @@ fn link_natively(
     sess.dcx().abort_if_errors();
 
     // Invoke the system linker
-    info!("{:?}", &cmd);
+    info!("{cmd:?}");
     let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
     let unknown_arg_regex =
         Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
@@ -796,7 +796,7 @@ fn link_natively(
                     cmd.arg(arg);
                 }
             }
-            info!("{:?}", &cmd);
+            info!("{cmd:?}");
             continue;
         }
 
@@ -817,7 +817,7 @@ fn link_natively(
                     cmd.arg(arg);
                 }
             }
-            info!("{:?}", &cmd);
+            info!("{cmd:?}");
             continue;
         }
 
@@ -878,7 +878,7 @@ fn link_natively(
                     cmd.arg(arg);
                 }
             }
-            info!("{:?}", &cmd);
+            info!("{cmd:?}");
             continue;
         }
 
@@ -996,7 +996,7 @@ fn link_natively(
                 sess.dcx().emit_err(errors::UnableToExeLinker {
                     linker_path,
                     error: e,
-                    command_formatted: format!("{:?}", &cmd),
+                    command_formatted: format!("{cmd:?}"),
                 });
             }
 
@@ -1567,7 +1567,7 @@ fn print_native_static_libs(
                 sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
                 // Prefix for greppability
                 // Note: This must not be translated as tools are allowed to depend on this exact string.
-                sess.dcx().note(format!("native-static-libs: {}", &lib_args.join(" ")));
+                sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
             }
         }
     }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 137f14fe706..399ac485850 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -806,6 +806,34 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     ongoing_codegen
 }
 
+/// Returns whether a call from the current crate to the [`Instance`] would produce a call
+/// from `compiler_builtins` to a symbol the linker must resolve.
+///
+/// Such calls from `compiler_bultins` are effectively impossible for the linker to handle. Some
+/// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is
+/// not guaranteed. So we used this function in codegen backends to ensure we do not generate any
+/// unlinkable calls.
+///
+/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
+pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+) -> bool {
+    fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+        if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name {
+            name.as_str().starts_with("llvm.")
+        } else {
+            false
+        }
+    }
+
+    let def_id = instance.def_id();
+    !def_id.is_local()
+        && tcx.is_compiler_builtins(LOCAL_CRATE)
+        && !is_llvm_intrinsic(tcx, def_id)
+        && !tcx.should_codegen_locally(instance)
+}
+
 impl CrateInfo {
     pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
         let crate_types = tcx.crate_types().to_vec();
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 56a893738df..bfa4c683d56 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -328,7 +328,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             sym::link_section => {
                 if let Some(val) = attr.value_str() {
                     if val.as_str().bytes().any(|b| b == 0) {
-                        let msg = format!("illegal null byte in link_section value: `{}`", &val);
+                        let msg = format!("illegal null byte in link_section value: `{val}`");
                         tcx.dcx().span_err(attr.span, msg);
                     } else {
                         codegen_fn_attrs.link_section = Some(val);
@@ -726,7 +726,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
         if *ordinal <= u16::MAX as u128 {
             Some(ordinal.get() as u16)
         } else {
-            let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
+            let msg = format!("ordinal value in `link_ordinal` is too large: `{ordinal}`");
             tcx.dcx()
                 .struct_span_err(attr.span, msg)
                 .with_note("the value may not exceed `u16::MAX`")
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 6a5525dc2b3..c9c8f02c491 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -3,7 +3,7 @@ use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
 use super::place::{PlaceRef, PlaceValue};
 use super::{CachedLlbb, FunctionCx, LocalRef};
 
-use crate::base;
+use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
 use crate::common::{self, IntPredicate};
 use crate::errors::CompilerBuiltinsCannotCall;
 use crate::meth;
@@ -18,7 +18,6 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
-use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_session::config::OptLevel;
 use rustc_span::{source_map::Spanned, sym, Span};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 0fbcb938d1a..559ec400577 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -130,7 +130,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
 
         let symbol_name = self.symbol_name(cx.tcx()).name;
 
-        debug!("symbol {}", &symbol_name);
+        debug!("symbol {symbol_name}");
 
         match *self {
             MonoItem::Static(def_id) => {
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index cea164df617..e7cee5220d6 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -82,6 +82,7 @@ pub fn from_target_feature(
                 Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature,
                 Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
                 Some(sym::xop_target_feature) => rust_features.xop_target_feature,
+                Some(sym::s390x_target_feature) => rust_features.s390x_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 523d55fe2d0..8700ec4c210 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
 use rustc_middle::ty::{Instance, InstanceKind, TypeVisitableExt};
 use rustc_mir_dataflow::Analysis;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
 use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
 
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 83b61ab1749..bd2a5812cfa 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -401,15 +401,46 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             }
             (ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => {
                 let val = self.read_immediate(src)?;
-                if data_a.principal() == data_b.principal() {
-                    // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
-                    // (But currently mismatching vtables violate the validity invariant so UB is triggered anyway.)
-                    return self.write_immediate(*val, dest);
-                }
+                // Take apart the old pointer, and find the dynamic type.
                 let (old_data, old_vptr) = val.to_scalar_pair();
                 let old_data = old_data.to_pointer(self)?;
                 let old_vptr = old_vptr.to_pointer(self)?;
                 let ty = self.get_ptr_vtable_ty(old_vptr, Some(data_a))?;
+
+                // Sanity-check that `supertrait_vtable_slot` in this type's vtable indeed produces
+                // our destination trait.
+                if cfg!(debug_assertions) {
+                    let vptr_entry_idx =
+                        self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
+                    let vtable_entries = self.vtable_entries(data_a.principal(), ty);
+                    if let Some(entry_idx) = vptr_entry_idx {
+                        let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
+                            vtable_entries.get(entry_idx)
+                        else {
+                            span_bug!(
+                                self.cur_span(),
+                                "invalid vtable entry index in {} -> {} upcast",
+                                src_pointee_ty,
+                                dest_pointee_ty
+                            );
+                        };
+                        let erased_trait_ref = upcast_trait_ref
+                            .map_bound(|r| ty::ExistentialTraitRef::erase_self_ty(*self.tcx, r));
+                        assert!(
+                            data_b
+                                .principal()
+                                .is_some_and(|b| self.eq_in_param_env(erased_trait_ref, b))
+                        );
+                    } else {
+                        // In this case codegen would keep using the old vtable. We don't want to do
+                        // that as it has the wrong trait. The reason codegen can do this is that
+                        // one vtable is a prefix of the other, so we double-check that.
+                        let vtable_entries_b = self.vtable_entries(data_b.principal(), ty);
+                        assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b);
+                    };
+                }
+
+                // Get the destination trait vtable and return that.
                 let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
                 self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
             }
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 6d3e5ea1031..9fddeec2973 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -2,11 +2,15 @@ use std::cell::Cell;
 use std::{fmt, mem};
 
 use either::{Either, Left, Right};
+use rustc_infer::infer::at::ToTrace;
+use rustc_infer::traits::ObligationCause;
+use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::{debug, info, info_span, instrument, trace};
 
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{
     CtfeProvenance, ErrorHandled, InvalidMetaKind, ReportedErrorInfo,
@@ -640,6 +644,32 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
+    /// Check if the two things are equal in the current param_env, using an infctx to get proper
+    /// equality checks.
+    pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
+    where
+        T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
+    {
+        // Fast path: compare directly.
+        if a == b {
+            return true;
+        }
+        // Slow path: spin up an inference context to check if these traits are sufficiently equal.
+        let infcx = self.tcx.infer_ctxt().build();
+        let ocx = ObligationCtxt::new(&infcx);
+        let cause = ObligationCause::dummy_with_span(self.cur_span());
+        // equate the two trait refs after normalization
+        let a = ocx.normalize(&cause, self.param_env, a);
+        let b = ocx.normalize(&cause, self.param_env, b);
+        if ocx.eq(&cause, self.param_env, a, b).is_ok() {
+            if ocx.select_all_or_error().is_empty() {
+                // All good.
+                return true;
+            }
+        }
+        return false;
+    }
+
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
     /// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
     /// and is primarily intended for the panic machinery.
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 25f6bd64055..56d3dc94104 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,7 +1,6 @@
 use std::borrow::Cow;
 
 use either::Either;
-use rustc_middle::ty::TyCtxt;
 use tracing::trace;
 
 use rustc_middle::{
@@ -867,7 +866,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 };
 
                 // Obtain the underlying trait we are working on, and the adjusted receiver argument.
-                let (dyn_trait, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
+                let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
                     receiver_place.layout.ty.kind()
                 {
                     let recv = self.unpack_dyn_star(&receiver_place, data)?;
@@ -898,20 +897,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
                 };
 
-                // Now determine the actual method to call. We can do that in two different ways and
-                // compare them to ensure everything fits.
-                let vtable_entries = if let Some(dyn_trait) = dyn_trait {
-                    let trait_ref = dyn_trait.with_self_ty(*self.tcx, dyn_ty);
-                    let trait_ref = self.tcx.erase_regions(trait_ref);
-                    self.tcx.vtable_entries(trait_ref)
-                } else {
-                    TyCtxt::COMMON_VTABLE_ENTRIES
-                };
+                // Now determine the actual method to call. Usually we use the easy way of just
+                // looking up the method at index `idx`.
+                let vtable_entries = self.vtable_entries(trait_, dyn_ty);
                 let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
                     // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
                     throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
                 };
                 trace!("Virtual call dispatches to {fn_inst:#?}");
+                // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that
+                // produces the same result.
                 if cfg!(debug_assertions) {
                     let tcx = *self.tcx;
 
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index bd2c6519421..fb50661b826 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -1,10 +1,7 @@
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::interpret::{InterpResult, Pointer};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt, VtblEntry};
 use rustc_target::abi::{Align, Size};
-use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::trace;
 
 use super::util::ensure_monomorphic_enough;
@@ -47,6 +44,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         Ok((layout.size, layout.align.abi))
     }
 
+    pub(super) fn vtable_entries(
+        &self,
+        trait_: Option<ty::PolyExistentialTraitRef<'tcx>>,
+        dyn_ty: Ty<'tcx>,
+    ) -> &'tcx [VtblEntry<'tcx>] {
+        if let Some(trait_) = trait_ {
+            let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty);
+            let trait_ref = self.tcx.erase_regions(trait_ref);
+            self.tcx.vtable_entries(trait_ref)
+        } else {
+            TyCtxt::COMMON_VTABLE_ENTRIES
+        }
+    }
+
     /// Check that the given vtable trait is valid for a pointer/reference/place with the given
     /// expected trait type.
     pub(super) fn check_vtable_for_type(
@@ -54,28 +65,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
         expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
     ) -> InterpResult<'tcx> {
-        // Fast path: if they are equal, it's all fine.
-        if expected_trait.principal() == vtable_trait {
-            return Ok(());
-        }
-        if let (Some(expected_trait), Some(vtable_trait)) =
-            (expected_trait.principal(), vtable_trait)
-        {
-            // Slow path: spin up an inference context to check if these traits are sufficiently equal.
-            let infcx = self.tcx.infer_ctxt().build();
-            let ocx = ObligationCtxt::new(&infcx);
-            let cause = ObligationCause::dummy_with_span(self.cur_span());
-            // equate the two trait refs after normalization
-            let expected_trait = ocx.normalize(&cause, self.param_env, expected_trait);
-            let vtable_trait = ocx.normalize(&cause, self.param_env, vtable_trait);
-            if ocx.eq(&cause, self.param_env, expected_trait, vtable_trait).is_ok() {
-                if ocx.select_all_or_error().is_empty() {
-                    // All good.
-                    return Ok(());
-                }
-            }
+        let eq = match (expected_trait.principal(), vtable_trait) {
+            (Some(a), Some(b)) => self.eq_in_param_env(a, b),
+            (None, None) => true,
+            _ => false,
+        };
+        if !eq {
+            throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
         }
-        throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
+        Ok(())
     }
 
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0120.md b/compiler/rustc_error_codes/src/error_codes/E0120.md
index dc7258d8731..aa701df5774 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0120.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0120.md
@@ -1,7 +1,7 @@
-Drop was implemented on a trait, which is not allowed: only structs and
-enums can implement Drop.
+`Drop` was implemented on a trait object or reference, which is not allowed;
+only structs, enums, and unions can implement Drop.
 
-Erroneous code example:
+Erroneous code examples:
 
 ```compile_fail,E0120
 trait MyTrait {}
@@ -11,8 +11,16 @@ impl Drop for MyTrait {
 }
 ```
 
-A workaround for this problem is to wrap the trait up in a struct, and implement
-Drop on that:
+```compile_fail,E0120
+struct Concrete {}
+
+impl Drop for &'_ mut Concrete  {
+    fn drop(&mut self) {}
+}
+```
+
+A workaround for traits is to create a wrapper struct with a generic type,
+add a trait bound to the type, and implement `Drop` on the wrapper:
 
 ```
 trait MyTrait {}
@@ -24,13 +32,13 @@ impl <T: MyTrait> Drop for MyWrapper<T> {
 
 ```
 
-Alternatively, wrapping trait objects requires something:
+Alternatively, the `Drop` wrapper can contain the trait object:
 
 ```
 trait MyTrait {}
 
-//or Box<MyTrait>, if you wanted an owned trait object
-struct MyWrapper<'a> { foo: &'a MyTrait }
+// or Box<dyn MyTrait>, if you wanted an owned trait object
+struct MyWrapper<'a> { foo: &'a dyn MyTrait }
 
 impl <'a> Drop for MyWrapper<'a> {
     fn drop(&mut self) {}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md
index effa597aad9..d4d26007aa5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0373.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0373.md
@@ -70,4 +70,4 @@ fn spawn<F: Future + Send + 'static>(future: F) {
 
 Similarly to closures, `async` blocks are not executed immediately and may
 capture closed-over data by reference. For more information, see
-https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.
+<https://rust-lang.github.io/async-book/03_async_await/01_chapter.html>.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0378.md b/compiler/rustc_error_codes/src/error_codes/E0378.md
index c6fe997f3dc..7d939b99b04 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0378.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0378.md
@@ -20,7 +20,7 @@ where
 
 The `DispatchFromDyn` trait currently can only be implemented for
 builtin pointer types and structs that are newtype wrappers around them
-— that is, the struct must have only one field (except for`PhantomData`),
+— that is, the struct must have only one field (except for `PhantomData`),
 and that field must itself implement `DispatchFromDyn`.
 
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0626.md b/compiler/rustc_error_codes/src/error_codes/E0626.md
index 28d543350ff..71c1f811aa7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0626.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0626.md
@@ -1,4 +1,4 @@
-This error occurs because a borrow in a coroutine persists across a
+This error occurs because a borrow in a movable coroutine persists across a
 yield point.
 
 Erroneous code example:
@@ -15,19 +15,35 @@ let mut b = #[coroutine] || {
 Pin::new(&mut b).resume(());
 ```
 
-At present, it is not permitted to have a yield that occurs while a
-borrow is still in scope. To resolve this error, the borrow must
-either be "contained" to a smaller scope that does not overlap the
-yield or else eliminated in another way. So, for example, we might
-resolve the previous example by removing the borrow and just storing
-the integer by value:
+Coroutines may be either unmarked, or marked with `static`. If it is unmarked,
+then the coroutine is considered "movable". At present, it is not permitted to
+have a yield in a movable coroutine that occurs while a borrow is still in
+scope. To resolve this error, the coroutine may be marked `static`:
+
+```
+# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
+# use std::ops::Coroutine;
+# use std::pin::Pin;
+let mut b = #[coroutine] static || { // <-- note the static keyword
+    let a = &String::from("hello, world");
+    yield ();
+    println!("{}", a);
+};
+let mut b = std::pin::pin!(b);
+b.as_mut().resume(());
+```
+
+If the coroutine must remain movable, for example to be used as `Unpin`
+without pinning it on the stack or in an allocation, we can alternatively
+resolve the previous example by removing the borrow and just storing the
+type by value:
 
 ```
 # #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
 # use std::ops::Coroutine;
 # use std::pin::Pin;
 let mut b = #[coroutine] || {
-    let a = 3;
+    let a = String::from("hello, world");
     yield ();
     println!("{}", a);
 };
diff --git a/compiler/rustc_error_codes/src/error_codes/E0771.md b/compiler/rustc_error_codes/src/error_codes/E0771.md
index 4f36590025b..74149eb79f6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0771.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0771.md
@@ -6,7 +6,7 @@ allowed.
 Erroneous code example:
 
 ```compile_fail,E0770
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 fn function_with_str<'a, const STRING: &'a str>() {} // error!
 ```
@@ -15,7 +15,7 @@ To fix this issue, the lifetime in the const generic need to be changed to
 `'static`:
 
 ```
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 fn function_with_str<const STRING: &'static str>() {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md
new file mode 100644
index 00000000000..da08cde3010
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0798.md
@@ -0,0 +1,39 @@
+Functions marked as `C-cmse-nonsecure-call` place restrictions on their
+inputs and outputs.
+
+- inputs must fit in the 4 available 32-bit argument registers. Alignment
+is relevant.
+- outputs must either fit in 4 bytes, or be a foundational type of
+size 8 (`i64`, `u64`, `f64`).
+- no generics can be used in the signature
+
+For more information,
+see [arm's aapcs32](https://github.com/ARM-software/abi-aa/releases).
+
+Erroneous code example:
+
+```ignore (only fails on supported targets)
+#![feature(abi_c_cmse_nonsecure_call)]
+
+#[no_mangle]
+pub fn test(
+    f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32,
+) -> u32 {
+    f(1, 2, 3, 4, 5)
+}
+```
+
+Arguments' alignment is respected. In the example below, padding is inserted
+so that the `u64` argument is passed in registers r2 and r3. There is then no
+room left for the final `f32` argument
+
+```ignore (only fails on supported targets)
+#![feature(abi_c_cmse_nonsecure_call)]
+
+#[no_mangle]
+pub fn test(
+    f: extern "C-cmse-nonsecure-call" fn(u32, u64, f32) -> u32,
+) -> u32 {
+    f(1, 2, 3.0)
+}
+```
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index d13d5e1bca2..2a7bc2501c0 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -536,6 +536,7 @@ E0794: 0794,
 E0795: 0795,
 E0796: 0796,
 E0797: 0797,
+E0798: 0798,
         );
     )
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 2086d4030f9..2a850d9303c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -15,6 +15,7 @@
 #![feature(box_patterns)]
 #![feature(error_reporter)]
 #![feature(extract_if)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs
index 67e4963fddf..69e7120e714 100644
--- a/compiler/rustc_errors/src/markdown/parse.rs
+++ b/compiler/rustc_errors/src/markdown/parse.rs
@@ -10,15 +10,15 @@ const CBK: &[u8] = b"```";
 const CIL: &[u8] = b"`";
 const CMT_E: &[u8] = b"-->";
 const CMT_S: &[u8] = b"<!--";
-const EMP: &[u8] = b"_";
+const EMP_U: &[u8] = b"_";
+const EMP_A: &[u8] = b"*";
 const HDG: &[u8] = b"#";
 const LNK_CHARS: &str = "$-_.+!*'()/&?=:%";
 const LNK_E: &[u8] = b"]";
 const LNK_S: &[u8] = b"[";
-const STG: &[u8] = b"**";
+const STG_U: &[u8] = b"__";
+const STG_A: &[u8] = b"**";
 const STK: &[u8] = b"~~";
-const UL1: &[u8] = b"* ";
-const UL2: &[u8] = b"- ";
 
 /// Pattern replacements
 const REPLACEMENTS: &[(&str, &str)] = &[
@@ -100,22 +100,29 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
         };
 
         let res: ParseResult<'_> = match (top_blk, prev) {
-            (_, Newline | Whitespace) if loop_buf.starts_with(CMT_S) => {
+            _ if loop_buf.starts_with(CMT_S) => {
                 parse_simple_pat(loop_buf, CMT_S, CMT_E, Po::TrimNoEsc, MdTree::Comment)
             }
             (true, Newline) if loop_buf.starts_with(CBK) => Some(parse_codeblock(loop_buf)),
-            (_, Newline | Whitespace) if loop_buf.starts_with(CIL) => parse_codeinline(loop_buf),
+            _ if loop_buf.starts_with(CIL) => parse_codeinline(loop_buf),
             (true, Newline | Whitespace) if loop_buf.starts_with(HDG) => parse_heading(loop_buf),
             (true, Newline) if loop_buf.starts_with(BRK) => {
                 Some((MdTree::HorizontalRule, parse_to_newline(loop_buf).1))
             }
-            (_, Newline | Whitespace) if loop_buf.starts_with(EMP) => {
-                parse_simple_pat(loop_buf, EMP, EMP, Po::None, MdTree::Emphasis)
+            (_, Newline) if unordered_list_start(loop_buf) => Some(parse_unordered_li(loop_buf)),
+            (_, Newline | Whitespace) if loop_buf.starts_with(STG_U) => {
+                parse_simple_pat(loop_buf, STG_U, STG_U, Po::None, MdTree::Strong)
             }
-            (_, Newline | Whitespace) if loop_buf.starts_with(STG) => {
-                parse_simple_pat(loop_buf, STG, STG, Po::None, MdTree::Strong)
+            _ if loop_buf.starts_with(STG_A) => {
+                parse_simple_pat(loop_buf, STG_A, STG_A, Po::None, MdTree::Strong)
             }
-            (_, Newline | Whitespace) if loop_buf.starts_with(STK) => {
+            (_, Newline | Whitespace) if loop_buf.starts_with(EMP_U) => {
+                parse_simple_pat(loop_buf, EMP_U, EMP_U, Po::None, MdTree::Emphasis)
+            }
+            _ if loop_buf.starts_with(EMP_A) => {
+                parse_simple_pat(loop_buf, EMP_A, EMP_A, Po::None, MdTree::Emphasis)
+            }
+            _ if loop_buf.starts_with(STK) => {
                 parse_simple_pat(loop_buf, STK, STK, Po::None, MdTree::Strikethrough)
             }
             (_, Newline | Whitespace) if loop_buf.starts_with(ANC_S) => {
@@ -130,11 +137,8 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
                     _ => None,
                 }
             }
-            (_, Newline) if (loop_buf.starts_with(UL1) || loop_buf.starts_with(UL2)) => {
-                Some(parse_unordered_li(loop_buf))
-            }
             (_, Newline) if ord_list_start(loop_buf).is_some() => Some(parse_ordered_li(loop_buf)),
-            (_, Newline | Whitespace) if loop_buf.starts_with(LNK_S) => {
+            _ if loop_buf.starts_with(LNK_S) => {
                 parse_any_link(loop_buf, top_blk && prev == Prev::Newline)
             }
             (_, Escape | _) => None,
@@ -251,7 +255,6 @@ fn parse_heading(buf: &[u8]) -> ParseResult<'_> {
 
 /// Bulleted list
 fn parse_unordered_li(buf: &[u8]) -> Parsed<'_> {
-    debug_assert!(buf.starts_with(b"* ") || buf.starts_with(b"- "));
     let (txt, rest) = get_indented_section(&buf[2..]);
     let ctx = Context { top_block: false, prev: Prev::Whitespace };
     let stream = parse_recursive(trim_ascii_start(txt), ctx);
@@ -267,25 +270,28 @@ fn parse_ordered_li(buf: &[u8]) -> Parsed<'_> {
     (MdTree::OrderedListItem(num, stream), rest)
 }
 
-/// Find first line that isn't empty or doesn't start with whitespace, that will
-/// be our contents
 fn get_indented_section(buf: &[u8]) -> (&[u8], &[u8]) {
-    let mut end = buf.len();
-    for (idx, window) in buf.windows(2).enumerate() {
-        let &[ch, next_ch] = window else { unreachable!("always 2 elements") };
-        if idx >= buf.len().saturating_sub(2) && next_ch == b'\n' {
-            // End of stream
-            end = buf.len().saturating_sub(1);
-            break;
-        } else if ch == b'\n' && (!next_ch.is_ascii_whitespace() || next_ch == b'\n') {
-            end = idx;
-            break;
+    let mut lines = buf.split(|&byte| byte == b'\n');
+    let mut end = lines.next().map_or(0, |line| line.len());
+    for line in lines {
+        if let Some(first) = line.first() {
+            if unordered_list_start(line) || !first.is_ascii_whitespace() {
+                break;
+            }
         }
+        end += line.len() + 1;
     }
 
     (&buf[..end], &buf[end..])
 }
 
+fn unordered_list_start(mut buf: &[u8]) -> bool {
+    while let [b' ', rest @ ..] = buf {
+        buf = rest;
+    }
+    matches!(buf, [b'*' | b'-', b' ', ..])
+}
+
 /// Verify a valid ordered list start (e.g. `1.`) and parse it. Returns the
 /// parsed number and offset of character after the dot.
 fn ord_list_start(buf: &[u8]) -> Option<(u16, usize)> {
diff --git a/compiler/rustc_errors/src/markdown/tests/parse.rs b/compiler/rustc_errors/src/markdown/tests/parse.rs
index e39e8c89b35..e2e3f354ff6 100644
--- a/compiler/rustc_errors/src/markdown/tests/parse.rs
+++ b/compiler/rustc_errors/src/markdown/tests/parse.rs
@@ -4,13 +4,13 @@ use ParseOpt as PO;
 #[test]
 fn test_parse_simple() {
     let buf = "**abcd** rest";
-    let (t, r) = parse_simple_pat(buf.as_bytes(), STG, STG, PO::None, MdTree::Strong).unwrap();
+    let (t, r) = parse_simple_pat(buf.as_bytes(), b"**", b"**", PO::None, MdTree::Strong).unwrap();
     assert_eq!(t, MdTree::Strong("abcd"));
     assert_eq!(r, b" rest");
 
     // Escaping should fail
     let buf = r"**abcd\** rest";
-    let res = parse_simple_pat(buf.as_bytes(), STG, STG, PO::None, MdTree::Strong);
+    let res = parse_simple_pat(buf.as_bytes(), b"**", b"**", PO::None, MdTree::Strong);
     assert!(res.is_none());
 }
 
@@ -141,12 +141,12 @@ fn test_indented_section() {
     assert_eq!(str::from_utf8(r).unwrap(), "\nnot ind");
 
     let (txt, rest) = get_indented_section(IND2.as_bytes());
-    assert_eq!(str::from_utf8(txt).unwrap(), "test end of stream\n  1\n  2");
-    assert_eq!(str::from_utf8(rest).unwrap(), "\n");
+    assert_eq!(str::from_utf8(txt).unwrap(), "test end of stream\n  1\n  2\n");
+    assert_eq!(str::from_utf8(rest).unwrap(), "");
 
     let (txt, rest) = get_indented_section(IND3.as_bytes());
-    assert_eq!(str::from_utf8(txt).unwrap(), "test empty lines\n  1\n  2");
-    assert_eq!(str::from_utf8(rest).unwrap(), "\n\nnot ind");
+    assert_eq!(str::from_utf8(txt).unwrap(), "test empty lines\n  1\n  2\n");
+    assert_eq!(str::from_utf8(rest).unwrap(), "\nnot ind");
 }
 
 const HBT: &str = r"# Heading
@@ -310,3 +310,56 @@ fn test_code_at_start() {
     let res = entrypoint(CODE_STARTLINE);
     assert_eq!(res, expected);
 }
+
+#[test]
+fn test_code_in_parens() {
+    let expected =
+        vec![MdTree::PlainText("("), MdTree::CodeInline("Foo"), MdTree::PlainText(")")].into();
+    let res = entrypoint("(`Foo`)");
+    assert_eq!(res, expected);
+}
+
+const LIST_WITH_SPACE: &str = "
+para
+ * l1
+ * l2
+";
+
+#[test]
+fn test_list_with_space() {
+    let expected = vec![
+        MdTree::PlainText("para"),
+        MdTree::ParagraphBreak,
+        MdTree::UnorderedListItem(vec![MdTree::PlainText("l1")].into()),
+        MdTree::LineBreak,
+        MdTree::UnorderedListItem(vec![MdTree::PlainText("l2")].into()),
+    ]
+    .into();
+    let res = entrypoint(LIST_WITH_SPACE);
+    assert_eq!(res, expected);
+}
+
+const SNAKE_CASE: &str = "
+foo*bar*
+foo**bar**
+foo_bar_
+foo__bar__
+";
+
+#[test]
+fn test_snake_case() {
+    let expected = vec![
+        MdTree::PlainText("foo"),
+        MdTree::Emphasis("bar"),
+        MdTree::PlainText(" "),
+        MdTree::PlainText("foo"),
+        MdTree::Strong("bar"),
+        MdTree::PlainText(" "),
+        MdTree::PlainText("foo_bar_"),
+        MdTree::PlainText(" "),
+        MdTree::PlainText("foo__bar__"),
+    ]
+    .into();
+    let res = entrypoint(SNAKE_CASE);
+    assert_eq!(res, expected);
+}
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 56ef609612a..4b730d307fd 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -352,10 +352,10 @@ fn check_occurrences(
             check_ops_is_prefix(psess, node_id, macros, binders, ops, span, name);
         }
         TokenTree::MetaVarExpr(dl, ref mve) => {
-            let Some(name) = mve.ident().map(MacroRulesNormalizedIdent::new) else {
-                return;
-            };
-            check_ops_is_prefix(psess, node_id, macros, binders, ops, dl.entire(), name);
+            mve.for_each_metavar((), |_, ident| {
+                let name = MacroRulesNormalizedIdent::new(*ident);
+                check_ops_is_prefix(psess, node_id, macros, binders, ops, dl.entire(), name);
+            });
         }
         TokenTree::Delimited(.., ref del) => {
             check_nested_occurrences(psess, node_id, &del.tts, macros, binders, ops, guar);
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 2964ac8cc58..c4ba98f581e 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -111,10 +111,18 @@ impl MetaVarExpr {
         Ok(rslt)
     }
 
-    pub(crate) fn ident(&self) -> Option<Ident> {
-        match *self {
-            MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
-            MetaVarExpr::Concat { .. } | MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
+    pub(crate) fn for_each_metavar<A>(&self, mut aux: A, mut cb: impl FnMut(A, &Ident) -> A) -> A {
+        match self {
+            MetaVarExpr::Concat(elems) => {
+                for elem in elems {
+                    if let MetaVarExprConcatElem::Var(ident) = elem {
+                        aux = cb(aux, ident)
+                    }
+                }
+                aux
+            }
+            MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => cb(aux, ident),
+            MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => aux,
         }
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 7e2ea8de5fc..62337756cd8 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -557,17 +557,13 @@ fn lockstep_iter_size(
             }
         }
         TokenTree::MetaVarExpr(_, expr) => {
-            let default_rslt = LockstepIterSize::Unconstrained;
-            let Some(ident) = expr.ident() else {
-                return default_rslt;
-            };
-            let name = MacroRulesNormalizedIdent::new(ident);
-            match lookup_cur_matched(name, interpolations, repeats) {
-                Some(MatchedSeq(ads)) => {
-                    default_rslt.with(LockstepIterSize::Constraint(ads.len(), name))
-                }
-                _ => default_rslt,
-            }
+            expr.for_each_metavar(LockstepIterSize::Unconstrained, |lis, ident| {
+                lis.with(lockstep_iter_size(
+                    &TokenTree::MetaVar(ident.span, *ident),
+                    interpolations,
+                    repeats,
+                ))
+            })
         }
         TokenTree::Token(..) => LockstepIterSize::Unconstrained,
     }
@@ -695,7 +691,23 @@ fn transcribe_metavar_expr<'a>(
                 let symbol = match element {
                     MetaVarExprConcatElem::Ident(elem) => elem.name,
                     MetaVarExprConcatElem::Literal(elem) => *elem,
-                    MetaVarExprConcatElem::Var(elem) => extract_var_symbol(dcx, *elem, interp)?,
+                    MetaVarExprConcatElem::Var(ident) => {
+                        match matched_from_ident(dcx, *ident, interp)? {
+                            NamedMatch::MatchedSeq(named_matches) => {
+                                let curr_idx = repeats.last().unwrap().0;
+                                match &named_matches[curr_idx] {
+                                    // FIXME(c410-f3r) Nested repetitions are unimplemented
+                                    MatchedSeq(_) => unimplemented!(),
+                                    MatchedSingle(pnr) => {
+                                        extract_symbol_from_pnr(dcx, pnr, ident.span)?
+                                    }
+                                }
+                            }
+                            NamedMatch::MatchedSingle(pnr) => {
+                                extract_symbol_from_pnr(dcx, pnr, ident.span)?
+                            }
+                        }
+                    }
                 };
                 concatenated.push_str(symbol.as_str());
             }
@@ -752,41 +764,48 @@ fn transcribe_metavar_expr<'a>(
 }
 
 /// Extracts an metavariable symbol that can be an identifier, a token tree or a literal.
-fn extract_var_symbol<'a>(
+fn extract_symbol_from_pnr<'a>(
     dcx: DiagCtxtHandle<'a>,
-    ident: Ident,
-    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+    pnr: &ParseNtResult,
+    span_err: Span,
 ) -> PResult<'a, Symbol> {
-    if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
-        if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
+    match pnr {
+        ParseNtResult::Ident(nt_ident, is_raw) => {
             if let IdentIsRaw::Yes = is_raw {
-                return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
+                return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
             }
             return Ok(nt_ident.name);
         }
-
-        if let ParseNtResult::Tt(TokenTree::Token(Token { kind, .. }, _)) = pnr {
-            if let TokenKind::Ident(symbol, is_raw) = kind {
-                if let IdentIsRaw::Yes = is_raw {
-                    return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
-                }
-                return Ok(*symbol);
-            }
-
-            if let TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }) = kind {
-                return Ok(*symbol);
+        ParseNtResult::Tt(TokenTree::Token(
+            Token { kind: TokenKind::Ident(symbol, is_raw), .. },
+            _,
+        )) => {
+            if let IdentIsRaw::Yes = is_raw {
+                return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
             }
+            return Ok(*symbol);
         }
-
-        if let ParseNtResult::Nt(nt) = pnr
-            && let Nonterminal::NtLiteral(expr) = &**nt
-            && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind
+        ParseNtResult::Tt(TokenTree::Token(
+            Token {
+                kind: TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }),
+                ..
+            },
+            _,
+        )) => {
+            return Ok(*symbol);
+        }
+        ParseNtResult::Nt(nt)
+            if let Nonterminal::NtLiteral(expr) = &**nt
+                && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) =
+                    &expr.kind =>
         {
             return Ok(*symbol);
         }
+        _ => Err(dcx
+            .struct_err(
+                "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`",
+            )
+            .with_note("currently only string literals are supported")
+            .with_span(span_err)),
     }
-    Err(dcx
-        .struct_err("metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`")
-        .with_note("currently only string literals are supported")
-        .with_span(ident.span))
 }
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 1db3774222a..9b5ed3b0876 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -312,6 +312,7 @@ declare_features! (
     (unstable, prfchw_target_feature, "1.78.0", Some(44839)),
     (unstable, riscv_target_feature, "1.45.0", Some(44839)),
     (unstable, rtm_target_feature, "1.35.0", Some(44839)),
+    (unstable, s390x_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
     (unstable, sse4a_target_feature, "1.27.0", Some(44839)),
     (unstable, tbm_target_feature, "1.27.0", Some(44839)),
     (unstable, wasm_target_feature, "1.30.0", Some(44839)),
@@ -339,8 +340,8 @@ declare_features! (
     (unstable, abi_riscv_interrupt, "1.73.0", Some(111889)),
     /// Allows `extern "x86-interrupt" fn()`.
     (unstable, abi_x86_interrupt, "1.17.0", Some(40180)),
-    /// Allows additional const parameter types, such as `&'static str` or user defined types
-    (incomplete, adt_const_params, "1.56.0", Some(95174)),
+    /// Allows additional const parameter types, such as `[u8; 10]` or user defined types
+    (unstable, adt_const_params, "1.56.0", Some(95174)),
     /// Allows defining an `#[alloc_error_handler]`.
     (unstable, alloc_error_handler, "1.29.0", Some(51540)),
     /// Allows trait methods with arbitrary self types.
@@ -630,6 +631,9 @@ declare_features! (
     (unstable, unsafe_attributes, "1.80.0", Some(123757)),
     /// Allows unsafe on extern declarations and safety qualifiers over internal items.
     (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
+    /// Allows const generic parameters to be defined with types that
+    /// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
+    (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
     /// Allows unsized fn parameters.
     (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 214b6587af3..68fdabd3529 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -253,7 +253,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
 
             for Attribute { id: Identifier { name: attr_name }, .. } in attributes {
                 let snake_name = Ident::new(
-                    &format!("{}{}", &crate_prefix, &attr_name.replace('-', "_")),
+                    &format!("{crate_prefix}{}", attr_name.replace('-', "_")),
                     resource_str.span(),
                 );
                 if !previous_attrs.insert(snake_name.clone()) {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 30c0e40206a..58cc0f62111 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -358,6 +358,7 @@ language_item_table! {
     PointerLike,             sym::pointer_like,        pointer_like,               Target::Trait,          GenericRequirement::Exact(0);
 
     ConstParamTy,            sym::const_param_ty,      const_param_ty_trait,       Target::Trait,          GenericRequirement::Exact(0);
+    UnsizedConstParamTy,     sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
 
     Poll,                    sym::Poll,                poll,                       Target::Enum,           GenericRequirement::None;
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant,        GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index b43559f4225..cc404daa51f 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -58,6 +58,23 @@ hir_analysis_cannot_capture_late_bound_ty =
 hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
     .label = `for<...>` is here
 
+hir_analysis_cmse_call_generic =
+    function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
+
+hir_analysis_cmse_call_inputs_stack_spill =
+    arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+    .label = {$plural ->
+        [false] this argument doesn't
+        *[true] these arguments don't
+    } fit in the available registers
+    .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+hir_analysis_cmse_call_output_stack_spill =
+    return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+    .label = this type doesn't fit in the available registers
+    .note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+    .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
 hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
 
 hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
@@ -82,6 +99,10 @@ hir_analysis_const_param_ty_impl_on_non_adt =
     the trait `ConstParamTy` may not be implemented for this type
     .label = type is not a structure or enumeration
 
+hir_analysis_const_param_ty_impl_on_unsized =
+    the trait `ConstParamTy` may not be implemented for this type
+    .label = type is not `Sized`
+
 hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
 
 hir_analysis_copy_impl_on_non_adt =
@@ -519,6 +540,11 @@ hir_analysis_typeof_reserved_keyword_used =
     .suggestion = consider replacing `typeof(...)` with an actual type
     .label = reserved keyword
 
+hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates
+    .label = unconstrained {$param_def_kind}
+    .const_param_note = expressions using a const parameter must map each value to a distinct output value
+    .const_param_note2 = proving the result of expressions other than the parameter are unique is not supported
+
 hir_analysis_unconstrained_opaque_type = unconstrained opaque type
     .note = `{$name}` must be used in combination with a concrete type within the same {$what}
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index dbc265ad3ff..27db5418165 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_type_ir::fold::TypeFoldable;
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 6c53625b590..c99f13468e2 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -21,7 +21,7 @@ use rustc_middle::ty::{
 use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index ce921f64481..e4d4b7df24e 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -7,7 +7,7 @@ use rustc_session::config::EntryFnType;
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
 
 use std::ops::Not;
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9fef31acef8..4c230ad84de 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -82,7 +82,6 @@ use rustc_errors::{pluralize, struct_span_code_err, Diag};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
-use rustc_infer::error_reporting::infer::ObligationCauseExt as _;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, TyCtxtInferExt as _};
 use rustc_infer::traits::ObligationCause;
@@ -96,10 +95,9 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::suggestions::{
-    ReturnsVisitor, TypeErrCtxtExt as _,
-};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _;
+use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 
 use crate::errors;
@@ -166,21 +164,42 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
         return;
     }
 
-    // For the wasm32 target statics with `#[link_section]` are placed into custom
-    // sections of the final output file, but this isn't link custom sections of
-    // other executable formats. Namely we can only embed a list of bytes,
-    // nothing with provenance (pointers to anything else). If any provenance
-    // show up, reject it here.
+    // For the wasm32 target statics with `#[link_section]` other than `.init_array`
+    // are placed into custom sections of the final output file, but this isn't like
+    // custom sections of other executable formats. Namely we can only embed a list
+    // of bytes, nothing with provenance (pointers to anything else). If any
+    // provenance show up, reject it here.
     // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
     // the consumer's responsibility to ensure all bytes that have been read
     // have defined values.
+    //
+    // The `.init_array` section is left to go through the normal custom section code path.
+    // When dealing with `.init_array` wasm-ld currently has several limitations. This manifests
+    // in workarounds in user-code.
+    //
+    //   * The linker fails to merge multiple items in a crate into the .init_array section.
+    //     To work around this, a single array can be used placing multiple items in the array.
+    //     #[link_section = ".init_array"]
+    //     static FOO: [unsafe extern "C" fn(); 2] = [ctor, ctor];
+    //   * Even symbols marked used get gc'd from dependant crates unless at least one symbol
+    //     in the crate is marked with an `#[export_name]`
+    //
+    //  Once `.init_array` support in wasm-ld is complete, the user code workarounds should
+    //  continue to work, but would no longer be necessary.
+
     if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
         && alloc.inner().provenance().ptrs().len() != 0
     {
-        let msg = "statics with a custom `#[link_section]` must be a \
+        if attrs
+            .link_section
+            .map(|link_section| !link_section.as_str().starts_with(".init_array"))
+            .unwrap()
+        {
+            let msg = "statics with a custom `#[link_section]` must be a \
                         simple list of bytes on the wasm target with no \
                         extra levels of indirection such as references";
-        tcx.dcx().span_err(tcx.def_span(id), msg);
+            tcx.dcx().span_err(tcx.def_span(id), msg);
+        }
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 809427f86ee..0316ef69bf8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -29,7 +29,7 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::misc::{
     type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
@@ -922,10 +922,8 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
         } => {
             let ty = tcx.type_of(param.def_id).instantiate_identity();
 
-            if tcx.features().adt_const_params {
+            if tcx.features().unsized_const_params {
                 enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
-                    let trait_def_id =
-                        tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span));
                     wfcx.register_bound(
                         ObligationCause::new(
                             hir_ty.span,
@@ -934,7 +932,21 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                         ),
                         wfcx.param_env,
                         ty,
-                        trait_def_id,
+                        tcx.require_lang_item(LangItem::UnsizedConstParamTy, Some(hir_ty.span)),
+                    );
+                    Ok(())
+                })
+            } else if tcx.features().adt_const_params {
+                enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
+                    wfcx.register_bound(
+                        ObligationCause::new(
+                            hir_ty.span,
+                            param.def_id,
+                            ObligationCauseCode::ConstParam(ty),
+                        ),
+                        wfcx.param_env,
+                        ty,
+                        tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span)),
                     );
                     Ok(())
                 })
@@ -958,14 +970,29 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                 diag.note("the only supported types are integers, `bool` and `char`");
 
                 let cause = ObligationCause::misc(hir_ty.span, param.def_id);
+                let adt_const_params_feature_string =
+                    " more complex and user defined types".to_string();
                 let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
                     tcx,
                     tcx.param_env(param.def_id),
                     ty,
+                    LangItem::ConstParamTy,
                     cause,
                 ) {
                     // Can never implement `ConstParamTy`, don't suggest anything.
-                    Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
+                    Err(
+                        ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
+                        | ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
+                    ) => None,
+                    Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
+                        Some(vec![
+                            (adt_const_params_feature_string, sym::adt_const_params),
+                            (
+                                " references to implement the `ConstParamTy` trait".into(),
+                                sym::unsized_const_params,
+                            ),
+                        ])
+                    }
                     // May be able to implement `ConstParamTy`. Only emit the feature help
                     // if the type is local, since the user may be able to fix the local type.
                     Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
@@ -985,20 +1012,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                             }
                         }
 
-                        ty_is_local(ty)
+                        ty_is_local(ty).then_some(vec![(
+                            adt_const_params_feature_string,
+                            sym::adt_const_params,
+                        )])
                     }
                     // Implments `ConstParamTy`, suggest adding the feature to enable.
-                    Ok(..) => true,
+                    Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]),
                 };
-                if may_suggest_feature {
-                    tcx.disabled_nightly_features(
-                        &mut diag,
-                        Some(param.hir_id),
-                        [(
-                            " more complex and user defined types".to_string(),
-                            sym::adt_const_params,
-                        )],
-                    );
+                if let Some(features) = may_suggest_feature {
+                    tcx.disabled_nightly_features(&mut diag, Some(param.hir_id), features);
                 }
 
                 Err(diag.emit())
@@ -1922,31 +1945,24 @@ fn report_bivariance<'tcx>(
     );
 
     if !usage_spans.is_empty() {
-        // First, check if the ADT is (probably) cyclical. We say probably here, since
-        // we're not actually looking into substitutions, just walking through fields.
-        // And we only recurse into the fields of ADTs, and not the hidden types of
-        // opaques or anything else fancy.
+        // First, check if the ADT/LTA is (probably) cyclical. We say probably here, since we're
+        // not actually looking into substitutions, just walking through fields / the "RHS".
+        // We don't recurse into the hidden types of opaques or anything else fancy.
         let item_def_id = item.owner_id.to_def_id();
-        let is_probably_cyclical = if matches!(
-            tcx.def_kind(item_def_id),
-            DefKind::Struct | DefKind::Union | DefKind::Enum
-        ) {
-            IsProbablyCyclical { tcx, adt_def_id: item_def_id, seen: Default::default() }
-                .visit_all_fields(tcx.adt_def(item_def_id))
-                .is_break()
-        } else {
-            false
-        };
-        // If the ADT is cyclical, then if at least one usage of the type parameter or
-        // the `Self` alias is present in the, then it's probably a cyclical struct, and
-        // we should call those parameter usages recursive rather than just saying they're
-        // unused...
+        let is_probably_cyclical =
+            IsProbablyCyclical { tcx, item_def_id, seen: Default::default() }
+                .visit_def(item_def_id)
+                .is_break();
+        // If the ADT/LTA is cyclical, then if at least one usage of the type parameter or
+        // the `Self` alias is present in the, then it's probably a cyclical struct/ type
+        // alias, and we should call those parameter usages recursive rather than just saying
+        // they're unused...
         //
         // We currently report *all* of the parameter usages, since computing the exact
         // subset is very involved, and the fact we're mentioning recursion at all is
         // likely to guide the user in the right direction.
         if is_probably_cyclical {
-            let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter {
+            return tcx.dcx().emit_err(errors::RecursiveGenericParameter {
                 spans: usage_spans,
                 param_span: param.span,
                 param_name,
@@ -1954,7 +1970,6 @@ fn report_bivariance<'tcx>(
                 help,
                 note: (),
             });
-            return diag.emit();
         }
     }
 
@@ -1974,42 +1989,51 @@ fn report_bivariance<'tcx>(
     diag.emit()
 }
 
-/// Detects cases where an ADT is trivially cyclical -- we want to detect this so
-/// /we only mention that its parameters are used cyclically if the ADT is truly
+/// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so
+/// we only mention that its parameters are used cyclically if the ADT/LTA is truly
 /// cyclical.
 ///
 /// Notably, we don't consider substitutions here, so this may have false positives.
 struct IsProbablyCyclical<'tcx> {
     tcx: TyCtxt<'tcx>,
-    adt_def_id: DefId,
+    item_def_id: DefId,
     seen: FxHashSet<DefId>,
 }
 
 impl<'tcx> IsProbablyCyclical<'tcx> {
-    fn visit_all_fields(&mut self, adt_def: ty::AdtDef<'tcx>) -> ControlFlow<(), ()> {
-        for field in adt_def.all_fields() {
-            self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
+    fn visit_def(&mut self, def_id: DefId) -> ControlFlow<(), ()> {
+        match self.tcx.def_kind(def_id) {
+            DefKind::Struct | DefKind::Enum | DefKind::Union => {
+                self.tcx.adt_def(def_id).all_fields().try_for_each(|field| {
+                    self.tcx.type_of(field.did).instantiate_identity().visit_with(self)
+                })
+            }
+            DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => {
+                self.tcx.type_of(def_id).instantiate_identity().visit_with(self)
+            }
+            _ => ControlFlow::Continue(()),
         }
-
-        ControlFlow::Continue(())
     }
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
     type Result = ControlFlow<(), ()>;
 
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
-        if let Some(adt_def) = t.ty_adt_def() {
-            if adt_def.did() == self.adt_def_id {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
+        let def_id = match ty.kind() {
+            ty::Adt(adt_def, _) => Some(adt_def.did()),
+            ty::Alias(ty::Weak, alias_ty) => Some(alias_ty.def_id),
+            _ => None,
+        };
+        if let Some(def_id) = def_id {
+            if def_id == self.item_def_id {
                 return ControlFlow::Break(());
             }
-
-            if self.seen.insert(adt_def.did()) {
-                self.visit_all_fields(adt_def)?;
+            if self.seen.insert(def_id) {
+                self.visit_def(def_id)?;
             }
         }
-
-        t.super_visit_with(self)
+        ty.super_visit_with(self)
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 2ecb170ec89..b35ee270fef 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{Span, DUMMY_SP};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::misc::{
     type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
     ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
@@ -36,9 +36,13 @@ pub(super) fn check_trait<'tcx>(
     let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
     let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
     res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
-    res = res.and(
-        checker.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty),
-    );
+    res = res.and(checker.check(lang_items.const_param_ty_trait(), |checker| {
+        visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
+    }));
+    res = res.and(checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
+        visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
+    }));
+
     res = res.and(
         checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
     );
@@ -103,7 +107,13 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
         Ok(()) => Ok(()),
         Err(CopyImplementationError::InfringingFields(fields)) => {
             let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
-            Err(infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span))
+            Err(infringing_fields_error(
+                tcx,
+                fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
+                LangItem::Copy,
+                impl_did,
+                span,
+            ))
         }
         Err(CopyImplementationError::NotAnAdt) => {
             let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
@@ -116,7 +126,12 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     }
 }
 
-fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
+fn visit_implementation_of_const_param_ty(
+    checker: &Checker<'_>,
+    kind: LangItem,
+) -> Result<(), ErrorGuaranteed> {
+    assert!(matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
+
     let tcx = checker.tcx;
     let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
@@ -125,21 +140,41 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
 
     let param_env = tcx.param_env(impl_did);
 
-    if let ty::ImplPolarity::Negative = header.polarity {
+    if let ty::ImplPolarity::Negative | ty::ImplPolarity::Reservation = header.polarity {
         return Ok(());
     }
 
     let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
-    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
+    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
         Ok(()) => Ok(()),
         Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
             let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
-            Err(infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span))
+            Err(infringing_fields_error(
+                tcx,
+                fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
+                LangItem::ConstParamTy,
+                impl_did,
+                span,
+            ))
         }
         Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
             let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
         }
+        Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
+            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            Err(infringing_fields_error(
+                tcx,
+                infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
+                LangItem::ConstParamTy,
+                impl_did,
+                span,
+            ))
+        }
+        Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
+            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
+        }
     }
 }
 
@@ -501,9 +536,9 @@ pub fn coerce_unsized_info<'tcx>(
     Ok(CoerceUnsizedInfo { custom_kind: kind })
 }
 
-fn infringing_fields_error(
-    tcx: TyCtxt<'_>,
-    fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>,
+fn infringing_fields_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
     lang_item: LangItem,
     impl_did: LocalDefId,
     impl_span: Span,
@@ -521,13 +556,13 @@ fn infringing_fields_error(
 
     let mut label_spans = Vec::new();
 
-    for (field, ty, reason) in fields {
+    for (span, ty, reason) in infringing_tys {
         // Only report an error once per type.
         if !seen_tys.insert(ty) {
             continue;
         }
 
-        label_spans.push(tcx.def_span(field.did));
+        label_spans.push(span);
 
         match reason {
             InfringingFieldsReason::Fulfill(fulfillment_errors) => {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 16f72f38d60..f2804ce31fa 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -517,9 +517,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> {
         if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
             return;
         }
-        let Some(origin) = self.infcx.type_var_origin(ty) else {
+        let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
             return ty.super_visit_with(self);
         };
+        let origin = self.infcx.type_var_origin(vid);
         if let Some(def_id) = origin.param_def_id {
             self.uncovered_params.insert(def_id);
         }
@@ -546,9 +547,10 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> {
         if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
             return ty;
         }
-        let Some(origin) = self.infcx.type_var_origin(ty) else {
+        let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
             return ty.super_fold_with(self);
         };
+        let origin = self.infcx.type_var_origin(vid);
         if let Some(def_id) = origin.param_def_id {
             // The generics of an `impl` don't have a parent, we can index directly.
             let index = self.generics.param_def_id_to_index[&def_id];
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 5e23d473274..565351268c9 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -84,6 +84,7 @@ pub fn provide(providers: &mut Providers) {
         coroutine_kind,
         coroutine_for_closure,
         is_type_alias_impl_trait,
+        rendered_precise_capturing_args,
         ..*providers
     };
 }
@@ -1882,3 +1883,23 @@ fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool
         _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
     }
 }
+
+fn rendered_precise_capturing_args<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Option<&'tcx [Symbol]> {
+    if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
+        tcx.opt_rpitit_info(def_id.to_def_id())
+    {
+        return tcx.rendered_precise_capturing_args(opaque_def_id);
+    }
+
+    tcx.hir_node_by_def_id(def_id).expect_item().expect_opaque_ty().bounds.iter().find_map(
+        |bound| match bound {
+            hir::GenericBound::Use(args, ..) => {
+                Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
+            }
+            _ => None,
+        },
+    )
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 7930f54038d..349dc9ad00e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -2094,11 +2094,7 @@ pub fn deny_non_region_late_bound(
             format!("late-bound {what} parameter not allowed on {where_}"),
         );
 
-        let guar = if tcx.features().non_lifetime_binders && first {
-            diag.emit()
-        } else {
-            diag.delay_as_bug()
-        };
+        let guar = diag.emit_unless(!tcx.features().non_lifetime_binders || !first);
 
         first = false;
         *arg = ResolvedArg::Error(guar);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 03311fed396..c83788928a9 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -279,6 +279,14 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_const_param_ty_impl_on_unsized)]
+pub struct ConstParamTyImplOnUnsized {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
 pub struct ConstParamTyImplOnNonAdt {
     #[primary_span]
@@ -1605,6 +1613,20 @@ pub(crate) enum UnusedGenericParameterHelp {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_unconstrained_generic_parameter)]
+pub(crate) struct UnconstrainedGenericParameter {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub param_name: Symbol,
+    pub param_def_kind: &'static str,
+    #[note(hir_analysis_const_param_note)]
+    pub const_param_note: Option<()>,
+    #[note(hir_analysis_const_param_note2)]
+    pub const_param_note2: Option<()>,
+}
+
+#[derive(Diagnostic)]
 pub enum UnnamedFieldsRepr<'a> {
     #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)]
     MissingReprC {
@@ -1673,3 +1695,30 @@ pub struct InvalidReceiverTy<'tcx> {
 #[note]
 #[help]
 pub struct EffectsWithoutNextSolver;
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)]
+#[note]
+pub struct CmseCallInputsStackSpill {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub plural: bool,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
+#[note(hir_analysis_note1)]
+#[note(hir_analysis_note2)]
+pub struct CmseCallOutputStackSpill {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cmse_call_generic, code = E0798)]
+pub struct CmseCallGeneric {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index 6426ad9dc18..10be69a9fbb 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -651,7 +651,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             self.path_segment.hir_id,
             num_params_to_take,
         );
-        debug!("suggested_args: {:?}", &suggested_args);
+        debug!("suggested_args: {suggested_args:?}");
 
         match self.angle_brackets {
             AngleBrackets::Missing => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
new file mode 100644
index 00000000000..e99717ce00f
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -0,0 +1,156 @@
+use rustc_errors::DiagCtxtHandle;
+use rustc_hir as hir;
+use rustc_hir::HirId;
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::{self, ParamEnv, TyCtxt};
+use rustc_span::Span;
+use rustc_target::spec::abi;
+
+use crate::errors;
+
+/// Check conditions on inputs and outputs that the cmse ABIs impose: arguments and results MUST be
+/// returned via registers (i.e. MUST NOT spill to the stack). LLVM will also validate these
+/// conditions, but by checking them here rustc can emit nicer error messages.
+pub fn validate_cmse_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    dcx: DiagCtxtHandle<'_>,
+    hir_id: HirId,
+    abi: abi::Abi,
+    fn_sig: ty::PolyFnSig<'tcx>,
+) {
+    if let abi::Abi::CCmseNonSecureCall = abi {
+        let hir_node = tcx.hir_node(hir_id);
+        let hir::Node::Ty(hir::Ty {
+            span: bare_fn_span,
+            kind: hir::TyKind::BareFn(bare_fn_ty),
+            ..
+        }) = hir_node
+        else {
+            // might happen when this ABI is used incorrectly. That will be handled elsewhere
+            return;
+        };
+
+        match is_valid_cmse_inputs(tcx, fn_sig) {
+            Ok(Ok(())) => {}
+            Ok(Err(index)) => {
+                // fn(x: u32, u32, u32, u16, y: u16) -> u32,
+                //                           ^^^^^^
+                let span = bare_fn_ty.param_names[index]
+                    .span
+                    .to(bare_fn_ty.decl.inputs[index].span)
+                    .to(bare_fn_ty.decl.inputs.last().unwrap().span);
+                let plural = bare_fn_ty.param_names.len() - index != 1;
+                dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural });
+            }
+            Err(layout_err) => {
+                if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
+                    dcx.emit_err(err);
+                }
+            }
+        }
+
+        match is_valid_cmse_output(tcx, fn_sig) {
+            Ok(true) => {}
+            Ok(false) => {
+                let span = bare_fn_ty.decl.output.span();
+                dcx.emit_err(errors::CmseCallOutputStackSpill { span });
+            }
+            Err(layout_err) => {
+                if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
+                    dcx.emit_err(err);
+                }
+            }
+        };
+    }
+}
+
+/// Returns whether the inputs will fit into the available registers
+fn is_valid_cmse_inputs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    fn_sig: ty::PolyFnSig<'tcx>,
+) -> Result<Result<(), usize>, &'tcx LayoutError<'tcx>> {
+    let mut span = None;
+    let mut accum = 0u64;
+
+    for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
+        let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
+
+        let align = layout.layout.align().abi.bytes();
+        let size = layout.layout.size().bytes();
+
+        accum += size;
+        accum = accum.next_multiple_of(Ord::max(4, align));
+
+        // i.e. exceeds 4 32-bit registers
+        if accum > 16 {
+            span = span.or(Some(index));
+        }
+    }
+
+    match span {
+        None => Ok(Ok(())),
+        Some(span) => Ok(Err(span)),
+    }
+}
+
+/// Returns whether the output will fit into the available registers
+fn is_valid_cmse_output<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    fn_sig: ty::PolyFnSig<'tcx>,
+) -> Result<bool, &'tcx LayoutError<'tcx>> {
+    let mut ret_ty = fn_sig.output().skip_binder();
+    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
+    let size = layout.layout.size().bytes();
+
+    if size <= 4 {
+        return Ok(true);
+    } else if size > 8 {
+        return Ok(false);
+    }
+
+    // next we need to peel any repr(transparent) layers off
+    'outer: loop {
+        let ty::Adt(adt_def, args) = ret_ty.kind() else {
+            break;
+        };
+
+        if !adt_def.repr().transparent() {
+            break;
+        }
+
+        // the first field with non-trivial size and alignment must be the data
+        for variant_def in adt_def.variants() {
+            for field_def in variant_def.fields.iter() {
+                let ty = field_def.ty(tcx, args);
+                let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?;
+
+                if !layout.layout.is_1zst() {
+                    ret_ty = ty;
+                    continue 'outer;
+                }
+            }
+        }
+    }
+
+    Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64)
+}
+
+fn cmse_layout_err<'tcx>(
+    layout_err: &'tcx LayoutError<'tcx>,
+    span: Span,
+) -> Option<crate::errors::CmseCallGeneric> {
+    use LayoutError::*;
+
+    match layout_err {
+        Unknown(ty) => {
+            if ty.is_impl_trait() {
+                None // prevent double reporting of this error
+            } else {
+                Some(errors::CmseCallGeneric { span })
+            }
+        }
+        SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
+            None // not our job to report these
+        }
+    }
+}
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 7b8a03def86..d6eb1a66902 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -14,6 +14,7 @@
 //! trait references and bounds.
 
 mod bounds;
+mod cmse;
 pub mod errors;
 pub mod generics;
 mod lint;
@@ -1087,7 +1088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     );
 
                     let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
-                    if let Some(suggested_name) = find_best_match_for_name(
+                    if let Some(variant_name) = find_best_match_for_name(
                         &adt_def
                             .variants()
                             .iter()
@@ -1095,12 +1096,66 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             .collect::<Vec<Symbol>>(),
                         assoc_ident.name,
                         None,
-                    ) {
-                        err.span_suggestion(
-                            assoc_ident.span,
+                    ) && let Some(variant) =
+                        adt_def.variants().iter().find(|s| s.name == variant_name)
+                    {
+                        let mut suggestion = vec![(assoc_ident.span, variant_name.to_string())];
+                        if let hir::Node::Stmt(hir::Stmt {
+                            kind: hir::StmtKind::Semi(ref expr),
+                            ..
+                        })
+                        | hir::Node::Expr(ref expr) = tcx.parent_hir_node(hir_ref_id)
+                            && let hir::ExprKind::Struct(..) = expr.kind
+                        {
+                            match variant.ctor {
+                                None => {
+                                    // struct
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        if variant.fields.is_empty() {
+                                            format!("{variant_name} {{}}")
+                                        } else {
+                                            format!(
+                                                "{variant_name} {{ {} }}",
+                                                variant
+                                                    .fields
+                                                    .iter()
+                                                    .map(|f| format!("{}: /* value */", f.name))
+                                                    .collect::<Vec<_>>()
+                                                    .join(", ")
+                                            )
+                                        },
+                                    )];
+                                }
+                                Some((hir::def::CtorKind::Fn, def_id)) => {
+                                    // tuple
+                                    let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
+                                    let inputs = fn_sig.inputs().skip_binder();
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        format!(
+                                            "{variant_name}({})",
+                                            inputs
+                                                .iter()
+                                                .map(|i| format!("/* {i} */"))
+                                                .collect::<Vec<_>>()
+                                                .join(", ")
+                                        ),
+                                    )];
+                                }
+                                Some((hir::def::CtorKind::Const, _)) => {
+                                    // unit
+                                    suggestion = vec![(
+                                        assoc_ident.span.with_hi(expr.span.hi()),
+                                        variant_name.to_string(),
+                                    )];
+                                }
+                            }
+                        }
+                        err.multipart_suggestion_verbose(
                             "there is a variant with a similar name",
-                            suggested_name,
-                            Applicability::MaybeIncorrect,
+                            suggestion,
+                            Applicability::HasPlaceholders,
                         );
                     } else {
                         err.span_label(
@@ -2324,6 +2379,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
         let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
 
+        // reject function types that violate cmse ABI requirements
+        cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
+
         // Find any late-bound regions declared in return type that do
         // not appear in the arguments. These are not well-formed.
         //
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 5cc1ec71757..f0fcbd5528f 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -8,15 +8,15 @@
 //! specialization errors. These things can (and probably should) be
 //! fixed, but for the moment it's easier to do these checks early.
 
-use crate::constrained_generic_params as cgp;
+use crate::{constrained_generic_params as cgp, errors::UnconstrainedGenericParameter};
 use min_specialization::check_min_specialization;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::{ErrorGuaranteed, Span, Symbol};
+use rustc_span::ErrorGuaranteed;
 
 mod min_specialization;
 
@@ -117,43 +117,34 @@ fn enforce_impl_params_are_constrained(
 
     let mut res = Ok(());
     for param in &impl_generics.own_params {
-        match param.kind {
+        let err = match param.kind {
             // Disallow ANY unconstrained type parameters.
             ty::GenericParamDefKind::Type { .. } => {
                 let param_ty = ty::ParamTy::for_def(param);
-                if !input_parameters.contains(&cgp::Parameter::from(param_ty)) {
-                    res = Err(report_unused_parameter(
-                        tcx,
-                        tcx.def_span(param.def_id),
-                        "type",
-                        param_ty.name,
-                    ));
-                }
+                !input_parameters.contains(&cgp::Parameter::from(param_ty))
             }
             ty::GenericParamDefKind::Lifetime => {
                 let param_lt = cgp::Parameter::from(param.to_early_bound_region_data());
-                if lifetimes_in_associated_types.contains(&param_lt) && // (*)
+                lifetimes_in_associated_types.contains(&param_lt) && // (*)
                     !input_parameters.contains(&param_lt)
-                {
-                    res = Err(report_unused_parameter(
-                        tcx,
-                        tcx.def_span(param.def_id),
-                        "lifetime",
-                        param.name,
-                    ));
-                }
             }
             ty::GenericParamDefKind::Const { .. } => {
                 let param_ct = ty::ParamConst::for_def(param);
-                if !input_parameters.contains(&cgp::Parameter::from(param_ct)) {
-                    res = Err(report_unused_parameter(
-                        tcx,
-                        tcx.def_span(param.def_id),
-                        "const",
-                        param_ct.name,
-                    ));
-                }
+                !input_parameters.contains(&cgp::Parameter::from(param_ct))
             }
+        };
+        if err {
+            let const_param_note =
+                matches!(param.kind, ty::GenericParamDefKind::Const { .. }).then_some(());
+            let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
+                span: tcx.def_span(param.def_id),
+                param_name: param.name,
+                param_def_kind: tcx.def_descr(param.def_id),
+                const_param_note,
+                const_param_note2: const_param_note,
+            });
+            diag.code(E0207);
+            res = Err(diag.emit());
         }
     }
     res
@@ -177,30 +168,3 @@ fn enforce_impl_params_are_constrained(
     // associated types. I believe this is sound, because lifetimes
     // used elsewhere are not projected back out.
 }
-
-fn report_unused_parameter(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    kind: &str,
-    name: Symbol,
-) -> ErrorGuaranteed {
-    let mut err = struct_span_code_err!(
-        tcx.dcx(),
-        span,
-        E0207,
-        "the {} parameter `{}` is not constrained by the \
-        impl trait, self type, or predicates",
-        kind,
-        name
-    );
-    err.span_label(span, format!("unconstrained {kind} parameter"));
-    if kind == "const" {
-        err.note(
-            "expressions using a const parameter must map each value to a distinct output value",
-        );
-        err.note(
-            "proving the result of expressions other than the parameter are unique is not supported",
-        );
-    }
-    err.emit()
-}
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 5b8b6e98125..2e5f99bb78b 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
@@ -78,7 +78,7 @@ use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_span::{ErrorGuaranteed, Span};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index af08f50f655..d953736c28c 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -249,7 +249,7 @@ fn check_explicit_predicates<'tcx>(
     let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
 
     for (outlives_predicate, &span) in explicit_predicates.as_ref().skip_binder() {
-        debug!("outlives_predicate = {:?}", &outlives_predicate);
+        debug!("outlives_predicate = {outlives_predicate:?}");
 
         // Careful: If we are inferring the effects of a `dyn Trait<..>`
         // type, then when we look up the predicates for `Trait`,
@@ -289,12 +289,12 @@ fn check_explicit_predicates<'tcx>(
             && let GenericArgKind::Type(ty) = outlives_predicate.0.unpack()
             && ty.walk().any(|arg| arg == self_ty.into())
         {
-            debug!("skipping self ty = {:?}", &ty);
+            debug!("skipping self ty = {ty:?}");
             continue;
         }
 
         let predicate = explicit_predicates.rebind(*outlives_predicate).instantiate(tcx, args);
-        debug!("predicate = {:?}", &predicate);
+        debug!("predicate = {predicate:?}");
         insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 341d533492d..65229722771 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -495,6 +495,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     err.span_label(self.span, "invalid cast");
                 }
 
+                fcx.suggest_no_capture_closure(&mut err, self.cast_ty, self.expr_ty);
                 self.try_suggest_collection_to_bool(fcx, &mut err);
 
                 err.emit();
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 08de871f6fa..79854976bdd 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -18,7 +18,6 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::error_reporting::traits::ArgKind;
-use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _;
 use rustc_trait_selection::traits;
 use rustc_type_ir::ClosureKind;
 use std::iter;
@@ -734,13 +733,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .map(|ty| ArgKind::from_expected_ty(*ty, None))
             .collect();
         let (closure_span, closure_arg_span, found_args) =
-            match self.get_fn_like_arguments(expr_map_node) {
+            match self.err_ctxt().get_fn_like_arguments(expr_map_node) {
                 Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args),
                 None => (None, None, Vec::new()),
             };
         let expected_span =
             expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
         let guar = self
+            .err_ctxt()
             .report_arg_count_mismatch(
                 expected_span,
                 closure_span,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 5e2a68e1f02..1bfe9734217 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -58,8 +58,6 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, DesugaringKind, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtSelectionErrExt as _;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index e957330d9a1..0d002c52fbb 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -53,8 +53,6 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
@@ -519,7 +517,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_error(tcx, e)
             }
             Res::Def(DefKind::Variant, _) => {
-                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
+                let e = report_unexpected_variant_res(
+                    tcx,
+                    res,
+                    Some(expr),
+                    qpath,
+                    expr.span,
+                    E0533,
+                    "value",
+                );
                 Ty::new_error(tcx, e)
             }
             _ => {
@@ -2210,8 +2216,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
-        match variant.ctor_kind() {
-            Some(CtorKind::Fn) => match ty.kind() {
+        match variant.ctor {
+            Some((CtorKind::Fn, def_id)) => match ty.kind() {
                 ty::Adt(adt, ..) if adt.is_enum() => {
                     err.span_label(
                         variant_ident_span,
@@ -2222,28 +2228,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ),
                     );
                     err.span_label(field.ident.span, "field does not exist");
+                    let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
+                    let inputs = fn_sig.inputs().skip_binder();
+                    let fields = format!(
+                        "({})",
+                        inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
+                    );
+                    let (replace_span, sugg) = match expr.kind {
+                        hir::ExprKind::Struct(qpath, ..) => {
+                            (qpath.span().shrink_to_hi().with_hi(expr.span.hi()), fields)
+                        }
+                        _ => {
+                            (expr.span, format!("{ty}::{variant}{fields}", variant = variant.name))
+                        }
+                    };
                     err.span_suggestion_verbose(
-                        expr.span,
+                        replace_span,
                         format!(
                             "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
                             adt = ty,
                             variant = variant.name,
                         ),
-                        format!(
-                            "{adt}::{variant}(/* fields */)",
-                            adt = ty,
-                            variant = variant.name,
-                        ),
+                        sugg,
                         Applicability::HasPlaceholders,
                     );
                 }
                 _ => {
                     err.span_label(variant_ident_span, format!("`{ty}` defined here"));
                     err.span_label(field.ident.span, "field does not exist");
+                    let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
+                    let inputs = fn_sig.inputs().skip_binder();
+                    let fields = format!(
+                        "({})",
+                        inputs.iter().map(|i| format!("/* {i} */")).collect::<Vec<_>>().join(", ")
+                    );
                     err.span_suggestion_verbose(
                         expr.span,
                         format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
-                        format!("{ty}(/* fields */)"),
+                        format!("{ty}{fields}"),
                         Applicability::HasPlaceholders,
                     );
                 }
@@ -2550,7 +2572,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base: &'tcx hir::Expr<'tcx>,
         ty: Ty<'tcx>,
     ) {
-        let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
+        let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else {
             err.span_label(field_ident.span, "unknown field");
             return;
         };
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 3cecbfd4275..9f3aeacd2c5 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -175,7 +175,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         };
         debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
 
-        let span = self.infcx.type_var_origin(ty).map(|origin| origin.span).unwrap_or(DUMMY_SP);
+        let span = ty.ty_vid().map_or(DUMMY_SP, |vid| self.infcx.type_var_origin(vid).span);
         self.demand_eqtype(span, ty, fallback);
         self.fallback_has_occurred.set(true);
         true
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index cc2c1a302f5..87e8afe6dd1 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -19,7 +19,6 @@ use rustc_hir_analysis::hir_ty_lowering::{
     GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
 };
 use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
-use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
 use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
@@ -37,7 +36,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 use rustc_target::abi::FieldIdx;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_trait_selection::traits::{
     self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
 };
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index f7abba35706..8e35efa53ae 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -338,8 +338,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
             type Result = ControlFlow<ty::GenericArg<'tcx>>;
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
-                if let Some(origin) = self.0.type_var_origin(ty)
-                    && let Some(def_id) = origin.param_def_id
+                if let ty::Infer(ty::TyVar(vid)) = *ty.kind()
+                    && let Some(def_id) = self.0.type_var_origin(vid).param_def_id
                     && let generics = self.0.tcx.generics_of(self.1)
                     && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
                     && let Some(arg) =
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 2b4025ca808..7c96a991bed 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -29,7 +29,6 @@ use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
 use rustc_hir_analysis::check::potentially_plural_count;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_index::IndexVec;
-use rustc_infer::error_reporting::infer::{FailureCode, ObligationCauseExt};
 use rustc_infer::infer::TypeTrace;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
@@ -39,6 +38,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, BytePos, Span, DUMMY_SP};
+use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 3fe87c03e74..39d73dae015 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -15,13 +15,13 @@ use hir::def_id::CRATE_DEF_ID;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
-use rustc_infer::error_reporting::infer::sub_relations::SubRelations;
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
 use rustc_infer::infer;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::{self, sym, Span, DUMMY_SP};
+use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
+use rustc_trait_selection::error_reporting::TypeErrCtxt;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use std::cell::{Cell, RefCell};
@@ -162,9 +162,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Creates an `TypeErrCtxt` with a reference to the in-progress
     /// `TypeckResults` which is used for diagnostics.
-    /// Use [`InferCtxt::err_ctxt`] to start one without a `TypeckResults`.
+    /// Use [`InferCtxtErrorExt::err_ctxt`] to start one without a `TypeckResults`.
     ///
-    /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
+    /// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
     pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
         let mut sub_relations = SubRelations::default();
         sub_relations.add_constraints(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index b3b4c5a56fb..fe7495deb2b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -32,8 +32,8 @@ use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, Symbol};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
 use rustc_trait_selection::error_reporting::traits::DefIdOrName;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -1107,12 +1107,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .tcx
                     .instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
                 let ty = match self.tcx.asyncness(fn_id) {
-                    ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
-                        span_bug!(
-                            fn_decl.output.span(),
-                            "failed to get output type of async function"
-                        )
-                    }),
+                    ty::Asyncness::Yes => {
+                        self.err_ctxt().get_impl_future_output_ty(ty).unwrap_or_else(|| {
+                            span_bug!(
+                                fn_decl.output.span(),
+                                "failed to get output type of async function"
+                            )
+                        })
+                    }
                     ty::Asyncness::No => ty,
                 };
                 let ty = self.normalize(expr.span, ty);
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index bdbdcee6446..2c793664509 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -53,7 +53,7 @@ use crate::expectation::Expectation;
 use crate::fn_ctxt::LoweredTy;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
@@ -346,6 +346,7 @@ impl<'tcx> EnclosingBreakables<'tcx> {
 fn report_unexpected_variant_res(
     tcx: TyCtxt<'_>,
     res: Res,
+    expr: Option<&hir::Expr<'_>>,
     qpath: &hir::QPath<'_>,
     span: Span,
     err_code: ErrCode,
@@ -356,7 +357,7 @@ fn report_unexpected_variant_res(
         _ => res.descr(),
     };
     let path_str = rustc_hir_pretty::qpath_to_string(&tcx, qpath);
-    let err = tcx
+    let mut err = tcx
         .dcx()
         .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
         .with_code(err_code);
@@ -366,6 +367,61 @@ fn report_unexpected_variant_res(
             err.with_span_label(span, "`fn` calls are not allowed in patterns")
                 .with_help(format!("for more information, visit {patterns_url}"))
         }
+        Res::Def(DefKind::Variant, _) if let Some(expr) = expr => {
+            err.span_label(span, format!("not a {expected}"));
+            let variant = tcx.expect_variant_res(res);
+            let sugg = if variant.fields.is_empty() {
+                " {}".to_string()
+            } else {
+                format!(
+                    " {{ {} }}",
+                    variant
+                        .fields
+                        .iter()
+                        .map(|f| format!("{}: /* value */", f.name))
+                        .collect::<Vec<_>>()
+                        .join(", ")
+                )
+            };
+            let descr = "you might have meant to create a new value of the struct";
+            let mut suggestion = vec![];
+            match tcx.parent_hir_node(expr.hir_id) {
+                hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Call(..),
+                    span: call_span,
+                    ..
+                }) => {
+                    suggestion.push((span.shrink_to_hi().with_hi(call_span.hi()), sugg));
+                }
+                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(..), hir_id, .. }) => {
+                    suggestion.push((expr.span.shrink_to_lo(), "(".to_string()));
+                    if let hir::Node::Expr(drop_temps) = tcx.parent_hir_node(*hir_id)
+                        && let hir::ExprKind::DropTemps(_) = drop_temps.kind
+                        && let hir::Node::Expr(parent) = tcx.parent_hir_node(drop_temps.hir_id)
+                        && let hir::ExprKind::If(condition, block, None) = parent.kind
+                        && condition.hir_id == drop_temps.hir_id
+                        && let hir::ExprKind::Block(block, _) = block.kind
+                        && block.stmts.is_empty()
+                        && let Some(expr) = block.expr
+                        && let hir::ExprKind::Path(..) = expr.kind
+                    {
+                        // Special case: you can incorrectly write an equality condition:
+                        // if foo == Struct { field } { /* if body */ }
+                        // which should have been written
+                        // if foo == (Struct { field }) { /* if body */ }
+                        suggestion.push((block.span.shrink_to_hi(), ")".to_string()));
+                    } else {
+                        suggestion.push((span.shrink_to_hi().with_hi(expr.span.hi()), sugg));
+                    }
+                }
+                _ => {
+                    suggestion.push((span.shrink_to_hi(), sugg));
+                }
+            }
+
+            err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
+            err
+        }
         _ => err.with_span_label(span, format!("not a {expected}")),
     }
     .emit()
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e817685e41c..9cb6124ab21 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -12,7 +12,6 @@ use rustc_hir::HirId;
 use rustc_hir_analysis::autoderef::{self, Autoderef};
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCauseCode;
@@ -34,6 +33,7 @@ use rustc_span::edit_distance::{
 };
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
+use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 425289ce3c5..da3ac2fea98 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -36,7 +36,6 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span};
 use rustc_span::{Symbol, DUMMY_SP};
 use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
-use rustc_trait_selection::error_reporting::traits::on_unimplemented::TypeErrCtxtExt as _;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
@@ -1265,9 +1264,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                         (
                             match parent_pred {
-                                None => format!("`{}`", &p),
+                                None => format!("`{p}`"),
                                 Some(parent_pred) => match format_pred(*parent_pred) {
-                                    None => format!("`{}`", &p),
+                                    None => format!("`{p}`"),
                                     Some((parent_p, _)) => {
                                         if !suggested
                                             && !suggested_bounds.contains(pred)
@@ -1596,16 +1595,127 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // that had unsatisfied trait bounds
         if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
             let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
-            if let Some(suggestion) = edit_distance::find_best_match_for_name(
+            if let Some(var_name) = edit_distance::find_best_match_for_name(
                 &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
                 item_name.name,
                 None,
-            ) {
-                err.span_suggestion(
-                    span,
+            ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == var_name)
+            {
+                let mut suggestion = vec![(span, var_name.to_string())];
+                if let SelfSource::QPath(ty) = source
+                    && let hir::Node::Expr(ref path_expr) = self.tcx.parent_hir_node(ty.hir_id)
+                    && let hir::ExprKind::Path(_) = path_expr.kind
+                    && let hir::Node::Stmt(hir::Stmt {
+                        kind: hir::StmtKind::Semi(ref parent), ..
+                    })
+                    | hir::Node::Expr(ref parent) = self.tcx.parent_hir_node(path_expr.hir_id)
+                {
+                    let replacement_span =
+                        if let hir::ExprKind::Call(..) | hir::ExprKind::Struct(..) = parent.kind {
+                            // We want to replace the parts that need to go, like `()` and `{}`.
+                            span.with_hi(parent.span.hi())
+                        } else {
+                            span
+                        };
+                    match (variant.ctor, parent.kind) {
+                        (None, hir::ExprKind::Struct(..)) => {
+                            // We want a struct and we have a struct. We won't suggest changing
+                            // the fields (at least for now).
+                            suggestion = vec![(span, var_name.to_string())];
+                        }
+                        (None, _) => {
+                            // struct
+                            suggestion = vec![(
+                                replacement_span,
+                                if variant.fields.is_empty() {
+                                    format!("{var_name} {{}}")
+                                } else {
+                                    format!(
+                                        "{var_name} {{ {} }}",
+                                        variant
+                                            .fields
+                                            .iter()
+                                            .map(|f| format!("{}: /* value */", f.name))
+                                            .collect::<Vec<_>>()
+                                            .join(", ")
+                                    )
+                                },
+                            )];
+                        }
+                        (Some((hir::def::CtorKind::Const, _)), _) => {
+                            // unit, remove the `()`.
+                            suggestion = vec![(replacement_span, var_name.to_string())];
+                        }
+                        (
+                            Some((hir::def::CtorKind::Fn, def_id)),
+                            hir::ExprKind::Call(rcvr, args),
+                        ) => {
+                            let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
+                            let inputs = fn_sig.inputs().skip_binder();
+                            // FIXME: reuse the logic for "change args" suggestion to account for types
+                            // involved and detect things like substitution.
+                            match (inputs, args) {
+                                (inputs, []) => {
+                                    // Add arguments.
+                                    suggestion.push((
+                                        rcvr.span.shrink_to_hi().with_hi(parent.span.hi()),
+                                        format!(
+                                            "({})",
+                                            inputs
+                                                .iter()
+                                                .map(|i| format!("/* {i} */"))
+                                                .collect::<Vec<String>>()
+                                                .join(", ")
+                                        ),
+                                    ));
+                                }
+                                (_, [arg]) if inputs.len() != args.len() => {
+                                    // Replace arguments.
+                                    suggestion.push((
+                                        arg.span,
+                                        inputs
+                                            .iter()
+                                            .map(|i| format!("/* {i} */"))
+                                            .collect::<Vec<String>>()
+                                            .join(", "),
+                                    ));
+                                }
+                                (_, [arg_start, .., arg_end]) if inputs.len() != args.len() => {
+                                    // Replace arguments.
+                                    suggestion.push((
+                                        arg_start.span.to(arg_end.span),
+                                        inputs
+                                            .iter()
+                                            .map(|i| format!("/* {i} */"))
+                                            .collect::<Vec<String>>()
+                                            .join(", "),
+                                    ));
+                                }
+                                // Argument count is the same, keep as is.
+                                _ => {}
+                            }
+                        }
+                        (Some((hir::def::CtorKind::Fn, def_id)), _) => {
+                            let fn_sig = self.tcx.fn_sig(def_id).instantiate_identity();
+                            let inputs = fn_sig.inputs().skip_binder();
+                            suggestion = vec![(
+                                replacement_span,
+                                format!(
+                                    "{var_name}({})",
+                                    inputs
+                                        .iter()
+                                        .map(|i| format!("/* {i} */"))
+                                        .collect::<Vec<String>>()
+                                        .join(", ")
+                                ),
+                            )];
+                        }
+                    }
+                }
+                err.multipart_suggestion_verbose(
                     "there is a variant with a similar name",
                     suggestion,
-                    Applicability::MaybeIncorrect,
+                    Applicability::HasPlaceholders,
                 );
             }
         }
@@ -3165,7 +3275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         return_type: Option<Ty<'tcx>>,
     ) {
-        let output_ty = match self.get_impl_future_output_ty(ty) {
+        let output_ty = match self.err_ctxt().get_impl_future_output_ty(ty) {
             Some(output_ty) => self.resolve_vars_if_possible(output_ty),
             _ => return,
         };
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index d59b8276d3a..7b5845388d4 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -18,7 +18,6 @@ use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{FulfillmentError, ObligationCtxt};
 use rustc_type_ir::TyKind::*;
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 6d1e9ff1f95..8afc6a48dfc 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1023,7 +1023,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
-                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected);
+                let e =
+                    report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0533, expected);
                 return Ty::new_error(tcx, e);
             }
             Res::SelfCtor(def_id) => {
@@ -1036,6 +1037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let e = report_unexpected_variant_res(
                         tcx,
                         res,
+                        None,
                         qpath,
                         pat.span,
                         E0533,
@@ -1189,7 +1191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         let report_unexpected_res = |res: Res| {
             let expected = "tuple struct or tuple variant";
-            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0164, expected);
+            let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
             on_error(e);
             e
         };
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 611854ce2af..4ef7f37b309 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -8,7 +8,6 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::HirId;
-use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@@ -18,7 +17,7 @@ use rustc_middle::ty::TypeSuperFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_trait_selection::solve;
 
 use std::mem;
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index c279195a7e9..e51734ff7a7 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -1,397 +1,5 @@
-infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
-    *[false] {""}
-}
-infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
-    *[false] {""}
-}
-infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
-    [true] , for some specific lifetime `'{$lifetime}`
-    *[false] {""}
-}
-
-infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`
-
-infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
-infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
-infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
-infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
-    [true] ...
-    *[false] {""}
-}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
-infer_ascribe_user_type_prove_predicate = ...so that the where clause holds
-
-infer_await_both_futures = consider `await`ing on both `Future`s
-infer_await_future = consider `await`ing on the `Future`
-infer_await_note = calling an async function returns a future
-
-infer_but_calling_introduces = {$has_param_name ->
-    [true] `{$param_name}`
-    *[false] `fn` parameter
-} has {$lifetime_kind ->
-    [true] lifetime `{$lifetime}`
-    *[false] an anonymous lifetime `'_`
-} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
-    .label1 = {$has_lifetime ->
-        [true] lifetime `{$lifetime}`
-        *[false] an anonymous lifetime `'_`
-    }
-    .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
-        [true] `impl` of `{$impl_path}`
-        *[false] inherent `impl`
-    }
-
-infer_but_needs_to_satisfy = {$has_param_name ->
-    [true] `{$param_name}`
-    *[false] `fn` parameter
-} has {$has_lifetime ->
-    [true] lifetime `{$lifetime}`
-    *[false] an anonymous lifetime `'_`
-} but it needs to satisfy a `'static` lifetime requirement
-    .influencer = this data with {$has_lifetime ->
-        [true] lifetime `{$lifetime}`
-        *[false] an anonymous lifetime `'_`
-    }...
-    .require = {$spans_empty ->
-        *[true] ...is used and required to live as long as `'static` here
-        [false] ...and is required to live as long as `'static` here
-    }
-    .used_here = ...is used here...
-    .introduced_by_bound = `'static` lifetime requirement introduced by this bound
-
-infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
-infer_consider_specifying_length = consider specifying the actual array length
-infer_data_flows = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] {""}
-} flows{$label_var2_exists ->
-    [true] {" "}into `{$label_var2}`
-    *[false] {""}
-} here
-
-infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
-infer_data_returned = ...but data{$label_var1_exists ->
-    [true] {" "}from `{$label_var1}`
-    *[false] {""}
-} is returned here
-
-infer_declared_different = this parameter and the return type are declared with different lifetimes...
-infer_declared_multiple = this type is declared with multiple lifetimes...
-infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
-infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
-infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
-
-infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
-
-infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
-
-infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
-    .label = lifetime `{$named}` required
-
-infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
-    .label = lifetime `{$named}` required
-
-infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
-
-infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
-infer_fps_cast = consider casting to a fn pointer
-infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
-
-infer_fps_items_are_distinct = fn items are distinct from fn pointers
-infer_fps_remove_ref = consider removing the reference
-infer_fps_use_ref = consider using a reference
-infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
-
-infer_full_type_written = the full type name has been written to '{$path}'
-
-infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
-infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
-infer_label_bad = {$bad_kind ->
-    *[other] cannot infer type
-    [more_info] cannot infer {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] the value of const parameter
-        [const] the value of the constant
-    } `{$name}`{$has_parent ->
-        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
-        *[false] {""}
-    }
-}
-
-infer_lf_bound_not_satisfied = lifetime bound not satisfied
-infer_lifetime_mismatch = lifetime mismatch
-
-infer_lifetime_param_suggestion = consider {$is_reuse ->
-    [true] reusing
-    *[false] introducing
-} a named lifetime parameter{$is_impl ->
-    [true] {" "}and update trait if needed
-    *[false] {""}
-}
-infer_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
-
-infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
-infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
-infer_meant_str_literal = if you meant to write a string literal, use double quotes
-infer_mismatched_static_lifetime = incompatible lifetime on type
-infer_more_targeted = {$has_param_name ->
-    [true] `{$param_name}`
-    *[false] `fn` parameter
-} has {$has_lifetime ->
-    [true] lifetime `{$lifetime}`
-    *[false] an anonymous lifetime `'_`
-} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
-
-infer_msl_introduces_static = introduces a `'static` lifetime requirement
-infer_msl_unmet_req = because this has an unmet lifetime requirement
-
-infer_nothing = {""}
-
-infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
-infer_oc_closure_selfref = closure/coroutine type that references itself
-infer_oc_const_compat = const not compatible with trait
-infer_oc_fn_lang_correct_type = {$lang_item_name ->
-        [panic_impl] `#[panic_handler]`
-        *[lang_item_name] lang item `{$lang_item_name}`
-    } function has wrong type
-infer_oc_fn_main_correct_type = `main` function has wrong type
-infer_oc_fn_start_correct_type = `#[start]` function has wrong type
-infer_oc_generic = mismatched types
-
-infer_oc_if_else_different = `if` and `else` have incompatible types
-infer_oc_intrinsic_correct_type = intrinsic has wrong type
-infer_oc_match_compat = `match` arms have incompatible types
-infer_oc_method_compat = method not compatible with trait
-infer_oc_method_correct_type = mismatched `self` parameter type
-infer_oc_no_diverge = `else` clause of `let...else` does not diverge
-infer_oc_no_else = `if` may be missing an `else` clause
-infer_oc_try_compat = `?` operator has incompatible types
-infer_oc_type_compat = type not compatible with trait
-infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
-    .label = opaque type defined here
-
 infer_opaque_hidden_type =
     opaque type's hidden type cannot be another opaque type from the same scope
     .label = one of the two opaque types used here has to be outside its defining scope
     .opaque_type = opaque type whose hidden type is being assigned
     .hidden_type = opaque type being used as hidden type
-
-infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
-infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
-
-infer_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it
-infer_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}`
-
-infer_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
-
-infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
-infer_prlf_defined_without_sub = the lifetime defined here...
-infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
-
-infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
-infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
-infer_reborrow = ...so that reference does not outlive borrowed content
-infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
-
-infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
-infer_region_explanation = {$pref_kind ->
-    *[should_not_happen] [{$pref_kind}]
-    [ref_valid_for] ...the reference is valid for
-    [content_valid_for] ...but the borrowed content is only valid for
-    [type_obj_valid_for] object type is valid for
-    [source_pointer_valid_for] source pointer is only valid for
-    [type_satisfy] type must satisfy
-    [type_outlive] type must outlive
-    [lf_param_instantiated_with] lifetime parameter instantiated with
-    [lf_param_must_outlive] but lifetime parameter must outlive
-    [lf_instantiated_with] lifetime instantiated with
-    [lf_must_outlive] but lifetime must outlive
-    [pointer_valid_for] the pointer is valid for
-    [data_valid_for] but the referenced data is only valid for
-    [empty] {""}
-}{$pref_kind ->
-    [empty] {""}
-    *[other] {" "}
-}{$desc_kind ->
-    *[should_not_happen] [{$desc_kind}]
-    [restatic] the static lifetime
-    [revar] lifetime {$desc_arg}
-    [as_defined] the lifetime `{$desc_arg}` as defined here
-    [as_defined_anon] the anonymous lifetime as defined here
-    [defined_here] the anonymous lifetime defined here
-    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
-}{$suff_kind ->
-    *[should_not_happen] [{$suff_kind}]
-    [empty]{""}
-    [continues] ...
-    [req_by_binding] {" "}as required by this binding
-}
-
-infer_relate_object_bound = ...so that it can be closed over into an object
-infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
-    [true] ...
-    *[false] {""}
-}
-infer_relate_param_bound_2 = ...that is required by this bound
-infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
-infer_ril_because_of = because of this returned expression
-infer_ril_introduced_by = requirement introduced by this return type
-infer_ril_introduced_here = `'static` requirement introduced here
-infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
-
-infer_source_kind_closure_return =
-    try giving this closure an explicit return type
-
-# coroutine_kind  may need to be translated
-infer_source_kind_fully_qualified =
-    try using a fully qualified path to specify the expected types
-
-infer_source_kind_subdiag_generic_label =
-    cannot infer {$is_type ->
-    [true] type
-    *[false] the value
-    } of the {$is_type ->
-    [true] type
-    *[false] const
-    } {$parent_exists ->
-    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
-    *[false] parameter {$param_name}
-    }
-
-infer_source_kind_subdiag_generic_suggestion =
-    consider specifying the generic {$arg_count ->
-    [one] argument
-    *[other] arguments
-    }
-
-infer_source_kind_subdiag_let = {$kind ->
-    [with_pattern] consider giving `{$name}` an explicit type
-    [closure] consider giving this closure parameter an explicit type
-    *[other] consider giving this pattern a type
-}{$x_kind ->
-    [has_name] , where the {$prefix_kind ->
-        *[type] type for {$prefix}
-        [const_with_param] value of const parameter
-        [const] value of the constant
-    } `{$arg_name}` is specified
-    [underscore] , where the placeholders `_` are specified
-    *[empty] {""}
-}
-
-infer_srs_add = consider returning the local binding `{$ident}`
-infer_srs_add_one = consider returning one of these bindings
-
-infer_srs_remove = consider removing this semicolon
-infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
-infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
-
-infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
-infer_subtype = ...so that the {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [fn_lang_correct_type] lang item function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-infer_subtype_2 = ...so that {$requirement ->
-    [method_compat] method type is compatible with trait
-    [type_compat] associated type is compatible with trait
-    [const_compat] const is compatible with trait
-    [expr_assignable] expression is assignable
-    [if_else_different] `if` and `else` have incompatible types
-    [no_else] `if` missing an `else` returns `()`
-    [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] `#[start]` function has the correct type
-    [fn_lang_correct_type] lang item function has the correct type
-    [intrinsic_correct_type] intrinsic has the correct type
-    [method_correct_type] method receiver has the correct type
-    *[other] types are compatible
-}
-
-infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
-
-infer_suggest_add_let_for_letchains = consider adding `let`
-
-infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
-infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
-
-infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
-infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
-    .found = found `{$found}`
-    .expected = expected `{$expected}`
-    .expected_found = expected signature `{$expected}`
-               {"   "}found signature `{$found}`
-
-infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
-    .label_satisfy = doesn't satisfy where-clause
-    .label_where = due to a where-clause on `{$def_id}`...
-    .label_dup = implementation of `{$trait_def_id}` is not general enough
-
-infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
-
-infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
-
-infer_type_annotations_needed = {$source_kind ->
-    [closure] type annotations needed for the closure `{$source_name}`
-    [normal] type annotations needed for `{$source_name}`
-    *[other] type annotations needed
-}
-    .label = type must be known at this point
-
-infer_types_declared_different = these two types are declared with different lifetimes...
-
-infer_warn_removing_apit_params = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable
-
-infer_where_copy_predicates = copy the `where` clause predicates from the trait
-
-infer_where_remove = remove the `where` clause
diff --git a/compiler/rustc_infer/src/error_reporting/mod.rs b/compiler/rustc_infer/src/error_reporting/mod.rs
deleted file mode 100644
index 132485ec661..00000000000
--- a/compiler/rustc_infer/src/error_reporting/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod infer;
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 2ce712e0bff..1a5c0137219 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,28 +1,5 @@
-use hir::GenericParamKind;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{
-    codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, IntoDiagArg,
-    MultiSpan, SubdiagMessageOp, Subdiagnostic,
-};
-use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::FnRetTy;
-use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
-use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
-use rustc_span::symbol::kw;
-use rustc_span::Symbol;
-use rustc_span::{symbol::Ident, BytePos, Span};
-
-use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
-use crate::error_reporting::infer::ObligationCauseAsDiagArg;
-use crate::fluent_generated as fluent;
-use crate::infer::need_type_info::UnderspecifiedArgKind;
-
-use std::path::PathBuf;
-
-pub mod note_and_explain;
+use rustc_macros::Diagnostic;
+use rustc_span::Span;
 
 #[derive(Diagnostic)]
 #[diag(infer_opaque_hidden_type)]
@@ -35,1599 +12,3 @@ pub struct OpaqueHiddenTypeDiag {
     #[note(infer_hidden_type)]
     pub hidden_type: Span,
 }
-
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0282)]
-pub struct AnnotationRequired<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Copy of `AnnotationRequired` for E0283
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0283)]
-pub struct AmbiguousImpl<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Copy of `AnnotationRequired` for E0284
-#[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = E0284)]
-pub struct AmbiguousReturn<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub source_kind: &'static str,
-    pub source_name: &'a str,
-    #[label]
-    pub failure_span: Option<Span>,
-    #[subdiagnostic]
-    pub bad_label: Option<InferenceBadError<'a>>,
-    #[subdiagnostic]
-    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
-    #[subdiagnostic]
-    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(infer_full_type_written)]
-    pub was_written: Option<()>,
-    pub path: PathBuf,
-}
-
-// Used when a better one isn't available
-#[derive(Subdiagnostic)]
-#[label(infer_label_bad)]
-pub struct InferenceBadError<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub bad_kind: &'static str,
-    pub prefix_kind: UnderspecifiedArgKind,
-    pub has_parent: bool,
-    pub prefix: &'a str,
-    pub parent_prefix: &'a str,
-    pub parent_name: String,
-    pub name: String,
-}
-
-#[derive(Subdiagnostic)]
-pub enum SourceKindSubdiag<'a> {
-    #[suggestion(
-        infer_source_kind_subdiag_let,
-        style = "verbose",
-        code = ": {type_name}",
-        applicability = "has-placeholders"
-    )]
-    LetLike {
-        #[primary_span]
-        span: Span,
-        name: String,
-        type_name: String,
-        kind: &'static str,
-        x_kind: &'static str,
-        prefix_kind: UnderspecifiedArgKind,
-        prefix: &'a str,
-        arg_name: String,
-    },
-    #[label(infer_source_kind_subdiag_generic_label)]
-    GenericLabel {
-        #[primary_span]
-        span: Span,
-        is_type: bool,
-        param_name: String,
-        parent_exists: bool,
-        parent_prefix: String,
-        parent_name: String,
-    },
-    #[suggestion(
-        infer_source_kind_subdiag_generic_suggestion,
-        style = "verbose",
-        code = "::<{args}>",
-        applicability = "has-placeholders"
-    )]
-    GenericSuggestion {
-        #[primary_span]
-        span: Span,
-        arg_count: usize,
-        args: String,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum SourceKindMultiSuggestion<'a> {
-    #[multipart_suggestion(
-        infer_source_kind_fully_qualified,
-        style = "verbose",
-        applicability = "has-placeholders"
-    )]
-    FullyQualified {
-        #[suggestion_part(code = "{def_path}({adjustment}")]
-        span_lo: Span,
-        #[suggestion_part(code = "{successor_pos}")]
-        span_hi: Span,
-        def_path: String,
-        adjustment: &'a str,
-        successor_pos: &'a str,
-    },
-    #[multipart_suggestion(
-        infer_source_kind_closure_return,
-        style = "verbose",
-        applicability = "has-placeholders"
-    )]
-    ClosureReturn {
-        #[suggestion_part(code = "{start_span_code}")]
-        start_span: Span,
-        start_span_code: String,
-        #[suggestion_part(code = " }}")]
-        end_span: Option<Span>,
-    },
-}
-
-impl<'a> SourceKindMultiSuggestion<'a> {
-    pub fn new_fully_qualified(
-        span: Span,
-        def_path: String,
-        adjustment: &'a str,
-        successor: (&'a str, BytePos),
-    ) -> Self {
-        Self::FullyQualified {
-            span_lo: span.shrink_to_lo(),
-            span_hi: span.shrink_to_hi().with_hi(successor.1),
-            def_path,
-            adjustment,
-            successor_pos: successor.0,
-        }
-    }
-
-    pub fn new_closure_return(
-        ty_info: String,
-        data: &'a FnRetTy<'a>,
-        should_wrap_expr: Option<Span>,
-    ) -> Self {
-        let arrow = match data {
-            FnRetTy::DefaultReturn(_) => " -> ",
-            _ => "",
-        };
-        let (start_span, start_span_code, end_span) = match should_wrap_expr {
-            Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
-            None => (data.span(), format!("{arrow}{ty_info}"), None),
-        };
-        Self::ClosureReturn { start_span, start_span_code, end_span }
-    }
-}
-
-pub enum RegionOriginNote<'a> {
-    Plain {
-        span: Span,
-        msg: DiagMessage,
-    },
-    WithName {
-        span: Span,
-        msg: DiagMessage,
-        name: &'a str,
-        continues: bool,
-    },
-    WithRequirement {
-        span: Span,
-        requirement: ObligationCauseAsDiagArg<'a>,
-        expected_found: Option<(DiagStyledString, DiagStyledString)>,
-    },
-}
-
-impl Subdiagnostic for RegionOriginNote<'_> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        let mut label_or_note = |span, msg: DiagMessage| {
-            let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
-            let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
-            let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
-            if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
-                diag.span_label(span, msg);
-            } else if span_is_primary && expanded_sub_count == 0 {
-                diag.note(msg);
-            } else {
-                diag.span_note(span, msg);
-            }
-        };
-        match self {
-            RegionOriginNote::Plain { span, msg } => {
-                label_or_note(span, msg);
-            }
-            RegionOriginNote::WithName { span, msg, name, continues } => {
-                label_or_note(span, msg);
-                diag.arg("name", name);
-                diag.arg("continues", continues);
-            }
-            RegionOriginNote::WithRequirement {
-                span,
-                requirement,
-                expected_found: Some((expected, found)),
-            } => {
-                label_or_note(span, fluent::infer_subtype);
-                diag.arg("requirement", requirement);
-
-                diag.note_expected_found(&"", expected, &"", found);
-            }
-            RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
-                // FIXME: this really should be handled at some earlier stage. Our
-                // handling of region checking when type errors are present is
-                // *terrible*.
-                label_or_note(span, fluent::infer_subtype_2);
-                diag.arg("requirement", requirement);
-            }
-        };
-    }
-}
-
-pub enum LifetimeMismatchLabels {
-    InRet {
-        param_span: Span,
-        ret_span: Span,
-        span: Span,
-        label_var1: Option<Ident>,
-    },
-    Normal {
-        hir_equal: bool,
-        ty_sup: Span,
-        ty_sub: Span,
-        span: Span,
-        sup: Option<Ident>,
-        sub: Option<Ident>,
-    },
-}
-
-impl Subdiagnostic for LifetimeMismatchLabels {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        match self {
-            LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
-                diag.span_label(param_span, fluent::infer_declared_different);
-                diag.span_label(ret_span, fluent::infer_nothing);
-                diag.span_label(span, fluent::infer_data_returned);
-                diag.arg("label_var1_exists", label_var1.is_some());
-                diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
-            }
-            LifetimeMismatchLabels::Normal {
-                hir_equal,
-                ty_sup,
-                ty_sub,
-                span,
-                sup: label_var1,
-                sub: label_var2,
-            } => {
-                if hir_equal {
-                    diag.span_label(ty_sup, fluent::infer_declared_multiple);
-                    diag.span_label(ty_sub, fluent::infer_nothing);
-                    diag.span_label(span, fluent::infer_data_lifetime_flow);
-                } else {
-                    diag.span_label(ty_sup, fluent::infer_types_declared_different);
-                    diag.span_label(ty_sub, fluent::infer_nothing);
-                    diag.span_label(span, fluent::infer_data_flows);
-                    diag.arg("label_var1_exists", label_var1.is_some());
-                    diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
-                    diag.arg("label_var2_exists", label_var2.is_some());
-                    diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
-                }
-            }
-        }
-    }
-}
-
-pub struct AddLifetimeParamsSuggestion<'a> {
-    pub tcx: TyCtxt<'a>,
-    pub generic_param_scope: LocalDefId,
-    pub sub: Region<'a>,
-    pub ty_sup: &'a hir::Ty<'a>,
-    pub ty_sub: &'a hir::Ty<'a>,
-    pub add_note: bool,
-}
-
-impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        let mut mk_suggestion = || {
-            let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
-            else {
-                return false;
-            };
-
-            let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
-            let is_impl = matches!(&node, hir::Node::ImplItem(_));
-            let (generics, parent_generics) = match node {
-                hir::Node::Item(&hir::Item {
-                    kind: hir::ItemKind::Fn(_, ref generics, ..),
-                    ..
-                })
-                | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
-                | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
-                    generics,
-                    match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id))
-                    {
-                        hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::Trait(_, _, ref generics, ..),
-                            ..
-                        })
-                        | hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }),
-                            ..
-                        }) => Some(generics),
-                        _ => None,
-                    },
-                ),
-                _ => return false,
-            };
-
-            let suggestion_param_name = generics
-                .params
-                .iter()
-                .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                .map(|p| p.name.ident().name)
-                .find(|i| *i != kw::UnderscoreLifetime);
-            let introduce_new = suggestion_param_name.is_none();
-
-            let mut default = "'a".to_string();
-            if let Some(parent_generics) = parent_generics {
-                let used: FxHashSet<_> = parent_generics
-                    .params
-                    .iter()
-                    .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                    .map(|p| p.name.ident().name)
-                    .filter(|i| *i != kw::UnderscoreLifetime)
-                    .map(|l| l.to_string())
-                    .collect();
-                if let Some(lt) =
-                    ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
-                {
-                    // We want a lifetime that *isn't* present in the `trait` or `impl` that assoc
-                    // `fn` belongs to. We could suggest reusing one of their lifetimes, but it is
-                    // likely to be an over-constraining lifetime requirement, so we always add a
-                    // lifetime to the `fn`.
-                    default = lt;
-                }
-            }
-            let suggestion_param_name =
-                suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
-
-            struct ImplicitLifetimeFinder {
-                suggestions: Vec<(Span, String)>,
-                suggestion_param_name: String,
-            }
-
-            impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
-                fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                    let make_suggestion = |ident: Ident| {
-                        if ident.name == kw::Empty && ident.span.is_empty() {
-                            format!("{}, ", self.suggestion_param_name)
-                        } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
-                            format!("{} ", self.suggestion_param_name)
-                        } else {
-                            self.suggestion_param_name.clone()
-                        }
-                    };
-                    match ty.kind {
-                        hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
-                            for segment in path.segments {
-                                if let Some(args) = segment.args {
-                                    if args.args.iter().all(|arg| {
-                                        matches!(
-                                            arg,
-                                            hir::GenericArg::Lifetime(lifetime)
-                                            if lifetime.ident.name == kw::Empty
-                                        )
-                                    }) {
-                                        self.suggestions.push((
-                                            segment.ident.span.shrink_to_hi(),
-                                            format!(
-                                                "<{}>",
-                                                args.args
-                                                    .iter()
-                                                    .map(|_| self.suggestion_param_name.clone())
-                                                    .collect::<Vec<_>>()
-                                                    .join(", ")
-                                            ),
-                                        ));
-                                    } else {
-                                        for arg in args.args {
-                                            if let hir::GenericArg::Lifetime(lifetime) = arg
-                                                && lifetime.is_anonymous()
-                                            {
-                                                self.suggestions.push((
-                                                    lifetime.ident.span,
-                                                    make_suggestion(lifetime.ident),
-                                                ));
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
-                            self.suggestions
-                                .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
-                        }
-                        _ => {}
-                    }
-                    walk_ty(self, ty);
-                }
-            }
-            let mut visitor = ImplicitLifetimeFinder {
-                suggestions: vec![],
-                suggestion_param_name: suggestion_param_name.clone(),
-            };
-            if let Some(fn_decl) = node.fn_decl()
-                && let hir::FnRetTy::Return(ty) = fn_decl.output
-            {
-                visitor.visit_ty(ty);
-            }
-            if visitor.suggestions.is_empty() {
-                // Do not suggest constraining the `&self` param, but rather the return type.
-                // If that is wrong (because it is not sufficient), a follow up error will tell the
-                // user to fix it. This way we lower the chances of *over* constraining, but still
-                // get the cake of "correctly" contrained in two steps.
-                visitor.visit_ty(self.ty_sup);
-            }
-            visitor.visit_ty(self.ty_sub);
-            if visitor.suggestions.is_empty() {
-                return false;
-            }
-            if introduce_new {
-                let new_param_suggestion = if let Some(first) =
-                    generics.params.iter().find(|p| !p.name.ident().span.is_empty())
-                {
-                    (first.span.shrink_to_lo(), format!("{suggestion_param_name}, "))
-                } else {
-                    (generics.span, format!("<{suggestion_param_name}>"))
-                };
-
-                visitor.suggestions.push(new_param_suggestion);
-            }
-            diag.multipart_suggestion_verbose(
-                fluent::infer_lifetime_param_suggestion,
-                visitor.suggestions,
-                Applicability::MaybeIncorrect,
-            );
-            diag.arg("is_impl", is_impl);
-            diag.arg("is_reuse", !introduce_new);
-
-            true
-        };
-        if mk_suggestion() && self.add_note {
-            diag.note(fluent::infer_lifetime_param_suggestion_elided);
-        }
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_lifetime_mismatch, code = E0623)]
-pub struct LifetimeMismatch<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub labels: LifetimeMismatchLabels,
-    #[subdiagnostic]
-    pub suggestion: AddLifetimeParamsSuggestion<'a>,
-}
-
-pub struct IntroducesStaticBecauseUnmetLifetimeReq {
-    pub unmet_requirements: MultiSpan,
-    pub binding_span: Span,
-}
-
-impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        mut self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        self.unmet_requirements
-            .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
-        diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
-    }
-}
-
-// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
-#[derive(Subdiagnostic)]
-pub enum DoesNotOutliveStaticFromImpl {
-    #[note(infer_does_not_outlive_static_from_impl)]
-    Spanned {
-        #[primary_span]
-        span: Span,
-    },
-    #[note(infer_does_not_outlive_static_from_impl)]
-    Unspanned,
-}
-
-#[derive(Subdiagnostic)]
-pub enum ImplicitStaticLifetimeSubdiag {
-    #[note(infer_implicit_static_lifetime_note)]
-    Note {
-        #[primary_span]
-        span: Span,
-    },
-    #[suggestion(
-        infer_implicit_static_lifetime_suggestion,
-        style = "verbose",
-        code = " + '_",
-        applicability = "maybe-incorrect"
-    )]
-    Sugg {
-        #[primary_span]
-        span: Span,
-    },
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_mismatched_static_lifetime)]
-pub struct MismatchedStaticLifetime<'a> {
-    #[primary_span]
-    pub cause_span: Span,
-    #[subdiagnostic]
-    pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
-    #[subdiagnostic]
-    pub expl: Option<note_and_explain::RegionExplanation<'a>>,
-    #[subdiagnostic]
-    pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
-    #[subdiagnostic]
-    pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
-}
-
-#[derive(Diagnostic)]
-pub enum ExplicitLifetimeRequired<'a> {
-    #[diag(infer_explicit_lifetime_required_with_ident, code = E0621)]
-    WithIdent {
-        #[primary_span]
-        #[label]
-        span: Span,
-        simple_ident: Ident,
-        named: String,
-        #[suggestion(
-            infer_explicit_lifetime_required_sugg_with_ident,
-            code = "{new_ty}",
-            applicability = "unspecified"
-        )]
-        new_ty_span: Span,
-        #[skip_arg]
-        new_ty: Ty<'a>,
-    },
-    #[diag(infer_explicit_lifetime_required_with_param_type, code = E0621)]
-    WithParamType {
-        #[primary_span]
-        #[label]
-        span: Span,
-        named: String,
-        #[suggestion(
-            infer_explicit_lifetime_required_sugg_with_param_type,
-            code = "{new_ty}",
-            applicability = "unspecified"
-        )]
-        new_ty_span: Span,
-        #[skip_arg]
-        new_ty: Ty<'a>,
-    },
-}
-
-pub enum TyOrSig<'tcx> {
-    Ty(Highlighted<'tcx, Ty<'tcx>>),
-    ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
-}
-
-impl IntoDiagArg for TyOrSig<'_> {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        match self {
-            TyOrSig::Ty(ty) => ty.into_diag_arg(),
-            TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
-        }
-    }
-}
-
-#[derive(Subdiagnostic)]
-pub enum ActualImplExplNotes<'tcx> {
-    #[note(infer_actual_impl_expl_expected_signature_two)]
-    ExpectedSignatureTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_any)]
-    ExpectedSignatureAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_some)]
-    ExpectedSignatureSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_signature_nothing)]
-    ExpectedSignatureNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_two)]
-    ExpectedPassiveTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_any)]
-    ExpectedPassiveAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_some)]
-    ExpectedPassiveSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_passive_nothing)]
-    ExpectedPassiveNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_expected_other_two)]
-    ExpectedOtherTwo {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_any)]
-    ExpectedOtherAny {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_some)]
-    ExpectedOtherSome {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-    },
-    #[note(infer_actual_impl_expl_expected_other_nothing)]
-    ExpectedOtherNothing {
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    },
-    #[note(infer_actual_impl_expl_but_actually_implements_trait)]
-    ButActuallyImplementsTrait {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-    },
-    #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
-    ButActuallyImplementedForTy {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-        ty: String,
-    },
-    #[note(infer_actual_impl_expl_but_actually_ty_implements)]
-    ButActuallyTyImplements {
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        has_lifetime: bool,
-        lifetime: usize,
-        ty: String,
-    },
-}
-
-pub enum ActualImplExpectedKind {
-    Signature,
-    Passive,
-    Other,
-}
-
-pub enum ActualImplExpectedLifetimeKind {
-    Two,
-    Any,
-    Some,
-    Nothing,
-}
-
-impl<'tcx> ActualImplExplNotes<'tcx> {
-    pub fn new_expected(
-        kind: ActualImplExpectedKind,
-        lt_kind: ActualImplExpectedLifetimeKind,
-        leading_ellipsis: bool,
-        ty_or_sig: TyOrSig<'tcx>,
-        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-        lifetime_1: usize,
-        lifetime_2: usize,
-    ) -> Self {
-        match (kind, lt_kind) {
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedSignatureTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedPassiveTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
-                Self::ExpectedOtherTwo {
-                    leading_ellipsis,
-                    ty_or_sig,
-                    trait_path,
-                    lifetime_1,
-                    lifetime_2,
-                }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
-                Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
-                Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
-            }
-            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
-                Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
-            }
-        }
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_trait_placeholder_mismatch)]
-pub struct TraitPlaceholderMismatch<'tcx> {
-    #[primary_span]
-    pub span: Span,
-    #[label(infer_label_satisfy)]
-    pub satisfy_span: Option<Span>,
-    #[label(infer_label_where)]
-    pub where_span: Option<Span>,
-    #[label(infer_label_dup)]
-    pub dup_span: Option<Span>,
-    pub def_id: String,
-    pub trait_def_id: String,
-
-    #[subdiagnostic]
-    pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
-}
-
-pub struct ConsiderBorrowingParamHelp {
-    pub spans: Vec<Span>,
-}
-
-impl Subdiagnostic for ConsiderBorrowingParamHelp {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        let mut type_param_span: MultiSpan = self.spans.clone().into();
-        for &span in &self.spans {
-            // Seems like we can't call f() here as Into<DiagMessage> is required
-            type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
-        }
-        let msg = f(diag, fluent::infer_tid_param_help.into());
-        diag.span_help(type_param_span, msg);
-    }
-}
-
-#[derive(Subdiagnostic)]
-#[help(infer_tid_rel_help)]
-pub struct RelationshipHelp;
-
-#[derive(Diagnostic)]
-#[diag(infer_trait_impl_diff)]
-pub struct TraitImplDiff {
-    #[primary_span]
-    #[label(infer_found)]
-    pub sp: Span,
-    #[label(infer_expected)]
-    pub trait_sp: Span,
-    #[note(infer_expected_found)]
-    pub note: (),
-    #[subdiagnostic]
-    pub param_help: ConsiderBorrowingParamHelp,
-    #[subdiagnostic]
-    // Seems like subdiagnostics are always pushed to the end, so this one
-    // also has to be a subdiagnostic to maintain order.
-    pub rel_help: Option<RelationshipHelp>,
-    pub expected: String,
-    pub found: String,
-}
-
-pub struct DynTraitConstraintSuggestion {
-    pub span: Span,
-    pub ident: Ident,
-}
-
-impl Subdiagnostic for DynTraitConstraintSuggestion {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        let mut multi_span: MultiSpan = vec![self.span].into();
-        multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
-        multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
-        let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
-        diag.span_note(multi_span, msg);
-        let msg = f(diag, fluent::infer_dtcs_suggestion.into());
-        diag.span_suggestion_verbose(
-            self.span.shrink_to_hi(),
-            msg,
-            " + '_",
-            Applicability::MaybeIncorrect,
-        );
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_but_calling_introduces, code = E0772)]
-pub struct ButCallingIntroduces {
-    #[label(infer_label1)]
-    pub param_ty_span: Span,
-    #[primary_span]
-    #[label(infer_label2)]
-    pub cause_span: Span,
-
-    pub has_param_name: bool,
-    pub param_name: String,
-    pub has_lifetime: bool,
-    pub lifetime: String,
-    pub assoc_item: Symbol,
-    pub has_impl_path: bool,
-    pub impl_path: String,
-}
-
-pub struct ReqIntroducedLocations {
-    pub span: MultiSpan,
-    pub spans: Vec<Span>,
-    pub fn_decl_span: Span,
-    pub cause_span: Span,
-    pub add_label: bool,
-}
-
-impl Subdiagnostic for ReqIntroducedLocations {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        mut self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        for sp in self.spans {
-            self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
-        }
-
-        if self.add_label {
-            self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
-        }
-        self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
-        let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
-        diag.span_note(self.span, msg);
-    }
-}
-
-pub struct MoreTargeted {
-    pub ident: Symbol,
-}
-
-impl Subdiagnostic for MoreTargeted {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        diag.code(E0772);
-        diag.primary_message(fluent::infer_more_targeted);
-        diag.arg("ident", self.ident);
-    }
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_but_needs_to_satisfy, code = E0759)]
-pub struct ButNeedsToSatisfy {
-    #[primary_span]
-    pub sp: Span,
-    #[label(infer_influencer)]
-    pub influencer_point: Span,
-    #[label(infer_used_here)]
-    pub spans: Vec<Span>,
-    #[label(infer_require)]
-    pub require_span_as_label: Option<Span>,
-    #[note(infer_require)]
-    pub require_span_as_note: Option<Span>,
-    #[note(infer_introduced_by_bound)]
-    pub bound: Option<Span>,
-
-    #[subdiagnostic]
-    pub req_introduces_loc: Option<ReqIntroducedLocations>,
-
-    pub has_param_name: bool,
-    pub param_name: String,
-    pub spans_empty: bool,
-    pub has_lifetime: bool,
-    pub lifetime: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_outlives_content, code = E0312)]
-pub struct OutlivesContent<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_outlives_bound, code = E0476)]
-pub struct OutlivesBound<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_fulfill_req_lifetime, code = E0477)]
-pub struct FulfillReqLifetime<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub ty: Ty<'a>,
-    #[subdiagnostic]
-    pub note: Option<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_lf_bound_not_satisfied, code = E0478)]
-pub struct LfBoundNotSatisfied<'a> {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_ref_longer_than_data, code = E0491)]
-pub struct RefLongerThanData<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub ty: Ty<'a>,
-    #[subdiagnostic]
-    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
-}
-
-#[derive(Subdiagnostic)]
-pub enum WhereClauseSuggestions {
-    #[suggestion(
-        infer_where_remove,
-        code = "",
-        applicability = "machine-applicable",
-        style = "verbose"
-    )]
-    Remove {
-        #[primary_span]
-        span: Span,
-    },
-    #[suggestion(
-        infer_where_copy_predicates,
-        code = "{space}where {trait_predicates}",
-        applicability = "machine-applicable",
-        style = "verbose"
-    )]
-    CopyPredicates {
-        #[primary_span]
-        span: Span,
-        space: &'static str,
-        trait_predicates: String,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum SuggestRemoveSemiOrReturnBinding {
-    #[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
-    RemoveAndBox {
-        #[suggestion_part(code = "Box::new(")]
-        first_lo: Span,
-        #[suggestion_part(code = ")")]
-        first_hi: Span,
-        #[suggestion_part(code = "Box::new(")]
-        second_lo: Span,
-        #[suggestion_part(code = ")")]
-        second_hi: Span,
-        #[suggestion_part(code = "")]
-        sp: Span,
-    },
-    #[suggestion(
-        infer_srs_remove,
-        style = "short",
-        code = "",
-        applicability = "machine-applicable"
-    )]
-    Remove {
-        #[primary_span]
-        sp: Span,
-    },
-    #[suggestion(
-        infer_srs_add,
-        style = "verbose",
-        code = "{code}",
-        applicability = "maybe-incorrect"
-    )]
-    Add {
-        #[primary_span]
-        sp: Span,
-        code: String,
-        ident: Ident,
-    },
-    #[note(infer_srs_add_one)]
-    AddOne {
-        #[primary_span]
-        spans: MultiSpan,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum ConsiderAddingAwait {
-    #[help(infer_await_both_futures)]
-    BothFuturesHelp,
-    #[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
-    BothFuturesSugg {
-        #[suggestion_part(code = ".await")]
-        first: Span,
-        #[suggestion_part(code = ".await")]
-        second: Span,
-    },
-    #[suggestion(
-        infer_await_future,
-        code = ".await",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    FutureSugg {
-        #[primary_span]
-        span: Span,
-    },
-    #[note(infer_await_note)]
-    FutureSuggNote {
-        #[primary_span]
-        span: Span,
-    },
-    #[multipart_suggestion(
-        infer_await_future,
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    FutureSuggMultiple {
-        #[suggestion_part(code = ".await")]
-        spans: Vec<Span>,
-    },
-}
-
-#[derive(Diagnostic)]
-pub enum PlaceholderRelationLfNotSatisfied {
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasBoth {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_with_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_with_sup)]
-        sup_span: Span,
-        sub_symbol: Symbol,
-        sup_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasSub {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_with_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_without_sup)]
-        sup_span: Span,
-        sub_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasSup {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_without_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_with_sup)]
-        sup_span: Span,
-        sup_symbol: Symbol,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    HasNone {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_defined_without_sub)]
-        sub_span: Span,
-        #[note(infer_prlf_must_outlive_without_sup)]
-        sup_span: Span,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-    #[diag(infer_lf_bound_not_satisfied)]
-    OnlyPrimarySpan {
-        #[primary_span]
-        span: Span,
-        #[note(infer_prlf_known_limitation)]
-        note: (),
-    },
-}
-
-#[derive(Diagnostic)]
-#[diag(infer_opaque_captures_lifetime, code = E0700)]
-pub struct OpaqueCapturesLifetime<'tcx> {
-    #[primary_span]
-    pub span: Span,
-    #[label]
-    pub opaque_ty_span: Span,
-    pub opaque_ty: Ty<'tcx>,
-}
-
-#[derive(Subdiagnostic)]
-pub enum FunctionPointerSuggestion<'a> {
-    #[suggestion(
-        infer_fps_use_ref,
-        code = "&{fn_name}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    UseRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-    },
-    #[suggestion(
-        infer_fps_remove_ref,
-        code = "{fn_name}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    RemoveRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-    },
-    #[suggestion(
-        infer_fps_cast,
-        code = "&({fn_name} as {sig})",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    CastRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast,
-        code = "{fn_name} as {sig}",
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    Cast {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast_both,
-        code = "{fn_name} as {found_sig}",
-        style = "hidden",
-        applicability = "maybe-incorrect"
-    )]
-    CastBoth {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        found_sig: Binder<'a, FnSig<'a>>,
-        expected_sig: Binder<'a, FnSig<'a>>,
-    },
-    #[suggestion(
-        infer_fps_cast_both,
-        code = "&({fn_name} as {found_sig})",
-        style = "hidden",
-        applicability = "maybe-incorrect"
-    )]
-    CastBothRef {
-        #[primary_span]
-        span: Span,
-        #[skip_arg]
-        fn_name: String,
-        #[skip_arg]
-        found_sig: Binder<'a, FnSig<'a>>,
-        expected_sig: Binder<'a, FnSig<'a>>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-#[note(infer_fps_items_are_distinct)]
-pub struct FnItemsAreDistinct;
-
-#[derive(Subdiagnostic)]
-#[note(infer_fn_uniq_types)]
-pub struct FnUniqTypes;
-
-#[derive(Subdiagnostic)]
-#[help(infer_fn_consider_casting)]
-pub struct FnConsiderCasting {
-    pub casting: String,
-}
-
-#[derive(Subdiagnostic)]
-pub enum SuggestAccessingField<'a> {
-    #[suggestion(
-        infer_suggest_accessing_field,
-        code = "{snippet}.{name}",
-        applicability = "maybe-incorrect"
-    )]
-    Safe {
-        #[primary_span]
-        span: Span,
-        snippet: String,
-        name: Symbol,
-        ty: Ty<'a>,
-    },
-    #[suggestion(
-        infer_suggest_accessing_field,
-        code = "unsafe {{ {snippet}.{name} }}",
-        applicability = "maybe-incorrect"
-    )]
-    Unsafe {
-        #[primary_span]
-        span: Span,
-        snippet: String,
-        name: Symbol,
-        ty: Ty<'a>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-#[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
-pub struct SuggestTuplePatternOne {
-    pub variant: String,
-    #[suggestion_part(code = "{variant}(")]
-    pub span_low: Span,
-    #[suggestion_part(code = ")")]
-    pub span_high: Span,
-}
-
-pub struct SuggestTuplePatternMany {
-    pub path: String,
-    pub cause_span: Span,
-    pub compatible_variants: Vec<String>,
-}
-
-impl Subdiagnostic for SuggestTuplePatternMany {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        f: &F,
-    ) {
-        diag.arg("path", self.path);
-        let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
-        diag.multipart_suggestions(
-            message,
-            self.compatible_variants.into_iter().map(|variant| {
-                vec![
-                    (self.cause_span.shrink_to_lo(), format!("{variant}(")),
-                    (self.cause_span.shrink_to_hi(), ")".to_string()),
-                ]
-            }),
-            rustc_errors::Applicability::MaybeIncorrect,
-        );
-    }
-}
-
-#[derive(Subdiagnostic)]
-pub enum TypeErrorAdditionalDiags {
-    #[suggestion(
-        infer_meant_byte_literal,
-        code = "b'{code}'",
-        applicability = "machine-applicable"
-    )]
-    MeantByteLiteral {
-        #[primary_span]
-        span: Span,
-        code: String,
-    },
-    #[suggestion(
-        infer_meant_char_literal,
-        code = "'{code}'",
-        applicability = "machine-applicable"
-    )]
-    MeantCharLiteral {
-        #[primary_span]
-        span: Span,
-        code: String,
-    },
-    #[multipart_suggestion(infer_meant_str_literal, applicability = "machine-applicable")]
-    MeantStrLiteral {
-        #[suggestion_part(code = "\"")]
-        start: Span,
-        #[suggestion_part(code = "\"")]
-        end: Span,
-    },
-    #[suggestion(
-        infer_consider_specifying_length,
-        code = "{length}",
-        applicability = "maybe-incorrect"
-    )]
-    ConsiderSpecifyingLength {
-        #[primary_span]
-        span: Span,
-        length: u64,
-    },
-    #[note(infer_try_cannot_convert)]
-    TryCannotConvert { found: String, expected: String },
-    #[suggestion(infer_tuple_trailing_comma, code = ",", applicability = "machine-applicable")]
-    TupleOnlyComma {
-        #[primary_span]
-        span: Span,
-    },
-    #[multipart_suggestion(infer_tuple_trailing_comma, applicability = "machine-applicable")]
-    TupleAlsoParentheses {
-        #[suggestion_part(code = "(")]
-        span_low: Span,
-        #[suggestion_part(code = ",)")]
-        span_high: Span,
-    },
-    #[suggestion(
-        infer_suggest_add_let_for_letchains,
-        style = "verbose",
-        applicability = "machine-applicable",
-        code = "let "
-    )]
-    AddLetForLetChains {
-        #[primary_span]
-        span: Span,
-    },
-}
-
-#[derive(Diagnostic)]
-pub enum ObligationCauseFailureCode {
-    #[diag(infer_oc_method_compat, code = E0308)]
-    MethodCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_type_compat, code = E0308)]
-    TypeCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_const_compat, code = E0308)]
-    ConstCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_try_compat, code = E0308)]
-    TryCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_match_compat, code = E0308)]
-    MatchCompat {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_if_else_different, code = E0308)]
-    IfElseDifferent {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_no_else, code = E0317)]
-    NoElse {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_no_diverge, code = E0308)]
-    NoDiverge {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_fn_main_correct_type, code = E0580)]
-    FnMainCorrectType {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_fn_start_correct_type, code = E0308)]
-    FnStartCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_fn_lang_correct_type, code = E0308)]
-    FnLangCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-        lang_item_name: Symbol,
-    },
-    #[diag(infer_oc_intrinsic_correct_type, code = E0308)]
-    IntrinsicCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_method_correct_type, code = E0308)]
-    MethodCorrectType {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_closure_selfref, code = E0644)]
-    ClosureSelfref {
-        #[primary_span]
-        span: Span,
-    },
-    #[diag(infer_oc_cant_coerce, code = E0308)]
-    CantCoerce {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-    #[diag(infer_oc_generic, code = E0308)]
-    Generic {
-        #[primary_span]
-        span: Span,
-        #[subdiagnostic]
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    },
-}
-
-#[derive(Subdiagnostic)]
-pub enum AddPreciseCapturing {
-    #[suggestion(
-        infer_precise_capturing_new,
-        style = "verbose",
-        code = " + use<{concatenated_bounds}>",
-        applicability = "machine-applicable"
-    )]
-    New {
-        #[primary_span]
-        span: Span,
-        new_lifetime: Symbol,
-        concatenated_bounds: String,
-    },
-    #[suggestion(
-        infer_precise_capturing_existing,
-        style = "verbose",
-        code = "{pre}{new_lifetime}{post}",
-        applicability = "machine-applicable"
-    )]
-    Existing {
-        #[primary_span]
-        span: Span,
-        new_lifetime: Symbol,
-        pre: &'static str,
-        post: &'static str,
-    },
-}
-
-pub struct AddPreciseCapturingAndParams {
-    pub suggs: Vec<(Span, String)>,
-    pub new_lifetime: Symbol,
-    pub apit_spans: Vec<Span>,
-}
-
-impl Subdiagnostic for AddPreciseCapturingAndParams {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        diag.arg("new_lifetime", self.new_lifetime);
-        diag.multipart_suggestion_verbose(
-            fluent::infer_precise_capturing_new_but_apit,
-            self.suggs,
-            Applicability::MaybeIncorrect,
-        );
-        diag.span_note(self.apit_spans, fluent::infer_warn_removing_apit_params);
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c9073d8c23e..3cee0a622f1 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -11,7 +11,6 @@ pub use BoundRegionConversionTime::*;
 pub use RegionVariableOrigin::*;
 pub use SubregionOrigin::*;
 
-use crate::error_reporting::infer::TypeErrCtxt;
 use crate::infer::relate::RelateResult;
 use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
 use free_regions::RegionRelations;
@@ -24,7 +23,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::Rollback;
 use rustc_data_structures::unify as ut;
-use rustc_errors::{Diag, ErrorGuaranteed};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::extension;
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
@@ -65,8 +65,6 @@ pub mod relate;
 pub mod resolve;
 pub(crate) mod snapshot;
 pub mod type_variable;
-// FIXME(error_reporting): Where should we put this?
-pub mod need_type_info;
 
 #[must_use]
 #[derive(Debug)]
@@ -698,36 +696,24 @@ impl<'tcx> InferCtxt<'tcx> {
         self.next_trait_solver
     }
 
-    /// Creates a `TypeErrCtxt` for emitting various inference errors.
-    /// During typeck, use `FnCtxt::err_ctxt` instead.
-    pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
-        TypeErrCtxt {
-            infcx: self,
-            sub_relations: Default::default(),
-            typeck_results: None,
-            fallback_has_occurred: false,
-            normalize_fn_sig: Box::new(|fn_sig| fn_sig),
-            autoderef_steps: Box::new(|ty| {
-                debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
-                vec![(ty, vec![])]
-            }),
-        }
-    }
-
     pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
 
-    /// Returns the origin of the type variable identified by `vid`, or `None`
-    /// if this is not a type variable.
+    /// Returns the origin of the type variable identified by `vid`.
     ///
-    /// No attempt is made to resolve `ty`.
-    pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
-        match *ty.kind() {
-            ty::Infer(ty::TyVar(vid)) => {
-                Some(self.inner.borrow_mut().type_variables().var_origin(vid))
-            }
-            _ => None,
+    /// No attempt is made to resolve `vid` to its root variable.
+    pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
+        self.inner.borrow_mut().type_variables().var_origin(vid)
+    }
+
+    /// Returns the origin of the const variable identified by `vid`
+    // FIXME: We should store origins separately from the unification table
+    // so this doesn't need to be optional.
+    pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin> {
+        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
+            ConstVariableValue::Known { .. } => None,
+            ConstVariableValue::Unknown { origin, .. } => Some(origin),
         }
     }
 
@@ -769,18 +755,6 @@ impl<'tcx> InferCtxt<'tcx> {
             .collect()
     }
 
-    // FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
-    // or we need to process the obligations.
-    pub fn can_eq_shallow<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
-    where
-        T: at::ToTrace<'tcx>,
-    {
-        let origin = &ObligationCause::dummy();
-        // We're only answering whether the types could be the same, and with
-        // opaque types, "they can be the same", via registering a hidden type.
-        self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::Yes, a, b).is_ok())
-    }
-
     #[instrument(skip(self), level = "debug")]
     pub fn sub_regions(
         &self,
@@ -1589,60 +1563,6 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    // [Note-Type-error-reporting]
-    // An invariant is that anytime the expected or actual type is Error (the special
-    // error type, meaning that an error occurred when typechecking this expression),
-    // this is a derived error. The error cascaded from another error (that was already
-    // reported), so it's not useful to display it to the user.
-    // The following methods implement this logic.
-    // They check if either the actual or expected type is Error, and don't print the error
-    // in this case. The typechecker should only ever report type errors involving mismatched
-    // types using one of these methods, and should not call span_err directly for such
-    // errors.
-    pub fn type_error_struct_with_diag<M>(
-        &self,
-        sp: Span,
-        mk_diag: M,
-        actual_ty: Ty<'tcx>,
-    ) -> Diag<'a>
-    where
-        M: FnOnce(String) -> Diag<'a>,
-    {
-        let actual_ty = self.resolve_vars_if_possible(actual_ty);
-        debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
-
-        let mut err = mk_diag(self.ty_to_string(actual_ty));
-
-        // Don't report an error if actual type is `Error`.
-        if actual_ty.references_error() {
-            err.downgrade_to_delayed_bug();
-        }
-
-        err
-    }
-
-    pub fn report_mismatched_types(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        expected: Ty<'tcx>,
-        actual: Ty<'tcx>,
-        err: TypeError<'tcx>,
-    ) -> Diag<'a> {
-        self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
-    }
-
-    pub fn report_mismatched_consts(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        expected: ty::Const<'tcx>,
-        actual: ty::Const<'tcx>,
-        err: TypeError<'tcx>,
-    ) -> Diag<'a> {
-        self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
-    }
-}
-
 /// Helper for [InferCtxt::ty_or_const_infer_var_changed] (see comment on that), currently
 /// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
 #[derive(Copy, Clone, Debug)]
@@ -1888,3 +1808,32 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 
     args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
+
+impl<'tcx> InferCtxt<'tcx> {
+    /// Given a [`hir::Block`], get the span of its last expression or
+    /// statement, peeling off any inner blocks.
+    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
+        let block = block.innermost_block();
+        if let Some(expr) = &block.expr {
+            expr.span
+        } else if let Some(stmt) = block.stmts.last() {
+            // possibly incorrect trailing `;` in the else arm
+            stmt.span
+        } else {
+            // empty block; point at its entirety
+            block.span
+        }
+    }
+
+    /// Given a [`hir::HirId`] for a block, get the span of its last expression
+    /// or statement, peeling off any inner blocks.
+    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
+        match self.tcx.hir_node(hir_id) {
+            hir::Node::Block(blk) => self.find_block_span(blk),
+            // The parser was in a weird state if either of these happen, but
+            // it's better not to panic.
+            hir::Node::Expr(e) => e.span,
+            _ => rustc_span::DUMMY_SP,
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 02ebf933f53..b65ac859667 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -34,7 +34,6 @@
 #[macro_use]
 extern crate tracing;
 
-pub mod error_reporting;
 mod errors;
 pub mod infer;
 pub mod traits;
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
deleted file mode 100644
index 7730fe29e09..00000000000
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-use super::ObjectSafetyViolation;
-
-use crate::infer::InferCtxt;
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::Span;
-use std::fmt;
-use std::iter;
-
-impl<'tcx> InferCtxt<'tcx> {
-    pub fn report_extra_impl_obligation<'a>(
-        &'a self,
-        error_span: Span,
-        impl_item_def_id: LocalDefId,
-        trait_item_def_id: DefId,
-        requirement: &dyn fmt::Display,
-    ) -> Diag<'a> {
-        let mut err = struct_span_code_err!(
-            self.dcx(),
-            error_span,
-            E0276,
-            "impl has stricter requirements than trait"
-        );
-
-        if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
-            if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                err.span_label(span, format!("definition of `{item_name}` from trait"));
-            }
-        }
-
-        err.span_label(error_span, format!("impl has extra requirement {requirement}"));
-
-        err
-    }
-}
-
-pub fn report_object_safety_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    hir_id: Option<hir::HirId>,
-    trait_def_id: DefId,
-    violations: &[ObjectSafetyViolation],
-) -> Diag<'tcx> {
-    let trait_str = tcx.def_path_str(trait_def_id);
-    let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
-        hir::Node::Item(item) => Some(item.ident.span),
-        _ => None,
-    });
-    let mut err = struct_span_code_err!(
-        tcx.dcx(),
-        span,
-        E0038,
-        "the trait `{}` cannot be made into an object",
-        trait_str
-    );
-    err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
-
-    if let Some(hir_id) = hir_id
-        && let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
-        && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
-    {
-        let mut hir_id = hir_id;
-        while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
-            hir_id = ty.hir_id;
-        }
-        if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
-            // Do not suggest `impl Trait` when dealing with things like super-traits.
-            err.span_suggestion_verbose(
-                ty.span.until(trait_ref.span),
-                "consider using an opaque type instead",
-                "impl ",
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-    let mut reported_violations = FxIndexSet::default();
-    let mut multi_span = vec![];
-    let mut messages = vec![];
-    for violation in violations {
-        if let ObjectSafetyViolation::SizedSelf(sp) = &violation
-            && !sp.is_empty()
-        {
-            // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
-            // with a `Span`.
-            reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
-        }
-        if reported_violations.insert(violation.clone()) {
-            let spans = violation.spans();
-            let msg = if trait_span.is_none() || spans.is_empty() {
-                format!("the trait cannot be made into an object because {}", violation.error_msg())
-            } else {
-                format!("...because {}", violation.error_msg())
-            };
-            if spans.is_empty() {
-                err.note(msg);
-            } else {
-                for span in spans {
-                    multi_span.push(span);
-                    messages.push(msg.clone());
-                }
-            }
-        }
-    }
-    let has_multi_span = !multi_span.is_empty();
-    let mut note_span = MultiSpan::from_spans(multi_span.clone());
-    if let (Some(trait_span), true) = (trait_span, has_multi_span) {
-        note_span.push_span_label(trait_span, "this trait cannot be made into an object...");
-    }
-    for (span, msg) in iter::zip(multi_span, messages) {
-        note_span.push_span_label(span, msg);
-    }
-    err.span_note(
-        note_span,
-        "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>",
-    );
-
-    // Only provide the help if its a local trait, otherwise it's not actionable.
-    if trait_span.is_some() {
-        let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
-        reported_violations.sort();
-
-        let mut potential_solutions: Vec<_> =
-            reported_violations.into_iter().map(|violation| violation.solution()).collect();
-        potential_solutions.sort();
-        // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
-        potential_solutions.dedup();
-        for solution in potential_solutions {
-            solution.add_to(&mut err);
-        }
-    }
-
-    let impls_of = tcx.trait_impls_of(trait_def_id);
-    let impls = if impls_of.blanket_impls().is_empty() {
-        impls_of
-            .non_blanket_impls()
-            .values()
-            .flatten()
-            .filter(|def_id| {
-                !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
-            })
-            .collect::<Vec<_>>()
-    } else {
-        vec![]
-    };
-    let externally_visible = if !impls.is_empty()
-        && let Some(def_id) = trait_def_id.as_local()
-        // We may be executing this during typeck, which would result in cycle
-        // if we used effective_visibilities query, which looks into opaque types
-        // (and therefore calls typeck).
-        && tcx.resolutions(()).effective_visibilities.is_exported(def_id)
-    {
-        true
-    } else {
-        false
-    };
-    match &impls[..] {
-        [] => {}
-        _ if impls.len() > 9 => {}
-        [only] if externally_visible => {
-            err.help(with_no_trimmed_paths!(format!(
-                "only type `{}` is seen to implement the trait in this crate, consider using it \
-                 directly instead",
-                tcx.type_of(*only).instantiate_identity(),
-            )));
-        }
-        [only] => {
-            err.help(with_no_trimmed_paths!(format!(
-                "only type `{}` implements the trait, consider using it directly instead",
-                tcx.type_of(*only).instantiate_identity(),
-            )));
-        }
-        impls => {
-            let mut types = impls
-                .iter()
-                .map(|t| {
-                    with_no_trimmed_paths!(format!("  {}", tcx.type_of(*t).instantiate_identity(),))
-                })
-                .collect::<Vec<_>>();
-            types.sort();
-            err.help(format!(
-                "the following types implement the trait, consider defining an enum where each \
-                 variant holds one of these types, implementing `{}` for this new enum and using \
-                 it instead:\n{}",
-                trait_str,
-                types.join("\n"),
-            ));
-        }
-    }
-    if externally_visible {
-        err.note(format!(
-            "`{trait_str}` can be implemented in other crates; if you want to support your users \
-             passing their own types here, you can't refer to a specific type",
-        ));
-    }
-
-    err
-}
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 556b3bd063d..7bc3af374fc 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -3,7 +3,6 @@
 //! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
 
 mod engine;
-pub mod error_reporting;
 mod project;
 mod structural_impls;
 pub mod util;
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 79d52914381..7d7b97e2eb1 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -403,8 +403,9 @@ lint_inner_macro_attribute_unstable = inner macro attributes are unstable
 
 lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly
     .label = use a different label that doesn't start with `0` or `1`
-    .note = an LLVM bug makes these labels ambiguous with a binary literal number
-    .note = see <https://bugs.llvm.org/show_bug.cgi?id=36144> for more information
+    .help = start numbering with `2` instead
+    .note1 = an LLVM bug makes these labels ambiguous with a binary literal number on x86
+    .note2 = see <https://github.com/llvm/llvm-project/issues/99547> for more information
 
 lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly
     .help = only local labels of the form `<number>:` should be used in inline asm
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 485c214ac9d..9ebada0fff3 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -66,6 +66,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
 use rustc_target::abi::Abi;
+use rustc_target::asm::InlineAsmArch;
 use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
@@ -2739,8 +2740,9 @@ declare_lint! {
     ///
     /// ### Example
     ///
-    /// ```rust,compile_fail
-    /// # #![feature(asm_experimental_arch)]
+    /// ```rust,ignore (fails on non-x86_64)
+    /// #![cfg(target_arch = "x86_64")]
+    ///
     /// use std::arch::asm;
     ///
     /// fn main() {
@@ -2750,19 +2752,32 @@ declare_lint! {
     /// }
     /// ```
     ///
-    /// {{produces}}
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: avoid using labels containing only the digits `0` and `1` in inline assembly
+    ///  --> <source>:7:15
+    ///   |
+    /// 7 |         asm!("0: jmp 0b");
+    ///   |               ^ use a different label that doesn't start with `0` or `1`
+    ///   |
+    ///   = help: start numbering with `2` instead
+    ///   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+    ///   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
+    ///   = note: `#[deny(binary_asm_labels)]` on by default
+    /// ```
     ///
     /// ### Explanation
     ///
-    /// A [LLVM bug] causes this code to fail to compile because it interprets the `0b` as a binary
-    /// literal instead of a reference to the previous local label `0`. Note that even though the
-    /// bug is marked as fixed, it only fixes a specific usage of intel syntax within standalone
-    /// files, not inline assembly. To work around this bug, don't use labels that could be
-    /// confused with a binary literal.
+    /// An [LLVM bug] causes this code to fail to compile because it interprets the `0b` as a binary
+    /// literal instead of a reference to the previous local label `0`. To work around this bug,
+    /// don't use labels that could be confused with a binary literal.
+    ///
+    /// This behavior is platform-specific to x86 and x86-64.
     ///
     /// See the explanation in [Rust By Example] for more details.
     ///
-    /// [LLVM bug]: https://bugs.llvm.org/show_bug.cgi?id=36144
+    /// [LLVM bug]: https://github.com/llvm/llvm-project/issues/99547
     /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels
     pub BINARY_ASM_LABELS,
     Deny,
@@ -2908,16 +2923,22 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels {
                                 InvalidAsmLabel::FormatArg { missing_precise_span },
                             );
                         }
-                        AsmLabelKind::Binary => {
-                            // the binary asm issue only occurs when using intel syntax
-                            if !options.contains(InlineAsmOptions::ATT_SYNTAX) {
-                                cx.emit_span_lint(
-                                    BINARY_ASM_LABELS,
-                                    span,
-                                    InvalidAsmLabel::Binary { missing_precise_span, span },
-                                )
-                            }
+                        // the binary asm issue only occurs when using intel syntax on x86 targets
+                        AsmLabelKind::Binary
+                            if !options.contains(InlineAsmOptions::ATT_SYNTAX)
+                                && matches!(
+                                    cx.tcx.sess.asm_arch,
+                                    Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) | None
+                                ) =>
+                        {
+                            cx.emit_span_lint(
+                                BINARY_ASM_LABELS,
+                                span,
+                                InvalidAsmLabel::Binary { missing_precise_span, span },
+                            )
                         }
+                        // No lint on anything other than x86
+                        AsmLabelKind::Binary => (),
                     };
                 }
             }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 290f91045c4..fc073233d97 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -322,6 +322,8 @@ fn register_builtins(store: &mut LintStore) {
         REFINING_IMPL_TRAIT_INTERNAL
     );
 
+    add_lint_group!("deprecated_safe", DEPRECATED_SAFE_2024);
+
     // Register renamed and removed lints.
     store.register_renamed("single_use_lifetime", "single_use_lifetimes");
     store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths");
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index ac5511faf19..6c5f366727f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2074,7 +2074,9 @@ pub enum InvalidAsmLabel {
         missing_precise_span: bool,
     },
     #[diag(lint_invalid_asm_label_binary)]
-    #[note]
+    #[help]
+    #[note(lint_note1)]
+    #[note(lint_note2)]
     Binary {
         #[note(lint_invalid_asm_label_no_span)]
         missing_precise_span: bool,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 04764b71b10..2f4e6a32308 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -37,7 +37,7 @@ declare_lint_pass! {
         DEPRECATED,
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DEPRECATED_IN_FUTURE,
-        DEPRECATED_SAFE,
+        DEPRECATED_SAFE_2024,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
         DUPLICATE_MACRO_ATTRIBUTES,
         ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
@@ -4812,8 +4812,8 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `deprecated_safe` lint detects unsafe functions being used as safe
-    /// functions.
+    /// The `deprecated_safe_2024` lint detects unsafe functions being used as
+    /// safe functions.
     ///
     /// ### Example
     ///
@@ -4832,8 +4832,8 @@ declare_lint! {
     ///
     /// Rust [editions] allow the language to evolve without breaking backward
     /// compatibility. This lint catches code that uses `unsafe` functions that
-    /// were declared as safe (non-`unsafe`) in earlier editions. If you switch
-    /// the compiler to a new edition without updating the code, then it
+    /// were declared as safe (non-`unsafe`) in editions prior to Rust 2024. If
+    /// you switch the compiler to Rust 2024 without updating the code, then it
     /// will fail to compile if you are using a function previously marked as
     /// safe.
     ///
@@ -4850,7 +4850,7 @@ declare_lint! {
     /// future.
     ///
     /// [editions]: https://doc.rust-lang.org/edition-guide/
-    pub DEPRECATED_SAFE,
+    pub DEPRECATED_SAFE_2024,
     Allow,
     "detects unsafe functions being used as safe functions",
     @future_incompatible = FutureIncompatibleInfo {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 0ba9b940eed..e5e430bc90d 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -7,6 +7,7 @@ use crate::rmeta::*;
 use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_data_structures::sync::{Lock, Lrc, OnceLock};
 use rustc_data_structures::unhash::UnhashMap;
@@ -83,12 +84,12 @@ pub(crate) struct CrateMetadata {
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
     /// so pre-decoding can probably be avoided.
-    trait_impls: FxHashMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
+    trait_impls: FxIndexMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
     /// Inherent impls which do not follow the normal coherence rules.
     ///
     /// These can be introduced using either `#![rustc_coherence_is_core]`
     /// or `#[rustc_allow_incoherent_impl]`.
-    incoherent_impls: FxHashMap<SimplifiedType, LazyArray<DefIndex>>,
+    incoherent_impls: FxIndexMap<SimplifiedType, LazyArray<DefIndex>>,
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6b240f0f0b3..bbd9ab5704f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -72,6 +72,15 @@ impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>> ProcessQueryValue<'
     }
 }
 
+impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>>
+    ProcessQueryValue<'tcx, Option<&'tcx [T]>> for Option<DecodeIterator<'a, 'tcx, T>>
+{
+    #[inline(always)]
+    fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> Option<&'tcx [T]> {
+        if let Some(iter) = self { Some(&*tcx.arena.alloc_from_iter(iter)) } else { None }
+    }
+}
+
 impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
     #[inline(always)]
     fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
@@ -249,6 +258,7 @@ provide! { tcx, def_id, other, cdata,
             .process_decoded(tcx, || panic!("{def_id:?} does not have coerce_unsized_info"))) }
     mir_const_qualif => { table }
     rendered_const => { table }
+    rendered_precise_capturing_args => { table }
     asyncness => { table_direct }
     fn_arg_names => { table }
     coroutine_kind => { table_direct }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 209316ca20f..6f31c0fa520 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2,7 +2,7 @@ use crate::errors::{FailCreateFileEncoder, FailWriteFile};
 use crate::rmeta::*;
 
 use rustc_ast::Attribute;
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
 use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -13,7 +13,6 @@ use rustc_hir_pretty::id_to_string;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::metadata_symbol_name;
 use rustc_middle::mir::interpret;
-use rustc_middle::query::LocalCrate;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
@@ -1496,6 +1495,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 self.tables
                     .is_type_alias_impl_trait
                     .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
+                self.encode_precise_capturing_args(def_id);
             }
             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
@@ -1508,10 +1508,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
         }
 
-        let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
-            tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true)
-        });
-        for (def_id, impls) in inherent_impls {
+        for (def_id, impls) in &tcx.crate_inherent_impls(()).unwrap().inherent_impls {
             record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
                 assert!(def_id.is_local());
                 def_id.index
@@ -1635,6 +1632,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     self.tables.assumed_wf_types_for_rpitit[def_id]
                         <- self.tcx.assumed_wf_types_for_rpitit(def_id)
                 );
+                self.encode_precise_capturing_args(def_id);
             }
         }
         if item.is_effects_desugaring {
@@ -1642,6 +1640,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
     }
 
+    fn encode_precise_capturing_args(&mut self, def_id: DefId) {
+        let Some(precise_capturing_args) = self.tcx.rendered_precise_capturing_args(def_id) else {
+            return;
+        };
+
+        record_array!(self.tables.rendered_precise_capturing_args[def_id] <- precise_capturing_args);
+    }
+
     fn encode_mir(&mut self) {
         if self.is_proc_macro {
             return;
@@ -1992,8 +1998,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
-            FxHashMap::default();
+        let mut trait_impls: FxIndexMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
+            FxIndexMap::default();
 
         for id in tcx.hir().items() {
             let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
@@ -2012,7 +2018,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     trait_ref.self_ty(),
                     TreatParams::AsCandidateKey,
                 );
-                fx_hash_map
+                trait_impls
                     .entry(trait_ref.def_id)
                     .or_default()
                     .push((id.owner_id.def_id.local_def_index, simplified_self_ty));
@@ -2033,47 +2039,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
         }
 
-        let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
-
-        // Bring everything into deterministic order for hashing
-        all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
-
-        let all_impls: Vec<_> = all_impls
+        let trait_impls: Vec<_> = trait_impls
             .into_iter()
-            .map(|(trait_def_id, mut impls)| {
-                // Bring everything into deterministic order for hashing
-                impls.sort_by_cached_key(|&(index, _)| {
-                    tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
-                });
-
-                TraitImpls {
-                    trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
-                    impls: self.lazy_array(&impls),
-                }
+            .map(|(trait_def_id, impls)| TraitImpls {
+                trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
+                impls: self.lazy_array(&impls),
             })
             .collect();
 
-        self.lazy_array(&all_impls)
+        self.lazy_array(&trait_impls)
     }
 
     #[instrument(level = "debug", skip(self))]
     fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
-        let all_impls = tcx.with_stable_hashing_context(|hcx| {
-            tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true)
-        });
 
-        let all_impls: Vec<_> = all_impls
-            .into_iter()
-            .map(|(&simp, impls)| {
-                let mut impls: Vec<_> =
-                    impls.into_iter().map(|def_id| def_id.local_def_index).collect();
-                impls.sort_by_cached_key(|&local_def_index| {
-                    tcx.hir().def_path_hash(LocalDefId { local_def_index })
-                });
-
-                IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
+        let all_impls: Vec<_> = tcx
+            .crate_inherent_impls(())
+            .unwrap()
+            .incoherent_impls
+            .iter()
+            .map(|(&simp, impls)| IncoherentImpls {
+                self_ty: simp,
+                impls: self.lazy_array(impls.iter().map(|def_id| def_id.local_def_index)),
             })
             .collect();
 
@@ -2317,32 +2306,6 @@ pub fn provide(providers: &mut Providers) {
                 span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
             })
         },
-        traits: |tcx, LocalCrate| {
-            let mut traits = Vec::new();
-            for id in tcx.hir().items() {
-                if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
-                    traits.push(id.owner_id.to_def_id())
-                }
-            }
-
-            // Bring everything into deterministic order.
-            traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
-            tcx.arena.alloc_slice(&traits)
-        },
-        trait_impls_in_crate: |tcx, LocalCrate| {
-            let mut trait_impls = Vec::new();
-            for id in tcx.hir().items() {
-                if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
-                    && tcx.impl_trait_ref(id.owner_id).is_some()
-                {
-                    trait_impls.push(id.owner_id.to_def_id())
-                }
-            }
-
-            // Bring everything into deterministic order.
-            trait_impls.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
-            tcx.arena.alloc_slice(&trait_impls)
-        },
 
         ..*providers
     }
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 2a44b3423ae..e565c8c1ea1 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -442,6 +442,7 @@ define_tables! {
     coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
     mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
     rendered_const: Table<DefIndex, LazyValue<String>>,
+    rendered_precise_capturing_args: Table<DefIndex, LazyArray<Symbol>>,
     asyncness: Table<DefIndex, ty::Asyncness>,
     fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
     coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index bf10a71dbae..75dc685a16a 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -103,6 +103,10 @@ declare_hooks! {
 
     /// Create a list-like THIR representation for debugging.
     hook thir_flat(key: LocalDefId) -> String;
+
+    /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
+    /// can just link to the upstream crate and therefore don't need a mono item.
+    hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool;
 }
 
 #[cold]
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index d1ccd158cf9..b113e81bd2d 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -112,7 +112,7 @@ pub fn report_unstable(
 ) {
     let msg = match reason {
         Some(r) => format!("use of unstable library feature '{feature}': {r}"),
-        None => format!("use of unstable library feature '{}'", &feature),
+        None => format!("use of unstable library feature '{feature}'"),
     };
 
     if is_soft {
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index bdd1eb11a38..15febfa7d9c 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -12,15 +12,13 @@ use std::fmt;
 use std::io;
 use std::io::{Read, Write};
 use std::num::NonZero;
-use std::sync::atomic::{AtomicU32, Ordering};
 
-use smallvec::{smallvec, SmallVec};
 use tracing::{debug, trace};
 
 use rustc_ast::LitKind;
 use rustc_attr::InlineAttr;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::{HashMapExt, Lock};
+use rustc_data_structures::sync::Lock;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
@@ -159,14 +157,9 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
     }
 }
 
-// Used to avoid infinite recursion when decoding cyclic allocations.
-type DecodingSessionId = NonZero<u32>;
-
 #[derive(Clone)]
 enum State {
     Empty,
-    InProgressNonAlloc(SmallVec<[DecodingSessionId; 1]>),
-    InProgress(SmallVec<[DecodingSessionId; 1]>, AllocId),
     Done(AllocId),
 }
 
@@ -180,13 +173,7 @@ pub struct AllocDecodingState {
 impl AllocDecodingState {
     #[inline]
     pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> {
-        static DECODER_SESSION_ID: AtomicU32 = AtomicU32::new(0);
-        let counter = DECODER_SESSION_ID.fetch_add(1, Ordering::SeqCst);
-
-        // Make sure this is never zero.
-        let session_id = DecodingSessionId::new((counter & 0x7FFFFFFF) + 1).unwrap();
-
-        AllocDecodingSession { state: self, session_id }
+        AllocDecodingSession { state: self }
     }
 
     pub fn new(data_offsets: Vec<u64>) -> Self {
@@ -200,7 +187,6 @@ impl AllocDecodingState {
 #[derive(Copy, Clone)]
 pub struct AllocDecodingSession<'s> {
     state: &'s AllocDecodingState,
-    session_id: DecodingSessionId,
 }
 
 impl<'s> AllocDecodingSession<'s> {
@@ -220,70 +206,35 @@ impl<'s> AllocDecodingSession<'s> {
             (alloc_kind, decoder.position())
         });
 
+        // We are going to hold this lock during the entire decoding of this allocation, which may
+        // require that we decode other allocations. This cannot deadlock for two reasons:
+        //
+        // At the time of writing, it is only possible to create an allocation that contains a pointer
+        // to itself using the const_allocate intrinsic (which is for testing only), and even attempting
+        // to evaluate such consts blows the stack. If we ever grow a mechanism for producing
+        // cyclic allocations, we will need a new strategy for decoding that doesn't bring back
+        // https://github.com/rust-lang/rust/issues/126741.
+        //
+        // It is also impossible to create two allocations (call them A and B) where A is a pointer to B, and B
+        // is a pointer to A, because attempting to evaluate either of those consts will produce a
+        // query cycle, failing compilation.
+        let mut entry = self.state.decoding_state[idx].lock();
         // Check the decoding state to see if it's already decoded or if we should
         // decode it here.
-        let alloc_id = {
-            let mut entry = self.state.decoding_state[idx].lock();
-
-            match *entry {
-                State::Done(alloc_id) => {
-                    return alloc_id;
-                }
-                ref mut entry @ State::Empty => {
-                    // We are allowed to decode.
-                    match alloc_kind {
-                        AllocDiscriminant::Alloc => {
-                            // If this is an allocation, we need to reserve an
-                            // `AllocId` so we can decode cyclic graphs.
-                            let alloc_id = decoder.interner().reserve_alloc_id();
-                            *entry = State::InProgress(smallvec![self.session_id], alloc_id);
-                            Some(alloc_id)
-                        }
-                        AllocDiscriminant::Fn
-                        | AllocDiscriminant::Static
-                        | AllocDiscriminant::VTable => {
-                            // Fns and statics cannot be cyclic, and their `AllocId`
-                            // is determined later by interning.
-                            *entry = State::InProgressNonAlloc(smallvec![self.session_id]);
-                            None
-                        }
-                    }
-                }
-                State::InProgressNonAlloc(ref mut sessions) => {
-                    if sessions.contains(&self.session_id) {
-                        bug!("this should be unreachable");
-                    } else {
-                        // Start decoding concurrently.
-                        sessions.push(self.session_id);
-                        None
-                    }
-                }
-                State::InProgress(ref mut sessions, alloc_id) => {
-                    if sessions.contains(&self.session_id) {
-                        // Don't recurse.
-                        return alloc_id;
-                    } else {
-                        // Start decoding concurrently.
-                        sessions.push(self.session_id);
-                        Some(alloc_id)
-                    }
-                }
-            }
-        };
+        if let State::Done(alloc_id) = *entry {
+            return alloc_id;
+        }
 
         // Now decode the actual data.
         let alloc_id = decoder.with_position(pos, |decoder| {
             match alloc_kind {
                 AllocDiscriminant::Alloc => {
+                    trace!("creating memory alloc ID");
                     let alloc = <ConstAllocation<'tcx> as Decodable<_>>::decode(decoder);
-                    // We already have a reserved `AllocId`.
-                    let alloc_id = alloc_id.unwrap();
-                    trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
-                    decoder.interner().set_alloc_id_same_memory(alloc_id, alloc);
-                    alloc_id
+                    trace!("decoded alloc {:?}", alloc);
+                    decoder.interner().reserve_and_set_memory_alloc(alloc)
                 }
                 AllocDiscriminant::Fn => {
-                    assert!(alloc_id.is_none());
                     trace!("creating fn alloc ID");
                     let instance = ty::Instance::decode(decoder);
                     trace!("decoded fn alloc instance: {:?}", instance);
@@ -291,35 +242,26 @@ impl<'s> AllocDecodingSession<'s> {
                     // Here we cannot call `reserve_and_set_fn_alloc` as that would use a query, which
                     // is not possible in this context. That's why the allocation stores
                     // whether it is unique or not.
-                    let alloc_id =
-                        decoder.interner().reserve_and_set_fn_alloc_internal(instance, unique);
-                    alloc_id
+                    decoder.interner().reserve_and_set_fn_alloc_internal(instance, unique)
                 }
                 AllocDiscriminant::VTable => {
-                    assert!(alloc_id.is_none());
                     trace!("creating vtable alloc ID");
                     let ty = <Ty<'_> as Decodable<D>>::decode(decoder);
                     let poly_trait_ref =
                         <Option<ty::PolyExistentialTraitRef<'_>> as Decodable<D>>::decode(decoder);
                     trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
-                    let alloc_id =
-                        decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref);
-                    alloc_id
+                    decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref)
                 }
                 AllocDiscriminant::Static => {
-                    assert!(alloc_id.is_none());
                     trace!("creating extern static alloc ID");
                     let did = <DefId as Decodable<D>>::decode(decoder);
                     trace!("decoded static def-ID: {:?}", did);
-                    let alloc_id = decoder.interner().reserve_and_set_static_alloc(did);
-                    alloc_id
+                    decoder.interner().reserve_and_set_static_alloc(did)
                 }
             }
         });
 
-        self.state.decoding_state[idx].with_lock(|entry| {
-            *entry = State::Done(alloc_id);
-        });
+        *entry = State::Done(alloc_id);
 
         alloc_id
     }
@@ -563,12 +505,6 @@ impl<'tcx> TyCtxt<'tcx> {
             bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
         }
     }
-
-    /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
-    /// twice for the same `(AllocId, Allocation)` pair.
-    fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
-        self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
-    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 817c7157b68..c7ea1d43383 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1261,6 +1261,7 @@ rustc_queries! {
         desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
+
     /// Gets the rendered value of the specified constant or associated constant.
     /// Used by rustdoc.
     query rendered_const(def_id: DefId) -> &'tcx String {
@@ -1268,6 +1269,13 @@ rustc_queries! {
         desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
+
+    /// Gets the rendered precise capturing args for an opaque for use in rustdoc.
+    query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> {
+        desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
+    }
+
     query impl_parent(def_id: DefId) -> Option<DefId> {
         desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index bd073cd891f..558590af7ec 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -40,7 +40,6 @@ use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
-use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
@@ -2083,6 +2082,8 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         incoherent_impls: trait_def::incoherent_impls_provider,
+        trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
+        traits: trait_def::traits_provider,
         const_param_default: consts::const_param_default,
         vtable_allocation: vtable::vtable_allocation_provider,
         ..*providers
@@ -2096,8 +2097,8 @@ pub fn provide(providers: &mut Providers) {
 /// (constructing this map requires touching the entire crate).
 #[derive(Clone, Debug, Default, HashStable)]
 pub struct CrateInherentImpls {
-    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
-    pub incoherent_impls: UnordMap<SimplifiedType, Vec<LocalDefId>>,
+    pub inherent_impls: FxIndexMap<LocalDefId, Vec<DefId>>,
+    pub incoherent_impls: FxIndexMap<SimplifiedType, Vec<LocalDefId>>,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 57cd2dc73c4..0e241663e18 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2627,7 +2627,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             self.prepare_region_info(value);
         }
 
-        debug!("self.used_region_names: {:?}", &self.used_region_names);
+        debug!("self.used_region_names: {:?}", self.used_region_names);
 
         let mut empty = true;
         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index da5860043c9..3bd9f6ad11b 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,16 +1,19 @@
-use crate::traits::specialization_graph;
-use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use crate::ty::{Ident, Ty, TyCtxt};
-use hir::def_id::LOCAL_CRATE;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use std::iter;
 use tracing::debug;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_macros::{Decodable, Encodable, HashStable};
 
+use crate::query::LocalCrate;
+use crate::traits::specialization_graph;
+use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use crate::ty::{Ident, Ty, TyCtxt};
+
 /// A trait's definition with type information.
 #[derive(HashStable, Encodable, Decodable)]
 pub struct TraitDef {
@@ -274,3 +277,27 @@ pub(super) fn incoherent_impls_provider(
 
     Ok(tcx.arena.alloc_slice(&impls))
 }
+
+pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
+    let mut traits = Vec::new();
+    for id in tcx.hir().items() {
+        if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
+            traits.push(id.owner_id.to_def_id())
+        }
+    }
+
+    tcx.arena.alloc_slice(&traits)
+}
+
+pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
+    let mut trait_impls = Vec::new();
+    for id in tcx.hir().items() {
+        if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
+            && tcx.impl_trait_ref(id.owner_id).is_some()
+        {
+            trait_impls.push(id.owner_id.to_def_id())
+        }
+    }
+
+    tcx.arena.alloc_slice(&trait_impls)
+}
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 027e2703e98..831853b0b48 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -14,7 +14,7 @@ pub fn find_self_call<'tcx>(
     local: Local,
     block: BasicBlock,
 ) -> Option<(DefId, GenericArgsRef<'tcx>)> {
-    debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
+    debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
     if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
         &body[block].terminator
     {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index b531a392efa..95bc8b3d0cb 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1598,6 +1598,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 for subcandidate in candidate.subcandidates.iter_mut() {
                     expanded_candidates.push(subcandidate);
                 }
+                // Note that the subcandidates have been added to `expanded_candidates`,
+                // but `candidate` itself has not. If the last candidate has more match pairs,
+                // they are handled separately by `test_remaining_match_pairs_after_or`.
             } else {
                 // A candidate that doesn't start with an or-pattern has nothing to
                 // expand, so it is included in the post-expansion list as-is.
@@ -1613,19 +1616,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             expanded_candidates.as_mut_slice(),
         );
 
-        // Simplify subcandidates and process any leftover match pairs.
-        for candidate in candidates_to_expand {
+        // Postprocess subcandidates, and process any leftover match pairs.
+        // (Only the last candidate can possibly have more match pairs.)
+        debug_assert!({
+            let mut all_except_last = candidates_to_expand.iter().rev().skip(1);
+            all_except_last.all(|candidate| candidate.match_pairs.is_empty())
+        });
+        for candidate in candidates_to_expand.iter_mut() {
             if !candidate.subcandidates.is_empty() {
-                self.finalize_or_candidate(span, scrutinee_span, candidate);
+                self.merge_trivial_subcandidates(candidate);
+                self.remove_never_subcandidates(candidate);
             }
         }
+        if let Some(last_candidate) = candidates_to_expand.last_mut() {
+            self.test_remaining_match_pairs_after_or(span, scrutinee_span, last_candidate);
+        }
 
         remainder_start.and(remaining_candidates)
     }
 
     /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
-    /// subcandidate. Any candidate that has been expanded that way should be passed to
-    /// `finalize_or_candidate` after its subcandidates have been processed.
+    /// subcandidate. Any candidate that has been expanded this way should also be postprocessed
+    /// at the end of [`Self::expand_and_match_or_candidates`].
     fn create_or_subcandidates<'pat>(
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
@@ -1642,7 +1654,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block;
     }
 
-    /// Simplify subcandidates and process any leftover match pairs. The candidate should have been
+    /// Try to merge all of the subcandidates of the given candidate into one. This avoids
+    /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The candidate should have been
     /// expanded with `create_or_subcandidates`.
     ///
     /// Given a pattern `(P | Q, R | S)` we (in principle) generate a CFG like
@@ -1695,105 +1708,130 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///      |
     ///     ...
     /// ```
-    fn finalize_or_candidate(
-        &mut self,
-        span: Span,
-        scrutinee_span: Span,
-        candidate: &mut Candidate<'_, 'tcx>,
-    ) {
-        if candidate.subcandidates.is_empty() {
+    ///
+    /// Note that this takes place _after_ the subcandidates have participated
+    /// in match tree lowering.
+    fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
+        assert!(!candidate.subcandidates.is_empty());
+        if candidate.has_guard {
+            // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
             return;
         }
 
-        self.merge_trivial_subcandidates(candidate);
+        // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
+        let can_merge = candidate.subcandidates.iter().all(|subcandidate| {
+            subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty()
+        });
+        if !can_merge {
+            return;
+        }
 
-        if !candidate.match_pairs.is_empty() {
-            let or_span = candidate.or_span.unwrap_or(candidate.extra_data.span);
-            let source_info = self.source_info(or_span);
-            // If more match pairs remain, test them after each subcandidate.
-            // We could add them to the or-candidates before the call to `test_or_pattern` but this
-            // would make it impossible to detect simplifiable or-patterns. That would guarantee
-            // exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`.
-            let mut last_otherwise = None;
-            candidate.visit_leaves(|leaf_candidate| {
-                last_otherwise = leaf_candidate.otherwise_block;
-            });
-            let remaining_match_pairs = mem::take(&mut candidate.match_pairs);
-            candidate.visit_leaves(|leaf_candidate| {
-                assert!(leaf_candidate.match_pairs.is_empty());
-                leaf_candidate.match_pairs.extend(remaining_match_pairs.iter().cloned());
-                let or_start = leaf_candidate.pre_binding_block.unwrap();
-                let otherwise =
-                    self.match_candidates(span, scrutinee_span, or_start, &mut [leaf_candidate]);
-                // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
-                // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
-                // directly to `last_otherwise`. If there is a guard,
-                // `leaf_candidate.otherwise_block` can be reached by guard failure as well, so we
-                // can't skip `Q`.
-                let or_otherwise = if leaf_candidate.has_guard {
-                    leaf_candidate.otherwise_block.unwrap()
-                } else {
-                    last_otherwise.unwrap()
-                };
-                self.cfg.goto(otherwise, source_info, or_otherwise);
-            });
+        let mut last_otherwise = None;
+        let shared_pre_binding_block = self.cfg.start_new_block();
+        // This candidate is about to become a leaf, so unset `or_span`.
+        let or_span = candidate.or_span.take().unwrap();
+        let source_info = self.source_info(or_span);
+
+        if candidate.false_edge_start_block.is_none() {
+            candidate.false_edge_start_block = candidate.subcandidates[0].false_edge_start_block;
+        }
+
+        // Remove the (known-trivial) subcandidates from the candidate tree,
+        // so that they aren't visible after match tree lowering, and wire them
+        // all to join up at a single shared pre-binding block.
+        // (Note that the subcandidates have already had their part of the match
+        // tree lowered by this point, which is why we can add a goto to them.)
+        for subcandidate in mem::take(&mut candidate.subcandidates) {
+            let subcandidate_block = subcandidate.pre_binding_block.unwrap();
+            self.cfg.goto(subcandidate_block, source_info, shared_pre_binding_block);
+            last_otherwise = subcandidate.otherwise_block;
         }
+        candidate.pre_binding_block = Some(shared_pre_binding_block);
+        assert!(last_otherwise.is_some());
+        candidate.otherwise_block = last_otherwise;
     }
 
-    /// Try to merge all of the subcandidates of the given candidate into one. This avoids
-    /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The candidate should have been
-    /// expanded with `create_or_subcandidates`.
-    fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
-        if candidate.subcandidates.is_empty() || candidate.has_guard {
-            // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
+    /// Never subcandidates may have a set of bindings inconsistent with their siblings,
+    /// which would break later code. So we filter them out. Note that we can't filter out
+    /// top-level candidates this way.
+    fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
+        if candidate.subcandidates.is_empty() {
             return;
         }
 
-        // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
-        let can_merge = candidate.subcandidates.iter().all(|subcandidate| {
-            subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty()
-        });
-        if can_merge {
-            let mut last_otherwise = None;
-            let any_matches = self.cfg.start_new_block();
-            let or_span = candidate.or_span.take().unwrap();
-            let source_info = self.source_info(or_span);
-            if candidate.false_edge_start_block.is_none() {
-                candidate.false_edge_start_block =
-                    candidate.subcandidates[0].false_edge_start_block;
-            }
-            for subcandidate in mem::take(&mut candidate.subcandidates) {
-                let or_block = subcandidate.pre_binding_block.unwrap();
-                self.cfg.goto(or_block, source_info, any_matches);
-                last_otherwise = subcandidate.otherwise_block;
-            }
-            candidate.pre_binding_block = Some(any_matches);
-            assert!(last_otherwise.is_some());
-            candidate.otherwise_block = last_otherwise;
-        } else {
-            // Never subcandidates may have a set of bindings inconsistent with their siblings,
-            // which would break later code. So we filter them out. Note that we can't filter out
-            // top-level candidates this way.
-            candidate.subcandidates.retain_mut(|candidate| {
-                if candidate.extra_data.is_never {
-                    candidate.visit_leaves(|subcandidate| {
-                        let block = subcandidate.pre_binding_block.unwrap();
-                        // That block is already unreachable but needs a terminator to make the MIR well-formed.
-                        let source_info = self.source_info(subcandidate.extra_data.span);
-                        self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
-                    });
-                    false
-                } else {
-                    true
-                }
-            });
-            if candidate.subcandidates.is_empty() {
-                // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
-                candidate.pre_binding_block = Some(self.cfg.start_new_block());
+        candidate.subcandidates.retain_mut(|candidate| {
+            if candidate.extra_data.is_never {
+                candidate.visit_leaves(|subcandidate| {
+                    let block = subcandidate.pre_binding_block.unwrap();
+                    // That block is already unreachable but needs a terminator to make the MIR well-formed.
+                    let source_info = self.source_info(subcandidate.extra_data.span);
+                    self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
+                });
+                false
+            } else {
+                true
             }
+        });
+        if candidate.subcandidates.is_empty() {
+            // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
+            candidate.pre_binding_block = Some(self.cfg.start_new_block());
         }
     }
 
+    /// If more match pairs remain, test them after each subcandidate.
+    /// We could have added them to the or-candidates during or-pattern expansion, but that
+    /// would make it impossible to detect simplifiable or-patterns. That would guarantee
+    /// exponentially large CFGs for cases like `(1 | 2, 3 | 4, ...)`.
+    fn test_remaining_match_pairs_after_or(
+        &mut self,
+        span: Span,
+        scrutinee_span: Span,
+        candidate: &mut Candidate<'_, 'tcx>,
+    ) {
+        if candidate.match_pairs.is_empty() {
+            return;
+        }
+
+        let or_span = candidate.or_span.unwrap_or(candidate.extra_data.span);
+        let source_info = self.source_info(or_span);
+        let mut last_otherwise = None;
+        candidate.visit_leaves(|leaf_candidate| {
+            last_otherwise = leaf_candidate.otherwise_block;
+        });
+
+        let remaining_match_pairs = mem::take(&mut candidate.match_pairs);
+        // We're testing match pairs that remained after an `Or`, so the remaining
+        // pairs should all be `Or` too, due to the sorting invariant.
+        debug_assert!(
+            remaining_match_pairs
+                .iter()
+                .all(|match_pair| matches!(match_pair.test_case, TestCase::Or { .. }))
+        );
+
+        candidate.visit_leaves(|leaf_candidate| {
+            // At this point the leaf's own match pairs have all been lowered
+            // and removed, so `extend` and assignment are equivalent,
+            // but extending can also recycle any existing vector capacity.
+            assert!(leaf_candidate.match_pairs.is_empty());
+            leaf_candidate.match_pairs.extend(remaining_match_pairs.iter().cloned());
+
+            let or_start = leaf_candidate.pre_binding_block.unwrap();
+            let otherwise =
+                self.match_candidates(span, scrutinee_span, or_start, &mut [leaf_candidate]);
+            // In a case like `(P | Q, R | S)`, if `P` succeeds and `R | S` fails, we know `(Q,
+            // R | S)` will fail too. If there is no guard, we skip testing of `Q` by branching
+            // directly to `last_otherwise`. If there is a guard,
+            // `leaf_candidate.otherwise_block` can be reached by guard failure as well, so we
+            // can't skip `Q`.
+            let or_otherwise = if leaf_candidate.has_guard {
+                leaf_candidate.otherwise_block.unwrap()
+            } else {
+                last_otherwise.unwrap()
+            };
+            self.cfg.goto(otherwise, source_info, or_otherwise);
+        });
+    }
+
     /// Pick a test to run. Which test doesn't matter as long as it is guaranteed to fully match at
     /// least one match pair. We currently simply pick the test corresponding to the first match
     /// pair of the first candidate in the list.
@@ -2162,92 +2200,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         self.ascribe_types(block, ascriptions);
 
-        // rust-lang/rust#27282: The `autoref` business deserves some
-        // explanation here.
-        //
-        // The intent of the `autoref` flag is that when it is true,
-        // then any pattern bindings of type T will map to a `&T`
-        // within the context of the guard expression, but will
-        // continue to map to a `T` in the context of the arm body. To
-        // avoid surfacing this distinction in the user source code
-        // (which would be a severe change to the language and require
-        // far more revision to the compiler), when `autoref` is true,
-        // then any occurrence of the identifier in the guard
-        // expression will automatically get a deref op applied to it.
-        //
-        // So an input like:
-        //
-        // ```
-        // let place = Foo::new();
-        // match place { foo if inspect(foo)
-        //     => feed(foo), ... }
-        // ```
-        //
-        // will be treated as if it were really something like:
-        //
-        // ```
-        // let place = Foo::new();
-        // match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
-        //     => { let tmp2 = place; feed(tmp2) }, ... }
-        // ```
-        //
-        // And an input like:
-        //
-        // ```
-        // let place = Foo::new();
-        // match place { ref mut foo if inspect(foo)
-        //     => feed(foo), ... }
-        // ```
-        //
-        // will be treated as if it were really something like:
-        //
-        // ```
-        // let place = Foo::new();
-        // match place { Foo { .. } if { let tmp1 = & &mut place; inspect(*tmp1) }
-        //     => { let tmp2 = &mut place; feed(tmp2) }, ... }
-        // ```
-        //
-        // In short, any pattern binding will always look like *some*
-        // kind of `&T` within the guard at least in terms of how the
-        // MIR-borrowck views it, and this will ensure that guard
-        // expressions cannot mutate their the match inputs via such
-        // bindings. (It also ensures that guard expressions can at
-        // most *copy* values from such bindings; non-Copy things
-        // cannot be moved via pattern bindings in guard expressions.)
-        //
-        // ----
-        //
-        // Implementation notes (under assumption `autoref` is true).
-        //
-        // To encode the distinction above, we must inject the
-        // temporaries `tmp1` and `tmp2`.
-        //
-        // There are two cases of interest: binding by-value, and binding by-ref.
-        //
-        // 1. Binding by-value: Things are simple.
-        //
-        //    * Establishing `tmp1` creates a reference into the
-        //      matched place. This code is emitted by
-        //      bind_matched_candidate_for_guard.
-        //
-        //    * `tmp2` is only initialized "lazily", after we have
-        //      checked the guard. Thus, the code that can trigger
-        //      moves out of the candidate can only fire after the
-        //      guard evaluated to true. This initialization code is
-        //      emitted by bind_matched_candidate_for_arm.
-        //
-        // 2. Binding by-reference: Things are tricky.
-        //
-        //    * Here, the guard expression wants a `&&` or `&&mut`
-        //      into the original input. This means we need to borrow
-        //      the reference that we create for the arm.
-        //    * So we eagerly create the reference for the arm and then take a
-        //      reference to that.
+        // Lower an instance of the arm guard (if present) for this candidate,
+        // and then perform bindings for the arm body.
         if let Some((arm, match_scope)) = arm_match_scope
             && let Some(guard) = arm.guard
         {
             let tcx = self.tcx;
 
+            // Bindings for guards require some extra handling to automatically
+            // insert implicit references/dereferences.
             self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
             let guard_frame = GuardFrame {
                 locals: bindings.clone().map(|b| GuardFrameLocal::new(b.var_id)).collect(),
@@ -2387,6 +2348,82 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    /// Binding for guards is a bit different from binding for the arm body,
+    /// because an extra layer of implicit reference/dereference is added.
+    ///
+    /// The idea is that any pattern bindings of type T will map to a `&T` within
+    /// the context of the guard expression, but will continue to map to a `T`
+    /// in the context of the arm body. To avoid surfacing this distinction in
+    /// the user source code (which would be a severe change to the language and
+    /// require far more revision to the compiler), any occurrence of the
+    /// identifier in the guard expression will automatically get a deref op
+    /// applied to it. (See the caller of [`Self::is_bound_var_in_guard`].)
+    ///
+    /// So an input like:
+    ///
+    /// ```ignore (illustrative)
+    /// let place = Foo::new();
+    /// match place { foo if inspect(foo)
+    ///     => feed(foo), ... }
+    /// ```
+    ///
+    /// will be treated as if it were really something like:
+    ///
+    /// ```ignore (illustrative)
+    /// let place = Foo::new();
+    /// match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
+    ///     => { let tmp2 = place; feed(tmp2) }, ... }
+    /// ```
+    ///
+    /// And an input like:
+    ///
+    /// ```ignore (illustrative)
+    /// let place = Foo::new();
+    /// match place { ref mut foo if inspect(foo)
+    ///     => feed(foo), ... }
+    /// ```
+    ///
+    /// will be treated as if it were really something like:
+    ///
+    /// ```ignore (illustrative)
+    /// let place = Foo::new();
+    /// match place { Foo { .. } if { let tmp1 = & &mut place; inspect(*tmp1) }
+    ///     => { let tmp2 = &mut place; feed(tmp2) }, ... }
+    /// ```
+    /// ---
+    ///
+    /// ## Implementation notes
+    ///
+    /// To encode the distinction above, we must inject the
+    /// temporaries `tmp1` and `tmp2`.
+    ///
+    /// There are two cases of interest: binding by-value, and binding by-ref.
+    ///
+    /// 1. Binding by-value: Things are simple.
+    ///
+    ///    * Establishing `tmp1` creates a reference into the
+    ///      matched place. This code is emitted by
+    ///      [`Self::bind_matched_candidate_for_guard`].
+    ///
+    ///    * `tmp2` is only initialized "lazily", after we have
+    ///      checked the guard. Thus, the code that can trigger
+    ///      moves out of the candidate can only fire after the
+    ///      guard evaluated to true. This initialization code is
+    ///      emitted by [`Self::bind_matched_candidate_for_arm_body`].
+    ///
+    /// 2. Binding by-reference: Things are tricky.
+    ///
+    ///    * Here, the guard expression wants a `&&` or `&&mut`
+    ///      into the original input. This means we need to borrow
+    ///      the reference that we create for the arm.
+    ///    * So we eagerly create the reference for the arm and then take a
+    ///      reference to that.
+    ///
+    /// ---
+    ///
+    /// See these PRs for some historical context:
+    /// - <https://github.com/rust-lang/rust/pull/49870> (introduction of autoref)
+    /// - <https://github.com/rust-lang/rust/pull/59114> (always use autoref)
     fn bind_matched_candidate_for_guard<'b>(
         &mut self,
         block: BasicBlock,
@@ -2418,10 +2455,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             );
             match binding.binding_mode.0 {
                 ByRef::No => {
+                    // The arm binding will be by value, so for the guard binding
+                    // just take a shared reference to the matched place.
                     let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, binding.source);
                     self.cfg.push_assign(block, source_info, ref_for_guard, rvalue);
                 }
                 ByRef::Yes(mutbl) => {
+                    // The arm binding will be by reference, so eagerly create it now.
                     let value_for_arm = self.storage_live_binding(
                         block,
                         binding.var_id,
@@ -2433,6 +2473,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let rvalue =
                         Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source);
                     self.cfg.push_assign(block, source_info, value_for_arm, rvalue);
+                    // For the guard binding, take a shared reference to that reference.
                     let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, value_for_arm);
                     self.cfg.push_assign(block, source_info, ref_for_guard, rvalue);
                 }
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index a65586ccdb7..6309f2ac98e 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -10,7 +10,7 @@ use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
-use rustc_session::lint::builtin::{DEPRECATED_SAFE, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
+use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::symbol::Symbol;
@@ -99,7 +99,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
             {
                 let sm = self.tcx.sess.source_map();
                 self.tcx.emit_node_span_lint(
-                    DEPRECATED_SAFE,
+                    DEPRECATED_SAFE_2024,
                     self.hir_context,
                     span,
                     CallToDeprecatedSafeFnRequiresUnsafe {
@@ -466,6 +466,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     }
                 }
             }
+            ExprKind::AddressOf { arg, .. } => {
+                if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind
+                // THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where
+                // UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps
+                    && let ExprKind::Deref { arg } = self.thir[arg].kind
+                    // FIXME(workingjubiee): we lack a clear reason to reject ThreadLocalRef here,
+                    // but we also have no conclusive reason to allow it either!
+                    && let ExprKind::StaticRef { .. } = self.thir[arg].kind
+                {
+                    // A raw ref to a place expr, even an "unsafe static", is okay!
+                    // We short-circuit to not recursively traverse this expression.
+                    return;
+                    // note: const_mut_refs enables this code, and it currently remains unsafe:
+                    // static mut BYTE: u8 = 0;
+                    // static mut BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(BYTE) };
+                    // static mut DEREF_BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(*BYTE_PTR) };
+                }
+            }
             ExprKind::Deref { arg } => {
                 if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
                     self.thir[arg].kind
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 28f9300b97a..99afb500e0b 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -939,9 +939,11 @@ impl<'tcx> Cx<'tcx> {
                 }
             }
 
-            // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
-            // a constant reference (or constant raw pointer for `static mut`) in MIR
+            // A source Rust `path::to::STATIC` is a place expr like *&ident is.
+            // In THIR, we make them exactly equivalent by inserting the implied *& or *&raw,
+            // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
             Res::Def(DefKind::Static { .. }, id) => {
+                // this is &raw for extern static or static mut, and & for other statics
                 let ty = self.tcx.static_ptr_ty(id);
                 let temp_lifetime = self
                     .rvalue_scopes
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 70065b5a2c3..95799cec94b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_pattern_analysis::errors::Uncovered;
 use rustc_pattern_analysis::rustc::{
-    Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport,
-    WitnessPat,
+    Constructor, DeconstructedPat, MatchArm, RevealedTy, RustcPatCtxt as PatCtxt, Usefulness,
+    UsefulnessReport, WitnessPat,
 };
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
@@ -998,27 +998,31 @@ fn report_non_exhaustive_match<'p, 'tcx>(
     err.note(format!("the matched value is of type `{}`", scrut_ty));
 
     if !is_empty_match {
-        let mut non_exhaustive_tys = FxIndexSet::default();
+        let mut special_tys = FxIndexSet::default();
         // Look at the first witness.
-        collect_non_exhaustive_tys(cx, &witnesses[0], &mut non_exhaustive_tys);
+        collect_special_tys(cx, &witnesses[0], &mut special_tys);
 
-        for ty in non_exhaustive_tys {
+        for ty in special_tys {
             if ty.is_ptr_sized_integral() {
-                if ty == cx.tcx.types.usize {
+                if ty.inner() == cx.tcx.types.usize {
                     err.note(format!(
                         "`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \
                              exhaustively",
                     ));
-                } else if ty == cx.tcx.types.isize {
+                } else if ty.inner() == cx.tcx.types.isize {
                     err.note(format!(
                         "`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \
                              exhaustively",
                     ));
                 }
-            } else if ty == cx.tcx.types.str_ {
+            } else if ty.inner() == cx.tcx.types.str_ {
                 err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary");
-            } else if cx.is_foreign_non_exhaustive_enum(cx.reveal_opaque_ty(ty)) {
+            } else if cx.is_foreign_non_exhaustive_enum(ty) {
                 err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively"));
+            } else if cx.is_uninhabited(ty.inner()) && cx.tcx.features().min_exhaustive_patterns {
+                // The type is uninhabited yet there is a witness: we must be in the `MaybeInvalid`
+                // case.
+                err.note(format!("`{ty}` is uninhabited but is not being matched by value, so a wildcard `_` is required"));
             }
         }
     }
@@ -1168,22 +1172,22 @@ fn joined_uncovered_patterns<'p, 'tcx>(
     }
 }
 
-fn collect_non_exhaustive_tys<'tcx>(
+/// Collect types that require specific explanations when they show up in witnesses.
+fn collect_special_tys<'tcx>(
     cx: &PatCtxt<'_, 'tcx>,
     pat: &WitnessPat<'_, 'tcx>,
-    non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
+    special_tys: &mut FxIndexSet<RevealedTy<'tcx>>,
 ) {
-    if matches!(pat.ctor(), Constructor::NonExhaustive) {
-        non_exhaustive_tys.insert(pat.ty().inner());
+    if matches!(pat.ctor(), Constructor::NonExhaustive | Constructor::Never) {
+        special_tys.insert(*pat.ty());
     }
     if let Constructor::IntRange(range) = pat.ctor() {
         if cx.is_range_beyond_boundaries(range, *pat.ty()) {
             // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
-            non_exhaustive_tys.insert(pat.ty().inner());
+            special_tys.insert(*pat.ty());
         }
     }
-    pat.iter_fields()
-        .for_each(|field_pat| collect_non_exhaustive_tys(cx, field_pat, non_exhaustive_tys))
+    pat.iter_fields().for_each(|field_pat| collect_special_tys(cx, field_pat, special_tys))
 }
 
 fn report_adt_defined_here<'tcx>(
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index a9bceeccdce..d44da42416d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -688,7 +688,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> {
         let init_loc_map = &move_data.init_loc_map;
         let rev_lookup = &move_data.rev_lookup;
 
-        debug!("initializes move_indexes {:?}", &init_loc_map[location]);
+        debug!("initializes move_indexes {:?}", init_loc_map[location]);
         trans.gen_all(init_loc_map[location].iter().copied());
 
         if let mir::StatementKind::StorageDead(local) = stmt.kind {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 261dcd52d71..658cc4c51a9 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -81,7 +81,7 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_target::spec::PanicStrategy;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::TyCtxtInferExt as _;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 08dba1de500..60230bea02e 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -102,7 +102,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 | StatementKind::Nop => (),
 
                 StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
-                    bug!("{:?} not found in this MIR phase!", &statement.kind)
+                    bug!("{:?} not found in this MIR phase!", statement.kind)
                 }
             }
         }
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 9edb8bcee6e..40c0c723d25 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -106,11 +106,11 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
             let parent = BasicBlock::from_usize(i);
             let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue };
 
-            if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {:?}", &opt_data)) {
+            if !tcx.consider_optimizing(|| format!("EarlyOtherwiseBranch {opt_data:?}")) {
                 break;
             }
 
-            trace!("SUCCESS: found optimization possibility to apply: {:?}", &opt_data);
+            trace!("SUCCESS: found optimization possibility to apply: {opt_data:?}");
 
             should_cleanup = true;
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index bfd505c0672..3655a677ba0 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -228,6 +228,7 @@ use rustc_middle::ty::{
     self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
     TypeVisitableExt, VtblEntry,
 };
+use rustc_middle::util::Providers;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::EntryFnType;
 use rustc_session::Limit;
@@ -399,7 +400,7 @@ fn collect_items_rec<'tcx>(
                 let instance = Instance::mono(tcx, def_id);
 
                 // Sanity check whether this ended up being collected accidentally
-                debug_assert!(should_codegen_locally(tcx, instance));
+                debug_assert!(tcx.should_codegen_locally(instance));
 
                 let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
                 // Nested statics have no type.
@@ -431,7 +432,7 @@ fn collect_items_rec<'tcx>(
         }
         MonoItem::Fn(instance) => {
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_codegen_locally(tcx, instance));
+            debug_assert!(tcx.should_codegen_locally(instance));
 
             // Keep track of the monomorphization recursion depth
             recursion_depth_reset = Some(check_recursion_limit(
@@ -475,7 +476,7 @@ fn collect_items_rec<'tcx>(
                         }
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
                             let instance = Instance::mono(tcx, *def_id);
-                            if should_codegen_locally(tcx, instance) {
+                            if tcx.should_codegen_locally(instance) {
                                 trace!("collecting static {:?}", def_id);
                                 used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
                             }
@@ -712,7 +713,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 if let ty::Closure(def_id, args) = *source_ty.kind() {
                     let instance =
                         Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce);
-                    if should_codegen_locally(self.tcx, instance) {
+                    if self.tcx.should_codegen_locally(instance) {
                         self.used_items.push(create_fn_mono_item(self.tcx, instance, span));
                     }
                 } else {
@@ -722,7 +723,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(self.tcx.is_thread_local_static(def_id));
                 let instance = Instance::mono(self.tcx, def_id);
-                if should_codegen_locally(self.tcx, instance) {
+                if self.tcx.should_codegen_locally(instance) {
                     trace!("collecting thread-local static {:?}", def_id);
                     self.used_items.push(respan(span, MonoItem::Static(def_id)));
                 }
@@ -749,7 +750,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
         let tcx = self.tcx;
         let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
             let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
-            if should_codegen_locally(tcx, instance) {
+            if tcx.should_codegen_locally(instance) {
                 this.used_items.push(create_fn_mono_item(tcx, instance, source));
             }
         };
@@ -783,7 +784,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                         }
                         mir::InlineAsmOperand::SymStatic { def_id } => {
                             let instance = Instance::mono(self.tcx, def_id);
-                            if should_codegen_locally(self.tcx, instance) {
+                            if self.tcx.should_codegen_locally(instance) {
                                 trace!("collecting asm sym static {:?}", def_id);
                                 self.used_items.push(respan(source, MonoItem::Static(def_id)));
                             }
@@ -873,7 +874,7 @@ fn visit_instance_use<'tcx>(
     output: &mut MonoItems<'tcx>,
 ) {
     debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
-    if !should_codegen_locally(tcx, instance) {
+    if !tcx.should_codegen_locally(instance) {
         return;
     }
     if let ty::InstanceKind::Intrinsic(def_id) = instance.def {
@@ -885,13 +886,13 @@ fn visit_instance_use<'tcx>(
             // codegen a call to that function without generating code for the function itself.
             let def_id = tcx.require_lang_item(LangItem::PanicNounwind, None);
             let panic_instance = Instance::mono(tcx, def_id);
-            if should_codegen_locally(tcx, panic_instance) {
+            if tcx.should_codegen_locally(panic_instance) {
                 output.push(create_fn_mono_item(tcx, panic_instance, source));
             }
         } else if tcx.has_attr(def_id, sym::rustc_intrinsic) {
             // Codegen the fallback body of intrinsics with fallback bodies
             let instance = ty::Instance::new(def_id, instance.args);
-            if should_codegen_locally(tcx, instance) {
+            if tcx.should_codegen_locally(instance) {
                 output.push(create_fn_mono_item(tcx, instance, source));
             }
         }
@@ -930,7 +931,7 @@ fn visit_instance_use<'tcx>(
 
 /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
 /// can just link to the upstream crate and therefore don't need a mono item.
-pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
+fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -> bool {
     let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
         return true;
     };
@@ -946,7 +947,7 @@ pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance
     }
 
     if tcx.is_reachable_non_generic(def_id)
-        || instance.polymorphize(tcx).upstream_monomorphization(tcx).is_some()
+        || instance.polymorphize(*tcx).upstream_monomorphization(*tcx).is_some()
     {
         // We can link to the item in question, no instance needed in this crate.
         return false;
@@ -1127,7 +1128,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
                     None
                 }
                 VtblEntry::Method(instance) => {
-                    Some(*instance).filter(|instance| should_codegen_locally(tcx, *instance))
+                    Some(*instance).filter(|instance| tcx.should_codegen_locally(*instance))
                 }
             })
             .map(|item| create_fn_mono_item(tcx, item, source));
@@ -1144,7 +1145,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
         GlobalAlloc::Static(def_id) => {
             assert!(!tcx.is_thread_local_static(def_id));
             let instance = Instance::mono(tcx, def_id);
-            if should_codegen_locally(tcx, instance) {
+            if tcx.should_codegen_locally(instance) {
                 trace!("collecting static {:?}", def_id);
                 output.push(dummy_spanned(MonoItem::Static(def_id)));
             }
@@ -1162,7 +1163,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
             }
         }
         GlobalAlloc::Function { instance, .. } => {
-            if should_codegen_locally(tcx, instance) {
+            if tcx.should_codegen_locally(instance) {
                 trace!("collecting {:?} with {:#?}", alloc_id, instance);
                 output.push(create_fn_mono_item(tcx, instance, DUMMY_SP));
             }
@@ -1284,7 +1285,7 @@ fn visit_mentioned_item<'tcx>(
             if let ty::Closure(def_id, args) = *source_ty.kind() {
                 let instance =
                     Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce);
-                if should_codegen_locally(tcx, instance) {
+                if tcx.should_codegen_locally(instance) {
                     output.push(create_fn_mono_item(tcx, instance, span));
                 }
             } else {
@@ -1557,7 +1558,7 @@ fn create_mono_items_for_default_impls<'tcx>(
         let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args, DUMMY_SP);
 
         let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
-        if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) {
+        if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) {
             output.push(mono_item);
         }
     }
@@ -1613,3 +1614,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
 
     (mono_items, state.usage_map.into_inner())
 }
+
+pub fn provide(providers: &mut Providers) {
+    providers.hooks.should_codegen_locally = should_codegen_locally;
+}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index aa3b4cd5b67..fc6e8e0d14f 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -5,14 +5,11 @@
 
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
-use rustc_middle::query::{Providers, TyCtxtAt};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::Instance;
-use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::def_id::DefId;
-use rustc_span::def_id::LOCAL_CRATE;
+use rustc_middle::util::Providers;
 use rustc_span::ErrorGuaranteed;
 
 mod collector;
@@ -21,8 +18,6 @@ mod partitioning;
 mod polymorphize;
 mod util;
 
-use collector::should_codegen_locally;
-
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 fn custom_coerce_unsize_info<'tcx>(
@@ -47,34 +42,6 @@ fn custom_coerce_unsize_info<'tcx>(
     }
 }
 
-/// Returns whether a call from the current crate to the [`Instance`] would produce a call
-/// from `compiler_builtins` to a symbol the linker must resolve.
-///
-/// Such calls from `compiler_bultins` are effectively impossible for the linker to handle. Some
-/// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is
-/// not guaranteed. So we used this function in codegen backends to ensure we do not generate any
-/// unlinkable calls.
-///
-/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
-pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    instance: Instance<'tcx>,
-) -> bool {
-    fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-        if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name {
-            name.as_str().starts_with("llvm.")
-        } else {
-            false
-        }
-    }
-
-    let def_id = instance.def_id();
-    !def_id.is_local()
-        && tcx.is_compiler_builtins(LOCAL_CRATE)
-        && !is_llvm_intrinsic(tcx, def_id)
-        && !should_codegen_locally(tcx, instance)
-}
-
 pub fn provide(providers: &mut Providers) {
     partitioning::provide(providers);
     polymorphize::provide(providers);
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 9a7c488833a..8c7c5e0074a 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -112,9 +112,9 @@ use rustc_middle::mir::mono::{
     CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
     Visibility,
 };
-use rustc_middle::query::Providers;
 use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
 use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceKind, TyCtxt};
+use rustc_middle::util::Providers;
 use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
 use rustc_session::CodegenUnits;
 use rustc_span::symbol::Symbol;
@@ -1314,4 +1314,6 @@ pub fn provide(providers: &mut Providers) {
             .find(|cgu| cgu.name() == name)
             .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
     };
+
+    collector::provide(providers);
 }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 4ce9e0f025c..c79dad3953b 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -524,6 +524,8 @@ parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}
     .label_opening_candidate = closing delimiter possibly meant for this
     .label_unclosed = unclosed delimiter
 
+parse_misplaced_return_type = place the return type after the function parameters
+
 parse_missing_comma_after_match_arm = expected `,` following `match` arm
     .suggestion = missing a comma here to end this `match` arm
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index da0701efddb..109d36fe689 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1503,6 +1503,20 @@ pub(crate) struct FnPtrWithGenerics {
 }
 
 #[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    parse_misplaced_return_type,
+    style = "verbose",
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct MisplacedReturnType {
+    #[suggestion_part(code = " {snippet}")]
+    pub fn_params_end: Span,
+    pub snippet: String,
+    #[suggestion_part(code = "")]
+    pub ret_ty_span: Span,
+}
+
+#[derive(Subdiagnostic)]
 #[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
 pub(crate) struct FnPtrWithGenericsSugg {
     #[suggestion_part(code = "{snippet}")]
@@ -1516,7 +1530,6 @@ pub(crate) struct FnPtrWithGenericsSugg {
 
 pub(crate) struct FnTraitMissingParen {
     pub span: Span,
-    pub machine_applicable: bool,
 }
 
 impl Subdiagnostic for FnTraitMissingParen {
@@ -1526,16 +1539,11 @@ impl Subdiagnostic for FnTraitMissingParen {
         _: &F,
     ) {
         diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
-        let applicability = if self.machine_applicable {
-            Applicability::MachineApplicable
-        } else {
-            Applicability::MaybeIncorrect
-        };
         diag.span_suggestion_short(
             self.span.shrink_to_hi(),
             crate::fluent_generated::parse_add_paren,
             "()",
-            applicability,
+            Applicability::MachineApplicable,
         );
     }
 }
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index a8fe35f45b3..0b2c3044039 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -124,7 +124,7 @@ impl<'a> Parser<'a> {
                 if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
 
             this.expect(&token::OpenDelim(Delimiter::Bracket))?;
-            let item = this.parse_attr_item(false)?;
+            let item = this.parse_attr_item(ForceCollect::No)?;
             this.expect(&token::CloseDelim(Delimiter::Bracket))?;
             let attr_sp = lo.to(this.prev_token.span);
 
@@ -248,16 +248,15 @@ impl<'a> Parser<'a> {
     ///     PATH
     ///     PATH `=` UNSUFFIXED_LIT
     /// The delimiters or `=` are still put into the resulting token stream.
-    pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> {
+    pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> {
         maybe_whole!(self, NtMeta, |attr| attr.into_inner());
 
-        let do_parse = |this: &mut Self| {
+        let do_parse = |this: &mut Self, _empty_attrs| {
             let is_unsafe = this.eat_keyword(kw::Unsafe);
             let unsafety = if is_unsafe {
                 let unsafe_span = this.prev_token.span;
                 this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
                 this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
-
                 ast::Safety::Unsafe(unsafe_span)
             } else {
                 ast::Safety::Default
@@ -268,10 +267,10 @@ impl<'a> Parser<'a> {
             if is_unsafe {
                 this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
             }
-            Ok(ast::AttrItem { unsafety, path, args, tokens: None })
+            Ok((ast::AttrItem { unsafety, path, args, tokens: None }, false))
         };
-        // Attr items don't have attributes
-        if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }
+        // Attr items don't have attributes.
+        self.collect_tokens_trailing_token(AttrWrapper::empty(), force_collect, do_parse)
     }
 
     /// Parses attributes that appear after the opening of an item. These should
@@ -303,17 +302,13 @@ impl<'a> Parser<'a> {
                 None
             };
             if let Some(attr) = attr {
-                let end_pos = self.num_bump_calls;
-                // If we are currently capturing tokens, mark the location of this inner attribute.
-                // If capturing ends up creating a `LazyAttrTokenStream`, we will include
-                // this replace range with it, removing the inner attribute from the final
-                // `AttrTokenStream`. Inner attributes are stored in the parsed AST note.
-                // During macro expansion, they are selectively inserted back into the
-                // token stream (the first inner attribute is removed each time we invoke the
-                // corresponding macro).
-                let range = start_pos..end_pos;
+                // If we are currently capturing tokens (i.e. we are within a call to
+                // `Parser::collect_tokens_trailing_tokens`) record the token positions of this
+                // inner attribute, for possible later processing in a `LazyAttrTokenStream`.
                 if let Capturing::Yes = self.capture_state.capturing {
-                    self.capture_state.inner_attr_ranges.insert(attr.id, (range, None));
+                    let end_pos = self.num_bump_calls;
+                    let range = start_pos..end_pos;
+                    self.capture_state.inner_attr_ranges.insert(attr.id, range);
                 }
                 attrs.push(attr);
             } else {
@@ -344,7 +339,7 @@ impl<'a> Parser<'a> {
         let mut expanded_attrs = Vec::with_capacity(1);
         while self.token.kind != token::Eof {
             let lo = self.token.span;
-            let item = self.parse_attr_item(true)?;
+            let item = self.parse_attr_item(ForceCollect::Yes)?;
             expanded_attrs.push((item, lo.to(self.prev_token.span)));
             if !self.eat(&token::Comma) {
                 break;
@@ -463,7 +458,8 @@ impl<'a> Parser<'a> {
     }
 }
 
-/// The attributes are complete if all attributes are either a doc comment or a builtin attribute other than `cfg_attr`
+/// The attributes are complete if all attributes are either a doc comment or a
+/// builtin attribute other than `cfg_attr`.
 pub fn is_complete(attrs: &[ast::Attribute]) -> bool {
     attrs.iter().all(|attr| {
         attr.is_doc_comment()
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 7e56e92f87b..dc5f98f7be8 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -17,12 +17,12 @@ use std::{iter, mem};
 ///
 /// This wrapper prevents direct access to the underlying `ast::AttrVec`.
 /// Parsing code can only get access to the underlying attributes
-/// by passing an `AttrWrapper` to `collect_tokens_trailing_tokens`.
+/// by passing an `AttrWrapper` to `collect_tokens_trailing_token`.
 /// This makes it difficult to accidentally construct an AST node
 /// (which stores an `ast::AttrVec`) without first collecting tokens.
 ///
 /// This struct has its own module, to ensure that the parser code
-/// cannot directly access the `attrs` field
+/// cannot directly access the `attrs` field.
 #[derive(Debug, Clone)]
 pub struct AttrWrapper {
     attrs: AttrVec,
@@ -76,14 +76,13 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
     })
 }
 
-// Produces a `TokenStream` on-demand. Using `cursor_snapshot`
-// and `num_calls`, we can reconstruct the `TokenStream` seen
-// by the callback. This allows us to avoid producing a `TokenStream`
-// if it is never needed - for example, a captured `macro_rules!`
-// argument that is never passed to a proc macro.
-// In practice token stream creation happens rarely compared to
-// calls to `collect_tokens` (see some statistics in #78736),
-// so we are doing as little up-front work as possible.
+// From a value of this type we can reconstruct the `TokenStream` seen by the
+// `f` callback passed to a call to `Parser::collect_tokens_trailing_token`, by
+// replaying the getting of the tokens. This saves us producing a `TokenStream`
+// if it is never needed, e.g. a captured `macro_rules!` argument that is never
+// passed to a proc macro. In practice, token stream creation happens rarely
+// compared to calls to `collect_tokens` (see some statistics in #78736) so we
+// are doing as little up-front work as possible.
 //
 // This also makes `Parser` very cheap to clone, since
 // there is no intermediate collection buffer to clone.
@@ -163,46 +162,55 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
 }
 
 impl<'a> Parser<'a> {
-    /// Records all tokens consumed by the provided callback,
-    /// including the current token. These tokens are collected
-    /// into a `LazyAttrTokenStream`, and returned along with the first part of
-    /// the callback's result. The second (bool) part of the callback's result
-    /// indicates if an extra token should be captured, e.g. a comma or
+    /// Parses code with `f`. If appropriate, it records the tokens (in
+    /// `LazyAttrTokenStream` form) that were parsed in the result, accessible
+    /// via the `HasTokens` trait. The second (bool) part of the callback's
+    /// result indicates if an extra token should be captured, e.g. a comma or
     /// semicolon.
     ///
     /// The `attrs` passed in are in `AttrWrapper` form, which is opaque. The
     /// `AttrVec` within is passed to `f`. See the comment on `AttrWrapper` for
     /// details.
     ///
-    /// Note: If your callback consumes an opening delimiter
-    /// (including the case where you call `collect_tokens`
-    /// when the current token is an opening delimiter),
-    /// you must also consume the corresponding closing delimiter.
+    /// Note: If your callback consumes an opening delimiter (including the
+    /// case where `self.token` is an opening delimiter on entry to this
+    /// function), you must also consume the corresponding closing delimiter.
+    /// E.g. you can consume `something ([{ }])` or `([{}])`, but not `([{}]`.
+    /// This restriction isn't a problem in practice, because parsed AST items
+    /// always have matching delimiters.
     ///
-    /// That is, you can consume
-    /// `something ([{ }])` or `([{}])`, but not `([{}]`
-    ///
-    /// This restriction shouldn't be an issue in practice,
-    /// since this function is used to record the tokens for
-    /// a parsed AST item, which always has matching delimiters.
+    /// The following example code will be used to explain things in comments
+    /// below. It has an outer attribute and an inner attribute. Parsing it
+    /// involves two calls to this method, one of which is indirectly
+    /// recursive.
+    /// ```ignore (fake attributes)
+    /// #[cfg_eval]                         // token pos
+    /// mod m {                             //   0.. 3
+    ///     #[cfg_attr(cond1, attr1)]       //   3..12
+    ///     fn g() {                        //  12..17
+    ///         #![cfg_attr(cond2, attr2)]  //  17..27
+    ///         let _x = 3;                 //  27..32
+    ///     }                               //  32..33
+    /// }                                   //  33..34
+    /// ```
     pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
         &mut self,
         attrs: AttrWrapper,
         force_collect: ForceCollect,
         f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, bool)>,
     ) -> PResult<'a, R> {
-        // We only bail out when nothing could possibly observe the collected tokens:
-        // 1. We cannot be force collecting tokens (since force-collecting requires tokens
-        //    by definition
+        // Skip collection when nothing could observe the collected tokens, i.e.
+        // all of the following conditions hold.
+        // - We are not force collecting tokens (because force collection
+        //   requires tokens by definition).
         if matches!(force_collect, ForceCollect::No)
-            // None of our outer attributes can require tokens (e.g. a proc-macro)
+            // - None of our outer attributes require tokens.
             && attrs.is_complete()
-            // If our target supports custom inner attributes, then we cannot bail
-            // out early, since we may need to capture tokens for a custom inner attribute
-            // invocation.
+            // - Our target doesn't support custom inner attributes (custom
+            //   inner attribute invocation might require token capturing).
             && !R::SUPPORTS_CUSTOM_INNER_ATTRS
-            // Never bail out early in `capture_cfg` mode, since there might be `#[cfg]`
-            // or `#[cfg_attr]` attributes.
+            // - We are not in `capture_cfg` mode (which requires tokens if
+            //   the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
             && !self.capture_cfg
         {
             return Ok(f(self, attrs.attrs)?.0);
@@ -214,6 +222,12 @@ impl<'a> Parser<'a> {
         let has_outer_attrs = !attrs.attrs.is_empty();
         let replace_ranges_start = self.capture_state.replace_ranges.len();
 
+        // We set and restore `Capturing::Yes` on either side of the call to
+        // `f`, so we can distinguish the outermost call to
+        // `collect_tokens_trailing_token` (e.g. parsing `m` in the example
+        // above) from any inner (indirectly recursive) calls (e.g. parsing `g`
+        // in the example above). This distinction is used below and in
+        // `Parser::parse_inner_attributes`.
         let (mut ret, capture_trailing) = {
             let prev_capturing = mem::replace(&mut self.capture_state.capturing, Capturing::Yes);
             let ret_and_trailing = f(self, attrs.attrs);
@@ -221,51 +235,46 @@ impl<'a> Parser<'a> {
             ret_and_trailing?
         };
 
-        // When we're not in `capture-cfg` mode, then bail out early if:
-        // 1. Our target doesn't support tokens at all (e.g we're parsing an `NtIdent`)
-        //    so there's nothing for us to do.
-        // 2. Our target already has tokens set (e.g. we've parsed something
-        //    like `#[my_attr] $item`). The actual parsing code takes care of
-        //    prepending any attributes to the nonterminal, so we don't need to
-        //    modify the already captured tokens.
-        // Note that this check is independent of `force_collect`- if we already
-        // have tokens, or can't even store them, then there's never a need to
-        // force collection of new tokens.
+        // When we're not in `capture_cfg` mode, then skip collecting and
+        // return early if either of the following conditions hold.
+        // - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
+        // - `Some(Some(_))`: Our target already has tokens set (e.g. we've
+        //   parsed something like `#[my_attr] $item`). The actual parsing code
+        //   takes care of prepending any attributes to the nonterminal, so we
+        //   don't need to modify the already captured tokens.
+        //
+        // Note that this check is independent of `force_collect`. There's no
+        // need to collect tokens when we don't support tokens or already have
+        // tokens.
         if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) {
             return Ok(ret);
         }
 
-        // This is very similar to the bail out check at the start of this function.
-        // Now that we've parsed an AST node, we have more information available.
+        // This is similar to the "skip collection" check at the start of this
+        // function, but now that we've parsed an AST node we have more
+        // information available. (If we return early here that means the
+        // setup, such as cloning the token cursor, was unnecessary. That's
+        // hard to avoid.)
+        //
+        // Skip collection when nothing could observe the collected tokens, i.e.
+        // all of the following conditions hold.
+        // - We are not force collecting tokens.
         if matches!(force_collect, ForceCollect::No)
-            // We now have inner attributes available, so this check is more precise
-            // than `attrs.is_complete()` at the start of the function.
-            // As a result, we don't need to check `R::SUPPORTS_CUSTOM_INNER_ATTRS`
+            // - None of our outer *or* inner attributes require tokens.
+            //   (`attrs` was just outer attributes, but `ret.attrs()` is outer
+            //   and inner attributes. That makes this check more precise than
+            //   `attrs.is_complete()` at the start of the function, and we can
+            //   skip the subsequent check on `R::SUPPORTS_CUSTOM_INNER_ATTRS`.
             && crate::parser::attr::is_complete(ret.attrs())
-            // Subtle: We call `has_cfg_or_cfg_attr` with the attrs from `ret`.
-            // This ensures that we consider inner attributes (e.g. `#![cfg]`),
-            // which require us to have tokens available
-            // We also call `has_cfg_or_cfg_attr` at the beginning of this function,
-            // but we only bail out if there's no possibility of inner attributes
-            // (!R::SUPPORTS_CUSTOM_INNER_ATTRS)
-            // We only capture about `#[cfg]` or `#[cfg_attr]` in `capture_cfg`
-            // mode - during normal parsing, we don't need any special capturing
-            // for those attributes, since they're builtin.
-            && !(self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()))
+            // - We are not in `capture_cfg` mode, or we are but there are no
+            //   `#[cfg]` or `#[cfg_attr]` attributes. (During normal
+            //   non-`capture_cfg` parsing, we don't need any special capturing
+            //   for those attributes, because they're builtin.)
+            && (!self.capture_cfg || !has_cfg_or_cfg_attr(ret.attrs()))
         {
             return Ok(ret);
         }
 
-        let mut inner_attr_replace_ranges = Vec::new();
-        // Take the captured ranges for any inner attributes that we parsed.
-        for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) {
-            if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) {
-                inner_attr_replace_ranges.push(attr_range);
-            } else {
-                self.dcx().span_delayed_bug(inner_attr.span, "Missing token range for attribute");
-            }
-        }
-
         let replace_ranges_end = self.capture_state.replace_ranges.len();
 
         assert!(
@@ -283,15 +292,28 @@ impl<'a> Parser<'a> {
 
         let num_calls = end_pos - start_pos;
 
+        // Take the captured ranges for any inner attributes that we parsed in
+        // `Parser::parse_inner_attributes`, and pair them in a `ReplaceRange`
+        // with `None`, which means the relevant tokens will be removed. (More
+        // details below.)
+        let mut inner_attr_replace_ranges = Vec::new();
+        for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) {
+            if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) {
+                inner_attr_replace_ranges.push((attr_range, None));
+            } else {
+                self.dcx().span_delayed_bug(inner_attr.span, "Missing token range for attribute");
+            }
+        }
+
         // This is hot enough for `deep-vector` that checking the conditions for an empty iterator
         // is measurably faster than actually executing the iterator.
         let replace_ranges: Box<[ReplaceRange]> =
             if replace_ranges_start == replace_ranges_end && inner_attr_replace_ranges.is_empty() {
                 Box::new([])
             } else {
-                // Grab any replace ranges that occur *inside* the current AST node.
-                // We will perform the actual replacement when we convert the `LazyAttrTokenStream`
-                // to an `AttrTokenStream`.
+                // Grab any replace ranges that occur *inside* the current AST node. We will
+                // perform the actual replacement only when we convert the `LazyAttrTokenStream` to
+                // an `AttrTokenStream`.
                 self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end]
                     .iter()
                     .cloned()
@@ -300,6 +322,28 @@ impl<'a> Parser<'a> {
                     .collect()
             };
 
+        // What is the status here when parsing the example code at the top of this method?
+        //
+        // When parsing `g`:
+        // - `start_pos..end_pos` is `12..33` (`fn g { ... }`, excluding the outer attr).
+        // - `inner_attr_replace_ranges` has one entry (`5..15`, when counting from `fn`), to
+        //   delete the inner attr's tokens.
+        //   - This entry is put into the lazy tokens for `g`, i.e. deleting the inner attr from
+        //     those tokens (if they get evaluated).
+        //   - Those lazy tokens are also put into an `AttrsTarget` that is appended to `self`'s
+        //     replace ranges at the bottom of this function, for processing when parsing `m`.
+        // - `replace_ranges_start..replace_ranges_end` is empty.
+        //
+        // When parsing `m`:
+        // - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute).
+        // - `inner_attr_replace_ranges` is empty.
+        // - `replace_range_start..replace_ranges_end` has two entries.
+        //   - One to delete the inner attribute (`17..27`), obtained when parsing `g` (see above).
+        //   - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`,
+        //     including its outer attribute), with:
+        //     - `attrs`: includes the outer and the inner attr.
+        //     - `tokens`: lazy tokens for `g` (with its inner attr deleted).
+
         let tokens = LazyAttrTokenStream::new(LazyAttrTokenStreamImpl {
             start_token,
             num_calls,
@@ -313,27 +357,37 @@ impl<'a> Parser<'a> {
             *target_tokens = Some(tokens.clone());
         }
 
-        let final_attrs = ret.attrs();
-
         // If `capture_cfg` is set and we're inside a recursive call to
         // `collect_tokens_trailing_token`, then we need to register a replace range
         // if we have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager cfg-expansion
         // on the captured token stream.
         if self.capture_cfg
             && matches!(self.capture_state.capturing, Capturing::Yes)
-            && has_cfg_or_cfg_attr(final_attrs)
+            && has_cfg_or_cfg_attr(ret.attrs())
         {
             assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
 
-            // Replace the entire AST node that we just parsed, including attributes, with
-            // `target`. If this AST node is inside an item that has `#[derive]`, then this will
-            // allow us to cfg-expand this AST node.
+            // What is the status here when parsing the example code at the top of this method?
+            //
+            // When parsing `g`, we add two entries:
+            // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with:
+            //   - `attrs`: includes the outer and the inner attr.
+            //   - `tokens`: lazy tokens for `g` (with its inner attr deleted).
+            // - `inner_attr_replace_ranges` contains the one entry to delete the inner attr's
+            //   tokens (`17..27`).
+            //
+            // When parsing `m`, we do nothing here.
+
+            // Set things up so that the entire AST node that we just parsed, including attributes,
+            // will be replaced with `target` in the lazy token stream. This will allow us to
+            // cfg-expand this AST node.
             let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos };
-            let target = AttrsTarget { attrs: final_attrs.iter().cloned().collect(), tokens };
+            let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
             self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target)));
             self.capture_state.replace_ranges.extend(inner_attr_replace_ranges);
         } else if matches!(self.capture_state.capturing, Capturing::No) {
-            // Only clear the ranges once we've finished capturing entirely.
+            // Only clear the ranges once we've finished capturing entirely, i.e. we've finished
+            // the outermost call to this method.
             self.capture_state.replace_ranges.clear();
             self.capture_state.inner_attr_ranges.clear();
         }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 326478a7175..1a0d9aa6378 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -430,7 +430,7 @@ impl<'a> Parser<'a> {
         &mut self,
         edible: &[TokenKind],
         inedible: &[TokenKind],
-    ) -> PResult<'a, Recovered> {
+    ) -> PResult<'a, ErrorGuaranteed> {
         debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
         fn tokens_to_string(tokens: &[TokenType]) -> String {
             let mut i = tokens.iter();
@@ -533,7 +533,7 @@ impl<'a> Parser<'a> {
                     sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
                 });
                 self.bump();
-                return Ok(Recovered::Yes(guar));
+                return Ok(guar);
             } else if self.look_ahead(0, |t| {
                 t == &token::CloseDelim(Delimiter::Brace)
                     || ((t.can_begin_expr() || t.can_begin_item())
@@ -557,7 +557,7 @@ impl<'a> Parser<'a> {
                     unexpected_token_label: Some(self.token.span),
                     sugg: ExpectedSemiSugg::AddSemi(span),
                 });
-                return Ok(Recovered::Yes(guar));
+                return Ok(guar);
             }
         }
 
@@ -712,7 +712,7 @@ impl<'a> Parser<'a> {
         if self.check_too_many_raw_str_terminators(&mut err) {
             if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
                 let guar = err.emit();
-                return Ok(Recovered::Yes(guar));
+                return Ok(guar);
             } else {
                 return Err(err);
             }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 78722ba26cb..fbc5b914600 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -17,6 +17,7 @@ use rustc_span::edit_distance::edit_distance;
 use rustc_span::edition::Edition;
 use rustc_span::source_map;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::ErrorGuaranteed;
 use rustc_span::{Span, DUMMY_SP};
 use std::fmt::Write;
 use std::mem;
@@ -2332,14 +2333,106 @@ impl<'a> Parser<'a> {
                 }
             }
         };
+
+        // Store the end of function parameters to give better diagnostics
+        // inside `parse_fn_body()`.
+        let fn_params_end = self.prev_token.span.shrink_to_hi();
+
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
 
+        // `fn_params_end` is needed only when it's followed by a where clause.
+        let fn_params_end =
+            if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
+
         let mut sig_hi = self.prev_token.span;
-        let body = self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body)?; // `;` or `{ ... }`.
+        // Either `;` or `{ ... }`.
+        let body =
+            self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
         let fn_sig_span = sig_lo.to(sig_hi);
         Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
     }
 
+    /// Provide diagnostics when function body is not found
+    fn error_fn_body_not_found(
+        &mut self,
+        ident_span: Span,
+        req_body: bool,
+        fn_params_end: Option<Span>,
+    ) -> PResult<'a, ErrorGuaranteed> {
+        let expected = if req_body {
+            &[token::OpenDelim(Delimiter::Brace)][..]
+        } else {
+            &[token::Semi, token::OpenDelim(Delimiter::Brace)]
+        };
+        match self.expected_one_of_not_found(&[], expected) {
+            Ok(error_guaranteed) => Ok(error_guaranteed),
+            Err(mut err) => {
+                if self.token.kind == token::CloseDelim(Delimiter::Brace) {
+                    // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
+                    // the AST for typechecking.
+                    err.span_label(ident_span, "while parsing this `fn`");
+                    Ok(err.emit())
+                } else if self.token.kind == token::RArrow
+                    && let Some(fn_params_end) = fn_params_end
+                {
+                    // Instead of a function body, the parser has encountered a right arrow
+                    // preceded by a where clause.
+
+                    // Find whether token behind the right arrow is a function trait and
+                    // store its span.
+                    let fn_trait_span =
+                        [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
+                            if self.prev_token.is_ident_named(symbol) {
+                                Some(self.prev_token.span)
+                            } else {
+                                None
+                            }
+                        });
+
+                    // Parse the return type (along with the right arrow) and store its span.
+                    // If there's a parse error, cancel it and return the existing error
+                    // as we are primarily concerned with the
+                    // expected-function-body-but-found-something-else error here.
+                    let arrow_span = self.token.span;
+                    let ty_span = match self.parse_ret_ty(
+                        AllowPlus::Yes,
+                        RecoverQPath::Yes,
+                        RecoverReturnSign::Yes,
+                    ) {
+                        Ok(ty_span) => ty_span.span().shrink_to_hi(),
+                        Err(parse_error) => {
+                            parse_error.cancel();
+                            return Err(err);
+                        }
+                    };
+                    let ret_ty_span = arrow_span.to(ty_span);
+
+                    if let Some(fn_trait_span) = fn_trait_span {
+                        // Typo'd Fn* trait bounds such as
+                        // fn foo<F>() where F: FnOnce -> () {}
+                        err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
+                    } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
+                    {
+                        // If token behind right arrow is not a Fn* trait, the programmer
+                        // probably misplaced the return type after the where clause like
+                        // `fn foo<T>() where T: Default -> u8 {}`
+                        err.primary_message(
+                            "return type should be specified after the function parameters",
+                        );
+                        err.subdiagnostic(errors::MisplacedReturnType {
+                            fn_params_end,
+                            snippet,
+                            ret_ty_span,
+                        });
+                    }
+                    Err(err)
+                } else {
+                    Err(err)
+                }
+            }
+        }
+    }
+
     /// Parse the "body" of a function.
     /// This can either be `;` when there's no body,
     /// or e.g. a block when the function is a provided one.
@@ -2349,6 +2442,7 @@ impl<'a> Parser<'a> {
         ident: &Ident,
         sig_hi: &mut Span,
         req_body: bool,
+        fn_params_end: Option<Span>,
     ) -> PResult<'a, Option<P<Block>>> {
         let has_semi = if req_body {
             self.token.kind == TokenKind::Semi
@@ -2377,33 +2471,7 @@ impl<'a> Parser<'a> {
             });
             (AttrVec::new(), Some(self.mk_block_err(span, guar)))
         } else {
-            let expected = if req_body {
-                &[token::OpenDelim(Delimiter::Brace)][..]
-            } else {
-                &[token::Semi, token::OpenDelim(Delimiter::Brace)]
-            };
-            if let Err(mut err) = self.expected_one_of_not_found(&[], expected) {
-                if self.token.kind == token::CloseDelim(Delimiter::Brace) {
-                    // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
-                    // the AST for typechecking.
-                    err.span_label(ident.span, "while parsing this `fn`");
-                    err.emit();
-                } else {
-                    // check for typo'd Fn* trait bounds such as
-                    // fn foo<F>() where F: FnOnce -> () {}
-                    if self.token.kind == token::RArrow {
-                        let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn]
-                            .into_iter()
-                            .any(|s| self.prev_token.is_ident_named(s));
-
-                        err.subdiagnostic(errors::FnTraitMissingParen {
-                            span: self.prev_token.span,
-                            machine_applicable,
-                        });
-                    }
-                    return Err(err);
-                }
-            }
+            self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
             (AttrVec::new(), None)
         };
         attrs.extend(inner_attrs);
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index c03527acb2c..7326b9ec51f 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -221,11 +221,12 @@ enum Capturing {
     Yes,
 }
 
+// This state is used by `Parser::collect_tokens_trailing_token`.
 #[derive(Clone, Debug)]
 struct CaptureState {
     capturing: Capturing,
     replace_ranges: Vec<ReplaceRange>,
-    inner_attr_ranges: FxHashMap<AttrId, ReplaceRange>,
+    inner_attr_ranges: FxHashMap<AttrId, Range<u32>>,
 }
 
 /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
@@ -425,6 +426,11 @@ impl<'a> Parser<'a> {
         // Make parser point to the first token.
         parser.bump();
 
+        // Change this from 1 back to 0 after the bump. This eases debugging of
+        // `Parser::collect_tokens_trailing_token` nicer because it makes the
+        // token positions 0-indexed which is nicer than 1-indexed.
+        parser.num_bump_calls = 0;
+
         parser
     }
 
@@ -495,6 +501,7 @@ impl<'a> Parser<'a> {
             FatalError.raise();
         } else {
             self.expected_one_of_not_found(edible, inedible)
+                .map(|error_guaranteed| Recovered::Yes(error_guaranteed))
         }
     }
 
@@ -942,11 +949,10 @@ impl<'a> Parser<'a> {
         let initial_semicolon = self.token.span;
 
         while self.eat(&TokenKind::Semi) {
-            let _ =
-                self.parse_stmt_without_recovery(false, ForceCollect::Yes).unwrap_or_else(|e| {
-                    e.cancel();
-                    None
-                });
+            let _ = self.parse_stmt_without_recovery(false, ForceCollect::No).unwrap_or_else(|e| {
+                e.cancel();
+                None
+            });
         }
 
         expect_err
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 41e31d76d62..886d6af1735 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -171,7 +171,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Path => {
                 NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
             }
-            NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)),
+            NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)),
             NonterminalKind::Vis => {
                 NtVis(P(self
                     .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 3ec891b4eea..d8de7c1bfa1 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -72,6 +72,7 @@ impl<'a> Parser<'a> {
                 lo,
                 attrs,
                 errors::InvalidVariableDeclarationSub::MissingLet,
+                force_collect,
             )?
         } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
             self.bump(); // `auto`
@@ -79,6 +80,7 @@ impl<'a> Parser<'a> {
                 lo,
                 attrs,
                 errors::InvalidVariableDeclarationSub::UseLetNotAuto,
+                force_collect,
             )?
         } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
             self.bump(); // `var`
@@ -86,6 +88,7 @@ impl<'a> Parser<'a> {
                 lo,
                 attrs,
                 errors::InvalidVariableDeclarationSub::UseLetNotVar,
+                force_collect,
             )?
         } else if self.check_path()
             && !self.token.is_qpath_start()
@@ -96,17 +99,17 @@ impl<'a> Parser<'a> {
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
             // that starts like a path (1 token), but it fact not a path.
             // Also, we avoid stealing syntax from `parse_item_`.
-            match force_collect {
-                ForceCollect::Yes => {
-                    self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))?
+            let stmt = self.collect_tokens_trailing_token(
+                AttrWrapper::empty(),
+                force_collect,
+                |this, _empty_attrs| Ok((this.parse_stmt_path_start(lo, attrs)?, false)),
+            );
+            match stmt {
+                Ok(stmt) => stmt,
+                Err(mut err) => {
+                    self.suggest_add_missing_let_for_stmt(&mut err);
+                    return Err(err);
                 }
-                ForceCollect::No => match self.parse_stmt_path_start(lo, attrs) {
-                    Ok(stmt) => stmt,
-                    Err(mut err) => {
-                        self.suggest_add_missing_let_for_stmt(&mut err);
-                        return Err(err);
-                    }
-                },
             }
         } else if let Some(item) = self.parse_item_common(
             attrs.clone(),
@@ -123,12 +126,13 @@ impl<'a> Parser<'a> {
             self.mk_stmt(lo, StmtKind::Empty)
         } else if self.token != token::CloseDelim(Delimiter::Brace) {
             // Remainder are line-expr stmts.
-            let e = match force_collect {
-                ForceCollect::Yes => self.collect_tokens_no_attrs(|this| {
-                    this.parse_expr_res(Restrictions::STMT_EXPR, attrs)
-                })?,
-                ForceCollect::No => self.parse_expr_res(Restrictions::STMT_EXPR, attrs)?,
-            };
+            let e = self.collect_tokens_trailing_token(
+                AttrWrapper::empty(),
+                force_collect,
+                |this, _empty_attrs| {
+                    Ok((this.parse_expr_res(Restrictions::STMT_EXPR, attrs)?, false))
+                },
+            )?;
             if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) {
                 let bl = self.parse_block()?;
                 // Destructuring assignment ... else.
@@ -231,13 +235,13 @@ impl<'a> Parser<'a> {
         lo: Span,
         attrs: AttrWrapper,
         subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub,
+        force_collect: ForceCollect,
     ) -> PResult<'a, Stmt> {
-        let stmt =
-            self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| {
-                let local = this.parse_local(attrs)?;
-                // FIXME - maybe capture semicolon in recovery?
-                Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), false))
-            })?;
+        let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
+            let local = this.parse_local(attrs)?;
+            // FIXME - maybe capture semicolon in recovery?
+            Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), false))
+        })?;
         self.dcx()
             .emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
         Ok(stmt)
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index cf791d332a2..491aa71155a 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -1522,7 +1522,7 @@ fn debug_lookahead() {
         },
     },
     tokens: [],
-    approx_token_stream_pos: 1,
+    approx_token_stream_pos: 0,
     ..
 }"
         );
@@ -1566,7 +1566,7 @@ fn debug_lookahead() {
             Parenthesis,
         ),
     ],
-    approx_token_stream_pos: 1,
+    approx_token_stream_pos: 0,
     ..
 }"
         );
@@ -1631,7 +1631,7 @@ fn debug_lookahead() {
         Semi,
         Eof,
     ],
-    approx_token_stream_pos: 1,
+    approx_token_stream_pos: 0,
     ..
 }"
         );
@@ -1663,7 +1663,7 @@ fn debug_lookahead() {
             No,
         ),
     ],
-    approx_token_stream_pos: 9,
+    approx_token_stream_pos: 8,
     ..
 }"
         );
@@ -1701,7 +1701,7 @@ fn debug_lookahead() {
             No,
         ),
     ],
-    approx_token_stream_pos: 9,
+    approx_token_stream_pos: 8,
     ..
 }"
         );
@@ -1728,7 +1728,7 @@ fn debug_lookahead() {
     tokens: [
         Eof,
     ],
-    approx_token_stream_pos: 15,
+    approx_token_stream_pos: 14,
     ..
 }"
         );
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 68b8af7d20e..a8134110010 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -21,6 +21,11 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 use thin_vec::{thin_vec, ThinVec};
 
+/// Signals whether parsing a type should allow `+`.
+///
+/// For example, let T be the type `impl Default + 'static`
+/// With `AllowPlus::Yes`, T will be parsed successfully
+/// With `AllowPlus::No`, parsing T will return a parse error
 #[derive(Copy, Clone, PartialEq)]
 pub(super) enum AllowPlus {
     Yes,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index ce2fa83810f..9cbd989cc0e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -34,7 +34,7 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
 use rustc_trait_selection::traits::ObligationCtxt;
 use std::cell::Cell;
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 603e98cfa92..6f59c782e06 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -8,7 +8,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::abi::{HasDataLayout, TargetDataLayout};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::{infer::TyCtxtInferExt, traits};
 
 use crate::errors::{
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index fb103705475..f3e8e547066 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -904,7 +904,7 @@ impl<Cx: PatCx> Constructor<Cx> {
             // be careful to detect strings here. However a string literal pattern will never
             // be reported as a non-exhaustiveness witness, so we can ignore this issue.
             Ref => {
-                write!(f, "&{:?}", &fields.next().unwrap())?;
+                write!(f, "&{:?}", fields.next().unwrap())?;
             }
             Slice(slice) => {
                 write!(f, "[")?;
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index 5e75976621e..e8d6c542c5f 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -190,7 +190,18 @@ impl<'p, Cx: PatCx> PatOrWild<'p, Cx> {
         }
     }
 
-    /// Expand this (possibly-nested) or-pattern into its alternatives.
+    /// Expand this or-pattern into its alternatives. This only expands one or-pattern; use
+    /// `flatten_or_pat` to recursively expand nested or-patterns.
+    pub(crate) fn expand_or_pat(self) -> SmallVec<[Self; 1]> {
+        match self {
+            PatOrWild::Pat(pat) if pat.is_or_pat() => {
+                pat.iter_fields().map(|ipat| PatOrWild::Pat(&ipat.pat)).collect()
+            }
+            _ => smallvec![self],
+        }
+    }
+
+    /// Recursively expand this (possibly-nested) or-pattern into its alternatives.
     pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> {
         match self {
             PatOrWild::Pat(pat) if pat.is_or_pat() => pat
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index d17ee8bff50..6ef2d69273e 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -40,9 +40,15 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcPatCtxt<'p, 'tcx>>;
 ///
 /// Use `.inner()` or deref to get to the `Ty<'tcx>`.
 #[repr(transparent)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct RevealedTy<'tcx>(Ty<'tcx>);
 
+impl<'tcx> fmt::Display for RevealedTy<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(fmt)
+    }
+}
+
 impl<'tcx> fmt::Debug for RevealedTy<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(fmt)
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 6e96a93473f..8486792b554 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -462,8 +462,9 @@
 //! # Or-patterns
 //!
 //! What we have described so far works well if there are no or-patterns. To handle them, if the
-//! first pattern of a row in the matrix is an or-pattern, we expand it by duplicating the rest of
-//! the row as necessary. This is handled automatically in [`Matrix`].
+//! first pattern of any row in the matrix is an or-pattern, we expand it by duplicating the rest of
+//! the row as necessary. For code reuse, this is implemented as "specializing with the `Or`
+//! constructor".
 //!
 //! This makes usefulness tracking subtle, because we also want to compute whether an alternative of
 //! an or-pattern is redundant, e.g. in `Some(_) | Some(0)`. We therefore track usefulness of each
@@ -875,6 +876,11 @@ impl<Cx: PatCx> PlaceInfo<Cx> {
             return Ok((smallvec![Constructor::PrivateUninhabited], vec![]));
         }
 
+        if ctors.clone().any(|c| matches!(c, Constructor::Or)) {
+            // If any constructor is `Or`, we expand or-patterns.
+            return Ok((smallvec![Constructor::Or], vec![]));
+        }
+
         let ctors_for_ty = cx.ctors_for_ty(&self.ty)?;
         debug!(?ctors_for_ty);
 
@@ -968,10 +974,6 @@ impl<'p, Cx: PatCx> PatStack<'p, Cx> {
         PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true }
     }
 
-    fn is_empty(&self) -> bool {
-        self.pats.is_empty()
-    }
-
     fn len(&self) -> usize {
         self.pats.len()
     }
@@ -984,10 +986,10 @@ impl<'p, Cx: PatCx> PatStack<'p, Cx> {
         self.pats.iter().copied()
     }
 
-    // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
-    // an or-pattern. Panics if `self` is empty.
+    // Expand the first or-pattern into its subpatterns. Only useful if the pattern is an
+    // or-pattern. Panics if `self` is empty.
     fn expand_or_pat(&self) -> impl Iterator<Item = PatStack<'p, Cx>> + Captures<'_> {
-        self.head().flatten_or_pat().into_iter().map(move |pat| {
+        self.head().expand_or_pat().into_iter().map(move |pat| {
             let mut new = self.clone();
             new.pats[0] = pat;
             new
@@ -1057,10 +1059,6 @@ struct MatrixRow<'p, Cx: PatCx> {
 }
 
 impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
-    fn is_empty(&self) -> bool {
-        self.pats.is_empty()
-    }
-
     fn len(&self) -> usize {
         self.pats.len()
     }
@@ -1073,12 +1071,14 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
         self.pats.iter()
     }
 
-    // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
-    // an or-pattern. Panics if `self` is empty.
-    fn expand_or_pat(&self) -> impl Iterator<Item = MatrixRow<'p, Cx>> + Captures<'_> {
-        self.pats.expand_or_pat().map(|patstack| MatrixRow {
+    // Expand the first or-pattern (if any) into its subpatterns. Panics if `self` is empty.
+    fn expand_or_pat(
+        &self,
+        parent_row: usize,
+    ) -> impl Iterator<Item = MatrixRow<'p, Cx>> + Captures<'_> {
+        self.pats.expand_or_pat().map(move |patstack| MatrixRow {
             pats: patstack,
-            parent_row: self.parent_row,
+            parent_row,
             is_under_guard: self.is_under_guard,
             useful: false,
             intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
@@ -1100,7 +1100,7 @@ impl<'p, Cx: PatCx> MatrixRow<'p, Cx> {
             parent_row,
             is_under_guard: self.is_under_guard,
             useful: false,
-            intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
+            intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`.
         })
     }
 }
@@ -1116,7 +1116,7 @@ impl<'p, Cx: PatCx> fmt::Debug for MatrixRow<'p, Cx> {
 /// Invariant: each row must have the same length, and each column must have the same type.
 ///
 /// Invariant: the first column must not contain or-patterns. This is handled by
-/// [`Matrix::expand_and_push`].
+/// [`Matrix::push`].
 ///
 /// In fact each column corresponds to a place inside the scrutinee of the match. E.g. after
 /// specializing `(,)` and `Some` on a pattern of type `(Option<u32>, bool)`, the first column of
@@ -1136,19 +1136,10 @@ struct Matrix<'p, Cx: PatCx> {
 }
 
 impl<'p, Cx: PatCx> Matrix<'p, Cx> {
-    /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
-    /// expands it. Internal method, prefer [`Matrix::new`].
-    fn expand_and_push(&mut self, mut row: MatrixRow<'p, Cx>) {
-        if !row.is_empty() && row.head().is_or_pat() {
-            // Expand nested or-patterns.
-            for mut new_row in row.expand_or_pat() {
-                new_row.intersects = BitSet::new_empty(self.rows.len());
-                self.rows.push(new_row);
-            }
-        } else {
-            row.intersects = BitSet::new_empty(self.rows.len());
-            self.rows.push(row);
-        }
+    /// Pushes a new row to the matrix. Internal method, prefer [`Matrix::new`].
+    fn push(&mut self, mut row: MatrixRow<'p, Cx>) {
+        row.intersects = BitSet::new_empty(self.rows.len());
+        self.rows.push(row);
     }
 
     /// Build a new matrix from an iterator of `MatchArm`s.
@@ -1170,9 +1161,9 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> {
                 parent_row: arm_id,
                 is_under_guard: arm.has_guard,
                 useful: false,
-                intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
+                intersects: BitSet::new_empty(0), // Initialized in `Matrix::push`.
             };
-            matrix.expand_and_push(v);
+            matrix.push(v);
         }
         matrix
     }
@@ -1209,22 +1200,38 @@ impl<'p, Cx: PatCx> Matrix<'p, Cx> {
         ctor: &Constructor<Cx>,
         ctor_is_relevant: bool,
     ) -> Result<Matrix<'p, Cx>, Cx::Error> {
-        let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor);
-        let arity = subfield_place_info.len();
-        let specialized_place_info =
-            subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect();
-        let mut matrix = Matrix {
-            rows: Vec::new(),
-            place_info: specialized_place_info,
-            wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
-        };
-        for (i, row) in self.rows().enumerate() {
-            if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
-                let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?;
-                matrix.expand_and_push(new_row);
+        if matches!(ctor, Constructor::Or) {
+            // Specializing with `Or` means expanding rows with or-patterns.
+            let mut matrix = Matrix {
+                rows: Vec::new(),
+                place_info: self.place_info.clone(),
+                wildcard_row_is_relevant: self.wildcard_row_is_relevant,
+            };
+            for (i, row) in self.rows().enumerate() {
+                for new_row in row.expand_or_pat(i) {
+                    matrix.push(new_row);
+                }
             }
+            Ok(matrix)
+        } else {
+            let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor);
+            let arity = subfield_place_info.len();
+            let specialized_place_info =
+                subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect();
+            let mut matrix = Matrix {
+                rows: Vec::new(),
+                place_info: specialized_place_info,
+                wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
+            };
+            for (i, row) in self.rows().enumerate() {
+                if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
+                    let new_row =
+                        row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?;
+                    matrix.push(new_row);
+                }
+            }
+            Ok(matrix)
         }
-        Ok(matrix)
     }
 
     /// Recover row usefulness and intersection information from a processed specialized matrix.
@@ -1465,7 +1472,9 @@ impl<Cx: PatCx> WitnessMatrix<Cx> {
         missing_ctors: &[Constructor<Cx>],
         ctor: &Constructor<Cx>,
     ) {
-        if self.is_empty() {
+        // The `Or` constructor indicates that we expanded or-patterns. This doesn't affect
+        // witnesses.
+        if self.is_empty() || matches!(ctor, Constructor::Or) {
             return;
         }
         if matches!(ctor, Constructor::Missing) {
@@ -1715,48 +1724,6 @@ pub enum Usefulness<'p, Cx: PatCx> {
     Redundant,
 }
 
-/// Report whether this pattern was found useful, and its subpatterns that were not useful if any.
-fn collect_pattern_usefulness<'p, Cx: PatCx>(
-    useful_subpatterns: &FxHashSet<PatId>,
-    pat: &'p DeconstructedPat<Cx>,
-) -> Usefulness<'p, Cx> {
-    fn pat_is_useful<'p, Cx: PatCx>(
-        useful_subpatterns: &FxHashSet<PatId>,
-        pat: &'p DeconstructedPat<Cx>,
-    ) -> bool {
-        if useful_subpatterns.contains(&pat.uid) {
-            true
-        } else if pat.is_or_pat()
-            && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, &f.pat))
-        {
-            // We always expand or patterns in the matrix, so we will never see the actual
-            // or-pattern (the one with constructor `Or`) in the column. As such, it will not be
-            // marked as useful itself, only its children will. We recover this information here.
-            true
-        } else {
-            false
-        }
-    }
-
-    let mut redundant_subpats = Vec::new();
-    pat.walk(&mut |p| {
-        if pat_is_useful(useful_subpatterns, p) {
-            // The pattern is useful, so we recurse to find redundant subpatterns.
-            true
-        } else {
-            // The pattern is redundant.
-            redundant_subpats.push(p);
-            false // stop recursing
-        }
-    });
-
-    if pat_is_useful(useful_subpatterns, pat) {
-        Usefulness::Useful(redundant_subpats)
-    } else {
-        Usefulness::Redundant
-    }
-}
-
 /// The output of checking a match for exhaustiveness and arm usefulness.
 pub struct UsefulnessReport<'p, Cx: PatCx> {
     /// For each arm of the input, whether that arm is useful after the arms above it.
@@ -1793,25 +1760,26 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>(
         .copied()
         .map(|arm| {
             debug!(?arm);
-            let usefulness = collect_pattern_usefulness(&cx.useful_subpatterns, arm.pat);
+            let usefulness = if cx.useful_subpatterns.contains(&arm.pat.uid) {
+                let mut redundant_subpats = Vec::new();
+                arm.pat.walk(&mut |subpat| {
+                    if cx.useful_subpatterns.contains(&subpat.uid) {
+                        true // keep recursing
+                    } else {
+                        redundant_subpats.push(subpat);
+                        false // stop recursing
+                    }
+                });
+                Usefulness::Useful(redundant_subpats)
+            } else {
+                Usefulness::Redundant
+            };
             debug!(?usefulness);
             (arm, usefulness)
         })
         .collect();
 
-    let mut arm_intersections: Vec<_> =
-        arms.iter().enumerate().map(|(i, _)| BitSet::new_empty(i)).collect();
-    for row in matrix.rows() {
-        let arm_id = row.parent_row;
-        for intersection in row.intersects.iter() {
-            // Convert the matrix row ids into arm ids (they can differ because we expand or-patterns).
-            let arm_intersection = matrix.rows[intersection].parent_row;
-            // Note: self-intersection can happen with or-patterns.
-            if arm_intersection != arm_id {
-                arm_intersections[arm_id].insert(arm_intersection);
-            }
-        }
-    }
+    let arm_intersections: Vec<_> = matrix.rows().map(|row| row.intersects.clone()).collect();
 
     Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses, arm_intersections })
 }
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 4b9c36ad39f..73d1a2ea49a 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -232,6 +232,8 @@ resolve_is_private =
 resolve_item_was_behind_feature =
     the item is gated behind the `{$feature}` feature
 
+resolve_item_was_cfg_out = the item is gated here
+
 resolve_items_in_traits_are_not_importable =
     items in traits are not importable
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 566223f98bf..bf7972e392c 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     BuiltinLintDiag::AmbiguousGlobImports { diag },
                 );
             } else {
-                let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", &diag.msg);
+                let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", diag.msg);
                 report_ambiguity_error(&mut err, diag);
                 err.emit();
             }
@@ -798,7 +798,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
             ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
                 let mut err =
-                    struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label);
+                    struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {label}");
                 err.span_label(span, label);
 
                 if let Some((suggestions, msg, applicability)) = suggestion {
@@ -2532,7 +2532,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 && let NestedMetaItem::MetaItem(meta_item) = &nested[0]
                 && let MetaItemKind::NameValue(feature_name) = &meta_item.kind
             {
-                let note = errors::ItemWasBehindFeature { feature: feature_name.symbol };
+                let note = errors::ItemWasBehindFeature {
+                    feature: feature_name.symbol,
+                    span: meta_item.span,
+                };
+                err.subdiagnostic(note);
+            } else {
+                let note = errors::ItemWasCfgOut { span: cfg.span };
                 err.subdiagnostic(note);
             }
         }
@@ -2887,7 +2893,7 @@ fn show_candidates(
                     ""
                 };
                 candidate.0 =
-                    format!("{add_use}{}{append}{trailing}{additional_newline}", &candidate.0);
+                    format!("{add_use}{}{append}{trailing}{additional_newline}", candidate.0);
             }
 
             match mode {
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 097f4af05c3..0a68231c6fe 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1228,6 +1228,15 @@ pub(crate) struct FoundItemConfigureOut {
 #[note(resolve_item_was_behind_feature)]
 pub(crate) struct ItemWasBehindFeature {
     pub(crate) feature: Symbol,
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(resolve_item_was_cfg_out)]
+pub(crate) struct ItemWasCfgOut {
+    #[primary_span]
+    pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 3896fe4c4fa..d05326ee311 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -694,7 +694,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             .collect::<Vec<_>>();
         let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
 
-        let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{}", &msg);
+        let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{msg}");
 
         if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.iter().last() {
             diag.note(note.clone());
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index dc7200465d9..51414d78596 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2763,7 +2763,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             let res = match kind {
                 RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()),
                 RibKind::Normal => {
-                    if self.r.tcx.features().non_lifetime_binders {
+                    // FIXME(non_lifetime_binders): Stop special-casing
+                    // const params to error out here.
+                    if self.r.tcx.features().non_lifetime_binders
+                        && matches!(param.kind, GenericParamKind::Type { .. })
+                    {
                         Res::Def(def_kind, def_id.to_def_id())
                     } else {
                         Res::Err
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 59460815321..4c49c15c472 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -339,7 +339,7 @@ pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGen
         }
     }
 
-    debug!("path_str: {:?}\nstripped segments: {:?}", path_str, &stripped_segments);
+    debug!("path_str: {path_str:?}\nstripped segments: {stripped_segments:?}");
 
     let stripped_path = stripped_segments.join("::");
 
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index f998fd599b7..190ea443189 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -238,12 +238,12 @@ fn encode_predicate<'tcx>(
     match predicate.as_ref().skip_binder() {
         ty::ExistentialPredicate::Trait(trait_ref) => {
             let name = encode_ty_name(tcx, trait_ref.def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
             s.push_str(&encode_args(tcx, trait_ref.args, trait_ref.def_id, true, dict, options));
         }
         ty::ExistentialPredicate::Projection(projection) => {
             let name = encode_ty_name(tcx, projection.def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
             s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options));
             match projection.term.unpack() {
                 TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
@@ -258,7 +258,7 @@ fn encode_predicate<'tcx>(
         }
         ty::ExistentialPredicate::AutoTrait(def_id) => {
             let name = encode_ty_name(tcx, *def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
         }
     };
     compress(dict, DictKey::Predicate(*predicate.as_ref().skip_binder()), &mut s);
@@ -416,7 +416,7 @@ pub fn encode_ty<'tcx>(
             // A<array-length><element-type>
             let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
             let mut s = String::from("A");
-            let _ = write!(s, "{}", &len);
+            let _ = write!(s, "{len}");
             s.push_str(&encode_ty(tcx, *ty0, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
@@ -492,13 +492,13 @@ pub fn encode_ty<'tcx>(
                 // calling convention (or extern types [i.e., ty::Foreign]) as <length><name>, where
                 // <name> is <unscoped-name>.
                 let name = tcx.item_name(def_id).to_string();
-                let _ = write!(s, "{}{}", name.len(), &name);
+                let _ = write!(s, "{}{}", name.len(), name);
                 compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             } else {
                 // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is
                 // <subst>, as vendor extended type.
                 let name = encode_ty_name(tcx, def_id);
-                let _ = write!(s, "u{}{}", name.len(), &name);
+                let _ = write!(s, "u{}{}", name.len(), name);
                 s.push_str(&encode_args(tcx, args, def_id, false, dict, options));
                 compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             }
@@ -530,7 +530,7 @@ pub fn encode_ty<'tcx>(
                 }
             } else {
                 let name = tcx.item_name(*def_id).to_string();
-                let _ = write!(s, "{}{}", name.len(), &name);
+                let _ = write!(s, "{}{}", name.len(), name);
             }
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
@@ -542,7 +542,7 @@ pub fn encode_ty<'tcx>(
             // as vendor extended type.
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
             s.push_str(&encode_args(tcx, args, *def_id, false, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
@@ -553,7 +553,7 @@ pub fn encode_ty<'tcx>(
             // as vendor extended type.
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
             let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args());
             s.push_str(&encode_args(tcx, parent_args, *def_id, false, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
@@ -565,7 +565,7 @@ pub fn encode_ty<'tcx>(
             // as vendor extended type.
             let mut s = String::new();
             let name = encode_ty_name(tcx, *def_id);
-            let _ = write!(s, "u{}{}", name.len(), &name);
+            let _ = write!(s, "u{}{}", name.len(), name);
             // Encode parent args only
             s.push_str(&encode_args(
                 tcx,
@@ -588,7 +588,7 @@ pub fn encode_ty<'tcx>(
             s.push('E');
             compress(dict, DictKey::Ty(Ty::new_imm_ref(tcx, *region, *ty0), TyQ::None), &mut s);
             if ty.is_mutable_ptr() {
-                s = format!("{}{}", "U3mut", &s);
+                s = format!("{}{}", "U3mut", s);
                 compress(dict, DictKey::Ty(ty, TyQ::Mut), &mut s);
             }
             typeid.push_str(&s);
@@ -600,10 +600,10 @@ pub fn encode_ty<'tcx>(
             let mut s = String::new();
             s.push_str(&encode_ty(tcx, *ptr_ty, dict, options));
             if !ty.is_mutable_ptr() {
-                s = format!("{}{}", "K", &s);
+                s = format!("{}{}", "K", s);
                 compress(dict, DictKey::Ty(*ptr_ty, TyQ::Const), &mut s);
             };
-            s = format!("{}{}", "P", &s);
+            s = format!("{}{}", "P", s);
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
         }
@@ -722,7 +722,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
     s.push('C');
     s.push_str(&to_disambiguator(tcx.stable_crate_id(def_path.krate).as_u64()));
     let crate_name = tcx.crate_name(def_path.krate).to_string();
-    let _ = write!(s, "{}{}", crate_name.len(), &crate_name);
+    let _ = write!(s, "{}{}", crate_name.len(), crate_name);
 
     // Disambiguators and names
     def_path.data.reverse();
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 f0f2d1fefd2..9b05576d721 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
@@ -9,10 +9,10 @@ use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{
-    self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable,
-    TypeVisitableExt, UintTy,
+    self, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, List, TraitRef, Ty,
+    TyCtxt, TypeFoldable, TypeVisitableExt, UintTy,
 };
-use rustc_span::sym;
+use rustc_span::{def_id::DefId, sym};
 use rustc_trait_selection::traits;
 use std::iter;
 use tracing::{debug, instrument};
@@ -360,41 +360,29 @@ pub fn transform_instance<'tcx>(
     if !options.contains(TransformTyOptions::USE_CONCRETE_SELF) {
         // Perform type erasure for calls on trait objects by transforming self into a trait object
         // of the trait that defines the method.
-        if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
-            && let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
-        {
-            let impl_method = tcx.associated_item(instance.def_id());
-            let method_id = impl_method
-                .trait_item_def_id
-                .expect("Part of a trait implementation, but not linked to the def_id?");
-            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.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
-                let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
-                    instance.args,
-                    ty::ParamEnv::reveal_all(),
-                    trait_ref,
-                );
-                let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
+        if let Some((trait_ref, method_id, ancestor)) = implemented_method(tcx, instance) {
+            // 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
+            let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
+                instance.args,
+                ty::ParamEnv::reveal_all(),
+                trait_ref,
+            );
+            let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref));
 
-                // At the call site, any call to this concrete function through a vtable will be
-                // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
-                // original method id, and we've recovered the trait arguments, we can make the callee
-                // instance we're computing the alias set for match the caller instance.
-                //
-                // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
-                // If we ever *do* start encoding the vtable index, we will need to generate an alias set
-                // based on which vtables we are putting this method into, as there will be more than one
-                // index value when supertraits are involved.
-                instance.def = ty::InstanceKind::Virtual(method_id, 0);
-                let abstract_trait_args =
-                    tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
-                instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args);
-            }
+            // At the call site, any call to this concrete function through a vtable will be
+            // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
+            // original method id, and we've recovered the trait arguments, we can make the callee
+            // instance we're computing the alias set for match the caller instance.
+            //
+            // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
+            // If we ever *do* start encoding the vtable index, we will need to generate an alias set
+            // based on which vtables we are putting this method into, as there will be more than one
+            // index value when supertraits are involved.
+            instance.def = ty::InstanceKind::Virtual(method_id, 0);
+            let abstract_trait_args =
+                tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
+            instance.args = instance.args.rebase_onto(tcx, ancestor, abstract_trait_args);
         } else if tcx.is_closure_like(instance.def_id()) {
             // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
             // instantiate it, and take the type of its only method as our own.
@@ -452,3 +440,36 @@ pub fn transform_instance<'tcx>(
 
     instance
 }
+
+fn implemented_method<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+) -> Option<(ty::EarlyBinder<'tcx, TraitRef<'tcx>>, DefId, DefId)> {
+    let trait_ref;
+    let method_id;
+    let trait_id;
+    let trait_method;
+    let ancestor = if let Some(impl_id) = tcx.impl_of_method(instance.def_id()) {
+        // Implementation in an `impl` block
+        trait_ref = tcx.impl_trait_ref(impl_id)?;
+        let impl_method = tcx.associated_item(instance.def_id());
+        method_id = impl_method.trait_item_def_id?;
+        trait_method = tcx.associated_item(method_id);
+        trait_id = trait_ref.skip_binder().def_id;
+        impl_id
+    } else if let InstanceKind::Item(def_id) = instance.def
+        && let Some(trait_method_bound) = tcx.opt_associated_item(def_id)
+    {
+        // Provided method in a `trait` block
+        trait_method = trait_method_bound;
+        method_id = instance.def_id();
+        trait_id = tcx.trait_of_item(method_id)?;
+        trait_ref = ty::EarlyBinder::bind(TraitRef::from_method(tcx, trait_id, instance.args));
+        trait_id
+    } else {
+        return None;
+    };
+    let vtable_possible =
+        traits::is_vtable_safe_method(tcx, trait_id, trait_method) && tcx.is_object_safe(trait_id);
+    vtable_possible.then_some((trait_ref, method_id, ancestor))
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index b64efadb261..2b30ca8a894 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -177,6 +177,7 @@ symbols! {
         CoerceUnsized,
         Command,
         ConstParamTy,
+        ConstParamTy_,
         Context,
         Continue,
         Copy,
@@ -336,6 +337,7 @@ symbols! {
         TyKind,
         Unknown,
         Unsize,
+        UnsizedConstParamTy,
         Upvars,
         Vec,
         VecDeque,
@@ -1689,6 +1691,7 @@ symbols! {
         rvalue_static_promotion,
         rwpi,
         s,
+        s390x_target_feature,
         safety,
         sanitize,
         sanitizer_cfi_generalize_pointers,
@@ -2001,6 +2004,8 @@ symbols! {
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
+        unsized_const_param_ty,
+        unsized_const_params,
         unsized_fn_params,
         unsized_locals,
         unsized_tuple_coercion,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 607eeac7ccd..0efe68252af 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1840,6 +1840,19 @@ supported_targets! {
 
     ("x86_64-unknown-linux-none", x86_64_unknown_linux_none),
 
+    ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi),
+    ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi),
+    ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi),
+    ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf),
+    ("thumbv8m.base-nuttx-eabi", thumbv8m_base_nuttx_eabi),
+    ("thumbv8m.main-nuttx-eabi", thumbv8m_main_nuttx_eabi),
+    ("thumbv8m.main-nuttx-eabihf", thumbv8m_main_nuttx_eabihf),
+    ("riscv32imc-unknown-nuttx-elf", riscv32imc_unknown_nuttx_elf),
+    ("riscv32imac-unknown-nuttx-elf", riscv32imac_unknown_nuttx_elf),
+    ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
+    ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
+    ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
+
 }
 
 /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
new file mode 100644
index 00000000000..aa51b8957fc
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
@@ -0,0 +1,29 @@
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        arch: "riscv32".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
+            max_atomic_width: Some(32),
+            features: "+m,+a,+c".into(),
+            panic_strategy: PanicStrategy::Unwind,
+            relocation_model: RelocModel::Static,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
new file mode 100644
index 00000000000..fe49951ebfd
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
@@ -0,0 +1,32 @@
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        arch: "riscv32".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
+            max_atomic_width: Some(32),
+            llvm_abiname: "ilp32f".into(),
+            features: "+m,+a,+c,+f".into(),
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: RelocModel::Static,
+            emit_debug_gdb_scripts: false,
+            eh_frame_header: false,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
new file mode 100644
index 00000000000..baee03e6833
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
@@ -0,0 +1,29 @@
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
+        llvm_target: "riscv32".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        arch: "riscv32".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+            linker: Some("rust-lld".into()),
+            cpu: "generic-rv32".into(),
+            max_atomic_width: Some(32),
+            features: "+m,+c".into(),
+            panic_strategy: PanicStrategy::Unwind,
+            relocation_model: RelocModel::Static,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
new file mode 100644
index 00000000000..6a468227ba6
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -0,0 +1,36 @@
+use crate::spec::SanitizerSet;
+use crate::spec::{cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
+use crate::spec::{RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        llvm_target: "riscv64".into(),
+        pointer_width: 64,
+        arch: "riscv64".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+            linker: Some("rust-lld".into()),
+            llvm_abiname: "lp64d".into(),
+            cpu: "generic-rv64".into(),
+            max_atomic_width: Some(64),
+            features: "+m,+a,+f,+d,+c".into(),
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: RelocModel::Static,
+            code_model: Some(CodeModel::Medium),
+            emit_debug_gdb_scripts: false,
+            eh_frame_header: false,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
new file mode 100644
index 00000000000..1e18466c206
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
@@ -0,0 +1,36 @@
+use crate::spec::SanitizerSet;
+use crate::spec::{cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
+use crate::spec::{RelocModel, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        llvm_target: "riscv64".into(),
+        pointer_width: 64,
+        arch: "riscv64".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+            linker: Some("rust-lld".into()),
+            llvm_abiname: "lp64d".into(),
+            cpu: "generic-rv64".into(),
+            max_atomic_width: Some(64),
+            features: "+m,+a,+c".into(),
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: RelocModel::Static,
+            code_model: Some(CodeModel::Medium),
+            emit_debug_gdb_scripts: false,
+            eh_frame_header: false,
+            supported_sanitizers: SanitizerSet::KERNELADDRESS,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
new file mode 100644
index 00000000000..ac37f403860
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
@@ -0,0 +1,33 @@
+// Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv6m-none-eabi".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabi".into(),
+            // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
+            // with +strict-align.
+            // Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
+            // The resulting atomics are ABI incompatible with atomics backed by libatomic.
+            features: "+strict-align,+atomics-32".into(),
+            // There are no atomic CAS instructions available in the instruction set of the ARMv6-M
+            // architecture
+            atomic_cas: false,
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
new file mode 100644
index 00000000000..e21facb78f9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
@@ -0,0 +1,35 @@
+// Targets the Cortex-M4 and Cortex-M7 processors (ARMv7E-M)
+//
+// This target assumes that the device doesn't have a FPU (Floating Point Unit) and lowers all the
+// floating point operations to software routines (intrinsics).
+//
+// As such, this target uses the "soft" calling convention (ABI) where floating point values are
+// passed to/from subroutines via general purpose registers (R0, R1, etc.).
+//
+// To opt-in to hardware accelerated floating point operations, you can use, for example,
+// `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv7em-none-eabi".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabi".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
new file mode 100644
index 00000000000..45092711d2e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
@@ -0,0 +1,43 @@
+// Targets the Cortex-M4F and Cortex-M7F processors (ARMv7E-M)
+//
+// This target assumes that the device does have a FPU (Floating Point Unit) and lowers all (single
+// precision) floating point operations to hardware instructions.
+//
+// Additionally, this target uses the "hard" floating convention (ABI) where floating point values
+// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
+//
+// To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv7em-none-eabihf".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabihf".into(),
+            // vfp4 is the lowest common denominator between the Cortex-M4F (vfp4) and the
+            // Cortex-M7 (vfp5).
+            // Both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
+            // available, and the Cortex-M4 only supports single-precision floating point operations
+            // whereas in the Cortex-M7 double-precision is optional.
+            //
+            // Reference:
+            // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
+            features: "+vfp4d16sp".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
new file mode 100644
index 00000000000..4424b9eaade
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
@@ -0,0 +1,26 @@
+// Targets the Cortex-M3 processor (ARMv7-M)
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv7m-none-eabi".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabi".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
new file mode 100644
index 00000000000..44c6fb0dd1b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
@@ -0,0 +1,29 @@
+// Targets the Cortex-M23 processor (Baseline ARMv8-M)
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv8m.base-none-eabi".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabi".into(),
+            // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
+            // with +strict-align.
+            features: "+strict-align".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
new file mode 100644
index 00000000000..2f0df7ae857
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
@@ -0,0 +1,27 @@
+// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
+// without the Floating Point extension.
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv8m.main-none-eabi".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabi".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
new file mode 100644
index 00000000000..ee31f17bc45
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
@@ -0,0 +1,32 @@
+// Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
+// with the Floating Point extension.
+
+use crate::spec::{base, cvs, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "thumbv8m.main-none-eabihf".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+        arch: "arm".into(),
+
+        options: TargetOptions {
+            families: cvs!["unix"],
+            os: "nuttx".into(),
+            abi: "eabihf".into(),
+            // If the Floating Point extension is implemented in the Cortex-M33
+            // processor, the Cortex-M33 Technical Reference Manual states that
+            // the FPU uses the FPv5 architecture, single-precision instructions
+            // and 16 D registers.
+            features: "+fp-armv8d16sp".into(),
+            max_atomic_width: Some(32),
+            ..base::thumb::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 6667efb14e2..4fb0323b6cf 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -4,6 +4,9 @@ use rustc_span::symbol::Symbol;
 /// Features that control behaviour of rustc, rather than the codegen.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
 
+/// Features that require special handling when passing to LLVM.
+pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
+
 /// Stability information for target features.
 #[derive(Debug, Clone, Copy)]
 pub enum Stability {
@@ -397,6 +400,13 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
     // tidy-alphabetical-end
 ];
 
+const IBMZ_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+    // tidy-alphabetical-start
+    ("backchain", Unstable(sym::s390x_target_feature)),
+    ("vector", Unstable(sym::s390x_target_feature)),
+    // tidy-alphabetical-end
+];
+
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primitives may be documented.
 ///
@@ -414,6 +424,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
         .chain(BPF_ALLOWED_FEATURES.iter())
         .chain(CSKY_ALLOWED_FEATURES)
         .chain(LOONGARCH_ALLOWED_FEATURES)
+        .chain(IBMZ_ALLOWED_FEATURES)
         .cloned()
 }
 
@@ -431,6 +442,7 @@ impl super::spec::Target {
             "bpf" => BPF_ALLOWED_FEATURES,
             "csky" => CSKY_ALLOWED_FEATURES,
             "loongarch64" => LOONGARCH_ALLOWED_FEATURES,
+            "s390x" => IBMZ_ALLOWED_FEATURES,
             _ => &[],
         }
     }
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index f96bd985237..137850f31d3 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -1,3 +1,65 @@
+trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
+    [true] , for some specific lifetime `'{$lifetime}`
+    *[false] {""}
+}
+
+trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`
+
+trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
+trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
+trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
+trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...
+trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
+    [true] ...
+    *[false] {""}
+}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
 trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len ->
         [one] argument
         *[other] arguments
@@ -8,8 +70,48 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
         *[other] arguments
     }
 
+trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds
+
 trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment
 
+trait_selection_await_both_futures = consider `await`ing on both `Future`s
+trait_selection_await_future = consider `await`ing on the `Future`
+trait_selection_await_note = calling an async function returns a future
+
+trait_selection_but_calling_introduces = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$lifetime_kind ->
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
+} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
+    .label1 = {$has_lifetime ->
+        [true] lifetime `{$lifetime}`
+        *[false] an anonymous lifetime `'_`
+    }
+    .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
+        [true] `impl` of `{$impl_path}`
+        *[false] inherent `impl`
+    }
+
+trait_selection_but_needs_to_satisfy = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$has_lifetime ->
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
+} but it needs to satisfy a `'static` lifetime requirement
+    .influencer = this data with {$has_lifetime ->
+        [true] lifetime `{$lifetime}`
+        *[false] an anonymous lifetime `'_`
+    }...
+    .require = {$spans_empty ->
+        *[true] ...is used and required to live as long as `'static` here
+        [false] ...and is required to live as long as `'static` here
+    }
+    .used_here = ...is used here...
+    .introduced_by_bound = `'static` lifetime requirement introduced by this bound
+
 trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here
 
 trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment
@@ -19,18 +121,67 @@ trait_selection_closure_kind_mismatch = expected a closure that implements the `
 
 trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here
 
+trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
+trait_selection_consider_specifying_length = consider specifying the actual array length
+trait_selection_data_flows = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] {""}
+} flows{$label_var2_exists ->
+    [true] {" "}into `{$label_var2}`
+    *[false] {""}
+} here
+
+trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here
+trait_selection_data_returned = ...but data{$label_var1_exists ->
+    [true] {" "}from `{$label_var1}`
+    *[false] {""}
+} is returned here
+
+trait_selection_declared_different = this parameter and the return type are declared with different lifetimes...
+trait_selection_declared_multiple = this type is declared with multiple lifetimes...
 trait_selection_disallowed_positional_argument = positional format arguments are not allowed here
     .help = only named format arguments with the name of one of the generic types are allowed in this context
 
+trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
+trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement
+trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
+trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement
+
 trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
 
 trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
     .label = empty on-clause here
 
+trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
+
+trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
+
+trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
+    .label = lifetime `{$named}` required
+
+trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
+    .label = lifetime `{$named}` required
+
+trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+
+trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same
+trait_selection_fps_cast = consider casting to a fn pointer
+trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+
+trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers
+trait_selection_fps_remove_ref = consider removing the reference
+trait_selection_fps_use_ref = consider using a reference
+trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+
+trait_selection_full_type_written = the full type name has been written to '{$path}'
+
 trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}`
     .other_label = `{$option_name}` is first declared here
     .label = `{$option_name}` is already declared here
 
+trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
+trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
 trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}`
 
 trait_selection_invalid_format_specifier = invalid format specifier
@@ -39,13 +190,52 @@ trait_selection_invalid_format_specifier = invalid format specifier
 trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
     .label = invalid on-clause here
 
+trait_selection_label_bad = {$bad_kind ->
+    *[other] cannot infer type
+    [more_info] cannot infer {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] the value of const parameter
+        [const] the value of the constant
+    } `{$name}`{$has_parent ->
+        [true] {" "}declared on the {$parent_prefix} `{$parent_name}`
+        *[false] {""}
+    }
+}
+
+trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied
+trait_selection_lifetime_mismatch = lifetime mismatch
+
+trait_selection_lifetime_param_suggestion = consider {$is_reuse ->
+    [true] reusing
+    *[false] introducing
+} a named lifetime parameter{$is_impl ->
+    [true] {" "}and update trait if needed
+    *[false] {""}
+}
+trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime
+
 trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute
     .help = only `message`, `note` and `label` are allowed as options
     .label = invalid option found here
 
+trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
+trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes
+trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes
+trait_selection_mismatched_static_lifetime = incompatible lifetime on type
 trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute
     .help = at least one of the `message`, `note` and `label` options are expected
 
+trait_selection_more_targeted = {$has_param_name ->
+    [true] `{$param_name}`
+    *[false] `fn` parameter
+} has {$has_lifetime ->
+    [true] lifetime `{$lifetime}`
+    *[false] an anonymous lifetime `'_`
+} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
+
+trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement
+trait_selection_msl_unmet_req = because this has an unmet lifetime requirement
+
 trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
         [none] {""}
        *[default] {" "}for type `{$self_desc}`
@@ -59,13 +249,214 @@ trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a
     .label = expected value here
     .note = eg `#[rustc_on_unimplemented(message="foo")]`
 
+trait_selection_nothing = {""}
+
+trait_selection_oc_cant_coerce = cannot coerce intrinsics to function pointers
+trait_selection_oc_closure_selfref = closure/coroutine type that references itself
+trait_selection_oc_const_compat = const not compatible with trait
+trait_selection_oc_fn_lang_correct_type = {$lang_item_name ->
+        [panic_impl] `#[panic_handler]`
+        *[lang_item_name] lang item `{$lang_item_name}`
+    } function has wrong type
+trait_selection_oc_fn_main_correct_type = `main` function has wrong type
+trait_selection_oc_fn_start_correct_type = `#[start]` function has wrong type
+trait_selection_oc_generic = mismatched types
+
+trait_selection_oc_if_else_different = `if` and `else` have incompatible types
+trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type
+trait_selection_oc_match_compat = `match` arms have incompatible types
+trait_selection_oc_method_compat = method not compatible with trait
+trait_selection_oc_method_correct_type = mismatched `self` parameter type
+trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge
+trait_selection_oc_no_else = `if` may be missing an `else` clause
+trait_selection_oc_try_compat = `?` operator has incompatible types
+trait_selection_oc_type_compat = type not compatible with trait
+trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
+    .label = opaque type defined here
+
+trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
+trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content...
+
+trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it
+trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}`
+
+trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
+
+trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
+trait_selection_prlf_defined_without_sub = the lifetime defined here...
+trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
+trait_selection_reborrow = ...so that reference does not outlive borrowed content
+trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
+
+trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
+trait_selection_region_explanation = {$pref_kind ->
+    *[should_not_happen] [{$pref_kind}]
+    [ref_valid_for] ...the reference is valid for
+    [content_valid_for] ...but the borrowed content is only valid for
+    [type_obj_valid_for] object type is valid for
+    [source_pointer_valid_for] source pointer is only valid for
+    [type_satisfy] type must satisfy
+    [type_outlive] type must outlive
+    [lf_param_instantiated_with] lifetime parameter instantiated with
+    [lf_param_must_outlive] but lifetime parameter must outlive
+    [lf_instantiated_with] lifetime instantiated with
+    [lf_must_outlive] but lifetime must outlive
+    [pointer_valid_for] the pointer is valid for
+    [data_valid_for] but the referenced data is only valid for
+    [empty] {""}
+}{$pref_kind ->
+    [empty] {""}
+    *[other] {" "}
+}{$desc_kind ->
+    *[should_not_happen] [{$desc_kind}]
+    [restatic] the static lifetime
+    [revar] lifetime {$desc_arg}
+    [as_defined] the lifetime `{$desc_arg}` as defined here
+    [as_defined_anon] the anonymous lifetime as defined here
+    [defined_here] the anonymous lifetime defined here
+    [defined_here_reg] the lifetime `{$desc_arg}` as defined here
+}{$suff_kind ->
+    *[should_not_happen] [{$suff_kind}]
+    [empty]{""}
+    [continues] ...
+    [req_by_binding] {" "}as required by this binding
+}
+
+trait_selection_relate_object_bound = ...so that it can be closed over into an object
+trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
+    [true] ...
+    *[false] {""}
+}
+trait_selection_relate_param_bound_2 = ...that is required by this bound
+trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
+trait_selection_ril_because_of = because of this returned expression
+trait_selection_ril_introduced_by = requirement introduced by this return type
+trait_selection_ril_introduced_here = `'static` requirement introduced here
+trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
+
+trait_selection_source_kind_closure_return =
+    try giving this closure an explicit return type
+
+# coroutine_kind  may need to be translated
+trait_selection_source_kind_fully_qualified =
+    try using a fully qualified path to specify the expected types
+
+trait_selection_source_kind_subdiag_generic_label =
+    cannot infer {$is_type ->
+    [true] type
+    *[false] the value
+    } of the {$is_type ->
+    [true] type
+    *[false] const
+    } {$parent_exists ->
+    [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
+    *[false] parameter {$param_name}
+    }
+
+trait_selection_source_kind_subdiag_generic_suggestion =
+    consider specifying the generic {$arg_count ->
+    [one] argument
+    *[other] arguments
+    }
+
+trait_selection_source_kind_subdiag_let = {$kind ->
+    [with_pattern] consider giving `{$name}` an explicit type
+    [closure] consider giving this closure parameter an explicit type
+    *[other] consider giving this pattern a type
+}{$x_kind ->
+    [has_name] , where the {$prefix_kind ->
+        *[type] type for {$prefix}
+        [const_with_param] value of const parameter
+        [const] value of the constant
+    } `{$arg_name}` is specified
+    [underscore] , where the placeholders `_` are specified
+    *[empty] {""}
+}
+
+trait_selection_srs_add = consider returning the local binding `{$ident}`
+trait_selection_srs_add_one = consider returning one of these bindings
+
+trait_selection_srs_remove = consider removing this semicolon
+trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions
+trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
+
+trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}`
+trait_selection_subtype = ...so that the {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [fn_lang_correct_type] lang item function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
+trait_selection_subtype_2 = ...so that {$requirement ->
+    [method_compat] method type is compatible with trait
+    [type_compat] associated type is compatible with trait
+    [const_compat] const is compatible with trait
+    [expr_assignable] expression is assignable
+    [if_else_different] `if` and `else` have incompatible types
+    [no_else] `if` missing an `else` returns `()`
+    [fn_main_correct_type] `main` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
+    [fn_lang_correct_type] lang item function has the correct type
+    [intrinsic_correct_type] intrinsic has the correct type
+    [method_correct_type] method receiver has the correct type
+    *[other] types are compatible
+}
+
+trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+
+trait_selection_suggest_add_let_for_letchains = consider adding `let`
+
+trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait
+trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+
+trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one
 
+trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
+    .found = found `{$found}`
+    .expected = expected `{$expected}`
+    .expected_found = expected signature `{$expected}`
+               {"   "}found signature `{$found}`
+
+trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
+    .label_satisfy = doesn't satisfy where-clause
+    .label_where = due to a where-clause on `{$def_id}`...
+    .label_dup = implementation of `{$trait_def_id}` is not general enough
+
+trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
+
+trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element
+
 trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
+trait_selection_type_annotations_needed = {$source_kind ->
+    [closure] type annotations needed for the closure `{$source_name}`
+    [normal] type annotations needed for `{$source_name}`
+    *[other] type annotations needed
+}
+    .label = type must be known at this point
+
+trait_selection_types_declared_different = these two types are declared with different lifetimes...
+
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
 
 trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}`
     .help = expect either a generic argument name or {"`{Self}`"} as format argument
 
+trait_selection_warn_removing_apit_params = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable
+
+trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait
+
+trait_selection_where_remove = remove the `where` clause
 trait_selection_wrapped_parser_error = {$description}
     .label = {$label}
diff --git a/compiler/rustc_infer/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 9998fbca056..daabdec8f9e 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -46,14 +46,12 @@
 //! time of error detection.
 
 use std::borrow::Cow;
-use std::ops::{ControlFlow, Deref};
+use std::ops::ControlFlow;
 use std::path::PathBuf;
 use std::{cmp, fmt, iter};
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_errors::{
-    pluralize, Applicability, Diag, DiagCtxtHandle, DiagStyledString, IntoDiagArg, StringPart,
-};
+use rustc_errors::{pluralize, Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
@@ -72,23 +70,23 @@ use rustc_middle::ty::{
 use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
 use crate::infer;
 use crate::infer::relate::{self, RelateResult, TypeRelation};
 use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
-    PredicateObligation,
 };
 
 mod note_and_explain;
 mod suggest;
 
+pub mod need_type_info;
+pub mod nice_region_error;
 pub mod region;
 pub mod sub_relations;
 
-pub mod nice_region_error;
-
 /// Makes a valid string literal from a string by escaping special characters (" and \),
 /// unless they are already escaped.
 fn escape_literal(s: &str) -> String {
@@ -111,48 +109,59 @@ fn escape_literal(s: &str) -> String {
     escaped
 }
 
-/// A helper for building type related errors. The `typeck_results`
-/// field is only populated during an in-progress typeck.
-/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
-///
-/// You must only create this if you intend to actually emit an error (or
-/// perhaps a warning, though preferably not.) It provides a lot of utility
-/// methods which should not be used during the happy path.
-pub struct TypeErrCtxt<'a, 'tcx> {
-    pub infcx: &'a InferCtxt<'tcx>,
-    pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
-
-    pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
-    pub fallback_has_occurred: bool,
+impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
+    // [Note-Type-error-reporting]
+    // An invariant is that anytime the expected or actual type is Error (the special
+    // error type, meaning that an error occurred when typechecking this expression),
+    // this is a derived error. The error cascaded from another error (that was already
+    // reported), so it's not useful to display it to the user.
+    // The following methods implement this logic.
+    // They check if either the actual or expected type is Error, and don't print the error
+    // in this case. The typechecker should only ever report type errors involving mismatched
+    // types using one of these methods, and should not call span_err directly for such
+    // errors.
+    pub fn type_error_struct_with_diag<M>(
+        &self,
+        sp: Span,
+        mk_diag: M,
+        actual_ty: Ty<'tcx>,
+    ) -> Diag<'a>
+    where
+        M: FnOnce(String) -> Diag<'a>,
+    {
+        let actual_ty = self.resolve_vars_if_possible(actual_ty);
+        debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
 
-    pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
+        let mut err = mk_diag(self.ty_to_string(actual_ty));
 
-    pub autoderef_steps:
-        Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
-}
+        // Don't report an error if actual type is `Error`.
+        if actual_ty.references_error() {
+            err.downgrade_to_delayed_bug();
+        }
 
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
-        self.infcx.dcx()
+        err
     }
 
-    /// This is just to avoid a potential footgun of accidentally
-    /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
-    #[deprecated(note = "you already have a `TypeErrCtxt`")]
-    #[allow(unused)]
-    pub fn err_ctxt(&self) -> ! {
-        bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
+    pub fn report_mismatched_types(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        expected: Ty<'tcx>,
+        actual: Ty<'tcx>,
+        err: TypeError<'tcx>,
+    ) -> Diag<'a> {
+        self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
     }
-}
 
-impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
-    type Target = InferCtxt<'tcx>;
-    fn deref(&self) -> &InferCtxt<'tcx> {
-        self.infcx
+    pub fn report_mismatched_consts(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        expected: ty::Const<'tcx>,
+        actual: ty::Const<'tcx>,
+        err: TypeError<'tcx>,
+    ) -> Diag<'a> {
+        self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
     }
-}
 
-impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, args) = match *ty.kind() {
             ty::Alias(_, ty::AliasTy { def_id, args, .. })
@@ -189,9 +198,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     .flatten()
             })
     }
-}
 
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// Adds a note if the types come from similarly named crates
     fn check_and_note_conflicting_crates(&self, err: &mut Diag<'_>, terr: TypeError<'tcx>) {
         use hir::def_id::CrateNum;
@@ -2190,32 +2197,3 @@ impl TyCategory {
         }
     }
 }
-
-impl<'tcx> InferCtxt<'tcx> {
-    /// Given a [`hir::Block`], get the span of its last expression or
-    /// statement, peeling off any inner blocks.
-    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
-        let block = block.innermost_block();
-        if let Some(expr) = &block.expr {
-            expr.span
-        } else if let Some(stmt) = block.stmts.last() {
-            // possibly incorrect trailing `;` in the else arm
-            stmt.span
-        } else {
-            // empty block; point at its entirety
-            block.span
-        }
-    }
-
-    /// Given a [`hir::HirId`] for a block, get the span of its last expression
-    /// or statement, peeling off any inner blocks.
-    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
-        match self.tcx.hir_node(hir_id) {
-            hir::Node::Block(blk) => self.find_block_span(blk),
-            // The parser was in a weird state if either of these happen, but
-            // it's better not to panic.
-            hir::Node::Expr(e) => e.span,
-            _ => rustc_span::DUMMY_SP,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 4f3dcd9043f..56ea70bcf1d 100644
--- a/compiler/rustc_infer/src/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1,4 +1,4 @@
-use crate::error_reporting::infer::TypeErrCtxt;
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{
     AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
     SourceKindMultiSuggestion, SourceKindSubdiag,
@@ -13,7 +13,6 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::infer::unify_key::ConstVariableValue;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{
@@ -183,9 +182,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
             warn!("resolved ty var in error message");
         }
 
-        let mut infcx_inner = infcx.inner.borrow_mut();
-        let ty_vars = infcx_inner.type_variables();
-        let var_origin = ty_vars.var_origin(ty_vid);
+        let var_origin = infcx.type_var_origin(ty_vid);
         if let Some(def_id) = var_origin.param_def_id
             // The `Self` param of a trait has the def-id of the trait,
             // since it's a synthetic parameter.
@@ -206,24 +203,8 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
         }
     };
     printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
-    let const_getter = move |ct_vid| match infcx
-        .inner
-        .borrow_mut()
-        .const_unification_table()
-        .probe_value(ct_vid)
-    {
-        ConstVariableValue::Known { value: _ } => {
-            warn!("resolved const var in error message");
-            None
-        }
-        ConstVariableValue::Unknown { origin, universe: _ } => {
-            if let Some(def_id) = origin.param_def_id {
-                Some(infcx.tcx.item_name(def_id))
-            } else {
-                None
-            }
-        }
-    };
+    let const_getter =
+        move |ct_vid| Some(infcx.tcx.item_name(infcx.const_var_origin(ct_vid)?.param_def_id?));
     printer.const_infer_name_resolver = Some(Box::new(const_getter));
     printer
 }
@@ -289,7 +270,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
     format!("fn({args}){ret}")
 }
 
-impl<'tcx> InferCtxt<'tcx> {
+impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// Extracts data used by diagnostic for either types or constants
     /// which were stuck during inference.
     pub fn extract_inference_diagnostics_data(
@@ -300,9 +281,7 @@ impl<'tcx> InferCtxt<'tcx> {
         match arg.unpack() {
             GenericArgKind::Type(ty) => {
                 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
-                    let mut inner = self.inner.borrow_mut();
-                    let ty_vars = &inner.type_variables();
-                    let var_origin = ty_vars.var_origin(ty_vid);
+                    let var_origin = self.infcx.type_var_origin(ty_vid);
                     if let Some(def_id) = var_origin.param_def_id
                         // The `Self` param of a trait has the def-id of the trait,
                         // since it's a synthetic parameter.
@@ -332,13 +311,7 @@ impl<'tcx> InferCtxt<'tcx> {
             }
             GenericArgKind::Const(ct) => {
                 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
-                    let origin =
-                        match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
-                            ConstVariableValue::Known { value } => {
-                                bug!("resolved infer var: {vid:?} {value}")
-                            }
-                            ConstVariableValue::Unknown { origin, universe: _ } => origin,
-                        };
+                    let origin = self.const_var_origin(vid).expect("expected unresolved const var");
                     if let Some(def_id) = origin.param_def_id {
                         return InferenceDiagnosticsData {
                             name: self.tcx.item_name(def_id).to_string(),
@@ -391,7 +364,7 @@ impl<'tcx> InferCtxt<'tcx> {
         span: Span,
         arg_data: InferenceDiagnosticsData,
         error_code: TypeAnnotationNeeded,
-    ) -> Diag<'_> {
+    ) -> Diag<'a> {
         let source_kind = "other";
         let source_name = "";
         let failure_span = None;
@@ -434,9 +407,7 @@ impl<'tcx> InferCtxt<'tcx> {
             }),
         }
     }
-}
 
-impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
@@ -453,7 +424,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             // If we don't have any typeck results we're outside
             // of a body, so we won't be able to get better info
             // here.
-            return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
+            return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
         let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
@@ -465,7 +436,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
 
         let Some(InferSource { span, kind }) = local_visitor.infer_source else {
-            return self.infcx.bad_inference_failure_err(failure_span, arg_data, error_code);
+            return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
         let (source_kind, name, path) = kind.ty_localized_msg(self);
@@ -887,7 +858,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 use ty::InferConst::*;
                 match (inner_ct.kind(), target_ct.kind()) {
                     (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => {
-                        self.tecx.inner.borrow_mut().const_unification_table().unioned(a_vid, b_vid)
+                        self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid)
                     }
                     _ => false,
                 }
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
index 74dcde03639..74dcde03639 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index b91b755d683..b91b755d683 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
index 550cc455e01..550cc455e01 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs
index ced4c384f02..b83ecd8320c 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs
@@ -1,4 +1,4 @@
-use crate::error_reporting::infer::TypeErrCtxt;
+use crate::error_reporting::TypeErrCtxt;
 use crate::infer::RegionResolutionError;
 use crate::infer::RegionResolutionError::*;
 use rustc_errors::{Diag, ErrorGuaranteed};
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
index d1802d2f5ee..d1802d2f5ee 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs
index 476ac3f1720..476ac3f1720 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
index e9f17a3e3e2..e9f17a3e3e2 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index ce157ff3dc8..ce157ff3dc8 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
index c58c7e13551..c58c7e13551 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index 30fa98c5526..30fa98c5526 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
index aeb3049c2ae..aeb3049c2ae 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/note.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index d5e7de897d0..f9110cfb3b9 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -1,4 +1,3 @@
-use super::TypeErrCtxt;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diag, MultiSpan};
 use rustc_hir as hir;
@@ -12,6 +11,9 @@ use rustc_middle::{
 };
 use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
 
+use crate::error_reporting::TypeErrCtxt;
+use crate::infer::InferCtxtExt;
+
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     pub fn note_and_explain_type_err(
         &self,
@@ -820,7 +822,7 @@ fn foo(&self) -> Self::T { String::new() }
                                 tcx.defaultness(item.id.owner_id)
                             {
                                 let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
-                                if self.infcx.can_eq_shallow(param_env, assoc_ty, found) {
+                                if self.infcx.can_eq(param_env, assoc_ty, found) {
                                     diag.span_label(
                                         item.span,
                                         "associated type defaults can't be assumed inside the \
@@ -843,7 +845,7 @@ fn foo(&self) -> Self::T { String::new() }
                         let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
                         if let hir::Defaultness::Default { has_value: true } =
                             tcx.defaultness(item.id.owner_id)
-                            && self.infcx.can_eq_shallow(param_env, assoc_ty, found)
+                            && self.infcx.can_eq(param_env, assoc_ty, found)
                         {
                             diag.span_label(
                                 item.span,
diff --git a/compiler/rustc_infer/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 5d41bb5d271..3cee8ff5f4c 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -18,7 +18,8 @@ use rustc_type_ir::Upcast as _;
 
 use super::nice_region_error::find_anon_type;
 use super::{nice_region_error, ObligationCauseAsDiagArg};
-use crate::error_reporting::infer::{ObligationCauseExt as _, TypeErrCtxt};
+use crate::error_reporting::infer::ObligationCauseExt as _;
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{
     self, note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound,
     OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
@@ -224,16 +225,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
             .add_to_diag(err),
             infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
+                RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow }
+                    .add_to_diag(err)
             }
             infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
+                RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound }
                     .add_to_diag(err);
             }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer_reference_outlives_referent,
+                    msg: fluent::trait_selection_reference_outlives_referent,
                     name: &self.ty_to_string(ty),
                     continues: false,
                 }
@@ -242,23 +244,32 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             infer::RelateParamBound(span, ty, opt_span) => {
                 RegionOriginNote::WithName {
                     span,
-                    msg: fluent::infer_relate_param_bound,
+                    msg: fluent::trait_selection_relate_param_bound,
                     name: &self.ty_to_string(ty),
                     continues: opt_span.is_some(),
                 }
                 .add_to_diag(err);
                 if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diag(err);
+                    RegionOriginNote::Plain {
+                        span,
+                        msg: fluent::trait_selection_relate_param_bound_2,
+                    }
+                    .add_to_diag(err);
                 }
             }
             infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diag(err);
+                RegionOriginNote::Plain {
+                    span,
+                    msg: fluent::trait_selection_relate_region_param_bound,
+                }
+                .add_to_diag(err);
             }
             infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diag(err);
+                RegionOriginNote::Plain {
+                    span,
+                    msg: fluent::trait_selection_compare_impl_item_obligation,
+                }
+                .add_to_diag(err);
             }
             infer::CheckAssociatedTypeBounds { ref parent, .. } => {
                 self.note_region_origin(err, parent);
@@ -266,7 +277,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             infer::AscribeUserTypeProvePredicate(span) => {
                 RegionOriginNote::Plain {
                     span,
-                    msg: fluent::infer_ascribe_user_type_prove_predicate,
+                    msg: fluent::trait_selection_ascribe_user_type_prove_predicate,
                 }
                 .add_to_diag(err);
             }
@@ -445,7 +456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 })
             }
             infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
-                let mut err = self.infcx.report_extra_impl_obligation(
+                let mut err = self.report_extra_impl_obligation(
                     span,
                     impl_item_def_id,
                     trait_item_def_id,
@@ -645,7 +656,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             trait_item_def_id,
         }) = origin
         {
-            return self.infcx.report_extra_impl_obligation(
+            return self.report_extra_impl_obligation(
                 span,
                 impl_item_def_id,
                 trait_item_def_id,
diff --git a/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs
index ef26a8ff7b8..ef26a8ff7b8 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/sub_relations.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/sub_relations.rs
diff --git a/compiler/rustc_infer/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index 4d11ab9fac6..1ef32d110b3 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -17,14 +17,13 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
 use rustc_span::{sym, Span};
 
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{
     ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
     FunctionPointerSuggestion, SuggestAccessingField, SuggestRemoveSemiOrReturnBinding,
     SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
 };
 
-use super::TypeErrCtxt;
-
 #[derive(Clone, Copy)]
 pub enum SuggestAsRefKind {
     Option,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs
index f6ac8fc7b61..cb7efeaae0b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs
@@ -1 +1,73 @@
+use std::ops::Deref;
+
+use rustc_errors::DiagCtxtHandle;
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::PredicateObligation;
+use rustc_macros::extension;
+use rustc_middle::bug;
+use rustc_middle::ty::{self, Ty};
+
+use crate::error_reporting::infer::sub_relations;
+
+pub mod infer;
 pub mod traits;
+
+/// A helper for building type related errors. The `typeck_results`
+/// field is only populated during an in-progress typeck.
+/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
+///
+/// You must only create this if you intend to actually emit an error (or
+/// perhaps a warning, though preferably not.) It provides a lot of utility
+/// methods which should not be used during the happy path.
+pub struct TypeErrCtxt<'a, 'tcx> {
+    pub infcx: &'a InferCtxt<'tcx>,
+    pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
+
+    pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
+    pub fallback_has_occurred: bool,
+
+    pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
+
+    pub autoderef_steps:
+        Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
+}
+
+#[extension(pub trait InferCtxtErrorExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
+    /// Creates a `TypeErrCtxt` for emitting various inference errors.
+    /// During typeck, use `FnCtxt::err_ctxt` instead.
+    fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
+        TypeErrCtxt {
+            infcx: self,
+            sub_relations: Default::default(),
+            typeck_results: None,
+            fallback_has_occurred: false,
+            normalize_fn_sig: Box::new(|fn_sig| fn_sig),
+            autoderef_steps: Box::new(|ty| {
+                debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck");
+                vec![(ty, vec![])]
+            }),
+        }
+    }
+}
+
+impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
+    pub fn dcx(&self) -> DiagCtxtHandle<'a> {
+        self.infcx.dcx()
+    }
+
+    /// This is just to avoid a potential footgun of accidentally
+    /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
+    #[deprecated(note = "you already have a `TypeErrCtxt`")]
+    #[allow(unused)]
+    pub fn err_ctxt(&self) -> ! {
+        bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
+    }
+}
+
+impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
+    type Target = InferCtxt<'tcx>;
+    fn deref(&self) -> &InferCtxt<'tcx> {
+        self.infcx
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index deab0451ccb..72a4d4c1205 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -8,21 +8,17 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor as _;
 use rustc_hir::LangItem;
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
-use rustc_infer::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
 use rustc_infer::traits::util::elaborate;
 use rustc_infer::traits::{
     Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation,
 };
-use rustc_macros::extension;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _};
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 
-use crate::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
-use crate::error_reporting::traits::{
-    to_pretty_impl_header, FindExprBySpan, InferCtxtPrivExt as _,
-};
+use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
+use crate::error_reporting::traits::{to_pretty_impl_header, FindExprBySpan};
+use crate::error_reporting::TypeErrCtxt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::ObligationCtxt;
 
@@ -153,10 +149,12 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
     ambiguities
 }
 
-#[extension(pub trait TypeErrCtxtAmbiguityExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed {
+    pub(super) fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> ErrorGuaranteed {
         // Unable to successfully determine, probably means
         // insufficient type information, but could mean
         // ambiguous impls. The latter *ought* to be a
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 0d040ddbacb..a7ea308a818 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1,6 +1,8 @@
-use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
-use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _};
-use crate::error_reporting::traits::infer_ctxt_ext::InferCtxtExt;
+use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
+use super::suggestions::get_explanation_based_on_obligation;
+use crate::error_reporting::infer::TyCategory;
+use crate::error_reporting::traits::report_object_safety_error;
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{
     AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
 };
@@ -24,10 +26,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
 use rustc_hir::{self as hir, LangItem};
-use rustc_infer::error_reporting::infer::TyCategory;
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
-use rustc_macros::extension;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::traits::SignatureMismatchData;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -49,14 +48,11 @@ use super::{
     ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate, UnsatisfiedConst,
 };
 
-pub use rustc_infer::traits::error_reporting::*;
-
-#[extension(pub trait TypeErrCtxtSelectionErrExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// The `root_obligation` parameter should be the `root_obligation` field
     /// from a `FulfillmentError`. If no `FulfillmentError` is available,
     /// then it should be the same as `obligation`.
-    fn report_selection_error(
+    pub fn report_selection_error(
         &self,
         mut obligation: PredicateObligation<'tcx>,
         root_obligation: &PredicateObligation<'tcx>,
@@ -682,9 +678,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     }
 }
 
-#[extension(pub(super) trait TypeErrCtxtExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool {
+    pub(super) 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 {
@@ -1142,7 +1140,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     }
 }
 
-#[extension(pub(super) trait InferCtxtPrivExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     fn can_match_trait(
         &self,
@@ -1182,7 +1179,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     // returns if `cond` not occurring implies that `error` does not occur - i.e., that
     // `error` occurring implies that `cond` occurs.
     #[instrument(level = "debug", skip(self), ret)]
-    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
+    pub(super) fn error_implies(
+        &self,
+        cond: ty::Predicate<'tcx>,
+        error: ty::Predicate<'tcx>,
+    ) -> bool {
         if cond == error {
             return true;
         }
@@ -1205,7 +1206,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip_all)]
-    fn report_projection_error(
+    pub(super) fn report_projection_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         error: &MismatchedProjectionTypes<'tcx>,
@@ -1455,7 +1456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn fuzzy_match_tys(
+    pub fn fuzzy_match_tys(
         &self,
         mut a: Ty<'tcx>,
         mut b: Ty<'tcx>,
@@ -1535,7 +1536,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {
+    pub(super) fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str {
         match kind {
             hir::ClosureKind::Closure => "a closure",
             hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => "a coroutine",
@@ -1585,7 +1586,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn find_similar_impl_candidates(
+    pub(super) fn find_similar_impl_candidates(
         &self,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Vec<ImplCandidate<'tcx>> {
@@ -1615,7 +1616,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         candidates
     }
 
-    fn report_similar_impl_candidates(
+    pub(super) fn report_similar_impl_candidates(
         &self,
         impl_candidates: &[ImplCandidate<'tcx>],
         trait_ref: ty::PolyTraitRef<'tcx>,
@@ -1989,7 +1990,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// `trait_ref`.
     ///
     /// For this to work, `new_self_ty` must have no escaping bound variables.
-    fn mk_trait_obligation_with_new_self_ty(
+    pub(super) fn mk_trait_obligation_with_new_self_ty(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
@@ -2041,7 +2042,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         })
     }
 
-    fn note_obligation_cause(&self, err: &mut Diag<'_>, obligation: &PredicateObligation<'tcx>) {
+    pub fn note_obligation_cause(
+        &self,
+        err: &mut Diag<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
         // First, attempt to add note to this error with an async-await-specific
         // message, and fall back to regular note otherwise.
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
@@ -2067,7 +2072,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn is_recursive_obligation(
+    pub(super) fn is_recursive_obligation(
         &self,
         obligated_types: &mut Vec<Ty<'tcx>>,
         cause_code: &ObligationCauseCode<'tcx>,
@@ -2596,7 +2601,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     })
                     .unwrap_or((found_span, None, found));
 
-                self.infcx.report_arg_count_mismatch(
+                self.report_arg_count_mismatch(
                     span,
                     closure_span,
                     expected,
@@ -2608,6 +2613,238 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         )
     }
 
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    pub fn get_fn_like_arguments(
+        &self,
+        node: Node<'_>,
+    ) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
+        let sm = self.tcx.sess.source_map();
+        let hir = self.tcx.hir();
+        Some(match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
+                ..
+            }) => (
+                fn_decl_span,
+                fn_arg_span,
+                hir.body(body)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = *arg.pat
+                        {
+                            Some(ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        sm.span_to_snippet(pat.span)
+                                            .ok()
+                                            .map(|snippet| (snippet, "_".to_owned()))
+                                    })
+                                    .collect::<Option<Vec<_>>>()?,
+                            ))
+                        } else {
+                            let name = sm.span_to_snippet(arg.pat.span).ok()?;
+                            Some(ArgKind::Arg(name, "_".to_owned()))
+                        }
+                    })
+                    .collect::<Option<Vec<ArgKind>>>()?,
+            ),
+            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
+            | Node::TraitItem(&hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(ref sig, _), ..
+            }) => (
+                sig.span,
+                None,
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.kind {
+                        hir::TyKind::Tup(tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(variant_data) => {
+                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
+                (span, None, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {node:?}"),
+        })
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    pub fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+        closure_arg_span: Option<Span>,
+    ) -> Diag<'a> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = matches!(other, &[ArgKind::Tuple(..)]);
+            match (arg_length, arguments.get(0)) {
+                (1, Some(ArgKind::Tuple(_, fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_code_err!(
+            self.dcx(),
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {kind} that takes {expected_str}"));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {found_str}"));
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion_verbose(
+                    closure_arg_span.unwrap_or(found_span),
+                    format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        pluralize!(expected_args.len())
+                    ),
+                    format!("|{underscores}|"),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion_verbose(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{sugg}|"),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
+                && fields.len() == found_args.len()
+                && is_closure
+            {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args
+                        .iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(
+                            ": ({})",
+                            fields
+                                .iter()
+                                .map(|(_, ty)| ty.to_owned())
+                                .collect::<Vec<String>>()
+                                .join(", ")
+                        )
+                    } else {
+                        String::new()
+                    },
+                );
+                err.span_suggestion_verbose(
+                    found_span,
+                    "change the closure to accept a tuple instead of individual arguments",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+
+        err
+    }
+
+    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
+    /// in that order, and returns the generic type corresponding to the
+    /// argument of that trait (corresponding to the closure arguments).
+    pub fn type_implements_fn_trait(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: ty::Binder<'tcx, Ty<'tcx>>,
+        polarity: ty::PredicatePolarity,
+    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
+        self.commit_if_ok(|_| {
+            for trait_def_id in [
+                self.tcx.lang_items().fn_trait(),
+                self.tcx.lang_items().fn_mut_trait(),
+                self.tcx.lang_items().fn_once_trait(),
+            ] {
+                let Some(trait_def_id) = trait_def_id else { continue };
+                // Make a fresh inference variable so we can determine what the generic parameters
+                // of the trait are.
+                let var = self.next_ty_var(DUMMY_SP);
+                // FIXME(effects)
+                let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
+                let obligation = Obligation::new(
+                    self.tcx,
+                    ObligationCause::dummy(),
+                    param_env,
+                    ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
+                );
+                let ocx = ObligationCtxt::new(self);
+                ocx.register_obligation(obligation);
+                if ocx.select_all_or_error().is_empty() {
+                    return Ok((
+                        self.tcx
+                            .fn_trait_kind_from_def_id(trait_def_id)
+                            .expect("expected to map DefId to ClosureKind"),
+                        ty.rebind(self.resolve_vars_if_possible(var)),
+                    ));
+                }
+            }
+
+            Err(())
+        })
+    }
+
     fn report_not_const_evaluatable_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs
deleted file mode 100644
index e8d7e80ac56..00000000000
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-// FIXME(error_reporting): This should be made into private methods on `TypeErrCtxt`.
-
-use crate::infer::InferCtxt;
-use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
-use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, Diag};
-use rustc_hir as hir;
-use rustc_hir::Node;
-use rustc_macros::extension;
-use rustc_middle::ty::{self, Ty};
-use rustc_span::{Span, DUMMY_SP};
-
-use super::ArgKind;
-
-#[extension(pub trait InferCtxtExt<'tcx>)]
-impl<'tcx> InferCtxt<'tcx> {
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
-        let sm = self.tcx.sess.source_map();
-        let hir = self.tcx.hir();
-        Some(match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
-                ..
-            }) => (
-                fn_decl_span,
-                fn_arg_span,
-                hir.body(body)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = *arg.pat
-                        {
-                            Some(ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        sm.span_to_snippet(pat.span)
-                                            .ok()
-                                            .map(|snippet| (snippet, "_".to_owned()))
-                                    })
-                                    .collect::<Option<Vec<_>>>()?,
-                            ))
-                        } else {
-                            let name = sm.span_to_snippet(arg.pat.span).ok()?;
-                            Some(ArgKind::Arg(name, "_".to_owned()))
-                        }
-                    })
-                    .collect::<Option<Vec<ArgKind>>>()?,
-            ),
-            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
-            | Node::TraitItem(&hir::TraitItem {
-                kind: hir::TraitItemKind::Fn(ref sig, _), ..
-            }) => (
-                sig.span,
-                None,
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.kind {
-                        hir::TyKind::Tup(tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(variant_data) => {
-                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
-                (span, None, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {node:?}"),
-        })
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-        closure_arg_span: Option<Span>,
-    ) -> Diag<'_> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = matches!(other, &[ArgKind::Tuple(..)]);
-            match (arg_length, arguments.get(0)) {
-                (1, Some(ArgKind::Tuple(_, fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_code_err!(
-            self.dcx(),
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {kind} that takes {expected_str}"));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {found_str}"));
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion_verbose(
-                    closure_arg_span.unwrap_or(found_span),
-                    format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        pluralize!(expected_args.len())
-                    ),
-                    format!("|{underscores}|"),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion_verbose(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{sugg}|"),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
-                && fields.len() == found_args.len()
-                && is_closure
-            {
-                let sugg = format!(
-                    "|({}){}|",
-                    found_args
-                        .iter()
-                        .map(|arg| match arg {
-                            ArgKind::Arg(name, _) => name.to_owned(),
-                            _ => "_".to_owned(),
-                        })
-                        .collect::<Vec<String>>()
-                        .join(", "),
-                    // add type annotations if available
-                    if found_args.iter().any(|arg| match arg {
-                        ArgKind::Arg(_, ty) => ty != "_",
-                        _ => false,
-                    }) {
-                        format!(
-                            ": ({})",
-                            fields
-                                .iter()
-                                .map(|(_, ty)| ty.to_owned())
-                                .collect::<Vec<String>>()
-                                .join(", ")
-                        )
-                    } else {
-                        String::new()
-                    },
-                );
-                err.span_suggestion_verbose(
-                    found_span,
-                    "change the closure to accept a tuple instead of individual arguments",
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-
-        err
-    }
-
-    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
-    /// in that order, and returns the generic type corresponding to the
-    /// argument of that trait (corresponding to the closure arguments).
-    fn type_implements_fn_trait(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: ty::Binder<'tcx, Ty<'tcx>>,
-        polarity: ty::PredicatePolarity,
-    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
-        self.commit_if_ok(|_| {
-            for trait_def_id in [
-                self.tcx.lang_items().fn_trait(),
-                self.tcx.lang_items().fn_mut_trait(),
-                self.tcx.lang_items().fn_once_trait(),
-            ] {
-                let Some(trait_def_id) = trait_def_id else { continue };
-                // Make a fresh inference variable so we can determine what the generic parameters
-                // of the trait are.
-                let var = self.next_ty_var(DUMMY_SP);
-                // FIXME(effects)
-                let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
-                let obligation = Obligation::new(
-                    self.tcx,
-                    ObligationCause::dummy(),
-                    param_env,
-                    ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
-                );
-                let ocx = ObligationCtxt::new(self);
-                ocx.register_obligation(obligation);
-                if ocx.select_all_or_error().is_empty() {
-                    return Ok((
-                        self.tcx
-                            .fn_trait_kind_from_def_id(trait_def_id)
-                            .expect("expected to map DefId to ClosureKind"),
-                        ty.rebind(self.resolve_vars_if_possible(var)),
-                    ));
-                }
-            }
-
-            Err(())
-        })
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 16dfa27b75a..87fdc5ddff8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -1,33 +1,27 @@
 pub mod ambiguity;
 mod fulfillment_errors;
-mod infer_ctxt_ext;
 pub mod on_unimplemented;
 mod overflow;
 pub mod suggestions;
 
-use std::iter;
+use std::{fmt, iter};
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_hir::def_id::DefId;
+use rustc_errors::{struct_span_code_err, Applicability, Diag, MultiSpan, E0038, E0276};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, LangItem};
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
 use rustc_infer::traits::{
-    Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError,
+    ObjectSafetyViolation, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
+    SelectionError,
 };
-use rustc_macros::extension;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::{ErrorGuaranteed, ExpnKind, Span};
 
-use ambiguity::TypeErrCtxtAmbiguityExt as _;
-use fulfillment_errors::TypeErrCtxtExt as _;
-use suggestions::TypeErrCtxtExt as _;
-
+use crate::error_reporting::TypeErrCtxt;
 use crate::traits::{FulfillmentError, FulfillmentErrorCode};
 
-pub use self::fulfillment_errors::*;
-pub use self::infer_ctxt_ext::*;
 pub use self::overflow::*;
 
 // When outputting impl candidates, prefer showing those that are more similar.
@@ -137,9 +131,8 @@ pub enum DefIdOrName {
     Name(&'static str),
 }
 
-#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    fn report_fulfillment_errors(
+    pub fn report_fulfillment_errors(
         &self,
         mut errors: Vec<FulfillmentError<'tcx>>,
     ) -> ErrorGuaranteed {
@@ -383,3 +376,194 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
     w.push(';');
     Some(w)
 }
+
+impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
+    pub fn report_extra_impl_obligation(
+        &self,
+        error_span: Span,
+        impl_item_def_id: LocalDefId,
+        trait_item_def_id: DefId,
+        requirement: &dyn fmt::Display,
+    ) -> Diag<'a> {
+        let mut err = struct_span_code_err!(
+            self.dcx(),
+            error_span,
+            E0276,
+            "impl has stricter requirements than trait"
+        );
+
+        if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
+            if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
+                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
+                err.span_label(span, format!("definition of `{item_name}` from trait"));
+            }
+        }
+
+        err.span_label(error_span, format!("impl has extra requirement {requirement}"));
+
+        err
+    }
+}
+
+pub fn report_object_safety_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    hir_id: Option<hir::HirId>,
+    trait_def_id: DefId,
+    violations: &[ObjectSafetyViolation],
+) -> Diag<'tcx> {
+    let trait_str = tcx.def_path_str(trait_def_id);
+    let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
+        hir::Node::Item(item) => Some(item.ident.span),
+        _ => None,
+    });
+    let mut err = struct_span_code_err!(
+        tcx.dcx(),
+        span,
+        E0038,
+        "the trait `{}` cannot be made into an object",
+        trait_str
+    );
+    err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
+
+    if let Some(hir_id) = hir_id
+        && let hir::Node::Ty(ty) = tcx.hir_node(hir_id)
+        && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
+    {
+        let mut hir_id = hir_id;
+        while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) {
+            hir_id = ty.hir_id;
+        }
+        if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
+            // Do not suggest `impl Trait` when dealing with things like super-traits.
+            err.span_suggestion_verbose(
+                ty.span.until(trait_ref.span),
+                "consider using an opaque type instead",
+                "impl ",
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+    let mut reported_violations = FxIndexSet::default();
+    let mut multi_span = vec![];
+    let mut messages = vec![];
+    for violation in violations {
+        if let ObjectSafetyViolation::SizedSelf(sp) = &violation
+            && !sp.is_empty()
+        {
+            // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
+            // with a `Span`.
+            reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
+        }
+        if reported_violations.insert(violation.clone()) {
+            let spans = violation.spans();
+            let msg = if trait_span.is_none() || spans.is_empty() {
+                format!("the trait cannot be made into an object because {}", violation.error_msg())
+            } else {
+                format!("...because {}", violation.error_msg())
+            };
+            if spans.is_empty() {
+                err.note(msg);
+            } else {
+                for span in spans {
+                    multi_span.push(span);
+                    messages.push(msg.clone());
+                }
+            }
+        }
+    }
+    let has_multi_span = !multi_span.is_empty();
+    let mut note_span = MultiSpan::from_spans(multi_span.clone());
+    if let (Some(trait_span), true) = (trait_span, has_multi_span) {
+        note_span.push_span_label(trait_span, "this trait cannot be made into an object...");
+    }
+    for (span, msg) in iter::zip(multi_span, messages) {
+        note_span.push_span_label(span, msg);
+    }
+    err.span_note(
+        note_span,
+        "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>",
+    );
+
+    // Only provide the help if its a local trait, otherwise it's not actionable.
+    if trait_span.is_some() {
+        let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
+        reported_violations.sort();
+
+        let mut potential_solutions: Vec<_> =
+            reported_violations.into_iter().map(|violation| violation.solution()).collect();
+        potential_solutions.sort();
+        // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
+        potential_solutions.dedup();
+        for solution in potential_solutions {
+            solution.add_to(&mut err);
+        }
+    }
+
+    let impls_of = tcx.trait_impls_of(trait_def_id);
+    let impls = if impls_of.blanket_impls().is_empty() {
+        impls_of
+            .non_blanket_impls()
+            .values()
+            .flatten()
+            .filter(|def_id| {
+                !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..))
+            })
+            .collect::<Vec<_>>()
+    } else {
+        vec![]
+    };
+    let externally_visible = if !impls.is_empty()
+        && let Some(def_id) = trait_def_id.as_local()
+        // We may be executing this during typeck, which would result in cycle
+        // if we used effective_visibilities query, which looks into opaque types
+        // (and therefore calls typeck).
+        && tcx.resolutions(()).effective_visibilities.is_exported(def_id)
+    {
+        true
+    } else {
+        false
+    };
+    match &impls[..] {
+        [] => {}
+        _ if impls.len() > 9 => {}
+        [only] if externally_visible => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` is seen to implement the trait in this crate, consider using it \
+                 directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        [only] => {
+            err.help(with_no_trimmed_paths!(format!(
+                "only type `{}` implements the trait, consider using it directly instead",
+                tcx.type_of(*only).instantiate_identity(),
+            )));
+        }
+        impls => {
+            let types = impls
+                .iter()
+                .map(|t| {
+                    with_no_trimmed_paths!(format!("  {}", tcx.type_of(*t).instantiate_identity(),))
+                })
+                .collect::<Vec<_>>();
+            err.help(format!(
+                "the following types implement the trait, consider defining an enum where each \
+                 variant holds one of these types, implementing `{}` for this new enum and using \
+                 it instead:\n{}",
+                trait_str,
+                types.join("\n"),
+            ));
+        }
+    }
+    if externally_visible {
+        err.note(format!(
+            "`{trait_str}` can be implemented in other crates; if you want to support your users \
+             passing their own types here, you can't refer to a specific type",
+        ));
+    }
+
+    err
+}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index a448e1924c8..f65de590ccf 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -1,5 +1,5 @@
 use super::{ObligationCauseCode, PredicateObligation};
-use crate::error_reporting::traits::fulfillment_errors::InferCtxtPrivExt;
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{
     EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
 };
@@ -13,8 +13,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
-use rustc_macros::{extension, LintDiagnostic};
+use rustc_macros::LintDiagnostic;
 use rustc_middle::bug;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgsRef;
@@ -41,7 +40,6 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
     sym::Trait,
 ];
 
-#[extension(pub trait TypeErrCtxtExt<'tcx>)]
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn impl_similar_to(
         &self,
@@ -109,7 +107,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    fn on_unimplemented_note(
+    pub fn on_unimplemented_note(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
index fe1771f9096..16fbff7816a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
@@ -5,17 +5,14 @@ use rustc_errors::{
 };
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
 use rustc_infer::traits::{Obligation, PredicateObligation};
-use rustc_macros::extension;
 use rustc_middle::ty::print::{FmtPrinter, Print};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::Limit;
 use rustc_span::Span;
 use rustc_type_ir::Upcast;
 
-use super::InferCtxtPrivExt;
-use crate::error_reporting::traits::suggestions::TypeErrCtxtExt;
+use crate::error_reporting::TypeErrCtxt;
 
 pub enum OverflowCause<'tcx> {
     DeeplyNormalize(ty::AliasTerm<'tcx>),
@@ -38,7 +35,6 @@ pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>(
     ));
 }
 
-#[extension(pub trait TypeErrCtxtOverflowExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// Reports that an overflow has occurred and halts compilation. We
     /// halt compilation unconditionally because it is important that
@@ -46,7 +42,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// whose result could not be truly determined and thus we can't say
     /// if the program type checks or not -- and they are unusual
     /// occurrences in any case.
-    fn report_overflow_error(
+    pub fn report_overflow_error(
         &self,
         cause: OverflowCause<'tcx>,
         span: Span,
@@ -59,7 +55,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         FatalError.raise();
     }
 
-    fn build_overflow_error(
+    pub fn build_overflow_error(
         &self,
         cause: OverflowCause<'tcx>,
         span: Span,
@@ -132,7 +128,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// whose result could not be truly determined and thus we can't say
     /// if the program type checks or not -- and they are unusual
     /// occurrences in any case.
-    fn report_overflow_obligation<T>(
+    pub fn report_overflow_obligation<T>(
         &self,
         obligation: &Obligation<'tcx, T>,
         suggest_increasing_limit: bool,
@@ -165,7 +161,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// that we can give a more helpful error message (and, in particular,
     /// we do not suggest increasing the overflow limit, which is not
     /// going to help).
-    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+    pub fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
         let cycle = self.resolve_vars_if_possible(cycle.to_owned());
         assert!(!cycle.is_empty());
 
@@ -179,7 +175,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         );
     }
 
-    fn report_overflow_no_abort(
+    pub fn report_overflow_no_abort(
         &self,
         obligation: PredicateObligation<'tcx>,
         suggest_increasing_limit: bool,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index fa2acdd4a54..885216e6216 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -5,11 +5,10 @@ use super::{
     PredicateObligation,
 };
 
+use crate::error_reporting::TypeErrCtxt;
 use crate::errors;
-use crate::infer::InferCtxt;
 use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
 
-use hir::def::CtorOf;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
@@ -17,15 +16,15 @@ use rustc_errors::{
     Style, SuggestionStyle,
 };
 use rustc_hir as hir;
+use rustc_hir::def::CtorOf;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::is_range_literal;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
-use rustc_infer::error_reporting::infer::TypeErrCtxt;
+use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
-use rustc_macros::extension;
 use rustc_middle::hir::map;
 use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError;
@@ -44,7 +43,6 @@ use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
 
-use crate::error_reporting::traits::fulfillment_errors::InferCtxtPrivExt;
 use crate::infer::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_middle::ty::print::{
@@ -241,9 +239,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
     }
 }
 
-#[extension(pub trait TypeErrCtxtExt<'a, 'tcx>)]
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
-    fn suggest_restricting_param_bound(
+    pub fn suggest_restricting_param_bound(
         &self,
         err: &mut Diag<'_>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
@@ -453,7 +450,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// When after several dereferencing, the reference satisfies the trait
     /// bound. This function provides dereference suggestion for this
     /// specific situation.
-    fn suggest_dereferences(
+    pub(super) fn suggest_dereferences(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -782,7 +779,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
     /// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling
     /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    fn suggest_fn_call(
+    pub(super) fn suggest_fn_call(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -898,7 +895,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         true
     }
 
-    fn check_for_binding_assigned_block_without_tail_expression(
+    pub(super) fn check_for_binding_assigned_block_without_tail_expression(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -974,7 +971,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_add_clone_to_arg(
+    pub(super) fn suggest_add_clone_to_arg(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -1074,7 +1071,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// Extracts information about a callable type for diagnostics. This is a
     /// heuristic -- it doesn't necessarily mean that a type is always callable,
     /// because the callable type must also be well-formed to be called.
-    fn extract_callable_info(
+    pub fn extract_callable_info(
         &self,
         body_id: LocalDefId,
         param_env: ty::ParamEnv<'tcx>,
@@ -1200,7 +1197,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) }
     }
 
-    fn suggest_add_reference_to_arg(
+    pub(super) fn suggest_add_reference_to_arg(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -1422,7 +1419,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     }
 
     // Suggest borrowing the type
-    fn suggest_borrowing_for_object_cast(
+    pub(super) fn suggest_borrowing_for_object_cast(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -1457,7 +1454,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
     /// suggest removing these references until we reach a type that implements the trait.
-    fn suggest_remove_reference(
+    pub(super) fn suggest_remove_reference(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -1578,7 +1575,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         false
     }
 
-    fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diag<'_>) {
+    pub(super) fn suggest_remove_await(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut Diag<'_>,
+    ) {
         let hir = self.tcx.hir();
         if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives()
             && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id)
@@ -1644,7 +1645,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
     /// Check if the trait bound is implemented for a different mutability and note it in the
     /// final error.
-    fn suggest_change_mut(
+    pub(super) fn suggest_change_mut(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -1720,7 +1721,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_semicolon_removal(
+    pub(super) fn suggest_semicolon_removal(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -1762,7 +1763,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         false
     }
 
-    fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
+    pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
         let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. }) =
             self.tcx.hir_node_by_def_id(obligation.cause.body_id)
         else {
@@ -1775,7 +1776,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
     /// applicable and signal that the error has been expanded appropriately and needs to be
     /// emitted.
-    fn suggest_impl_trait(
+    pub(super) fn suggest_impl_trait(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -1793,25 +1794,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         err.children.clear();
 
         let span = obligation.cause.span;
-        if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
+        let body = self.tcx.hir().body_owned_by(obligation.cause.body_id);
+
+        let mut visitor = ReturnsVisitor::default();
+        visitor.visit_body(&body);
+
+        let (pre, impl_span) = if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
             && snip.starts_with("dyn ")
         {
-            err.span_suggestion(
-                span.with_hi(span.lo() + BytePos(4)),
-                "return an `impl Trait` instead of a `dyn Trait`, \
-                if all returned values are the same type",
+            ("", span.with_hi(span.lo() + BytePos(4)))
+        } else {
+            ("dyn ", span.shrink_to_lo())
+        };
+        let alternatively = if visitor
+            .returns
+            .iter()
+            .map(|expr| self.typeck_results.as_ref().unwrap().expr_ty_adjusted_opt(expr))
+            .collect::<FxHashSet<_>>()
+            .len()
+            <= 1
+        {
+            err.span_suggestion_verbose(
+                impl_span,
+                "consider returning an `impl Trait` instead of a `dyn Trait`",
                 "impl ",
                 Applicability::MaybeIncorrect,
             );
-        }
-
-        let body = self.tcx.hir().body_owned_by(obligation.cause.body_id);
-
-        let mut visitor = ReturnsVisitor::default();
-        visitor.visit_body(&body);
+            "alternatively, "
+        } else {
+            err.help("if there were a single returned type, you could use `impl Trait` instead");
+            ""
+        };
 
-        let mut sugg =
-            vec![(span.shrink_to_lo(), "Box<".to_string()), (span.shrink_to_hi(), ">".to_string())];
+        let mut sugg = vec![
+            (span.shrink_to_lo(), format!("Box<{pre}")),
+            (span.shrink_to_hi(), ">".to_string()),
+        ];
         sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
             let span =
                 expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
@@ -1837,7 +1855,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }));
 
         err.multipart_suggestion(
-            "box the return type, and wrap all of the returned values in `Box::new`",
+            format!(
+                "{alternatively}box the return type, and wrap all of the returned values in \
+                 `Box::new`",
+            ),
             sugg,
             Applicability::MaybeIncorrect,
         );
@@ -1845,7 +1866,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         true
     }
 
-    fn point_at_returns_when_relevant(
+    pub(super) fn point_at_returns_when_relevant(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -1877,7 +1898,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn report_closure_arg_mismatch(
+    pub(super) fn report_closure_arg_mismatch(
         &self,
         span: Span,
         found_span: Option<Span>,
@@ -2156,7 +2177,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_fully_qualified_path(
+    pub(super) fn suggest_fully_qualified_path(
         &self,
         err: &mut Diag<'_>,
         item_def_id: DefId,
@@ -2223,7 +2244,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     ///
     /// Returns `true` if an async-await specific note was added to the diagnostic.
     #[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
-    fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
+    pub fn maybe_note_obligation_cause_for_async_await<G: EmissionGuarantee>(
         &self,
         err: &mut Diag<'_, G>,
         obligation: &PredicateObligation<'tcx>,
@@ -2692,7 +2713,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         );
     }
 
-    fn note_obligation_cause_code<G: EmissionGuarantee, T>(
+    pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
         &self,
         body_id: LocalDefId,
         err: &mut Diag<'_, G>,
@@ -3534,7 +3555,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     #[instrument(
         level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
     )]
-    fn suggest_await_before_try(
+    pub(super) fn suggest_await_before_try(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -3591,7 +3612,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_floating_point_literal(
+    pub(super) fn suggest_floating_point_literal(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -3615,7 +3636,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_derive(
+    pub fn suggest_derive(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -3681,7 +3702,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_dereferencing_index(
+    pub(super) fn suggest_dereferencing_index(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -4303,7 +4324,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     /// If the type that failed selection is an array or a reference to an array,
     /// but the trait is implemented for slices, suggest that the user converts
     /// the array into a slice.
-    fn suggest_convert_to_slice(
+    pub(super) fn suggest_convert_to_slice(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
@@ -4375,7 +4396,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn explain_hrtb_projection(
+    pub(super) fn explain_hrtb_projection(
         &self,
         diag: &mut Diag<'_>,
         pred: ty::PolyTraitPredicate<'tcx>,
@@ -4441,7 +4462,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_desugaring_async_fn_in_trait(
+    pub(super) fn suggest_desugaring_async_fn_in_trait(
         &self,
         err: &mut Diag<'_>,
         trait_ref: ty::PolyTraitRef<'tcx>,
@@ -4525,7 +4546,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         );
     }
 
-    fn ty_kind_suggestion(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option<String> {
+    pub fn ty_kind_suggestion(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Option<String> {
         let tcx = self.infcx.tcx;
         let implements_default = |ty| {
             let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
@@ -4587,7 +4612,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         })
     }
 
-    fn suggest_add_result_as_return_type(
+    pub(super) fn suggest_add_result_as_return_type(
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
@@ -4628,7 +4653,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip_all)]
-    fn suggest_unsized_bound_if_applicable(
+    pub(super) fn suggest_unsized_bound_if_applicable(
         &self,
         err: &mut Diag<'_>,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index a46cba35b2d..0ee4485a365 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,11 +1,30 @@
-use crate::fluent_generated as fluent;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    codes::*, Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
-    SubdiagMessageOp, Subdiagnostic,
+    codes::*, Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
+    EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
 };
+use rustc_hir as hir;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{walk_ty, Visitor};
+use rustc_hir::FnRetTy;
+use rustc_hir::GenericParamKind;
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::{self, print::PrintTraitRefExt as _, ClosureKind, PolyTraitRef, Ty};
-use rustc_span::{Span, Symbol};
+use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
+use rustc_middle::ty::{
+    self, print::PrintTraitRefExt as _, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty,
+    TyCtxt,
+};
+use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::{BytePos, Span};
+
+use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind;
+use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
+use crate::error_reporting::infer::ObligationCauseAsDiagArg;
+use crate::fluent_generated as fluent;
+
+use std::path::PathBuf;
+
+pub mod note_and_explain;
 
 #[derive(Diagnostic)]
 #[diag(trait_selection_dump_vtable_entries)]
@@ -170,3 +189,1613 @@ pub(crate) struct AsyncClosureNotFn {
     pub span: Span,
     pub kind: &'static str,
 }
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_type_annotations_needed, code = E0282)]
+pub struct AnnotationRequired<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub source_kind: &'static str,
+    pub source_name: &'a str,
+    #[label]
+    pub failure_span: Option<Span>,
+    #[subdiagnostic]
+    pub bad_label: Option<InferenceBadError<'a>>,
+    #[subdiagnostic]
+    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
+    #[subdiagnostic]
+    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(trait_selection_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
+}
+
+// Copy of `AnnotationRequired` for E0283
+#[derive(Diagnostic)]
+#[diag(trait_selection_type_annotations_needed, code = E0283)]
+pub struct AmbiguousImpl<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub source_kind: &'static str,
+    pub source_name: &'a str,
+    #[label]
+    pub failure_span: Option<Span>,
+    #[subdiagnostic]
+    pub bad_label: Option<InferenceBadError<'a>>,
+    #[subdiagnostic]
+    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
+    #[subdiagnostic]
+    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(trait_selection_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
+}
+
+// Copy of `AnnotationRequired` for E0284
+#[derive(Diagnostic)]
+#[diag(trait_selection_type_annotations_needed, code = E0284)]
+pub struct AmbiguousReturn<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub source_kind: &'static str,
+    pub source_name: &'a str,
+    #[label]
+    pub failure_span: Option<Span>,
+    #[subdiagnostic]
+    pub bad_label: Option<InferenceBadError<'a>>,
+    #[subdiagnostic]
+    pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
+    #[subdiagnostic]
+    pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(trait_selection_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
+}
+
+// Used when a better one isn't available
+#[derive(Subdiagnostic)]
+#[label(trait_selection_label_bad)]
+pub struct InferenceBadError<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub bad_kind: &'static str,
+    pub prefix_kind: UnderspecifiedArgKind,
+    pub has_parent: bool,
+    pub prefix: &'a str,
+    pub parent_prefix: &'a str,
+    pub parent_name: String,
+    pub name: String,
+}
+
+#[derive(Subdiagnostic)]
+pub enum SourceKindSubdiag<'a> {
+    #[suggestion(
+        trait_selection_source_kind_subdiag_let,
+        style = "verbose",
+        code = ": {type_name}",
+        applicability = "has-placeholders"
+    )]
+    LetLike {
+        #[primary_span]
+        span: Span,
+        name: String,
+        type_name: String,
+        kind: &'static str,
+        x_kind: &'static str,
+        prefix_kind: UnderspecifiedArgKind,
+        prefix: &'a str,
+        arg_name: String,
+    },
+    #[label(trait_selection_source_kind_subdiag_generic_label)]
+    GenericLabel {
+        #[primary_span]
+        span: Span,
+        is_type: bool,
+        param_name: String,
+        parent_exists: bool,
+        parent_prefix: String,
+        parent_name: String,
+    },
+    #[suggestion(
+        trait_selection_source_kind_subdiag_generic_suggestion,
+        style = "verbose",
+        code = "::<{args}>",
+        applicability = "has-placeholders"
+    )]
+    GenericSuggestion {
+        #[primary_span]
+        span: Span,
+        arg_count: usize,
+        args: String,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum SourceKindMultiSuggestion<'a> {
+    #[multipart_suggestion(
+        trait_selection_source_kind_fully_qualified,
+        style = "verbose",
+        applicability = "has-placeholders"
+    )]
+    FullyQualified {
+        #[suggestion_part(code = "{def_path}({adjustment}")]
+        span_lo: Span,
+        #[suggestion_part(code = "{successor_pos}")]
+        span_hi: Span,
+        def_path: String,
+        adjustment: &'a str,
+        successor_pos: &'a str,
+    },
+    #[multipart_suggestion(
+        trait_selection_source_kind_closure_return,
+        style = "verbose",
+        applicability = "has-placeholders"
+    )]
+    ClosureReturn {
+        #[suggestion_part(code = "{start_span_code}")]
+        start_span: Span,
+        start_span_code: String,
+        #[suggestion_part(code = " }}")]
+        end_span: Option<Span>,
+    },
+}
+
+impl<'a> SourceKindMultiSuggestion<'a> {
+    pub fn new_fully_qualified(
+        span: Span,
+        def_path: String,
+        adjustment: &'a str,
+        successor: (&'a str, BytePos),
+    ) -> Self {
+        Self::FullyQualified {
+            span_lo: span.shrink_to_lo(),
+            span_hi: span.shrink_to_hi().with_hi(successor.1),
+            def_path,
+            adjustment,
+            successor_pos: successor.0,
+        }
+    }
+
+    pub fn new_closure_return(
+        ty_info: String,
+        data: &'a FnRetTy<'a>,
+        should_wrap_expr: Option<Span>,
+    ) -> Self {
+        let arrow = match data {
+            FnRetTy::DefaultReturn(_) => " -> ",
+            _ => "",
+        };
+        let (start_span, start_span_code, end_span) = match should_wrap_expr {
+            Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
+            None => (data.span(), format!("{arrow}{ty_info}"), None),
+        };
+        Self::ClosureReturn { start_span, start_span_code, end_span }
+    }
+}
+
+pub enum RegionOriginNote<'a> {
+    Plain {
+        span: Span,
+        msg: DiagMessage,
+    },
+    WithName {
+        span: Span,
+        msg: DiagMessage,
+        name: &'a str,
+        continues: bool,
+    },
+    WithRequirement {
+        span: Span,
+        requirement: ObligationCauseAsDiagArg<'a>,
+        expected_found: Option<(DiagStyledString, DiagStyledString)>,
+    },
+}
+
+impl Subdiagnostic for RegionOriginNote<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        let mut label_or_note = |span, msg: DiagMessage| {
+            let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
+            let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
+            let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
+            if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
+                diag.span_label(span, msg);
+            } else if span_is_primary && expanded_sub_count == 0 {
+                diag.note(msg);
+            } else {
+                diag.span_note(span, msg);
+            }
+        };
+        match self {
+            RegionOriginNote::Plain { span, msg } => {
+                label_or_note(span, msg);
+            }
+            RegionOriginNote::WithName { span, msg, name, continues } => {
+                label_or_note(span, msg);
+                diag.arg("name", name);
+                diag.arg("continues", continues);
+            }
+            RegionOriginNote::WithRequirement {
+                span,
+                requirement,
+                expected_found: Some((expected, found)),
+            } => {
+                label_or_note(span, fluent::trait_selection_subtype);
+                diag.arg("requirement", requirement);
+
+                diag.note_expected_found(&"", expected, &"", found);
+            }
+            RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
+                // FIXME: this really should be handled at some earlier stage. Our
+                // handling of region checking when type errors are present is
+                // *terrible*.
+                label_or_note(span, fluent::trait_selection_subtype_2);
+                diag.arg("requirement", requirement);
+            }
+        };
+    }
+}
+
+pub enum LifetimeMismatchLabels {
+    InRet {
+        param_span: Span,
+        ret_span: Span,
+        span: Span,
+        label_var1: Option<Ident>,
+    },
+    Normal {
+        hir_equal: bool,
+        ty_sup: Span,
+        ty_sub: Span,
+        span: Span,
+        sup: Option<Ident>,
+        sub: Option<Ident>,
+    },
+}
+
+impl Subdiagnostic for LifetimeMismatchLabels {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        match self {
+            LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
+                diag.span_label(param_span, fluent::trait_selection_declared_different);
+                diag.span_label(ret_span, fluent::trait_selection_nothing);
+                diag.span_label(span, fluent::trait_selection_data_returned);
+                diag.arg("label_var1_exists", label_var1.is_some());
+                diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
+            }
+            LifetimeMismatchLabels::Normal {
+                hir_equal,
+                ty_sup,
+                ty_sub,
+                span,
+                sup: label_var1,
+                sub: label_var2,
+            } => {
+                if hir_equal {
+                    diag.span_label(ty_sup, fluent::trait_selection_declared_multiple);
+                    diag.span_label(ty_sub, fluent::trait_selection_nothing);
+                    diag.span_label(span, fluent::trait_selection_data_lifetime_flow);
+                } else {
+                    diag.span_label(ty_sup, fluent::trait_selection_types_declared_different);
+                    diag.span_label(ty_sub, fluent::trait_selection_nothing);
+                    diag.span_label(span, fluent::trait_selection_data_flows);
+                    diag.arg("label_var1_exists", label_var1.is_some());
+                    diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
+                    diag.arg("label_var2_exists", label_var2.is_some());
+                    diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
+                }
+            }
+        }
+    }
+}
+
+pub struct AddLifetimeParamsSuggestion<'a> {
+    pub tcx: TyCtxt<'a>,
+    pub generic_param_scope: LocalDefId,
+    pub sub: Region<'a>,
+    pub ty_sup: &'a hir::Ty<'a>,
+    pub ty_sub: &'a hir::Ty<'a>,
+    pub add_note: bool,
+}
+
+impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        let mut mk_suggestion = || {
+            let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
+            else {
+                return false;
+            };
+
+            let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
+            let is_impl = matches!(&node, hir::Node::ImplItem(_));
+            let (generics, parent_generics) = match node {
+                hir::Node::Item(&hir::Item {
+                    kind: hir::ItemKind::Fn(_, ref generics, ..),
+                    ..
+                })
+                | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
+                | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
+                    generics,
+                    match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id))
+                    {
+                        hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::Trait(_, _, ref generics, ..),
+                            ..
+                        })
+                        | hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }),
+                            ..
+                        }) => Some(generics),
+                        _ => None,
+                    },
+                ),
+                _ => return false,
+            };
+
+            let suggestion_param_name = generics
+                .params
+                .iter()
+                .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                .map(|p| p.name.ident().name)
+                .find(|i| *i != kw::UnderscoreLifetime);
+            let introduce_new = suggestion_param_name.is_none();
+
+            let mut default = "'a".to_string();
+            if let Some(parent_generics) = parent_generics {
+                let used: FxHashSet<_> = parent_generics
+                    .params
+                    .iter()
+                    .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                    .map(|p| p.name.ident().name)
+                    .filter(|i| *i != kw::UnderscoreLifetime)
+                    .map(|l| l.to_string())
+                    .collect();
+                if let Some(lt) =
+                    ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
+                {
+                    // We want a lifetime that *isn't* present in the `trait` or `impl` that assoc
+                    // `fn` belongs to. We could suggest reusing one of their lifetimes, but it is
+                    // likely to be an over-constraining lifetime requirement, so we always add a
+                    // lifetime to the `fn`.
+                    default = lt;
+                }
+            }
+            let suggestion_param_name =
+                suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
+
+            struct ImplicitLifetimeFinder {
+                suggestions: Vec<(Span, String)>,
+                suggestion_param_name: String,
+            }
+
+            impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
+                fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+                    let make_suggestion = |ident: Ident| {
+                        if ident.name == kw::Empty && ident.span.is_empty() {
+                            format!("{}, ", self.suggestion_param_name)
+                        } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
+                            format!("{} ", self.suggestion_param_name)
+                        } else {
+                            self.suggestion_param_name.clone()
+                        }
+                    };
+                    match ty.kind {
+                        hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
+                            for segment in path.segments {
+                                if let Some(args) = segment.args {
+                                    if args.args.iter().all(|arg| {
+                                        matches!(
+                                            arg,
+                                            hir::GenericArg::Lifetime(lifetime)
+                                            if lifetime.ident.name == kw::Empty
+                                        )
+                                    }) {
+                                        self.suggestions.push((
+                                            segment.ident.span.shrink_to_hi(),
+                                            format!(
+                                                "<{}>",
+                                                args.args
+                                                    .iter()
+                                                    .map(|_| self.suggestion_param_name.clone())
+                                                    .collect::<Vec<_>>()
+                                                    .join(", ")
+                                            ),
+                                        ));
+                                    } else {
+                                        for arg in args.args {
+                                            if let hir::GenericArg::Lifetime(lifetime) = arg
+                                                && lifetime.is_anonymous()
+                                            {
+                                                self.suggestions.push((
+                                                    lifetime.ident.span,
+                                                    make_suggestion(lifetime.ident),
+                                                ));
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
+                            self.suggestions
+                                .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
+                        }
+                        _ => {}
+                    }
+                    walk_ty(self, ty);
+                }
+            }
+            let mut visitor = ImplicitLifetimeFinder {
+                suggestions: vec![],
+                suggestion_param_name: suggestion_param_name.clone(),
+            };
+            if let Some(fn_decl) = node.fn_decl()
+                && let hir::FnRetTy::Return(ty) = fn_decl.output
+            {
+                visitor.visit_ty(ty);
+            }
+            if visitor.suggestions.is_empty() {
+                // Do not suggest constraining the `&self` param, but rather the return type.
+                // If that is wrong (because it is not sufficient), a follow up error will tell the
+                // user to fix it. This way we lower the chances of *over* constraining, but still
+                // get the cake of "correctly" contrained in two steps.
+                visitor.visit_ty(self.ty_sup);
+            }
+            visitor.visit_ty(self.ty_sub);
+            if visitor.suggestions.is_empty() {
+                return false;
+            }
+            if introduce_new {
+                let new_param_suggestion = if let Some(first) =
+                    generics.params.iter().find(|p| !p.name.ident().span.is_empty())
+                {
+                    (first.span.shrink_to_lo(), format!("{suggestion_param_name}, "))
+                } else {
+                    (generics.span, format!("<{suggestion_param_name}>"))
+                };
+
+                visitor.suggestions.push(new_param_suggestion);
+            }
+            diag.multipart_suggestion_verbose(
+                fluent::trait_selection_lifetime_param_suggestion,
+                visitor.suggestions,
+                Applicability::MaybeIncorrect,
+            );
+            diag.arg("is_impl", is_impl);
+            diag.arg("is_reuse", !introduce_new);
+
+            true
+        };
+        if mk_suggestion() && self.add_note {
+            diag.note(fluent::trait_selection_lifetime_param_suggestion_elided);
+        }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_lifetime_mismatch, code = E0623)]
+pub struct LifetimeMismatch<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub labels: LifetimeMismatchLabels,
+    #[subdiagnostic]
+    pub suggestion: AddLifetimeParamsSuggestion<'a>,
+}
+
+pub struct IntroducesStaticBecauseUnmetLifetimeReq {
+    pub unmet_requirements: MultiSpan,
+    pub binding_span: Span,
+}
+
+impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        mut self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        self.unmet_requirements
+            .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static);
+        diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req);
+    }
+}
+
+// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
+#[derive(Subdiagnostic)]
+pub enum DoesNotOutliveStaticFromImpl {
+    #[note(trait_selection_does_not_outlive_static_from_impl)]
+    Spanned {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(trait_selection_does_not_outlive_static_from_impl)]
+    Unspanned,
+}
+
+#[derive(Subdiagnostic)]
+pub enum ImplicitStaticLifetimeSubdiag {
+    #[note(trait_selection_implicit_static_lifetime_note)]
+    Note {
+        #[primary_span]
+        span: Span,
+    },
+    #[suggestion(
+        trait_selection_implicit_static_lifetime_suggestion,
+        style = "verbose",
+        code = " + '_",
+        applicability = "maybe-incorrect"
+    )]
+    Sugg {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_mismatched_static_lifetime)]
+pub struct MismatchedStaticLifetime<'a> {
+    #[primary_span]
+    pub cause_span: Span,
+    #[subdiagnostic]
+    pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
+    #[subdiagnostic]
+    pub expl: Option<note_and_explain::RegionExplanation<'a>>,
+    #[subdiagnostic]
+    pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
+    #[subdiagnostic]
+    pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
+}
+
+#[derive(Diagnostic)]
+pub enum ExplicitLifetimeRequired<'a> {
+    #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)]
+    WithIdent {
+        #[primary_span]
+        #[label]
+        span: Span,
+        simple_ident: Ident,
+        named: String,
+        #[suggestion(
+            trait_selection_explicit_lifetime_required_sugg_with_ident,
+            code = "{new_ty}",
+            applicability = "unspecified"
+        )]
+        new_ty_span: Span,
+        #[skip_arg]
+        new_ty: Ty<'a>,
+    },
+    #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)]
+    WithParamType {
+        #[primary_span]
+        #[label]
+        span: Span,
+        named: String,
+        #[suggestion(
+            trait_selection_explicit_lifetime_required_sugg_with_param_type,
+            code = "{new_ty}",
+            applicability = "unspecified"
+        )]
+        new_ty_span: Span,
+        #[skip_arg]
+        new_ty: Ty<'a>,
+    },
+}
+
+pub enum TyOrSig<'tcx> {
+    Ty(Highlighted<'tcx, Ty<'tcx>>),
+    ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
+}
+
+impl IntoDiagArg for TyOrSig<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        match self {
+            TyOrSig::Ty(ty) => ty.into_diag_arg(),
+            TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
+        }
+    }
+}
+
+#[derive(Subdiagnostic)]
+pub enum ActualImplExplNotes<'tcx> {
+    #[note(trait_selection_actual_impl_expl_expected_signature_two)]
+    ExpectedSignatureTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_signature_any)]
+    ExpectedSignatureAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_signature_some)]
+    ExpectedSignatureSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_signature_nothing)]
+    ExpectedSignatureNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_passive_two)]
+    ExpectedPassiveTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_passive_any)]
+    ExpectedPassiveAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_passive_some)]
+    ExpectedPassiveSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_passive_nothing)]
+    ExpectedPassiveNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_other_two)]
+    ExpectedOtherTwo {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_other_any)]
+    ExpectedOtherAny {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_other_some)]
+    ExpectedOtherSome {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_expected_other_nothing)]
+    ExpectedOtherNothing {
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    },
+    #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)]
+    ButActuallyImplementsTrait {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+    },
+    #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)]
+    ButActuallyImplementedForTy {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+        ty: String,
+    },
+    #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)]
+    ButActuallyTyImplements {
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        has_lifetime: bool,
+        lifetime: usize,
+        ty: String,
+    },
+}
+
+pub enum ActualImplExpectedKind {
+    Signature,
+    Passive,
+    Other,
+}
+
+pub enum ActualImplExpectedLifetimeKind {
+    Two,
+    Any,
+    Some,
+    Nothing,
+}
+
+impl<'tcx> ActualImplExplNotes<'tcx> {
+    pub fn new_expected(
+        kind: ActualImplExpectedKind,
+        lt_kind: ActualImplExpectedLifetimeKind,
+        leading_ellipsis: bool,
+        ty_or_sig: TyOrSig<'tcx>,
+        trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+        lifetime_1: usize,
+        lifetime_2: usize,
+    ) -> Self {
+        match (kind, lt_kind) {
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedSignatureTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedPassiveTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
+                Self::ExpectedOtherTwo {
+                    leading_ellipsis,
+                    ty_or_sig,
+                    trait_path,
+                    lifetime_1,
+                    lifetime_2,
+                }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
+                Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
+                Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
+            }
+            (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
+                Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
+            }
+        }
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_trait_placeholder_mismatch)]
+pub struct TraitPlaceholderMismatch<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    #[label(trait_selection_label_satisfy)]
+    pub satisfy_span: Option<Span>,
+    #[label(trait_selection_label_where)]
+    pub where_span: Option<Span>,
+    #[label(trait_selection_label_dup)]
+    pub dup_span: Option<Span>,
+    pub def_id: String,
+    pub trait_def_id: String,
+
+    #[subdiagnostic]
+    pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
+}
+
+pub struct ConsiderBorrowingParamHelp {
+    pub spans: Vec<Span>,
+}
+
+impl Subdiagnostic for ConsiderBorrowingParamHelp {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        f: &F,
+    ) {
+        let mut type_param_span: MultiSpan = self.spans.clone().into();
+        for &span in &self.spans {
+            // Seems like we can't call f() here as Into<DiagMessage> is required
+            type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
+        }
+        let msg = f(diag, fluent::trait_selection_tid_param_help.into());
+        diag.span_help(type_param_span, msg);
+    }
+}
+
+#[derive(Subdiagnostic)]
+#[help(trait_selection_tid_rel_help)]
+pub struct RelationshipHelp;
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_trait_impl_diff)]
+pub struct TraitImplDiff {
+    #[primary_span]
+    #[label(trait_selection_found)]
+    pub sp: Span,
+    #[label(trait_selection_expected)]
+    pub trait_sp: Span,
+    #[note(trait_selection_expected_found)]
+    pub note: (),
+    #[subdiagnostic]
+    pub param_help: ConsiderBorrowingParamHelp,
+    #[subdiagnostic]
+    // Seems like subdiagnostics are always pushed to the end, so this one
+    // also has to be a subdiagnostic to maintain order.
+    pub rel_help: Option<RelationshipHelp>,
+    pub expected: String,
+    pub found: String,
+}
+
+pub struct DynTraitConstraintSuggestion {
+    pub span: Span,
+    pub ident: Ident,
+}
+
+impl Subdiagnostic for DynTraitConstraintSuggestion {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        f: &F,
+    ) {
+        let mut multi_span: MultiSpan = vec![self.span].into();
+        multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
+        multi_span
+            .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
+        let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into());
+        diag.span_note(multi_span, msg);
+        let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into());
+        diag.span_suggestion_verbose(
+            self.span.shrink_to_hi(),
+            msg,
+            " + '_",
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_but_calling_introduces, code = E0772)]
+pub struct ButCallingIntroduces {
+    #[label(trait_selection_label1)]
+    pub param_ty_span: Span,
+    #[primary_span]
+    #[label(trait_selection_label2)]
+    pub cause_span: Span,
+
+    pub has_param_name: bool,
+    pub param_name: String,
+    pub has_lifetime: bool,
+    pub lifetime: String,
+    pub assoc_item: Symbol,
+    pub has_impl_path: bool,
+    pub impl_path: String,
+}
+
+pub struct ReqIntroducedLocations {
+    pub span: MultiSpan,
+    pub spans: Vec<Span>,
+    pub fn_decl_span: Span,
+    pub cause_span: Span,
+    pub add_label: bool,
+}
+
+impl Subdiagnostic for ReqIntroducedLocations {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        mut self,
+        diag: &mut Diag<'_, G>,
+        f: &F,
+    ) {
+        for sp in self.spans {
+            self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
+        }
+
+        if self.add_label {
+            self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
+        }
+        self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
+        let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into());
+        diag.span_note(self.span, msg);
+    }
+}
+
+pub struct MoreTargeted {
+    pub ident: Symbol,
+}
+
+impl Subdiagnostic for MoreTargeted {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        diag.code(E0772);
+        diag.primary_message(fluent::trait_selection_more_targeted);
+        diag.arg("ident", self.ident);
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_but_needs_to_satisfy, code = E0759)]
+pub struct ButNeedsToSatisfy {
+    #[primary_span]
+    pub sp: Span,
+    #[label(trait_selection_influencer)]
+    pub influencer_point: Span,
+    #[label(trait_selection_used_here)]
+    pub spans: Vec<Span>,
+    #[label(trait_selection_require)]
+    pub require_span_as_label: Option<Span>,
+    #[note(trait_selection_require)]
+    pub require_span_as_note: Option<Span>,
+    #[note(trait_selection_introduced_by_bound)]
+    pub bound: Option<Span>,
+
+    #[subdiagnostic]
+    pub req_introduces_loc: Option<ReqIntroducedLocations>,
+
+    pub has_param_name: bool,
+    pub param_name: String,
+    pub spans_empty: bool,
+    pub has_lifetime: bool,
+    pub lifetime: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_outlives_content, code = E0312)]
+pub struct OutlivesContent<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_outlives_bound, code = E0476)]
+pub struct OutlivesBound<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_fulfill_req_lifetime, code = E0477)]
+pub struct FulfillReqLifetime<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'a>,
+    #[subdiagnostic]
+    pub note: Option<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)]
+pub struct LfBoundNotSatisfied<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_ref_longer_than_data, code = E0491)]
+pub struct RefLongerThanData<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'a>,
+    #[subdiagnostic]
+    pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum WhereClauseSuggestions {
+    #[suggestion(
+        trait_selection_where_remove,
+        code = "",
+        applicability = "machine-applicable",
+        style = "verbose"
+    )]
+    Remove {
+        #[primary_span]
+        span: Span,
+    },
+    #[suggestion(
+        trait_selection_where_copy_predicates,
+        code = "{space}where {trait_predicates}",
+        applicability = "machine-applicable",
+        style = "verbose"
+    )]
+    CopyPredicates {
+        #[primary_span]
+        span: Span,
+        space: &'static str,
+        trait_predicates: String,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestRemoveSemiOrReturnBinding {
+    #[multipart_suggestion(
+        trait_selection_srs_remove_and_box,
+        applicability = "machine-applicable"
+    )]
+    RemoveAndBox {
+        #[suggestion_part(code = "Box::new(")]
+        first_lo: Span,
+        #[suggestion_part(code = ")")]
+        first_hi: Span,
+        #[suggestion_part(code = "Box::new(")]
+        second_lo: Span,
+        #[suggestion_part(code = ")")]
+        second_hi: Span,
+        #[suggestion_part(code = "")]
+        sp: Span,
+    },
+    #[suggestion(
+        trait_selection_srs_remove,
+        style = "short",
+        code = "",
+        applicability = "machine-applicable"
+    )]
+    Remove {
+        #[primary_span]
+        sp: Span,
+    },
+    #[suggestion(
+        trait_selection_srs_add,
+        style = "verbose",
+        code = "{code}",
+        applicability = "maybe-incorrect"
+    )]
+    Add {
+        #[primary_span]
+        sp: Span,
+        code: String,
+        ident: Ident,
+    },
+    #[note(trait_selection_srs_add_one)]
+    AddOne {
+        #[primary_span]
+        spans: MultiSpan,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum ConsiderAddingAwait {
+    #[help(trait_selection_await_both_futures)]
+    BothFuturesHelp,
+    #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")]
+    BothFuturesSugg {
+        #[suggestion_part(code = ".await")]
+        first: Span,
+        #[suggestion_part(code = ".await")]
+        second: Span,
+    },
+    #[suggestion(
+        trait_selection_await_future,
+        code = ".await",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    FutureSugg {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(trait_selection_await_note)]
+    FutureSuggNote {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(
+        trait_selection_await_future,
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    FutureSuggMultiple {
+        #[suggestion_part(code = ".await")]
+        spans: Vec<Span>,
+    },
+}
+
+#[derive(Diagnostic)]
+pub enum PlaceholderRelationLfNotSatisfied {
+    #[diag(trait_selection_lf_bound_not_satisfied)]
+    HasBoth {
+        #[primary_span]
+        span: Span,
+        #[note(trait_selection_prlf_defined_with_sub)]
+        sub_span: Span,
+        #[note(trait_selection_prlf_must_outlive_with_sup)]
+        sup_span: Span,
+        sub_symbol: Symbol,
+        sup_symbol: Symbol,
+        #[note(trait_selection_prlf_known_limitation)]
+        note: (),
+    },
+    #[diag(trait_selection_lf_bound_not_satisfied)]
+    HasSub {
+        #[primary_span]
+        span: Span,
+        #[note(trait_selection_prlf_defined_with_sub)]
+        sub_span: Span,
+        #[note(trait_selection_prlf_must_outlive_without_sup)]
+        sup_span: Span,
+        sub_symbol: Symbol,
+        #[note(trait_selection_prlf_known_limitation)]
+        note: (),
+    },
+    #[diag(trait_selection_lf_bound_not_satisfied)]
+    HasSup {
+        #[primary_span]
+        span: Span,
+        #[note(trait_selection_prlf_defined_without_sub)]
+        sub_span: Span,
+        #[note(trait_selection_prlf_must_outlive_with_sup)]
+        sup_span: Span,
+        sup_symbol: Symbol,
+        #[note(trait_selection_prlf_known_limitation)]
+        note: (),
+    },
+    #[diag(trait_selection_lf_bound_not_satisfied)]
+    HasNone {
+        #[primary_span]
+        span: Span,
+        #[note(trait_selection_prlf_defined_without_sub)]
+        sub_span: Span,
+        #[note(trait_selection_prlf_must_outlive_without_sup)]
+        sup_span: Span,
+        #[note(trait_selection_prlf_known_limitation)]
+        note: (),
+    },
+    #[diag(trait_selection_lf_bound_not_satisfied)]
+    OnlyPrimarySpan {
+        #[primary_span]
+        span: Span,
+        #[note(trait_selection_prlf_known_limitation)]
+        note: (),
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(trait_selection_opaque_captures_lifetime, code = E0700)]
+pub struct OpaqueCapturesLifetime<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub opaque_ty_span: Span,
+    pub opaque_ty: Ty<'tcx>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum FunctionPointerSuggestion<'a> {
+    #[suggestion(
+        trait_selection_fps_use_ref,
+        code = "&{fn_name}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    UseRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+    },
+    #[suggestion(
+        trait_selection_fps_remove_ref,
+        code = "{fn_name}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    RemoveRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+    },
+    #[suggestion(
+        trait_selection_fps_cast,
+        code = "&({fn_name} as {sig})",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    CastRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        trait_selection_fps_cast,
+        code = "{fn_name} as {sig}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    Cast {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        trait_selection_fps_cast_both,
+        code = "{fn_name} as {found_sig}",
+        style = "hidden",
+        applicability = "maybe-incorrect"
+    )]
+    CastBoth {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        found_sig: Binder<'a, FnSig<'a>>,
+        expected_sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        trait_selection_fps_cast_both,
+        code = "&({fn_name} as {found_sig})",
+        style = "hidden",
+        applicability = "maybe-incorrect"
+    )]
+    CastBothRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        found_sig: Binder<'a, FnSig<'a>>,
+        expected_sig: Binder<'a, FnSig<'a>>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[note(trait_selection_fps_items_are_distinct)]
+pub struct FnItemsAreDistinct;
+
+#[derive(Subdiagnostic)]
+#[note(trait_selection_fn_uniq_types)]
+pub struct FnUniqTypes;
+
+#[derive(Subdiagnostic)]
+#[help(trait_selection_fn_consider_casting)]
+pub struct FnConsiderCasting {
+    pub casting: String,
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestAccessingField<'a> {
+    #[suggestion(
+        trait_selection_suggest_accessing_field,
+        code = "{snippet}.{name}",
+        applicability = "maybe-incorrect"
+    )]
+    Safe {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+        name: Symbol,
+        ty: Ty<'a>,
+    },
+    #[suggestion(
+        trait_selection_suggest_accessing_field,
+        code = "unsafe {{ {snippet}.{name} }}",
+        applicability = "maybe-incorrect"
+    )]
+    Unsafe {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+        name: Symbol,
+        ty: Ty<'a>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")]
+pub struct SuggestTuplePatternOne {
+    pub variant: String,
+    #[suggestion_part(code = "{variant}(")]
+    pub span_low: Span,
+    #[suggestion_part(code = ")")]
+    pub span_high: Span,
+}
+
+pub struct SuggestTuplePatternMany {
+    pub path: String,
+    pub cause_span: Span,
+    pub compatible_variants: Vec<String>,
+}
+
+impl Subdiagnostic for SuggestTuplePatternMany {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        f: &F,
+    ) {
+        diag.arg("path", self.path);
+        let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into());
+        diag.multipart_suggestions(
+            message,
+            self.compatible_variants.into_iter().map(|variant| {
+                vec![
+                    (self.cause_span.shrink_to_lo(), format!("{variant}(")),
+                    (self.cause_span.shrink_to_hi(), ")".to_string()),
+                ]
+            }),
+            rustc_errors::Applicability::MaybeIncorrect,
+        );
+    }
+}
+
+#[derive(Subdiagnostic)]
+pub enum TypeErrorAdditionalDiags {
+    #[suggestion(
+        trait_selection_meant_byte_literal,
+        code = "b'{code}'",
+        applicability = "machine-applicable"
+    )]
+    MeantByteLiteral {
+        #[primary_span]
+        span: Span,
+        code: String,
+    },
+    #[suggestion(
+        trait_selection_meant_char_literal,
+        code = "'{code}'",
+        applicability = "machine-applicable"
+    )]
+    MeantCharLiteral {
+        #[primary_span]
+        span: Span,
+        code: String,
+    },
+    #[multipart_suggestion(
+        trait_selection_meant_str_literal,
+        applicability = "machine-applicable"
+    )]
+    MeantStrLiteral {
+        #[suggestion_part(code = "\"")]
+        start: Span,
+        #[suggestion_part(code = "\"")]
+        end: Span,
+    },
+    #[suggestion(
+        trait_selection_consider_specifying_length,
+        code = "{length}",
+        applicability = "maybe-incorrect"
+    )]
+    ConsiderSpecifyingLength {
+        #[primary_span]
+        span: Span,
+        length: u64,
+    },
+    #[note(trait_selection_try_cannot_convert)]
+    TryCannotConvert { found: String, expected: String },
+    #[suggestion(
+        trait_selection_tuple_trailing_comma,
+        code = ",",
+        applicability = "machine-applicable"
+    )]
+    TupleOnlyComma {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(
+        trait_selection_tuple_trailing_comma,
+        applicability = "machine-applicable"
+    )]
+    TupleAlsoParentheses {
+        #[suggestion_part(code = "(")]
+        span_low: Span,
+        #[suggestion_part(code = ",)")]
+        span_high: Span,
+    },
+    #[suggestion(
+        trait_selection_suggest_add_let_for_letchains,
+        style = "verbose",
+        applicability = "machine-applicable",
+        code = "let "
+    )]
+    AddLetForLetChains {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
+pub enum ObligationCauseFailureCode {
+    #[diag(trait_selection_oc_method_compat, code = E0308)]
+    MethodCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_type_compat, code = E0308)]
+    TypeCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_const_compat, code = E0308)]
+    ConstCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_try_compat, code = E0308)]
+    TryCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_match_compat, code = E0308)]
+    MatchCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_if_else_different, code = E0308)]
+    IfElseDifferent {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_no_else, code = E0317)]
+    NoElse {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(trait_selection_oc_no_diverge, code = E0308)]
+    NoDiverge {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)]
+    FnMainCorrectType {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(trait_selection_oc_fn_start_correct_type, code = E0308)]
+    FnStartCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
+    FnLangCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+        lang_item_name: Symbol,
+    },
+    #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)]
+    IntrinsicCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_method_correct_type, code = E0308)]
+    MethodCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_closure_selfref, code = E0644)]
+    ClosureSelfref {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(trait_selection_oc_cant_coerce, code = E0308)]
+    CantCoerce {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(trait_selection_oc_generic, code = E0308)]
+    Generic {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum AddPreciseCapturing {
+    #[suggestion(
+        trait_selection_precise_capturing_new,
+        style = "verbose",
+        code = " + use<{concatenated_bounds}>",
+        applicability = "machine-applicable"
+    )]
+    New {
+        #[primary_span]
+        span: Span,
+        new_lifetime: Symbol,
+        concatenated_bounds: String,
+    },
+    #[suggestion(
+        trait_selection_precise_capturing_existing,
+        style = "verbose",
+        code = "{pre}{new_lifetime}{post}",
+        applicability = "machine-applicable"
+    )]
+    Existing {
+        #[primary_span]
+        span: Span,
+        new_lifetime: Symbol,
+        pre: &'static str,
+        post: &'static str,
+    },
+}
+
+pub struct AddPreciseCapturingAndParams {
+    pub suggs: Vec<(Span, String)>,
+    pub new_lifetime: Symbol,
+    pub apit_spans: Vec<Span>,
+}
+
+impl Subdiagnostic for AddPreciseCapturingAndParams {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _f: &F,
+    ) {
+        diag.arg("new_lifetime", self.new_lifetime);
+        diag.multipart_suggestion_verbose(
+            fluent::trait_selection_precise_capturing_new_but_apit,
+            self.suggs,
+            Applicability::MaybeIncorrect,
+        );
+        diag.span_note(self.apit_spans, fluent::trait_selection_warn_removing_apit_params);
+    }
+}
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index d71b7f3c264..1f18cd8c8d8 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -173,7 +173,7 @@ impl Subdiagnostic for RegionExplanation<'_> {
         diag.arg("desc_kind", self.desc.kind);
         diag.arg("desc_arg", self.desc.arg);
 
-        let msg = f(diag, fluent::infer_region_explanation.into());
+        let msg = f(diag, fluent::trait_selection_region_explanation.into());
         if let Some(span) = self.desc.span {
             diag.span_note(span, msg);
         } else {
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index d0a12d73941..1bd66266936 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -22,11 +22,14 @@
 #![feature(control_flow_enum)]
 #![feature(extract_if)]
 #![feature(if_let_guard)]
+#![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
+#![feature(try_blocks)]
 #![feature(type_alias_impl_trait)]
 #![feature(unwrap_infallible)]
+#![feature(yeet_expr)]
 #![recursion_limit = "512"] // For rustdoc
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index ca313590265..ddaef7c159f 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,7 +1,8 @@
 use std::fmt::Debug;
 use std::marker::PhantomData;
 
-use crate::error_reporting::traits::{OverflowCause, TypeErrCtxtOverflowExt};
+use crate::error_reporting::traits::OverflowCause;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
 use rustc_data_structures::stack::ensure_sufficient_stack;
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index bdc27e734f9..49730b532a3 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -3,7 +3,7 @@ use std::fmt::Debug;
 
 use super::{FromSolverError, TraitEngine};
 use super::{FulfillmentContext, ScrubbedTraitError};
-use crate::error_reporting::traits::TypeErrCtxtExt;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::regions::InferCtxtRegionExt;
 use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
 use crate::solve::NextSolverError;
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 5597c8be592..cc0bb7a60b2 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,4 +1,3 @@
-use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
 use crate::infer::{InferCtxt, TyOrConstInferVar};
 use crate::traits::normalize::normalize_with_depth_to;
 use rustc_data_structures::captures::Captures;
@@ -25,6 +24,7 @@ use super::Unimplemented;
 use super::{const_evaluatable, ScrubbedTraitError};
 use super::{FulfillmentError, FulfillmentErrorCode};
 
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::traits::project::PolyProjectionObligation;
 use crate::traits::project::ProjectionCacheKeyExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index baec2268629..d749b686803 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -4,6 +4,7 @@ use crate::regions::InferCtxtRegionExt;
 use crate::traits::{self, FulfillmentError, ObligationCause};
 
 use hir::LangItem;
+use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -19,6 +20,8 @@ pub enum CopyImplementationError<'tcx> {
 }
 
 pub enum ConstParamTyImplementationError<'tcx> {
+    UnsizedConstParamsFeatureRequired,
+    InvalidInnerTyOfBuiltinTy(Vec<(Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
     InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
     NotAnAdtOrBuiltinAllowed,
 }
@@ -77,9 +80,9 @@ pub fn type_allowed_to_implement_copy<'tcx>(
     Ok(())
 }
 
-/// Checks that the fields of the type (an ADT) all implement `ConstParamTy`.
+/// Checks that the fields of the type (an ADT) all implement `(Unsized?)ConstParamTy`.
 ///
-/// If fields don't implement `ConstParamTy`, return an error containing a list of
+/// If fields don't implement `(Unsized?)ConstParamTy`, return an error containing a list of
 /// those violating fields.
 ///
 /// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
@@ -87,35 +90,95 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     self_type: Ty<'tcx>,
+    lang_item: LangItem,
     parent_cause: ObligationCause<'tcx>,
 ) -> Result<(), ConstParamTyImplementationError<'tcx>> {
-    let (adt, args) = match self_type.kind() {
-        // `core` provides these impls.
-        ty::Uint(_)
-        | ty::Int(_)
-        | ty::Bool
-        | ty::Char
-        | ty::Str
-        | ty::Array(..)
-        | ty::Slice(_)
-        | ty::Ref(.., hir::Mutability::Not)
-        | ty::Tuple(_) => return Ok(()),
+    assert!(matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
 
-        &ty::Adt(adt, args) => (adt, args),
+    let inner_tys: Vec<_> = match *self_type.kind() {
+        // Trivially okay as these types are all:
+        // - Sized
+        // - Contain no nested types
+        // - Have structural equality
+        ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => return Ok(()),
+
+        // Handle types gated under `feature(unsized_const_params)`
+        // FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
+        ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
+            if lang_item == LangItem::UnsizedConstParamTy =>
+        {
+            vec![inner_ty]
+        }
+        ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
+            vec![Ty::new_slice(tcx, tcx.types.u8)]
+        }
+        ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
+            return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
+        }
+
+        ty::Array(inner_ty, _) => vec![inner_ty],
+
+        // `str` morally acts like a newtype around `[u8]`
+        ty::Tuple(inner_tys) => inner_tys.into_iter().collect(),
+
+        ty::Adt(adt, args) if adt.is_enum() || adt.is_struct() => {
+            all_fields_implement_trait(
+                tcx,
+                param_env,
+                self_type,
+                adt,
+                args,
+                parent_cause.clone(),
+                lang_item,
+            )
+            .map_err(ConstParamTyImplementationError::InfrigingFields)?;
+
+            vec![]
+        }
 
         _ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
     };
 
-    all_fields_implement_trait(
-        tcx,
-        param_env,
-        self_type,
-        adt,
-        args,
-        parent_cause,
-        hir::LangItem::ConstParamTy,
-    )
-    .map_err(ConstParamTyImplementationError::InfrigingFields)?;
+    let mut infringing_inner_tys = vec![];
+    for inner_ty in inner_tys {
+        // We use an ocx per inner ty for better diagnostics
+        let infcx = tcx.infer_ctxt().build();
+        let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
+
+        ocx.register_bound(
+            parent_cause.clone(),
+            param_env,
+            inner_ty,
+            tcx.require_lang_item(lang_item, Some(parent_cause.span)),
+        );
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Fulfill(errors)));
+            continue;
+        }
+
+        // Check regions assuming the self type of the impl is WF
+        let outlives_env = OutlivesEnvironment::with_bounds(
+            param_env,
+            infcx.implied_bounds_tys(
+                param_env,
+                parent_cause.body_id,
+                &FxIndexSet::from_iter([self_type]),
+            ),
+        );
+        let errors = infcx.resolve_regions(&outlives_env);
+        if !errors.is_empty() {
+            infringing_inner_tys.push((inner_ty, InfringingFieldsReason::Regions(errors)));
+            continue;
+        }
+    }
+
+    if !infringing_inner_tys.is_empty() {
+        return Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(
+            infringing_inner_tys,
+        ));
+    }
 
     Ok(())
 }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index f7eb1730582..c57ca014799 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -22,7 +22,7 @@ mod util;
 pub mod vtable;
 pub mod wf;
 
-use crate::error_reporting::traits::TypeErrCtxtExt as _;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::regions::InferCtxtRegionExt;
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 01ba8c02ea6..26cb9bb5a3d 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -3,7 +3,7 @@
 use super::SelectionContext;
 use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
 use crate::error_reporting::traits::OverflowCause;
-use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::solve::NextSolverError;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::at::At;
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index c11e86abef8..75f1af7fcf5 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -3,7 +3,7 @@
 //! `normalize_canonicalized_projection_ty` query when it encounters projections.
 
 use crate::error_reporting::traits::OverflowCause;
-use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7a93f59f163..d6590322caa 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -18,7 +18,7 @@ use super::{
     TraitQueryMode,
 };
 
-use crate::error_reporting::traits::TypeErrCtxtOverflowExt;
+use crate::error_reporting::InferCtxtErrorExt;
 use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
 use crate::solve::InferCtxtSelectExt as _;
 use crate::traits::normalize::normalize_with_depth;
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 8f56f9c0f3e..4645d828461 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -364,7 +364,9 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
 }
 
 /// Given a `dyn Subtrait` and `dyn Supertrait` trait object, find the slot of
-/// // the trait vptr in the subtrait's vtable.
+/// the trait vptr in the subtrait's vtable.
+///
+/// A return value of `None` means that the original vtable can be reused.
 pub(crate) fn supertrait_vtable_slot<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: (
@@ -373,20 +375,22 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     ),
 ) -> Option<usize> {
     debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
-
     let (source, target) = key;
-    let ty::Dynamic(source, _, _) = *source.kind() else {
+
+    // If the target principal is `None`, we can just return `None`.
+    let ty::Dynamic(target, _, _) = *target.kind() else {
         bug!();
     };
-    let source_principal = tcx
-        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
+    let target_principal = tcx
+        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?)
         .with_self_ty(tcx, tcx.types.trait_object_dummy_self);
 
-    let ty::Dynamic(target, _, _) = *target.kind() else {
+    // Given that we have a target principal, it is a bug for there not to be a source principal.
+    let ty::Dynamic(source, _, _) = *source.kind() else {
         bug!();
     };
-    let target_principal = tcx
-        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal().unwrap())
+    let source_principal = tcx
+        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
         .with_self_ty(tcx, tcx.types.trait_object_dummy_self);
 
     let vtable_segment_callback = {
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 3ee5fd876ff..ada2c8e81de 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -7,7 +7,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtOverflowExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{
     ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
     Unimplemented,
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 2d70fdc3935..06cd6389efc 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -2,7 +2,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
-use rustc_trait_selection::error_reporting::traits::TypeErrCtxtOverflowExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{
     normalize::NormalizationResult, CanonicalAliasGoal, NoSolution,
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index f1683f5449f..1a51c95ecdf 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -65,15 +65,13 @@ impl<I: Interner> fmt::Debug for ConstKind<I> {
 
         match self {
             Param(param) => write!(f, "{param:?}"),
-            Infer(var) => write!(f, "{:?}", &var),
+            Infer(var) => write!(f, "{var:?}"),
             Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
             Placeholder(placeholder) => write!(f, "{placeholder:?}"),
-            Unevaluated(uv) => {
-                write!(f, "{:?}", &uv)
-            }
-            Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &ty),
+            Unevaluated(uv) => write!(f, "{uv:?}"),
+            Value(ty, valtree) => write!(f, "({valtree:?}: {ty:?})"),
             Error(_) => write!(f, "{{const error}}"),
-            Expr(expr) => write!(f, "{:?}", &expr),
+            Expr(expr) => write!(f, "{expr:?}"),
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 7abcc370c88..140c89af147 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -232,7 +232,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
 
             ReStatic => f.write_str("'static"),
 
-            ReVar(vid) => write!(f, "{:?}", &vid),
+            ReVar(vid) => write!(f, "{vid:?}"),
 
             RePlaceholder(placeholder) => write!(f, "{placeholder:?}"),
 
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 4ffebef9f1f..9896425a341 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -367,18 +367,16 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
             }
             Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
             Str => write!(f, "str"),
-            Array(t, c) => write!(f, "[{:?}; {:?}]", &t, &c),
-            Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &t, &p),
+            Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
+            Pat(t, p) => write!(f, "pattern_type!({t:?} is {p:?})"),
             Slice(t) => write!(f, "[{:?}]", &t),
             RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty),
             Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t),
             FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(),
-            FnPtr(s) => write!(f, "{:?}", &s),
+            FnPtr(s) => write!(f, "{s:?}"),
             Dynamic(p, r, repr) => match repr {
-                DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &p, &r),
-                DynKind::DynStar => {
-                    write!(f, "dyn* {:?} + {:?}", &p, &r)
-                }
+                DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
+                DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
             },
             Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(),
             CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(),
@@ -392,7 +390,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
                     if count > 0 {
                         write!(f, ", ")?;
                     }
-                    write!(f, "{:?}", &ty)?;
+                    write!(f, "{ty:?}")?;
                     count += 1;
                 }
                 // unary tuples need a trailing comma
@@ -1050,7 +1048,7 @@ impl<I: Interner> fmt::Debug for FnSig<I> {
             if i > 0 {
                 write!(f, ", ")?;
             }
-            write!(f, "{:?}", &ty)?;
+            write!(f, "{ty:?}")?;
         }
         if *c_variadic {
             if inputs.is_empty() {
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 83734a0d138..18ecccb4536 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -179,7 +179,7 @@ fn pretty_terminator_head<W: Write>(writer: &mut W, terminator: &TerminatorKind)
             if !expected {
                 write!(writer, "!")?;
             }
-            write!(writer, "{}, ", &pretty_operand(cond))?;
+            write!(writer, "{}, ", pretty_operand(cond))?;
             pretty_assert_message(writer, msg)?;
             write!(writer, ")")
         }
@@ -325,7 +325,7 @@ fn pretty_ty_const(ct: &TyConst) -> String {
 fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
     match rval {
         Rvalue::AddressOf(mutability, place) => {
-            write!(writer, "&raw {}(*{:?})", &pretty_mut(*mutability), place)
+            write!(writer, "&raw {}(*{:?})", pretty_mut(*mutability), place)
         }
         Rvalue::Aggregate(aggregate_kind, operands) => {
             // FIXME: Add pretty_aggregate function that returns a pretty string
@@ -336,13 +336,13 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
             write!(writer, ")")
         }
         Rvalue::BinaryOp(bin, op1, op2) => {
-            write!(writer, "{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
+            write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2))
         }
         Rvalue::Cast(_, op, ty) => {
             write!(writer, "{} as {}", pretty_operand(op), ty)
         }
         Rvalue::CheckedBinaryOp(bin, op1, op2) => {
-            write!(writer, "Checked{:?}({}, {})", bin, &pretty_operand(op1), pretty_operand(op2))
+            write!(writer, "Checked{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2))
         }
         Rvalue::CopyForDeref(deref) => {
             write!(writer, "CopyForDeref({:?})", deref)
@@ -363,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), &pretty_ty_const(cnst))
+            write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst))
         }
         Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::ThreadLocalRef(item) => {
diff --git a/config.example.toml b/config.example.toml
index a2c2fa1c2bd..26687bcfb37 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -333,6 +333,7 @@
 #    "rust-analyzer-proc-macro-srv",
 #    "analysis",
 #    "src",
+#    "wasm-component-ld",
 #]
 
 # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index f299aa0124d..405430377e5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -704,7 +704,7 @@ impl<T> Box<[T]> {
     }
 
     /// Constructs a new boxed slice with uninitialized contents. Returns an error if
-    /// the allocation fails
+    /// the allocation fails.
     ///
     /// # Examples
     ///
@@ -739,7 +739,7 @@ impl<T> Box<[T]> {
     }
 
     /// Constructs a new boxed slice with uninitialized contents, with the memory
-    /// being filled with `0` bytes. Returns an error if the allocation fails
+    /// being filled with `0` bytes. Returns an error if the allocation fails.
     ///
     /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
     /// of this method.
@@ -831,6 +831,85 @@ impl<T, A: Allocator> Box<[T], A> {
     pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> {
         unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) }
     }
+
+    /// Constructs a new boxed slice with uninitialized contents in the provided allocator. Returns an error if
+    /// the allocation fails.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let mut values = Box::<[u32], _>::try_new_uninit_slice_in(3, System)?;
+    /// let values = unsafe {
+    ///     // Deferred initialization:
+    ///     values[0].as_mut_ptr().write(1);
+    ///     values[1].as_mut_ptr().write(2);
+    ///     values[2].as_mut_ptr().write(3);
+    ///     values.assume_init()
+    /// };
+    ///
+    /// assert_eq!(*values, [1, 2, 3]);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_uninit_slice_in(
+        len: usize,
+        alloc: A,
+    ) -> Result<Box<[mem::MaybeUninit<T>], A>, AllocError> {
+        let ptr = if T::IS_ZST || len == 0 {
+            NonNull::dangling()
+        } else {
+            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
+                Ok(l) => l,
+                Err(_) => return Err(AllocError),
+            };
+            alloc.allocate(layout)?.cast()
+        };
+        unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) }
+    }
+
+    /// Constructs a new boxed slice with uninitialized contents in the provided allocator, with the memory
+    /// being filled with `0` bytes. Returns an error if the allocation fails.
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(allocator_api, new_uninit)]
+    ///
+    /// use std::alloc::System;
+    ///
+    /// let values = Box::<[u32], _>::try_new_zeroed_slice_in(3, System)?;
+    /// let values = unsafe { values.assume_init() };
+    ///
+    /// assert_eq!(*values, [0, 0, 0]);
+    /// # Ok::<(), std::alloc::AllocError>(())
+    /// ```
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    #[inline]
+    pub fn try_new_zeroed_slice_in(
+        len: usize,
+        alloc: A,
+    ) -> Result<Box<[mem::MaybeUninit<T>], A>, AllocError> {
+        let ptr = if T::IS_ZST || len == 0 {
+            NonNull::dangling()
+        } else {
+            let layout = match Layout::array::<mem::MaybeUninit<T>>(len) {
+                Ok(l) => l,
+                Err(_) => return Err(AllocError),
+            };
+            alloc.allocate_zeroed(layout)?.cast()
+        };
+        unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) }
+    }
 }
 
 impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 4ccb585862c..36fae1c1596 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -1026,7 +1026,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
 /// assert_eq!(format!("{}", value), "a");
 /// assert_eq!(format!("{:?}", value), "'a'");
 ///
-/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value));
+/// let wrapped = fmt::FormatterFn(|f| write!(f, "{value:?}"));
 /// assert_eq!(format!("{}", wrapped), "'a'");
 /// assert_eq!(format!("{:?}", wrapped), "'a'");
 /// ```
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 49f89e70255..0ec46412e95 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -165,6 +165,7 @@
 #![feature(const_unsafecell_get_mut)]
 #![feature(const_waker)]
 #![feature(coverage_attribute)]
+#![feature(do_not_recommend)]
 #![feature(duration_consts_float)]
 #![feature(internal_impls_macro)]
 #![feature(ip)]
@@ -248,6 +249,7 @@
 #![feature(transparent_unions)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
+#![feature(unsized_const_params)]
 #![feature(unsized_fn_params)]
 #![feature(with_negative_coherence)]
 // tidy-alphabetical-end
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 21abd7c036b..a87528033c0 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -975,31 +975,73 @@ pub trait PointerLike {}
 /// that all fields are also `ConstParamTy`, which implies that recursively, all fields
 /// are `StructuralPartialEq`.
 #[lang = "const_param_ty"]
-#[unstable(feature = "adt_const_params", issue = "95174")]
+#[unstable(feature = "unsized_const_params", issue = "95174")]
 #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 #[allow(multiple_supertrait_upcastable)]
-pub trait ConstParamTy: StructuralPartialEq + Eq {}
+// We name this differently than the derive macro so that the `adt_const_params` can
+// be used independently of `unsized_const_params` without requiring a full path
+// to the derive macro every time it is used. This should be renamed on stabilization.
+pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
 
 /// Derive macro generating an impl of the trait `ConstParamTy`.
 #[rustc_builtin_macro]
+#[allow_internal_unstable(unsized_const_params)]
 #[unstable(feature = "adt_const_params", issue = "95174")]
 pub macro ConstParamTy($item:item) {
     /* compiler built-in */
 }
 
+#[cfg_attr(not(bootstrap), lang = "unsized_const_param_ty")]
+#[unstable(feature = "unsized_const_params", issue = "95174")]
+#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
+/// A marker for types which can be used as types of `const` generic parameters.
+///
+/// Equivalent to [`ConstParamTy_`] except that this is used by
+/// the `unsized_const_params` to allow for fake unstable impls.
+pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
+
+/// Derive macro generating an impl of the trait `ConstParamTy`.
+#[cfg(not(bootstrap))]
+#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
+#[cfg_attr(not(bootstrap), allow_internal_unstable(unsized_const_params))]
+#[cfg_attr(not(bootstrap), unstable(feature = "unsized_const_params", issue = "95174"))]
+pub macro UnsizedConstParamTy($item:item) {
+    /* compiler built-in */
+}
+
 // FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure`
 marker_impls! {
     #[unstable(feature = "adt_const_params", issue = "95174")]
-    ConstParamTy for
+    ConstParamTy_ for
+        usize, u8, u16, u32, u64, u128,
+        isize, i8, i16, i32, i64, i128,
+        bool,
+        char,
+        (),
+        {T: ConstParamTy_, const N: usize} [T; N],
+}
+#[cfg(bootstrap)]
+marker_impls! {
+    #[unstable(feature = "adt_const_params", issue = "95174")]
+    ConstParamTy_ for
+        str,
+        {T: ConstParamTy_} [T],
+        {T: ConstParamTy_ + ?Sized} &T,
+}
+
+marker_impls! {
+    #[unstable(feature = "unsized_const_params", issue = "95174")]
+    UnsizedConstParamTy for
         usize, u8, u16, u32, u64, u128,
         isize, i8, i16, i32, i64, i128,
         bool,
         char,
-        str /* Technically requires `[u8]: ConstParamTy` */,
         (),
-        {T: ConstParamTy, const N: usize} [T; N],
-        {T: ConstParamTy} [T],
-        {T: ?Sized + ConstParamTy} &T,
+        {T: UnsizedConstParamTy, const N: usize} [T; N],
+
+        str,
+        {T: UnsizedConstParamTy} [T],
+        {T: UnsizedConstParamTy + ?Sized} &T,
 }
 
 /// A common trait implemented by all function pointers.
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index 827426b2358..ea73c5b80ba 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -1,4 +1,4 @@
-use crate::marker::ConstParamTy;
+use crate::marker::{ConstParamTy_, UnsizedConstParamTy};
 
 /// Are values of a type transmutable into values of another type?
 ///
@@ -39,7 +39,9 @@ pub struct Assume {
 }
 
 #[unstable(feature = "transmutability", issue = "99571")]
-impl ConstParamTy for Assume {}
+impl ConstParamTy_ for Assume {}
+#[unstable(feature = "transmutability", issue = "99571")]
+impl UnsizedConstParamTy for Assume {}
 
 impl Assume {
     /// Do not assume that *you* have ensured any safety properties are met.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 034af6a0d57..4e8e0ecdde9 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -3,7 +3,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::ascii;
-use crate::hint;
 use crate::intrinsics;
 use crate::mem;
 use crate::str::FromStr;
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 0c6f06dc017..d80d3241b1e 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -3,6 +3,7 @@
 use crate::cmp::Ordering;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
+use crate::hint;
 use crate::intrinsics;
 use crate::marker::{Freeze, StructuralPartialEq};
 use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
@@ -604,7 +605,6 @@ macro_rules! nonzero_integer {
             }
 
             nonzero_integer_signedness_dependent_methods! {
-                Self = $Ty,
                 Primitive = $signedness $Int,
                 UnsignedPrimitive = $Uint,
             }
@@ -823,7 +823,7 @@ macro_rules! nonzero_integer {
             }
         }
 
-        nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int);
+        nonzero_integer_signedness_dependent_impls!($signedness $Int);
     };
 
     (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
@@ -849,7 +849,7 @@ macro_rules! nonzero_integer {
 
 macro_rules! nonzero_integer_signedness_dependent_impls {
     // Impls for unsigned nonzero types only.
-    ($Ty:ident unsigned $Int:ty) => {
+    (unsigned $Int:ty) => {
         #[stable(feature = "nonzero_div", since = "1.51.0")]
         impl Div<NonZero<$Int>> for $Int {
             type Output = $Int;
@@ -897,7 +897,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
         }
     };
     // Impls for signed nonzero types only.
-    ($Ty:ident signed $Int:ty) => {
+    (signed $Int:ty) => {
         #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
         impl Neg for NonZero<$Int> {
             type Output = Self;
@@ -918,7 +918,6 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
 macro_rules! nonzero_integer_signedness_dependent_methods {
     // Associated items for unsigned nonzero types only.
     (
-        Self = $Ty:ident,
         Primitive = unsigned $Int:ident,
         UnsignedPrimitive = $Uint:ty,
     ) => {
@@ -1224,11 +1223,60 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
 
             intrinsics::ctpop(self.get()) < 2
         }
+
+        /// Returns the square root of the number, rounded down.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        /// ```
+        /// #![feature(isqrt)]
+        /// # use std::num::NonZero;
+        /// #
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let ten = NonZero::new(10", stringify!($Int), ")?;")]
+        #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ")?;")]
+        ///
+        /// assert_eq!(ten.isqrt(), three);
+        /// # Some(())
+        /// # }
+        #[unstable(feature = "isqrt", issue = "116226")]
+        #[rustc_const_unstable(feature = "isqrt", issue = "116226")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn isqrt(self) -> Self {
+            // The algorithm is based on the one presented in
+            // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)>
+            // which cites as source the following C code:
+            // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>.
+
+            let mut op = self.get();
+            let mut res = 0;
+            let mut one = 1 << (self.ilog2() & !1);
+
+            while one != 0 {
+                if op >= res + one {
+                    op -= res + one;
+                    res = (res >> 1) + one;
+                } else {
+                    res >>= 1;
+                }
+                one >>= 2;
+            }
+
+            // SAFETY: The result fits in an integer with half as many bits.
+            // Inform the optimizer about it.
+            unsafe { hint::assert_unchecked(res < 1 << (Self::BITS / 2)) };
+
+            // SAFETY: The square root of an integer >= 1 is always >= 1.
+            unsafe { Self::new_unchecked(res) }
+        }
     };
 
     // Associated items for signed nonzero types only.
     (
-        Self = $Ty:ident,
         Primitive = signed $Int:ident,
         UnsignedPrimitive = $Uint:ty,
     ) => {
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index ad72c29758b..d50bcde0157 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1226,10 +1226,9 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_ilog2(self) -> Option<u32> {
-            if let Some(x) = NonZero::new(self) {
-                Some(x.ilog2())
-            } else {
-                None
+            match NonZero::new(self) {
+                Some(x) => Some(x.ilog2()),
+                None => None,
             }
         }
 
@@ -1248,10 +1247,9 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_ilog10(self) -> Option<u32> {
-            if let Some(x) = NonZero::new(self) {
-                Some(x.ilog10())
-            } else {
-                None
+            match NonZero::new(self) {
+                Some(x) => Some(x.ilog10()),
+                None => None,
             }
         }
 
@@ -2590,37 +2588,10 @@ macro_rules! uint_impl {
                       without modifying the original"]
         #[inline]
         pub const fn isqrt(self) -> Self {
-            if self < 2 {
-                return self;
-            }
-
-            // The algorithm is based on the one presented in
-            // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)>
-            // which cites as source the following C code:
-            // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>.
-
-            let mut op = self;
-            let mut res = 0;
-            let mut one = 1 << (self.ilog2() & !1);
-
-            while one != 0 {
-                if op >= res + one {
-                    op -= res + one;
-                    res = (res >> 1) + one;
-                } else {
-                    res >>= 1;
-                }
-                one >>= 2;
+            match NonZero::new(self) {
+                Some(x) => x.isqrt().get(),
+                None => 0,
             }
-
-            // SAFETY: the result is positive and fits in an integer with half as many bits.
-            // Inform the optimizer about it.
-            unsafe {
-                hint::assert_unchecked(0 < res);
-                hint::assert_unchecked(res < 1 << (Self::BITS / 2));
-            }
-
-            res
         }
 
         /// Performs Euclidean division.
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 1a8fe1e6051..d93cb8d10e6 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -2507,6 +2507,7 @@ impl<T> ops::FromResidual for Option<T> {
     }
 }
 
+#[diagnostic::do_not_recommend]
 #[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
 impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> {
     #[inline]
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index f8cdcc000c5..7f278296b7b 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1990,7 +1990,7 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Res
         }
     }
 }
-
+#[diagnostic::do_not_recommend]
 #[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
 impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
     #[inline]
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 8e961d8adc3..bc376b13f64 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -1,8 +1,9 @@
 // See core/src/primitive_docs.rs for documentation.
 
 use crate::cmp::Ordering::{self, *};
-use crate::marker::ConstParamTy;
+use crate::marker::ConstParamTy_;
 use crate::marker::StructuralPartialEq;
+use crate::marker::UnsizedConstParamTy;
 
 // Recursive macro for implementing n-ary tuple functions and operations
 //
@@ -49,8 +50,15 @@ macro_rules! tuple_impls {
 
         maybe_tuple_doc! {
             $($T)+ @
-            #[unstable(feature = "structural_match", issue = "31434")]
-            impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+)
+            #[unstable(feature = "adt_const_params", issue = "95174")]
+            impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+)
+            {}
+        }
+
+        maybe_tuple_doc! {
+            $($T)+ @
+            #[unstable(feature = "unsized_const_params", issue = "95174")]
+            impl<$($T: UnsizedConstParamTy),+> UnsizedConstParamTy for ($($T,)+)
             {}
         }
 
diff --git a/library/core/tests/future.rs b/library/core/tests/future.rs
index db417256dd0..93aca72d590 100644
--- a/library/core/tests/future.rs
+++ b/library/core/tests/future.rs
@@ -56,7 +56,7 @@ fn test_join() {
 
         let y = String::new();
         let x = join!(async {
-            println!("{}", &y);
+            println!("{y}");
             1
         })
         .await;
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 04c3d3bf9c3..82c248c5a7b 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -157,7 +157,10 @@ mod imp {
             // going to be cross-lang LTOed anyway. However, using expose is shorter and
             // requires less unsafe.
             let addr: usize = ptr.expose_provenance();
+            #[cfg(bootstrap)]
             let image_base = unsafe { addr_of!(__ImageBase) }.addr();
+            #[cfg(not(bootstrap))]
+            let image_base = addr_of!(__ImageBase).addr();
             let offset: usize = addr - image_base;
             Self(offset as u32)
         }
@@ -250,7 +253,10 @@ extern "C" {
 // This is fine since the MSVC runtime uses string comparison on the type name
 // to match TypeDescriptors rather than pointer equality.
 static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
+    #[cfg(bootstrap)]
     pVFTable: unsafe { addr_of!(TYPE_INFO_VTABLE) } as *const _,
+    #[cfg(not(bootstrap))]
+    pVFTable: addr_of!(TYPE_INFO_VTABLE) as *const _,
     spare: core::ptr::null_mut(),
     name: TYPE_NAME,
 };
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 581d7e3efe3..57247359fbf 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -1544,10 +1544,10 @@ impl fmt::Debug for Literal {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("Literal")
             // format the kind on one line even in {:#?} mode
-            .field("kind", &format_args!("{:?}", &self.0.kind))
+            .field("kind", &format_args!("{:?}", self.0.kind))
             .field("symbol", &self.0.symbol)
             // format `Some("...")` on one line even in {:#?} mode
-            .field("suffix", &format_args!("{:?}", &self.0.suffix))
+            .field("suffix", &format_args!("{:?}", self.0.suffix))
             .field("span", &self.0.span)
             .finish()
     }
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index b991b1cf22d..3db2f113860 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -56,7 +56,7 @@ hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true
 wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
 
 [target.'cfg(target_os = "uefi")'.dependencies]
-r-efi = { version = "4.2.0", features = ['rustc-dep-of-std'] }
+r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
 r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }
 
 [features]
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 5ca631399aa..c1fc2e5488d 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -683,7 +683,7 @@ fn recursive_rmdir_toctou() {
     let drop_canary_arc = Arc::new(());
     let drop_canary_weak = Arc::downgrade(&drop_canary_arc);
 
-    eprintln!("x: {:?}", &victim_del_path);
+    eprintln!("x: {victim_del_path:?}");
 
     // victim just continuously removes `victim_del`
     thread::spawn(move || {
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index f366cb8f42b..8de27367a3f 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -775,7 +775,7 @@ impl Error {
     ///
     /// impl Display for MyError {
     ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "MyError: {}", &self.v)
+    ///         write!(f, "MyError: {}", self.v)
     ///     }
     /// }
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f0a73a308a4..eb30a3355e5 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -293,6 +293,7 @@
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(dropck_eyepatch)]
+#![feature(extended_varargs_abi_support)]
 #![feature(f128)]
 #![feature(f16)]
 #![feature(if_let_guard)]
diff --git a/library/std/src/os/horizon/mod.rs b/library/std/src/os/horizon/mod.rs
index 326d0ae9cb9..14ce409f42c 100644
--- a/library/std/src/os/horizon/mod.rs
+++ b/library/std/src/os/horizon/mod.rs
@@ -1,5 +1,6 @@
 //! Definitions for Horizon OS
 
+#![forbid(unsafe_op_in_unsafe_fn)]
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;
diff --git a/library/std/src/os/horizon/raw.rs b/library/std/src/os/horizon/raw.rs
index 929fa7db1f9..e5368ea265a 100644
--- a/library/std/src/os/horizon/raw.rs
+++ b/library/std/src/os/horizon/raw.rs
@@ -38,6 +38,7 @@ pub type time_t = libc::time_t;
 #[repr(C)]
 #[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
+#[allow(dead_code)] // This exists for parity with other `raw` modules, but isn't actually used.
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_dev: dev_t,
diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs
index 19b4fe22093..e75bcf74e5c 100644
--- a/library/std/src/os/solid/io.rs
+++ b/library/std/src/os/solid/io.rs
@@ -44,7 +44,6 @@
 //!
 //! [`BorrowedFd<'a>`]: crate::os::solid::io::BorrowedFd
 
-#![deny(unsafe_op_in_unsafe_fn)]
 #![unstable(feature = "solid_ext", issue = "none")]
 
 use crate::fmt;
diff --git a/library/std/src/os/solid/mod.rs b/library/std/src/os/solid/mod.rs
index 0bb83c73ddf..75824048e24 100644
--- a/library/std/src/os/solid/mod.rs
+++ b/library/std/src/os/solid/mod.rs
@@ -1,4 +1,5 @@
 #![stable(feature = "rust1", since = "1.0.0")]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 pub mod ffi;
 pub mod io;
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index 27947d91c99..7cac8c39ea8 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -471,6 +471,13 @@ pub trait MetadataExt {
     /// `fs::metadata` or `File::metadata`, then this will return `Some`.
     #[unstable(feature = "windows_by_handle", issue = "63010")]
     fn file_index(&self) -> Option<u64>;
+
+    /// Returns the change time, which is the last time file metadata was changed, such as
+    /// renames, attributes, etc
+    ///
+    /// This will return `None` if the `Metadata` instance was not created using the `FILE_BASIC_INFO` type.
+    #[unstable(feature = "windows_change_time", issue = "121478")]
+    fn change_time(&self) -> Option<u64>;
 }
 
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -499,6 +506,9 @@ impl MetadataExt for Metadata {
     fn file_index(&self) -> Option<u64> {
         self.as_inner().file_index()
     }
+    fn change_time(&self) -> Option<u64> {
+        self.as_inner().changed_u64()
+    }
 }
 
 /// Windows-specific extensions to [`fs::FileType`].
diff --git a/library/std/src/sys/backtrace.rs b/library/std/src/sys/backtrace.rs
index 7401d8ce320..133ea520e30 100644
--- a/library/std/src/sys/backtrace.rs
+++ b/library/std/src/sys/backtrace.rs
@@ -1,4 +1,5 @@
 //! Common code for printing backtraces.
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
 use crate::borrow::Cow;
@@ -62,73 +63,76 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
     // Start immediately if we're not using a short backtrace.
     let mut start = print_fmt != PrintFmt::Short;
     set_image_base();
-    backtrace_rs::trace_unsynchronized(|frame| {
-        if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
-            return false;
-        }
+    // SAFETY: we roll our own locking in this town
+    unsafe {
+        backtrace_rs::trace_unsynchronized(|frame| {
+            if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
+                return false;
+            }
 
-        let mut hit = false;
-        backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
-            hit = true;
-
-            // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
-            // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
-            // called before the panic hook, so we won't ignore any frames if there is no
-            // invoke of `__rust_begin_short_backtrace`.
-            if print_fmt == PrintFmt::Short {
-                if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
-                    if start && sym.contains("__rust_begin_short_backtrace") {
-                        start = false;
-                        return;
-                    }
-                    if sym.contains("__rust_end_short_backtrace") {
-                        start = true;
-                        return;
-                    }
-                    if !start {
-                        omitted_count += 1;
+            let mut hit = false;
+            backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
+                hit = true;
+
+                // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
+                // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
+                // called before the panic hook, so we won't ignore any frames if there is no
+                // invoke of `__rust_begin_short_backtrace`.
+                if print_fmt == PrintFmt::Short {
+                    if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
+                        if start && sym.contains("__rust_begin_short_backtrace") {
+                            start = false;
+                            return;
+                        }
+                        if sym.contains("__rust_end_short_backtrace") {
+                            start = true;
+                            return;
+                        }
+                        if !start {
+                            omitted_count += 1;
+                        }
                     }
                 }
-            }
 
-            if start {
-                if omitted_count > 0 {
-                    debug_assert!(print_fmt == PrintFmt::Short);
-                    // only print the message between the middle of frames
-                    if !first_omit {
-                        let _ = writeln!(
-                            bt_fmt.formatter(),
-                            "      [... omitted {} frame{} ...]",
-                            omitted_count,
-                            if omitted_count > 1 { "s" } else { "" }
-                        );
+                if start {
+                    if omitted_count > 0 {
+                        debug_assert!(print_fmt == PrintFmt::Short);
+                        // only print the message between the middle of frames
+                        if !first_omit {
+                            let _ = writeln!(
+                                bt_fmt.formatter(),
+                                "      [... omitted {} frame{} ...]",
+                                omitted_count,
+                                if omitted_count > 1 { "s" } else { "" }
+                            );
+                        }
+                        first_omit = false;
+                        omitted_count = 0;
                     }
-                    first_omit = false;
-                    omitted_count = 0;
+                    res = bt_fmt.frame().symbol(frame, symbol);
                 }
-                res = bt_fmt.frame().symbol(frame, symbol);
+            });
+            #[cfg(target_os = "nto")]
+            if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
+                if !hit && start {
+                    use crate::backtrace_rs::SymbolName;
+                    res = bt_fmt.frame().print_raw(
+                        frame.ip(),
+                        Some(SymbolName::new("__my_thread_exit".as_bytes())),
+                        None,
+                        None,
+                    );
+                }
+                return false;
             }
-        });
-        #[cfg(target_os = "nto")]
-        if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
             if !hit && start {
-                use crate::backtrace_rs::SymbolName;
-                res = bt_fmt.frame().print_raw(
-                    frame.ip(),
-                    Some(SymbolName::new("__my_thread_exit".as_bytes())),
-                    None,
-                    None,
-                );
+                res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
             }
-            return false;
-        }
-        if !hit && start {
-            res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
-        }
 
-        idx += 1;
-        res.is_ok()
-    });
+            idx += 1;
+            res.is_ok()
+        })
+    };
     res?;
     bt_fmt.finish()?;
     if print_fmt == PrintFmt::Short {
diff --git a/library/std/src/sys/pal/common/alloc.rs b/library/std/src/sys/pal/common/alloc.rs
index 598b6db71f5..54506c32296 100644
--- a/library/std/src/sys/pal/common/alloc.rs
+++ b/library/std/src/sys/pal/common/alloc.rs
@@ -1,3 +1,4 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::cmp;
 use crate::ptr;
@@ -46,14 +47,16 @@ pub unsafe fn realloc_fallback(
     old_layout: Layout,
     new_size: usize,
 ) -> *mut u8 {
-    // Docs for GlobalAlloc::realloc require this to be valid:
-    let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
+    // SAFETY: Docs for GlobalAlloc::realloc require this to be valid
+    unsafe {
+        let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
 
-    let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
-    if !new_ptr.is_null() {
-        let size = cmp::min(old_layout.size(), new_size);
-        ptr::copy_nonoverlapping(ptr, new_ptr, size);
-        GlobalAlloc::dealloc(alloc, ptr, old_layout);
+        let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
+        if !new_ptr.is_null() {
+            let size = cmp::min(old_layout.size(), new_size);
+            ptr::copy_nonoverlapping(ptr, new_ptr, size);
+            GlobalAlloc::dealloc(alloc, ptr, old_layout);
+        }
+        new_ptr
     }
-    new_ptr
 }
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 9a7741ddda7..0b158fb63df 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -1,6 +1,6 @@
 #![allow(dead_code)]
 #![allow(missing_docs, nonstandard_style)]
-#![deny(unsafe_op_in_unsafe_fn)]
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 pub mod abi;
 
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 23aa4da14a7..29984a915b8 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -12,15 +12,21 @@
 use r_efi::efi::{self, Guid};
 use r_efi::protocols::{device_path, device_path_to_text};
 
-use crate::ffi::OsString;
+use crate::ffi::{OsStr, OsString};
 use crate::io::{self, const_io_error};
 use crate::mem::{size_of, MaybeUninit};
-use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
+use crate::os::uefi::{self, env::boot_services, ffi::OsStrExt, ffi::OsStringExt};
 use crate::ptr::NonNull;
 use crate::slice;
 use crate::sync::atomic::{AtomicPtr, Ordering};
 use crate::sys_common::wstr::WStrUnits;
 
+type BootInstallMultipleProtocolInterfaces =
+    unsafe extern "efiapi" fn(_: *mut r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
+
+type BootUninstallMultipleProtocolInterfaces =
+    unsafe extern "efiapi" fn(_: r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
+
 const BOOT_SERVICES_UNAVAILABLE: io::Error =
     const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
 
@@ -221,3 +227,192 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
     let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
     NonNull::new(runtime_services)
 }
+
+pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);
+
+impl DevicePath {
+    pub(crate) fn from_text(p: &OsStr) -> io::Result<Self> {
+        fn inner(
+            p: &OsStr,
+            protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
+        ) -> io::Result<DevicePath> {
+            let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec<u16>>();
+            if path_vec[..path_vec.len() - 1].contains(&0) {
+                return Err(const_io_error!(
+                    io::ErrorKind::InvalidInput,
+                    "strings passed to UEFI cannot contain NULs",
+                ));
+            }
+
+            let path =
+                unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
+
+            NonNull::new(path).map(DevicePath).ok_or_else(|| {
+                const_io_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path")
+            })
+        }
+
+        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+            AtomicPtr::new(crate::ptr::null_mut());
+
+        if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
+            if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
+                handle,
+                r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
+            ) {
+                return inner(p, protocol);
+            }
+        }
+
+        let handles = locate_handles(r_efi::protocols::device_path_from_text::PROTOCOL_GUID)?;
+        for handle in handles {
+            if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
+                handle,
+                r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
+            ) {
+                LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
+                return inner(p, protocol);
+            }
+        }
+
+        io::Result::Err(const_io_error!(
+            io::ErrorKind::NotFound,
+            "DevicePathFromText Protocol not found"
+        ))
+    }
+
+    pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
+        self.0.as_ptr()
+    }
+}
+
+impl Drop for DevicePath {
+    fn drop(&mut self) {
+        if let Some(bt) = boot_services() {
+            let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
+            unsafe {
+                ((*bt.as_ptr()).free_pool)(self.0.as_ptr() as *mut crate::ffi::c_void);
+            }
+        }
+    }
+}
+
+pub(crate) struct OwnedProtocol<T> {
+    guid: r_efi::efi::Guid,
+    handle: NonNull<crate::ffi::c_void>,
+    protocol: *mut T,
+}
+
+impl<T> OwnedProtocol<T> {
+    // FIXME: Consider using unsafe trait for matching protocol with guid
+    pub(crate) unsafe fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
+        let bt: NonNull<r_efi::efi::BootServices> =
+            boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
+        let protocol: *mut T = Box::into_raw(Box::new(protocol));
+        let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
+
+        // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
+        let func: BootInstallMultipleProtocolInterfaces =
+            unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };
+
+        let r = unsafe {
+            func(
+                &mut handle,
+                &mut guid as *mut _ as *mut crate::ffi::c_void,
+                protocol as *mut crate::ffi::c_void,
+                crate::ptr::null_mut() as *mut crate::ffi::c_void,
+            )
+        };
+
+        if r.is_error() {
+            drop(unsafe { Box::from_raw(protocol) });
+            return Err(crate::io::Error::from_raw_os_error(r.as_usize()));
+        };
+
+        let handle = NonNull::new(handle)
+            .ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;
+
+        Ok(Self { guid, handle, protocol })
+    }
+
+    pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
+        self.handle
+    }
+}
+
+impl<T> Drop for OwnedProtocol<T> {
+    fn drop(&mut self) {
+        // Do not deallocate a runtime protocol
+        if let Some(bt) = boot_services() {
+            let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
+            // FIXME: Move into r-efi once extended_varargs_abi_support is stablized
+            let func: BootUninstallMultipleProtocolInterfaces = unsafe {
+                crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)
+            };
+            let status = unsafe {
+                func(
+                    self.handle.as_ptr(),
+                    &mut self.guid as *mut _ as *mut crate::ffi::c_void,
+                    self.protocol as *mut crate::ffi::c_void,
+                    crate::ptr::null_mut() as *mut crate::ffi::c_void,
+                )
+            };
+
+            // Leak the protocol in case uninstall fails
+            if status == r_efi::efi::Status::SUCCESS {
+                let _ = unsafe { Box::from_raw(self.protocol) };
+            }
+        }
+    }
+}
+
+impl<T> AsRef<T> for OwnedProtocol<T> {
+    fn as_ref(&self) -> &T {
+        unsafe { self.protocol.as_ref().unwrap() }
+    }
+}
+
+pub(crate) struct OwnedTable<T> {
+    layout: crate::alloc::Layout,
+    ptr: *mut T,
+}
+
+impl<T> OwnedTable<T> {
+    pub(crate) fn from_table_header(hdr: &r_efi::efi::TableHeader) -> Self {
+        let header_size = hdr.header_size as usize;
+        let layout = crate::alloc::Layout::from_size_align(header_size, 8).unwrap();
+        let ptr = unsafe { crate::alloc::alloc(layout) as *mut T };
+        Self { layout, ptr }
+    }
+
+    pub(crate) const fn as_ptr(&self) -> *const T {
+        self.ptr
+    }
+
+    pub(crate) const fn as_mut_ptr(&self) -> *mut T {
+        self.ptr
+    }
+}
+
+impl OwnedTable<r_efi::efi::SystemTable> {
+    pub(crate) fn from_table(tbl: *const r_efi::efi::SystemTable) -> Self {
+        let hdr = unsafe { (*tbl).hdr };
+
+        let owned_tbl = Self::from_table_header(&hdr);
+        unsafe {
+            crate::ptr::copy_nonoverlapping(
+                tbl as *const u8,
+                owned_tbl.as_mut_ptr() as *mut u8,
+                hdr.header_size as usize,
+            )
+        };
+
+        owned_tbl
+    }
+}
+
+impl<T> Drop for OwnedTable<T> {
+    fn drop(&mut self) {
+        unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
+    }
+}
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 4d50d9e8c3d..c54e9477bfc 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -25,7 +25,6 @@ pub mod net;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod stdio;
 pub mod thread;
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs
new file mode 100644
index 00000000000..5c7c8415ee2
--- /dev/null
+++ b/library/std/src/sys/pal/uefi/process.rs
@@ -0,0 +1,689 @@
+use r_efi::protocols::simple_text_output;
+
+use crate::ffi::OsStr;
+use crate::ffi::OsString;
+use crate::fmt;
+use crate::io;
+use crate::num::NonZero;
+use crate::num::NonZeroI32;
+use crate::path::Path;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::unsupported;
+use crate::sys_common::process::{CommandEnv, CommandEnvs};
+
+pub use crate::ffi::OsString as EnvKey;
+
+use super::helpers;
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+#[derive(Debug)]
+pub struct Command {
+    prog: OsString,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+}
+
+impl Command {
+    pub fn new(program: &OsStr) -> Command {
+        Command { prog: program.to_os_string(), stdout: None, stderr: None }
+    }
+
+    // FIXME: Implement arguments as reverse of parsing algorithm
+    pub fn arg(&mut self, _arg: &OsStr) {
+        panic!("unsupported")
+    }
+
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
+        panic!("unsupported")
+    }
+
+    pub fn cwd(&mut self, _dir: &OsStr) {
+        panic!("unsupported")
+    }
+
+    pub fn stdin(&mut self, _stdin: Stdio) {
+        panic!("unsupported")
+    }
+
+    pub fn stdout(&mut self, stdout: Stdio) {
+        self.stdout = Some(stdout);
+    }
+
+    pub fn stderr(&mut self, stderr: Stdio) {
+        self.stderr = Some(stderr);
+    }
+
+    pub fn get_program(&self) -> &OsStr {
+        self.prog.as_ref()
+    }
+
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        panic!("unsupported")
+    }
+
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        panic!("unsupported")
+    }
+
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        None
+    }
+
+    pub fn spawn(
+        &mut self,
+        _default: Stdio,
+        _needs_stdin: bool,
+    ) -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+
+    fn create_pipe(
+        s: Stdio,
+    ) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::PipeProtocol>>> {
+        match s {
+            Stdio::MakePipe => unsafe {
+                helpers::OwnedProtocol::create(
+                    uefi_command_internal::PipeProtocol::new(),
+                    simple_text_output::PROTOCOL_GUID,
+                )
+            }
+            .map(Some),
+            Stdio::Null => unsafe {
+                helpers::OwnedProtocol::create(
+                    uefi_command_internal::PipeProtocol::null(),
+                    simple_text_output::PROTOCOL_GUID,
+                )
+            }
+            .map(Some),
+            Stdio::Inherit => Ok(None),
+        }
+    }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;
+
+        // Setup Stdout
+        let stdout = self.stdout.unwrap_or(Stdio::MakePipe);
+        let stdout = Self::create_pipe(stdout)?;
+        if let Some(con) = stdout {
+            cmd.stdout_init(con)
+        } else {
+            cmd.stdout_inherit()
+        };
+
+        // Setup Stderr
+        let stderr = self.stderr.unwrap_or(Stdio::MakePipe);
+        let stderr = Self::create_pipe(stderr)?;
+        if let Some(con) = stderr {
+            cmd.stderr_init(con)
+        } else {
+            cmd.stderr_inherit()
+        };
+
+        let stat = cmd.start_image()?;
+
+        let stdout = cmd.stdout()?;
+        let stderr = cmd.stderr()?;
+
+        Ok((ExitStatus(stat), stdout, stderr))
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        pipe.diverge()
+    }
+}
+
+impl From<io::Stdout> for Stdio {
+    fn from(_: io::Stdout) -> Stdio {
+        // FIXME: This is wrong.
+        // Instead, the Stdio we have here should be a unit struct.
+        panic!("unsupported")
+    }
+}
+
+impl From<io::Stderr> for Stdio {
+    fn from(_: io::Stderr) -> Stdio {
+        // FIXME: This is wrong.
+        // Instead, the Stdio we have here should be a unit struct.
+        panic!("unsupported")
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(_file: File) -> Stdio {
+        // FIXME: This is wrong.
+        // Instead, the Stdio we have here should be a unit struct.
+        panic!("unsupported")
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[non_exhaustive]
+pub struct ExitStatus(r_efi::efi::Status);
+
+impl ExitStatus {
+    pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
+        if self.0 == r_efi::efi::Status::SUCCESS { Ok(()) } else { Err(ExitStatusError(self.0)) }
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        Some(self.0.as_usize() as i32)
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let err_str = super::os::error_string(self.0.as_usize());
+        write!(f, "{}", err_str)
+    }
+}
+
+impl Default for ExitStatus {
+    fn default() -> Self {
+        ExitStatus(r_efi::efi::Status::SUCCESS)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct ExitStatusError(r_efi::efi::Status);
+
+impl fmt::Debug for ExitStatusError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let err_str = super::os::error_string(self.0.as_usize());
+        write!(f, "{}", err_str)
+    }
+}
+
+impl Into<ExitStatus> for ExitStatusError {
+    fn into(self) -> ExitStatus {
+        ExitStatus(self.0)
+    }
+}
+
+impl ExitStatusError {
+    pub fn code(self) -> Option<NonZero<i32>> {
+        NonZeroI32::new(self.0.as_usize() as i32)
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(bool);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(false);
+    pub const FAILURE: ExitCode = ExitCode(true);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
+impl From<u8> for ExitCode {
+    fn from(code: u8) -> Self {
+        match code {
+            0 => Self::SUCCESS,
+            1..=255 => Self::FAILURE,
+        }
+    }
+}
+
+pub struct Process(!);
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        self.0
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        self.0
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        self.0
+    }
+}
+
+pub struct CommandArgs<'a> {
+    iter: crate::slice::Iter<'a, OsString>,
+}
+
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+
+    fn next(&mut self) -> Option<&'a OsStr> {
+        self.iter.next().map(|x| x.as_ref())
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+impl<'a> fmt::Debug for CommandArgs<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter.clone()).finish()
+    }
+}
+
+#[allow(dead_code)]
+mod uefi_command_internal {
+    use r_efi::protocols::{loaded_image, simple_text_output};
+
+    use super::super::helpers;
+    use crate::ffi::{OsStr, OsString};
+    use crate::io::{self, const_io_error};
+    use crate::mem::MaybeUninit;
+    use crate::os::uefi::env::{boot_services, image_handle, system_table};
+    use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
+    use crate::ptr::NonNull;
+    use crate::slice;
+    use crate::sys::pal::uefi::helpers::OwnedTable;
+    use crate::sys_common::wstr::WStrUnits;
+
+    pub struct Image {
+        handle: NonNull<crate::ffi::c_void>,
+        stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
+        stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
+        st: OwnedTable<r_efi::efi::SystemTable>,
+        args: Option<Vec<u16>>,
+    }
+
+    impl Image {
+        pub fn load_image(p: &OsStr) -> io::Result<Self> {
+            let path = helpers::DevicePath::from_text(p)?;
+            let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
+                .ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
+                .cast();
+            let mut child_handle: MaybeUninit<r_efi::efi::Handle> = MaybeUninit::uninit();
+            let image_handle = image_handle();
+
+            let r = unsafe {
+                ((*boot_services.as_ptr()).load_image)(
+                    r_efi::efi::Boolean::FALSE,
+                    image_handle.as_ptr(),
+                    path.as_ptr(),
+                    crate::ptr::null_mut(),
+                    0,
+                    child_handle.as_mut_ptr(),
+                )
+            };
+
+            if r.is_error() {
+                Err(io::Error::from_raw_os_error(r.as_usize()))
+            } else {
+                let child_handle = unsafe { child_handle.assume_init() };
+                let child_handle = NonNull::new(child_handle).unwrap();
+
+                let loaded_image: NonNull<loaded_image::Protocol> =
+                    helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();
+                let st = OwnedTable::from_table(unsafe { (*loaded_image.as_ptr()).system_table });
+
+                Ok(Self { handle: child_handle, stdout: None, stderr: None, st, args: None })
+            }
+        }
+
+        pub fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
+            self.update_st_crc32()?;
+
+            // Use our system table instead of the default one
+            let loaded_image: NonNull<loaded_image::Protocol> =
+                helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
+            unsafe {
+                (*loaded_image.as_ptr()).system_table = self.st.as_mut_ptr();
+            }
+
+            let boot_services: NonNull<r_efi::efi::BootServices> = boot_services()
+                .ok_or_else(|| const_io_error!(io::ErrorKind::NotFound, "Boot Services not found"))?
+                .cast();
+            let mut exit_data_size: usize = 0;
+            let mut exit_data: MaybeUninit<*mut u16> = MaybeUninit::uninit();
+
+            let r = unsafe {
+                ((*boot_services.as_ptr()).start_image)(
+                    self.handle.as_ptr(),
+                    &mut exit_data_size,
+                    exit_data.as_mut_ptr(),
+                )
+            };
+
+            // Drop exitdata
+            if exit_data_size != 0 {
+                unsafe {
+                    let exit_data = exit_data.assume_init();
+                    ((*boot_services.as_ptr()).free_pool)(exit_data as *mut crate::ffi::c_void);
+                }
+            }
+
+            Ok(r)
+        }
+
+        fn set_stdout(
+            &mut self,
+            handle: r_efi::efi::Handle,
+            protocol: *mut simple_text_output::Protocol,
+        ) {
+            unsafe {
+                (*self.st.as_mut_ptr()).console_out_handle = handle;
+                (*self.st.as_mut_ptr()).con_out = protocol;
+            }
+        }
+
+        fn set_stderr(
+            &mut self,
+            handle: r_efi::efi::Handle,
+            protocol: *mut simple_text_output::Protocol,
+        ) {
+            unsafe {
+                (*self.st.as_mut_ptr()).standard_error_handle = handle;
+                (*self.st.as_mut_ptr()).std_err = protocol;
+            }
+        }
+
+        pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
+            self.set_stdout(
+                protocol.handle().as_ptr(),
+                protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol,
+            );
+            self.stdout = Some(protocol);
+        }
+
+        pub fn stdout_inherit(&mut self) {
+            let st: NonNull<r_efi::efi::SystemTable> = system_table().cast();
+            unsafe { self.set_stdout((*st.as_ptr()).console_out_handle, (*st.as_ptr()).con_out) }
+        }
+
+        pub fn stderr_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
+            self.set_stderr(
+                protocol.handle().as_ptr(),
+                protocol.as_ref() as *const PipeProtocol as *mut simple_text_output::Protocol,
+            );
+            self.stderr = Some(protocol);
+        }
+
+        pub fn stderr_inherit(&mut self) {
+            let st: NonNull<r_efi::efi::SystemTable> = system_table().cast();
+            unsafe { self.set_stderr((*st.as_ptr()).standard_error_handle, (*st.as_ptr()).std_err) }
+        }
+
+        pub fn stderr(&self) -> io::Result<Vec<u8>> {
+            match &self.stderr {
+                Some(stderr) => stderr.as_ref().utf8(),
+                None => Ok(Vec::new()),
+            }
+        }
+
+        pub fn stdout(&self) -> io::Result<Vec<u8>> {
+            match &self.stdout {
+                Some(stdout) => stdout.as_ref().utf8(),
+                None => Ok(Vec::new()),
+            }
+        }
+
+        pub fn set_args(&mut self, args: &OsStr) {
+            let loaded_image: NonNull<loaded_image::Protocol> =
+                helpers::open_protocol(self.handle, loaded_image::PROTOCOL_GUID).unwrap();
+
+            let mut args = args.encode_wide().collect::<Vec<u16>>();
+            let args_size = (crate::mem::size_of::<u16>() * args.len()) as u32;
+
+            unsafe {
+                (*loaded_image.as_ptr()).load_options =
+                    args.as_mut_ptr() as *mut crate::ffi::c_void;
+                (*loaded_image.as_ptr()).load_options_size = args_size;
+            }
+
+            self.args = Some(args);
+        }
+
+        fn update_st_crc32(&mut self) -> io::Result<()> {
+            let bt: NonNull<r_efi::efi::BootServices> = boot_services().unwrap().cast();
+            let st_size = unsafe { (*self.st.as_ptr()).hdr.header_size as usize };
+            let mut crc32: u32 = 0;
+
+            // Set crc to 0 before calcuation
+            unsafe {
+                (*self.st.as_mut_ptr()).hdr.crc32 = 0;
+            }
+
+            let r = unsafe {
+                ((*bt.as_ptr()).calculate_crc32)(
+                    self.st.as_mut_ptr() as *mut crate::ffi::c_void,
+                    st_size,
+                    &mut crc32,
+                )
+            };
+
+            if r.is_error() {
+                Err(io::Error::from_raw_os_error(r.as_usize()))
+            } else {
+                unsafe {
+                    (*self.st.as_mut_ptr()).hdr.crc32 = crc32;
+                }
+                Ok(())
+            }
+        }
+    }
+
+    impl Drop for Image {
+        fn drop(&mut self) {
+            if let Some(bt) = boot_services() {
+                let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
+                unsafe {
+                    ((*bt.as_ptr()).unload_image)(self.handle.as_ptr());
+                }
+            }
+        }
+    }
+
+    #[repr(C)]
+    pub struct PipeProtocol {
+        reset: simple_text_output::ProtocolReset,
+        output_string: simple_text_output::ProtocolOutputString,
+        test_string: simple_text_output::ProtocolTestString,
+        query_mode: simple_text_output::ProtocolQueryMode,
+        set_mode: simple_text_output::ProtocolSetMode,
+        set_attribute: simple_text_output::ProtocolSetAttribute,
+        clear_screen: simple_text_output::ProtocolClearScreen,
+        set_cursor_position: simple_text_output::ProtocolSetCursorPosition,
+        enable_cursor: simple_text_output::ProtocolEnableCursor,
+        mode: *mut simple_text_output::Mode,
+        _buffer: Vec<u16>,
+    }
+
+    impl PipeProtocol {
+        pub fn new() -> Self {
+            let mode = Box::new(simple_text_output::Mode {
+                max_mode: 0,
+                mode: 0,
+                attribute: 0,
+                cursor_column: 0,
+                cursor_row: 0,
+                cursor_visible: r_efi::efi::Boolean::FALSE,
+            });
+            Self {
+                reset: Self::reset,
+                output_string: Self::output_string,
+                test_string: Self::test_string,
+                query_mode: Self::query_mode,
+                set_mode: Self::set_mode,
+                set_attribute: Self::set_attribute,
+                clear_screen: Self::clear_screen,
+                set_cursor_position: Self::set_cursor_position,
+                enable_cursor: Self::enable_cursor,
+                mode: Box::into_raw(mode),
+                _buffer: Vec::new(),
+            }
+        }
+
+        pub fn null() -> Self {
+            let mode = Box::new(simple_text_output::Mode {
+                max_mode: 0,
+                mode: 0,
+                attribute: 0,
+                cursor_column: 0,
+                cursor_row: 0,
+                cursor_visible: r_efi::efi::Boolean::FALSE,
+            });
+            Self {
+                reset: Self::reset_null,
+                output_string: Self::output_string_null,
+                test_string: Self::test_string,
+                query_mode: Self::query_mode,
+                set_mode: Self::set_mode,
+                set_attribute: Self::set_attribute,
+                clear_screen: Self::clear_screen,
+                set_cursor_position: Self::set_cursor_position,
+                enable_cursor: Self::enable_cursor,
+                mode: Box::into_raw(mode),
+                _buffer: Vec::new(),
+            }
+        }
+
+        pub fn utf8(&self) -> io::Result<Vec<u8>> {
+            OsString::from_wide(&self._buffer)
+                .into_string()
+                .map(Into::into)
+                .map_err(|_| const_io_error!(io::ErrorKind::Other, "utf8 conversion failed"))
+        }
+
+        extern "efiapi" fn reset(
+            proto: *mut simple_text_output::Protocol,
+            _: r_efi::efi::Boolean,
+        ) -> r_efi::efi::Status {
+            let proto: *mut PipeProtocol = proto.cast();
+            unsafe {
+                (*proto)._buffer.clear();
+            }
+            r_efi::efi::Status::SUCCESS
+        }
+
+        extern "efiapi" fn reset_null(
+            _: *mut simple_text_output::Protocol,
+            _: r_efi::efi::Boolean,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::SUCCESS
+        }
+
+        extern "efiapi" fn output_string(
+            proto: *mut simple_text_output::Protocol,
+            buf: *mut r_efi::efi::Char16,
+        ) -> r_efi::efi::Status {
+            let proto: *mut PipeProtocol = proto.cast();
+            let buf_len = unsafe {
+                if let Some(x) = WStrUnits::new(buf) {
+                    x.count()
+                } else {
+                    return r_efi::efi::Status::INVALID_PARAMETER;
+                }
+            };
+            let buf_slice = unsafe { slice::from_raw_parts(buf, buf_len) };
+
+            unsafe {
+                (*proto)._buffer.extend_from_slice(buf_slice);
+            };
+
+            r_efi::efi::Status::SUCCESS
+        }
+
+        extern "efiapi" fn output_string_null(
+            _: *mut simple_text_output::Protocol,
+            _: *mut r_efi::efi::Char16,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::SUCCESS
+        }
+
+        extern "efiapi" fn test_string(
+            _: *mut simple_text_output::Protocol,
+            _: *mut r_efi::efi::Char16,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::SUCCESS
+        }
+
+        extern "efiapi" fn query_mode(
+            _: *mut simple_text_output::Protocol,
+            _: usize,
+            _: *mut usize,
+            _: *mut usize,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+
+        extern "efiapi" fn set_mode(
+            _: *mut simple_text_output::Protocol,
+            _: usize,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+
+        extern "efiapi" fn set_attribute(
+            _: *mut simple_text_output::Protocol,
+            _: usize,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+
+        extern "efiapi" fn clear_screen(
+            _: *mut simple_text_output::Protocol,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+
+        extern "efiapi" fn set_cursor_position(
+            _: *mut simple_text_output::Protocol,
+            _: usize,
+            _: usize,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+
+        extern "efiapi" fn enable_cursor(
+            _: *mut simple_text_output::Protocol,
+            _: r_efi::efi::Boolean,
+        ) -> r_efi::efi::Status {
+            r_efi::efi::Status::UNSUPPORTED
+        }
+    }
+
+    impl Drop for PipeProtocol {
+        fn drop(&mut self) {
+            unsafe {
+                let _ = Box::from_raw(self.mode);
+            }
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index eb3a57c212b..625ba5247f1 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -67,7 +67,7 @@ cfg_if::cfg_if! {
     ))] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-            libc::memalign(layout.align(), layout.size()) as *mut u8
+            unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 }
         }
     } else {
         #[inline]
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index b8dc1538a63..bedb06043a7 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -4,7 +4,6 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{Shutdown, SocketAddr};
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
-use crate::str;
 use crate::sys::fd::FileDesc;
 use crate::sys::pal::unix::IsMinusOne;
 use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
@@ -47,7 +46,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
 
     #[cfg(not(target_os = "espidf"))]
     let detail = unsafe {
-        str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
+        // We can't always expect a UTF-8 environment. When we don't get that luxury,
+        // it's better to give a low-quality error message than none at all.
+        CStr::from_ptr(libc::gai_strerror(err)).to_string_lossy()
     };
 
     #[cfg(target_os = "espidf")]
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/pal/unix/process/process_unsupported.rs
index 33d359d3f84..90d53464c83 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/pal/unix/process/process_unsupported.rs
@@ -1,4 +1,3 @@
-use crate::fmt;
 use crate::io;
 use crate::num::NonZero;
 use crate::sys::pal::unix::unsupported::*;
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 0db08c1a926..6eeec48bf5e 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -87,13 +87,18 @@ mod imp {
     // out many large systems and all implementations allow returning from a
     // signal handler to work. For a more detailed explanation see the
     // comments on #26458.
+    /// SIGSEGV/SIGBUS entry point
+    /// # Safety
+    /// Rust doesn't call this, it *gets called*.
+    #[forbid(unsafe_op_in_unsafe_fn)]
     unsafe extern "C" fn signal_handler(
         signum: libc::c_int,
         info: *mut libc::siginfo_t,
         _data: *mut libc::c_void,
     ) {
         let (start, end) = GUARD.get();
-        let addr = (*info).si_addr() as usize;
+        // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`.
+        let addr = unsafe { (*info).si_addr().addr() };
 
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
@@ -105,9 +110,11 @@ mod imp {
             rtabort!("stack overflow");
         } else {
             // Unregister ourselves by reverting back to the default behavior.
-            let mut action: sigaction = mem::zeroed();
+            // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
+            let mut action: sigaction = unsafe { mem::zeroed() };
             action.sa_sigaction = SIG_DFL;
-            sigaction(signum, &action, ptr::null_mut());
+            // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
+            unsafe { sigaction(signum, &action, ptr::null_mut()) };
 
             // See comment above for why this function returns.
         }
@@ -117,32 +124,45 @@ mod imp {
     static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
     static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
 
+    /// # Safety
+    /// Must be called only once
+    #[forbid(unsafe_op_in_unsafe_fn)]
     pub unsafe fn init() {
         PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
 
         // Always write to GUARD to ensure the TLS variable is allocated.
-        let guard = install_main_guard().unwrap_or(0..0);
+        let guard = unsafe { install_main_guard().unwrap_or(0..0) };
         GUARD.set((guard.start, guard.end));
 
-        let mut action: sigaction = mem::zeroed();
+        // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
+        let mut action: sigaction = unsafe { mem::zeroed() };
         for &signal in &[SIGSEGV, SIGBUS] {
-            sigaction(signal, ptr::null_mut(), &mut action);
+            // SAFETY: just fetches the current signal handler into action
+            unsafe { sigaction(signal, ptr::null_mut(), &mut action) };
             // Configure our signal handler if one is not already set.
             if action.sa_sigaction == SIG_DFL {
+                if !NEED_ALTSTACK.load(Ordering::Relaxed) {
+                    // haven't set up our sigaltstack yet
+                    NEED_ALTSTACK.store(true, Ordering::Release);
+                    let handler = unsafe { make_handler(true) };
+                    MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
+                    mem::forget(handler);
+                }
                 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                 action.sa_sigaction = signal_handler as sighandler_t;
-                sigaction(signal, &action, ptr::null_mut());
-                NEED_ALTSTACK.store(true, Ordering::Relaxed);
+                // SAFETY: only overriding signals if the default is set
+                unsafe { sigaction(signal, &action, ptr::null_mut()) };
             }
         }
-
-        let handler = make_handler(true);
-        MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
-        mem::forget(handler);
     }
 
+    /// # Safety
+    /// Must be called only once
+    #[forbid(unsafe_op_in_unsafe_fn)]
     pub unsafe fn cleanup() {
-        drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed));
+        // FIXME: I probably cause more bugs than I'm worth!
+        // see https://github.com/rust-lang/rust/issues/111272
+        unsafe { drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)) };
     }
 
     unsafe fn get_stack() -> libc::stack_t {
@@ -187,34 +207,48 @@ mod imp {
         libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
     }
 
+    /// # Safety
+    /// Mutates the alternate signal stack
+    #[forbid(unsafe_op_in_unsafe_fn)]
     pub unsafe fn make_handler(main_thread: bool) -> Handler {
-        if !NEED_ALTSTACK.load(Ordering::Relaxed) {
+        if !NEED_ALTSTACK.load(Ordering::Acquire) {
             return Handler::null();
         }
 
         if !main_thread {
             // Always write to GUARD to ensure the TLS variable is allocated.
-            let guard = current_guard().unwrap_or(0..0);
+            let guard = unsafe { current_guard() }.unwrap_or(0..0);
             GUARD.set((guard.start, guard.end));
         }
 
-        let mut stack = mem::zeroed();
-        sigaltstack(ptr::null(), &mut stack);
+        // SAFETY: assuming stack_t is zero-initializable
+        let mut stack = unsafe { mem::zeroed() };
+        // SAFETY: reads current stack_t into stack
+        unsafe { sigaltstack(ptr::null(), &mut stack) };
         // Configure alternate signal stack, if one is not already set.
         if stack.ss_flags & SS_DISABLE != 0 {
-            stack = get_stack();
-            sigaltstack(&stack, ptr::null_mut());
+            // SAFETY: We warned our caller this would happen!
+            unsafe {
+                stack = get_stack();
+                sigaltstack(&stack, ptr::null_mut());
+            }
             Handler { data: stack.ss_sp as *mut libc::c_void }
         } else {
             Handler::null()
         }
     }
 
+    /// # Safety
+    /// Must be called
+    /// - only with our handler or nullptr
+    /// - only when done with our altstack
+    /// This disables the alternate signal stack!
+    #[forbid(unsafe_op_in_unsafe_fn)]
     pub unsafe fn drop_handler(data: *mut libc::c_void) {
         if !data.is_null() {
             let sigstack_size = sigstack_size();
             let page_size = PAGE_SIZE.load(Ordering::Relaxed);
-            let stack = libc::stack_t {
+            let disabling_stack = libc::stack_t {
                 ss_sp: ptr::null_mut(),
                 ss_flags: SS_DISABLE,
                 // Workaround for bug in macOS implementation of sigaltstack
@@ -223,10 +257,11 @@ mod imp {
                 // both ss_sp and ss_size should be ignored in this case.
                 ss_size: sigstack_size,
             };
-            sigaltstack(&stack, ptr::null_mut());
-            // We know from `get_stackp` that the alternate stack we installed is part of a mapping
-            // that started one page earlier, so walk back a page and unmap from there.
-            munmap(data.sub(page_size), sigstack_size + page_size);
+            // SAFETY: we warned the caller this disables the alternate signal stack!
+            unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) };
+            // SAFETY: We know from `get_stackp` that the alternate stack we installed is part of
+            // a mapping that started one page earlier, so walk back a page and unmap from there.
+            unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
         }
     }
 
@@ -455,6 +490,7 @@ mod imp {
     }
 
     #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
+    // FIXME: I am probably not unsafe.
     unsafe fn current_guard() -> Option<Range<usize>> {
         let stackptr = get_stack_start()?;
         let stackaddr = stackptr.addr();
@@ -469,6 +505,7 @@ mod imp {
         target_os = "netbsd",
         target_os = "l4re"
     ))]
+    // FIXME: I am probably not unsafe.
     unsafe fn current_guard() -> Option<Range<usize>> {
         let mut ret = None;
         let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index 296d19a926d..84f3d6a5399 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -8,7 +8,7 @@
 
 use crate::ffi::CStr;
 use crate::mem;
-use crate::os::raw::{c_char, c_int, c_uint, c_ulong, c_ushort, c_void};
+use crate::os::raw::{c_uint, c_ulong, c_ushort, c_void};
 use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
 use crate::ptr;
 
@@ -19,12 +19,6 @@ pub use windows_sys::*;
 
 pub type WCHAR = u16;
 
-pub type socklen_t = c_int;
-pub type ADDRESS_FAMILY = c_ushort;
-pub use FD_SET as fd_set;
-pub use LINGER as linger;
-pub use TIMEVAL as timeval;
-
 pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i32 as _);
 
 // https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170
@@ -42,20 +36,6 @@ pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
 pub const OBJ_DONT_REPARSE: u32 = windows_sys::OBJ_DONT_REPARSE as u32;
 pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: u32 =
     windows_sys::FRS_ERR_SYSVOL_POPULATE_TIMEOUT as u32;
-pub const AF_INET: c_int = windows_sys::AF_INET as c_int;
-pub const AF_INET6: c_int = windows_sys::AF_INET6 as c_int;
-
-#[repr(C)]
-pub struct ip_mreq {
-    pub imr_multiaddr: in_addr,
-    pub imr_interface: in_addr,
-}
-
-#[repr(C)]
-pub struct ipv6_mreq {
-    pub ipv6mr_multiaddr: in6_addr,
-    pub ipv6mr_interface: c_uint,
-}
 
 // Equivalent to the `NT_SUCCESS` C preprocessor macro.
 // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
@@ -127,45 +107,6 @@ pub struct MOUNT_POINT_REPARSE_BUFFER {
     pub PathBuffer: WCHAR,
 }
 
-#[repr(C)]
-pub struct SOCKADDR_STORAGE_LH {
-    pub ss_family: ADDRESS_FAMILY,
-    pub __ss_pad1: [c_char; 6],
-    pub __ss_align: i64,
-    pub __ss_pad2: [c_char; 112],
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct sockaddr_in {
-    pub sin_family: ADDRESS_FAMILY,
-    pub sin_port: c_ushort,
-    pub sin_addr: in_addr,
-    pub sin_zero: [c_char; 8],
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct sockaddr_in6 {
-    pub sin6_family: ADDRESS_FAMILY,
-    pub sin6_port: c_ushort,
-    pub sin6_flowinfo: c_ulong,
-    pub sin6_addr: in6_addr,
-    pub sin6_scope_id: c_ulong,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct in_addr {
-    pub s_addr: u32,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct in6_addr {
-    pub s6_addr: [u8; 16],
-}
-
 // Desktop specific functions & types
 cfg_if::cfg_if! {
 if #[cfg(not(target_vendor = "uwp"))] {
@@ -205,42 +146,6 @@ pub unsafe extern "system" fn ReadFileEx(
     )
 }
 
-// POSIX compatibility shims.
-pub unsafe fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int {
-    windows_sys::recv(socket, buf.cast::<u8>(), len, flags)
-}
-pub unsafe fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int {
-    windows_sys::send(socket, buf.cast::<u8>(), len, flags)
-}
-pub unsafe fn recvfrom(
-    socket: SOCKET,
-    buf: *mut c_void,
-    len: c_int,
-    flags: c_int,
-    addr: *mut SOCKADDR,
-    addrlen: *mut c_int,
-) -> c_int {
-    windows_sys::recvfrom(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
-}
-pub unsafe fn sendto(
-    socket: SOCKET,
-    buf: *const c_void,
-    len: c_int,
-    flags: c_int,
-    addr: *const SOCKADDR,
-    addrlen: c_int,
-) -> c_int {
-    windows_sys::sendto(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
-}
-pub unsafe fn getaddrinfo(
-    node: *const c_char,
-    service: *const c_char,
-    hints: *const ADDRINFOA,
-    res: *mut *mut ADDRINFOA,
-) -> c_int {
-    windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
-}
-
 cfg_if::cfg_if! {
 if #[cfg(not(target_vendor = "uwp"))] {
 pub unsafe fn NtReadFile(
diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt
index 5ad4a3731d8..794e2c90c52 100644
--- a/library/std/src/sys/pal/windows/c/bindings.txt
+++ b/library/std/src/sys/pal/windows/c/bindings.txt
@@ -2059,6 +2059,7 @@ Windows.Win32.Networking.WinSock.SOCK_RDM
 Windows.Win32.Networking.WinSock.SOCK_SEQPACKET
 Windows.Win32.Networking.WinSock.SOCK_STREAM
 Windows.Win32.Networking.WinSock.SOCKADDR
+Windows.Win32.Networking.WinSock.SOCKADDR_STORAGE
 Windows.Win32.Networking.WinSock.SOCKADDR_UN
 Windows.Win32.Networking.WinSock.SOCKET
 Windows.Win32.Networking.WinSock.SOCKET_ERROR
diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs
index fea00fec9ae..eae0f775860 100644
--- a/library/std/src/sys/pal/windows/c/windows_sys.rs
+++ b/library/std/src/sys/pal/windows/c/windows_sys.rs
@@ -2890,6 +2890,14 @@ pub struct SOCKADDR {
 }
 #[repr(C)]
 #[derive(Clone, Copy)]
+pub struct SOCKADDR_STORAGE {
+    pub ss_family: ADDRESS_FAMILY,
+    pub __ss_pad1: [i8; 6],
+    pub __ss_align: i64,
+    pub __ss_pad2: [i8; 112],
+}
+#[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SOCKADDR_UN {
     pub sun_family: ADDRESS_FAMILY,
     pub sun_path: [i8; 108],
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs
index 48c39392047..15d446786ad 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -32,6 +32,7 @@ pub struct FileAttr {
     creation_time: c::FILETIME,
     last_access_time: c::FILETIME,
     last_write_time: c::FILETIME,
+    change_time: Option<c::FILETIME>,
     file_size: u64,
     reparse_tag: u32,
     volume_serial_number: Option<u32>,
@@ -377,6 +378,7 @@ impl File {
                 creation_time: info.ftCreationTime,
                 last_access_time: info.ftLastAccessTime,
                 last_write_time: info.ftLastWriteTime,
+                change_time: None, // Only available in FILE_BASIC_INFO
                 file_size: (info.nFileSizeLow as u64) | ((info.nFileSizeHigh as u64) << 32),
                 reparse_tag,
                 volume_serial_number: Some(info.dwVolumeSerialNumber),
@@ -413,6 +415,10 @@ impl File {
                     dwLowDateTime: info.LastWriteTime as u32,
                     dwHighDateTime: (info.LastWriteTime >> 32) as u32,
                 },
+                change_time: Some(c::FILETIME {
+                    dhLowDateTime: info.ChangeTime as c::DWORD,
+                    dhHighDateTime: (info.ChangeTime >> 32) as c::DWORD,
+                }),
                 file_size: 0,
                 reparse_tag: 0,
                 volume_serial_number: None,
@@ -957,6 +963,10 @@ impl FileAttr {
         to_u64(&self.creation_time)
     }
 
+    pub fn changed_u64(&self) -> Option<u64> {
+        self.change_time.as_ref().map(|c| to_u64(c))
+    }
+
     pub fn volume_serial_number(&self) -> Option<u32> {
         self.volume_serial_number
     }
@@ -976,6 +986,7 @@ impl From<c::WIN32_FIND_DATAW> for FileAttr {
             creation_time: wfd.ftCreationTime,
             last_access_time: wfd.ftLastAccessTime,
             last_write_time: wfd.ftLastWriteTime,
+            change_time: None,
             file_size: ((wfd.nFileSizeHigh as u64) << 32) | (wfd.nFileSizeLow as u64),
             reparse_tag: if wfd.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
                 // reserved unless this is a reparse point
diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/pal/windows/net.rs
index d51fb56238f..b7ecff032e4 100644
--- a/library/std/src/sys/pal/windows/net.rs
+++ b/library/std/src/sys/pal/windows/net.rs
@@ -17,14 +17,100 @@ use crate::time::Duration;
 
 use core::ffi::{c_int, c_long, c_ulong, c_ushort};
 
+#[allow(non_camel_case_types)]
 pub type wrlen_t = i32;
 
 pub mod netc {
-    pub use crate::sys::c::ADDRESS_FAMILY as sa_family_t;
-    pub use crate::sys::c::ADDRINFOA as addrinfo;
-    pub use crate::sys::c::SOCKADDR as sockaddr;
-    pub use crate::sys::c::SOCKADDR_STORAGE_LH as sockaddr_storage;
-    pub use crate::sys::c::*;
+    //! BSD socket compatibility shim
+    //!
+    //! Some Windows API types are not quite what's expected by our cross-platform
+    //! net code. E.g. naming differences or different pointer types.
+    use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET};
+    use core::ffi::{c_char, c_int, c_uint, c_ulong, c_ushort, c_void};
+
+    // re-exports from Windows API bindings.
+    pub use crate::sys::c::{
+        bind, connect, freeaddrinfo, getpeername, getsockname, getsockopt, listen, setsockopt,
+        ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IPPROTO_IP, IPPROTO_IPV6,
+        IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY,
+        IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL,
+        SOCKADDR as sockaddr, SOCKADDR_STORAGE as sockaddr_storage, SOCK_DGRAM, SOCK_STREAM,
+        SOL_SOCKET, SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO,
+    };
+
+    #[allow(non_camel_case_types)]
+    pub type socklen_t = c_int;
+
+    pub const AF_INET: i32 = c::AF_INET as i32;
+    pub const AF_INET6: i32 = c::AF_INET6 as i32;
+
+    // The following two structs use a union in the generated bindings but
+    // our cross-platform code expects a normal field so it's redefined here.
+    // As a consequence, we also need to redefine other structs that use this struct.
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct in_addr {
+        pub s_addr: u32,
+    }
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct in6_addr {
+        pub s6_addr: [u8; 16],
+    }
+
+    #[repr(C)]
+    pub struct ip_mreq {
+        pub imr_multiaddr: in_addr,
+        pub imr_interface: in_addr,
+    }
+
+    #[repr(C)]
+    pub struct ipv6_mreq {
+        pub ipv6mr_multiaddr: in6_addr,
+        pub ipv6mr_interface: c_uint,
+    }
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in {
+        pub sin_family: ADDRESS_FAMILY,
+        pub sin_port: c_ushort,
+        pub sin_addr: in_addr,
+        pub sin_zero: [c_char; 8],
+    }
+
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct sockaddr_in6 {
+        pub sin6_family: ADDRESS_FAMILY,
+        pub sin6_port: c_ushort,
+        pub sin6_flowinfo: c_ulong,
+        pub sin6_addr: in6_addr,
+        pub sin6_scope_id: c_ulong,
+    }
+
+    pub unsafe fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int {
+        unsafe { c::send(socket, buf.cast::<u8>(), len, flags) }
+    }
+    pub unsafe fn sendto(
+        socket: SOCKET,
+        buf: *const c_void,
+        len: c_int,
+        flags: c_int,
+        addr: *const SOCKADDR,
+        addrlen: c_int,
+    ) -> c_int {
+        unsafe { c::sendto(socket, buf.cast::<u8>(), len, flags, addr, addrlen) }
+    }
+    pub unsafe fn getaddrinfo(
+        node: *const c_char,
+        service: *const c_char,
+        hints: *const ADDRINFOA,
+        res: *mut *mut ADDRINFOA,
+    ) -> c_int {
+        unsafe { c::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res) }
+    }
 }
 
 pub struct Socket(OwnedSocket);
@@ -102,8 +188,8 @@ where
 impl Socket {
     pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
         let family = match *addr {
-            SocketAddr::V4(..) => c::AF_INET,
-            SocketAddr::V6(..) => c::AF_INET6,
+            SocketAddr::V4(..) => netc::AF_INET,
+            SocketAddr::V6(..) => netc::AF_INET6,
         };
         let socket = unsafe {
             c::WSASocketW(
@@ -157,7 +243,7 @@ impl Socket {
                     return Err(io::Error::ZERO_TIMEOUT);
                 }
 
-                let mut timeout = c::timeval {
+                let mut timeout = c::TIMEVAL {
                     tv_sec: cmp::min(timeout.as_secs(), c_long::MAX as u64) as c_long,
                     tv_usec: timeout.subsec_micros() as c_long,
                 };
@@ -167,7 +253,7 @@ impl Socket {
                 }
 
                 let fds = {
-                    let mut fds = unsafe { mem::zeroed::<c::fd_set>() };
+                    let mut fds = unsafe { mem::zeroed::<c::FD_SET>() };
                     fds.fd_count = 1;
                     fds.fd_array[0] = self.as_raw();
                     fds
@@ -295,8 +381,8 @@ impl Socket {
         buf: &mut [u8],
         flags: c_int,
     ) -> io::Result<(usize, SocketAddr)> {
-        let mut storage = unsafe { mem::zeroed::<c::SOCKADDR_STORAGE_LH>() };
-        let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
+        let mut storage = unsafe { mem::zeroed::<c::SOCKADDR_STORAGE>() };
+        let mut addrlen = mem::size_of_val(&storage) as netc::socklen_t;
         let length = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
 
         // On unix when a socket is shut down all further reads return 0, so we
@@ -399,7 +485,7 @@ impl Socket {
     }
 
     pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
-        let linger = c::linger {
+        let linger = c::LINGER {
             l_onoff: linger.is_some() as c_ushort,
             l_linger: linger.unwrap_or_default().as_secs() as c_ushort,
         };
@@ -408,7 +494,7 @@ impl Socket {
     }
 
     pub fn linger(&self) -> io::Result<Option<Duration>> {
-        let val: c::linger = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
+        let val: c::LINGER = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
 
         Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
     }
diff --git a/library/std/src/sys/path/unsupported_backslash.rs b/library/std/src/sys/path/unsupported_backslash.rs
index 7045c9be25b..855f443678c 100644
--- a/library/std/src/sys/path/unsupported_backslash.rs
+++ b/library/std/src/sys/path/unsupported_backslash.rs
@@ -1,3 +1,4 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
 use crate::ffi::OsStr;
 use crate::io;
 use crate::path::{Path, PathBuf, Prefix};
diff --git a/library/std/src/sys/sync/mutex/itron.rs b/library/std/src/sys/sync/mutex/itron.rs
index 4ba32a8fbcd..b29c7e1d034 100644
--- a/library/std/src/sys/sync/mutex/itron.rs
+++ b/library/std/src/sys/sync/mutex/itron.rs
@@ -1,5 +1,6 @@
 //! Mutex implementation backed by μITRON mutexes. Assumes `acre_mtx` and
 //! `TA_INHERIT` are available.
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::sys::pal::itron::{
     abi,
diff --git a/library/std/src/sys/sync/rwlock/solid.rs b/library/std/src/sys/sync/rwlock/solid.rs
index 7558eee8edd..a8fef685ceb 100644
--- a/library/std/src/sys/sync/rwlock/solid.rs
+++ b/library/std/src/sys/sync/rwlock/solid.rs
@@ -1,4 +1,5 @@
 //! A readers-writer lock implementation backed by the SOLID kernel extension.
+#![forbid(unsafe_op_in_unsafe_fn)]
 
 use crate::sys::pal::{
     abi,
diff --git a/library/std/src/sys/thread_local/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs
index f6cd457046f..e08ac44e1af 100644
--- a/library/std/src/sys/thread_local/guard/windows.rs
+++ b/library/std/src/sys/thread_local/guard/windows.rs
@@ -78,19 +78,6 @@ pub fn enable() {
 pub static CALLBACK: unsafe extern "system" fn(*mut c_void, u32, *mut c_void) = tls_callback;
 
 unsafe extern "system" fn tls_callback(_h: *mut c_void, dw_reason: u32, _pv: *mut c_void) {
-    // See comments above for what this is doing. Note that we don't need this
-    // trickery on GNU windows, just on MSVC.
-    #[cfg(all(target_env = "msvc", not(target_thread_local)))]
-    {
-        extern "C" {
-            static _tls_used: u8;
-        }
-
-        unsafe {
-            ptr::from_ref(&_tls_used).read_volatile();
-        }
-    }
-
     if dw_reason == c::DLL_THREAD_DETACH || dw_reason == c::DLL_PROCESS_DETACH {
         #[cfg(target_thread_local)]
         unsafe {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 7b98f2ae763..e9731bc85d6 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -161,7 +161,7 @@ mod tests;
 use crate::any::Any;
 use crate::cell::{Cell, OnceCell, UnsafeCell};
 use crate::env;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
@@ -487,11 +487,7 @@ impl Builder {
             amt
         });
 
-        let my_thread = name.map_or_else(Thread::new_unnamed, |name| unsafe {
-            Thread::new(
-                CString::new(name).expect("thread name may not contain interior null bytes"),
-            )
-        });
+        let my_thread = name.map_or_else(Thread::new_unnamed, Thread::new);
         let their_thread = my_thread.clone();
 
         let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
@@ -1299,10 +1295,51 @@ impl ThreadId {
 /// The internal representation of a `Thread`'s name.
 enum ThreadName {
     Main,
-    Other(CString),
+    Other(ThreadNameString),
     Unnamed,
 }
 
+// This module ensures private fields are kept private, which is necessary to enforce the safety requirements.
+mod thread_name_string {
+    use super::ThreadName;
+    use crate::ffi::{CStr, CString};
+    use core::str;
+
+    /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated.
+    pub(crate) struct ThreadNameString {
+        inner: CString,
+    }
+    impl core::ops::Deref for ThreadNameString {
+        type Target = CStr;
+        fn deref(&self) -> &CStr {
+            &self.inner
+        }
+    }
+    impl From<String> for ThreadNameString {
+        fn from(s: String) -> Self {
+            Self {
+                inner: CString::new(s).expect("thread name may not contain interior null bytes"),
+            }
+        }
+    }
+    impl ThreadName {
+        pub fn as_cstr(&self) -> Option<&CStr> {
+            match self {
+                ThreadName::Main => Some(c"main"),
+                ThreadName::Other(other) => Some(other),
+                ThreadName::Unnamed => None,
+            }
+        }
+
+        pub fn as_str(&self) -> Option<&str> {
+            // SAFETY: `as_cstr` can only return `Some` for a fixed CStr or a `ThreadNameString`,
+            // which is guaranteed to be UTF-8.
+            self.as_cstr().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) })
+        }
+    }
+}
+pub(crate) use thread_name_string::ThreadNameString;
+
 /// The internal representation of a `Thread` handle
 struct Inner {
     name: ThreadName, // Guaranteed to be UTF-8
@@ -1342,25 +1379,20 @@ pub struct Thread {
 
 impl Thread {
     /// Used only internally to construct a thread object without spawning.
-    ///
-    /// # Safety
-    /// `name` must be valid UTF-8.
-    pub(crate) unsafe fn new(name: CString) -> Thread {
-        unsafe { Self::new_inner(ThreadName::Other(name)) }
+    pub(crate) fn new(name: String) -> Thread {
+        Self::new_inner(ThreadName::Other(name.into()))
     }
 
     pub(crate) fn new_unnamed() -> Thread {
-        unsafe { Self::new_inner(ThreadName::Unnamed) }
+        Self::new_inner(ThreadName::Unnamed)
     }
 
     // Used in runtime to construct main thread
     pub(crate) fn new_main() -> Thread {
-        unsafe { Self::new_inner(ThreadName::Main) }
+        Self::new_inner(ThreadName::Main)
     }
 
-    /// # Safety
-    /// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
-    unsafe fn new_inner(name: ThreadName) -> Thread {
+    fn new_inner(name: ThreadName) -> Thread {
         // We have to use `unsafe` here to construct the `Parker` in-place,
         // which is required for the UNIX implementation.
         //
@@ -1483,15 +1515,11 @@ impl Thread {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub fn name(&self) -> Option<&str> {
-        self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) })
+        self.inner.name.as_str()
     }
 
     fn cname(&self) -> Option<&CStr> {
-        match &self.inner.name {
-            ThreadName::Main => Some(c"main"),
-            ThreadName::Other(other) => Some(&other),
-            ThreadName::Unnamed => None,
-        }
+        self.inner.name.as_cstr()
     }
 }
 
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 7e38a0996e5..9acd85cddde 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -51,6 +51,7 @@ check-aux:
 	$(Q)$(BOOTSTRAP) test --stage 2 \
 		src/tools/cargo \
 		src/tools/cargotest \
+		src/etc/test-float-parse \
 		$(BOOTSTRAP_ARGS)
 	# Run standard library tests in Miri.
 	$(Q)BOOTSTRAP_SKIP_TARGET_SANITY=1 \
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 8235d4634b7..ed5b9edc86d 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -466,6 +466,7 @@ tool_check_step!(CargoMiri, "src/tools/miri/cargo-miri", SourceType::InTree);
 tool_check_step!(Rls, "src/tools/rls", SourceType::InTree);
 tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);
 tool_check_step!(MiroptTestTools, "src/tools/miropt-test-tools", SourceType::InTree);
+tool_check_step!(TestFloatParse, "src/etc/test-float-parse", SourceType::InTree);
 
 tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false);
 
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index 40a2112b192..ee7fb368a8c 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -326,4 +326,5 @@ lint_any!(
     Rustfmt, "src/tools/rustfmt", "rustfmt";
     RustInstaller, "src/tools/rust-installer", "rust-installer";
     Tidy, "src/tools/tidy", "tidy";
+    TestFloatParse, "src/etc/test-float-parse", "test-float-parse";
 );
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index d4dd3e546ec..3e79acad1c4 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -695,7 +695,7 @@ fn copy_sanitizers(
             || target == "x86_64-apple-ios"
         {
             // Update the library’s install name to reflect that it has been renamed.
-            apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", &runtime.name));
+            apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
             // Upon renaming the install name, the code signature of the file will invalidate,
             // so we will sign it again.
             apple_darwin_sign_file(builder, &dst);
@@ -1820,12 +1820,14 @@ impl Step for Assemble {
                     &self_contained_lld_dir.join(exe(name, target_compiler.host)),
                 );
             }
+        }
 
-            // In addition to `rust-lld` also install `wasm-component-ld` when
-            // LLD is enabled. This is a relatively small binary that primarily
-            // delegates to the `rust-lld` binary for linking and then runs
-            // logic to create the final binary. This is used by the
-            // `wasm32-wasip2` target of Rust.
+        // In addition to `rust-lld` also install `wasm-component-ld` when
+        // LLD is enabled. This is a relatively small binary that primarily
+        // delegates to the `rust-lld` binary for linking and then runs
+        // logic to create the final binary. This is used by the
+        // `wasm32-wasip2` target of Rust.
+        if builder.build_wasm_component_ld() {
             let wasm_component_ld_exe =
                 builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
                     compiler: build_compiler,
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 1e9d2025bc7..649bcdd8733 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -472,6 +472,11 @@ impl Step for Rustc {
                     );
                 }
             }
+            if builder.build_wasm_component_ld() {
+                let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
+                let ld = exe("wasm-component-ld", compiler.host);
+                builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
+            }
 
             // Man pages
             t!(fs::create_dir_all(image.join("share/man/man1")));
@@ -1040,6 +1045,8 @@ impl Step for PlainSourceTarball {
                 .arg(builder.src.join("./src/tools/opt-dist/Cargo.toml"))
                 .arg("--sync")
                 .arg(builder.src.join("./src/tools/rustc-perf/Cargo.toml"))
+                .arg("--sync")
+                .arg(builder.src.join("./src/tools/rustbook/Cargo.toml"))
                 // Will read the libstd Cargo.toml
                 // which uses the unstable `public-dependency` feature.
                 .env("RUSTC_BOOTSTRAP", "1")
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 633e66afe59..d8204ea00f7 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -1172,6 +1172,12 @@ impl Step for RustcBook {
     /// in the "md-doc" directory in the build output directory. Then
     /// "rustbook" is used to convert it to HTML.
     fn run(self, builder: &Builder<'_>) {
+        // These submodules are required to be checked out to build rustbook
+        // because they have Cargo dependencies that are needed.
+        #[allow(clippy::single_element_loop)] // This will change soon.
+        for path in ["src/doc/book"] {
+            builder.update_submodule(Path::new(path));
+        }
         let out_base = builder.md_doc_out(self.target).join("rustc");
         t!(fs::create_dir_all(&out_base));
         let out_listing = out_base.join("src/lints");
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 888290a0479..f234b08f5e2 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -26,7 +26,6 @@ use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind};
 
 use crate::utils::exec::command;
 use build_helper::ci::CiEnv;
-use build_helper::git::get_git_merge_base;
 
 #[derive(Clone)]
 pub struct LlvmResult {
@@ -154,26 +153,18 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
 /// This retrieves the LLVM sha we *want* to use, according to git history.
 pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
     let llvm_sha = if is_git {
-        // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we
-        // walk back further to the last bors merge commit that actually changed LLVM. The first
-        // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD`
-        // in that case.
-        let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src))
-            .unwrap_or_else(|_| "HEAD".into());
-        let mut rev_list = helpers::git(Some(&config.src));
-        rev_list.args(&[
-            PathBuf::from("rev-list"),
-            format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
-            "-n1".into(),
-            "--first-parent".into(),
-            closest_upstream.into(),
-            "--".into(),
-            config.src.join("src/llvm-project"),
-            config.src.join("src/bootstrap/download-ci-llvm-stamp"),
-            // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
-            config.src.join("src/version"),
-        ]);
-        output(rev_list.as_command_mut()).trim().to_owned()
+        helpers::get_closest_merge_base_commit(
+            Some(&config.src),
+            &config.git_config(),
+            &config.stage0_metadata.config.git_merge_commit_email,
+            &[
+                config.src.join("src/llvm-project"),
+                config.src.join("src/bootstrap/download-ci-llvm-stamp"),
+                // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
+                config.src.join("src/version"),
+            ],
+        )
+        .unwrap()
     } else if let Some(info) = channel::read_commit_info_file(&config.src) {
         info.sha.trim().to_owned()
     } else {
@@ -1411,7 +1402,7 @@ impl Step for Libunwind {
                 }
             }
         }
-        assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);
+        assert_eq!(cpp_len, count, "Can't get object files from {out_dir:?}");
 
         cc_cfg.compile("unwind");
         out_dir
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 3f0cbde64e3..cc5931c68db 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3505,3 +3505,80 @@ impl Step for CodegenGCC {
         cargo.into_cmd().run(builder);
     }
 }
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TestFloatParse {
+    path: PathBuf,
+    host: TargetSelection,
+}
+
+impl Step for TestFloatParse {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/etc/test-float-parse")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        for path in run.paths {
+            let path = path.assert_single_path().path.clone();
+            run.builder.ensure(Self { path, host: run.target });
+        }
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let bootstrap_host = builder.config.build;
+        let compiler = builder.compiler(0, bootstrap_host);
+        let path = self.path.to_str().unwrap();
+        let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
+
+        builder.ensure(compile::Std::new(compiler, self.host));
+
+        // Run any unit tests in the crate
+        let cargo_test = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolStd,
+            bootstrap_host,
+            "test",
+            path,
+            SourceType::InTree,
+            &[],
+        );
+
+        run_cargo_test(
+            cargo_test,
+            &[],
+            &[],
+            crate_name,
+            crate_name,
+            compiler,
+            bootstrap_host,
+            builder,
+        );
+
+        // Run the actual parse tests.
+        let mut cargo_run = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolStd,
+            bootstrap_host,
+            "run",
+            path,
+            SourceType::InTree,
+            &[],
+        );
+
+        cargo_run.arg("--");
+        if builder.config.args().is_empty() {
+            // By default, exclude tests that take longer than ~1m.
+            cargo_run.arg("--skip-huge");
+        } else {
+            cargo_run.args(builder.config.args());
+        }
+
+        cargo_run.into_cmd().run(builder);
+    }
+}
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 2f8b41334fc..087df2f8a88 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -9,7 +9,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun,
 use crate::core::config::TargetSelection;
 use crate::utils::channel::GitInfo;
 use crate::utils::exec::{command, BootstrapCommand};
-use crate::utils::helpers::{add_dylib_path, exe, t};
+use crate::utils::helpers::{add_dylib_path, exe, get_closest_merge_base_commit, git, t};
 use crate::Compiler;
 use crate::Mode;
 use crate::{gha, Kind};
@@ -554,6 +554,57 @@ impl Step for Rustdoc {
         }
         let target = target_compiler.host;
 
+        let bin_rustdoc = || {
+            let sysroot = builder.sysroot(target_compiler);
+            let bindir = sysroot.join("bin");
+            t!(fs::create_dir_all(&bindir));
+            let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host));
+            let _ = fs::remove_file(&bin_rustdoc);
+            bin_rustdoc
+        };
+
+        // If CI rustc is enabled and we haven't modified the rustdoc sources,
+        // use the precompiled rustdoc from CI rustc's sysroot to speed up bootstrapping.
+        if builder.download_rustc()
+            && target_compiler.stage > 0
+            && builder.rust_info().is_managed_git_subrepository()
+        {
+            let commit = get_closest_merge_base_commit(
+                Some(&builder.config.src),
+                &builder.config.git_config(),
+                &builder.config.stage0_metadata.config.git_merge_commit_email,
+                &[],
+            )
+            .unwrap();
+
+            let librustdoc_src = builder.config.src.join("src/librustdoc");
+            let rustdoc_src = builder.config.src.join("src/tools/rustdoc");
+
+            // FIXME: The change detection logic here is quite similar to `Config::download_ci_rustc_commit`.
+            // It would be better to unify them.
+            let has_changes = !git(Some(&builder.config.src))
+                .allow_failure()
+                .run_always()
+                .args(["diff-index", "--quiet", &commit])
+                .arg("--")
+                .arg(librustdoc_src)
+                .arg(rustdoc_src)
+                .run(builder)
+                .is_success();
+
+            if !has_changes {
+                let precompiled_rustdoc = builder
+                    .config
+                    .ci_rustc_dir()
+                    .join("bin")
+                    .join(exe("rustdoc", target_compiler.host));
+
+                let bin_rustdoc = bin_rustdoc();
+                builder.copy_link(&precompiled_rustdoc, &bin_rustdoc);
+                return bin_rustdoc;
+            }
+        }
+
         let build_compiler = if builder.download_rustc() && target_compiler.stage == 1 {
             // We already have the stage 1 compiler, we don't need to cut the stage.
             builder.compiler(target_compiler.stage, builder.config.build)
@@ -614,11 +665,7 @@ impl Step for Rustdoc {
 
         // don't create a stage0-sysroot/bin directory.
         if target_compiler.stage > 0 {
-            let sysroot = builder.sysroot(target_compiler);
-            let bindir = sysroot.join("bin");
-            t!(fs::create_dir_all(&bindir));
-            let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host));
-            let _ = fs::remove_file(&bin_rustdoc);
+            let bin_rustdoc = bin_rustdoc();
             builder.copy_link(&tool_rustdoc, &bin_rustdoc);
             bin_rustdoc
         } else {
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 62342ee4792..e6b3cb320cf 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -34,8 +34,10 @@ impl Step for Vendor {
             cmd.arg("--versioned-dirs");
         }
 
-        // cargo submodule must be present for `x vendor` to work.
-        builder.build.update_submodule(Path::new("src/tools/cargo"));
+        // These submodules must be present for `x vendor` to work.
+        for path in ["src/tools/cargo", "src/doc/book"] {
+            builder.build.update_submodule(Path::new(path));
+        }
 
         // Sync these paths by default.
         for p in [
@@ -44,6 +46,7 @@ impl Step for Vendor {
             "compiler/rustc_codegen_cranelift/Cargo.toml",
             "compiler/rustc_codegen_gcc/Cargo.toml",
             "src/bootstrap/Cargo.toml",
+            "src/tools/rustbook/Cargo.toml",
         ] {
             cmd.arg("--sync").arg(builder.src.join(p));
         }
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 6d6df650b14..78fbea2e810 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -826,6 +826,7 @@ impl<'a> Builder<'a> {
                 clippy::Rustdoc,
                 clippy::Rustfmt,
                 clippy::RustInstaller,
+                clippy::TestFloatParse,
                 clippy::Tidy,
             ),
             Kind::Check | Kind::Fix => describe!(
@@ -840,6 +841,7 @@ impl<'a> Builder<'a> {
                 check::Rls,
                 check::Rustfmt,
                 check::RustAnalyzer,
+                check::TestFloatParse,
                 check::Bootstrap,
             ),
             Kind::Test => describe!(
@@ -901,6 +903,7 @@ impl<'a> Builder<'a> {
                 test::RustdocJson,
                 test::HtmlCheck,
                 test::RustInstaller,
+                test::TestFloatParse,
                 // Run bootstrap close to the end as it's unlikely to fail
                 test::Bootstrap,
                 // Run run-make last, since these won't pass without make on Windows
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index a78a213f530..e32288e2caf 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -20,7 +20,7 @@ use crate::core::build_steps::llvm;
 use crate::core::config::flags::{Color, Flags, Warnings};
 use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::channel::{self, GitInfo};
-use crate::utils::helpers::{self, exe, output, t};
+use crate::utils::helpers::{self, exe, get_closest_merge_base_commit, output, t};
 use build_helper::exit;
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
@@ -2482,14 +2482,13 @@ impl Config {
 
         // Look for a version to compare to based on the current commit.
         // Only commits merged by bors will have CI artifacts.
-        let merge_base = output(
-            helpers::git(Some(&self.src))
-                .arg("rev-list")
-                .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
-                .args(["-n1", "--first-parent", "HEAD"])
-                .as_command_mut(),
-        );
-        let commit = merge_base.trim_end();
+        let commit = get_closest_merge_base_commit(
+            Some(&self.src),
+            &self.git_config(),
+            &self.stage0_metadata.config.git_merge_commit_email,
+            &[],
+        )
+        .unwrap();
         if commit.is_empty() {
             println!("ERROR: could not find commit hash for downloading rustc");
             println!("HELP: maybe your repository history is too shallow?");
@@ -2500,7 +2499,7 @@ impl Config {
 
         // Warn if there were changes to the compiler or standard library since the ancestor commit.
         let has_changes = !t!(helpers::git(Some(&self.src))
-            .args(["diff-index", "--quiet", commit])
+            .args(["diff-index", "--quiet", &commit])
             .arg("--")
             .args([self.src.join("compiler"), self.src.join("library")])
             .as_command_mut()
@@ -2576,14 +2575,13 @@ impl Config {
     ) -> Option<String> {
         // Look for a version to compare to based on the current commit.
         // Only commits merged by bors will have CI artifacts.
-        let merge_base = output(
-            helpers::git(Some(&self.src))
-                .arg("rev-list")
-                .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email))
-                .args(["-n1", "--first-parent", "HEAD"])
-                .as_command_mut(),
-        );
-        let commit = merge_base.trim_end();
+        let commit = get_closest_merge_base_commit(
+            Some(&self.src),
+            &self.git_config(),
+            &self.stage0_metadata.config.git_merge_commit_email,
+            &[],
+        )
+        .unwrap();
         if commit.is_empty() {
             println!("error: could not find commit hash for downloading components from CI");
             println!("help: maybe your repository history is too shallow?");
@@ -2594,7 +2592,7 @@ impl Config {
 
         // Warn if there were changes to the compiler or standard library since the ancestor commit.
         let mut git = helpers::git(Some(&self.src));
-        git.args(["diff-index", "--quiet", commit, "--"]);
+        git.args(["diff-index", "--quiet", &commit, "--"]);
 
         // Handle running from a directory other than the top level
         let top_level = &self.src;
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index a77c20067e6..79bea50c626 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -439,7 +439,7 @@ 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/doc/book", "library/backtrace", "library/stdarch"];
+            let rust_submodules = ["library/backtrace", "library/stdarch"];
             for s in rust_submodules {
                 build.update_submodule(Path::new(s));
             }
@@ -1414,6 +1414,19 @@ Executed at: {executed_at}"#,
         None
     }
 
+    /// Returns whether it's requested that `wasm-component-ld` is built as part
+    /// of the sysroot. This is done either with the `extended` key in
+    /// `config.toml` or with the `tools` set.
+    fn build_wasm_component_ld(&self) -> bool {
+        if self.config.extended {
+            return true;
+        }
+        match &self.config.tools {
+            Some(set) => set.contains("wasm-component-ld"),
+            None => false,
+        }
+    }
+
     /// Returns the root of the "rootfs" image that this target will be using,
     /// if one was configured.
     ///
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index d6fa7fc0bbe..20d79e490ec 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -142,15 +142,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
         build.cxx.borrow_mut().insert(target, compiler);
     }
 
-    build.verbose(|| println!("CC_{} = {:?}", &target.triple, build.cc(target)));
-    build.verbose(|| println!("CFLAGS_{} = {:?}", &target.triple, cflags));
+    build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
+    build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
     if let Ok(cxx) = build.cxx(target) {
         let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
-        build.verbose(|| println!("CXX_{} = {:?}", &target.triple, cxx));
-        build.verbose(|| println!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
+        build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
+        build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
     }
     if let Some(ar) = ar {
-        build.verbose(|| println!("AR_{} = {:?}", &target.triple, ar));
+        build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
         build.ar.borrow_mut().insert(target, ar);
     }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 6a7c5c0f9b7..083418ed066 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -205,4 +205,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "`debug-logging` option has been removed from the default `tools` profile.",
     },
+    ChangeInfo {
+        change_id: 127866,
+        severity: ChangeSeverity::Info,
+        summary: "the `wasm-component-ld` tool is now built as part of `build.extended` and can be a member of `build.tools`",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 3c82fa189be..690d7318f94 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -3,6 +3,7 @@
 //! Simple things like testing the various filesystem operations here and there,
 //! not a lot of interesting happenings here unfortunately.
 
+use build_helper::git::{get_git_merge_base, output_result, GitConfig};
 use build_helper::util::fail;
 use std::env;
 use std::ffi::OsStr;
@@ -202,7 +203,9 @@ pub fn target_supports_cranelift_backend(target: TargetSelection) -> bool {
             || target.contains("aarch64")
             || target.contains("s390x")
             || target.contains("riscv64gc")
-    } else if target.contains("darwin") || target.is_windows() {
+    } else if target.contains("darwin") {
+        target.contains("x86_64") || target.contains("aarch64")
+    } else if target.is_windows() {
         target.contains("x86_64")
     } else {
         false
@@ -521,3 +524,26 @@ pub fn git(source_dir: Option<&Path>) -> BootstrapCommand {
 
     git
 }
+
+/// Returns the closest commit available from upstream for the given `author` and `target_paths`.
+///
+/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD.
+pub fn get_closest_merge_base_commit(
+    source_dir: Option<&Path>,
+    config: &GitConfig<'_>,
+    author: &str,
+    target_paths: &[PathBuf],
+) -> Result<String, String> {
+    let mut git = git(source_dir).capture_stdout();
+
+    let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into());
+
+    git.arg(Path::new("rev-list"));
+    git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
+
+    if !target_paths.is_empty() {
+        git.arg("--").args(target_paths);
+    }
+
+    Ok(output_result(git.as_command_mut())?.trim().to_owned())
+}
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 9378c35127f..28a295e3e2a 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -244,7 +244,7 @@ impl<'a> Tarball<'a> {
             cmd.arg("generate")
                 .arg("--image-dir")
                 .arg(&this.image_dir)
-                .arg(format!("--component-name={}", &component_name));
+                .arg(format!("--component-name={component_name}"));
 
             if let Some((dir, dirs)) = this.bulk_dirs.split_first() {
                 let mut arg = dir.as_os_str().to_os_string();
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 962484593b4..2621e9a6031 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -85,9 +85,9 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun
 COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
 RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
 
-RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0-linux.tar.gz | \
+RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \
   tar -xz
-ENV WASI_SDK_PATH=/tmp/wasi-sdk-22.0
+ENV WASI_SDK_PATH=/tmp/wasi-sdk-23.0-x86_64-linux
 
 COPY scripts/freebsd-toolchain.sh /tmp/
 RUN /tmp/freebsd-toolchain.sh i686
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
index c7b3376e2f1..d7c2d3fde5b 100644
--- a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
+++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
@@ -11,4 +11,4 @@
 #    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
 #
 
-reuse
+reuse>=4.0,<5.0
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
index b0f598f77ea..8784e18864b 100644
--- a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
+++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
@@ -4,6 +4,10 @@
 #
 #    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
 #
+attrs==23.2.0 \
+    --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
+    --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
+    # via reuse
 binaryornot==0.4.4 \
     --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \
     --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4
@@ -14,71 +18,91 @@ boolean-py==4.0 \
     # via
     #   license-expression
     #   reuse
-chardet==5.1.0 \
-    --hash=sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5 \
-    --hash=sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9
+chardet==5.2.0 \
+    --hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \
+    --hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970
     # via
     #   binaryornot
     #   python-debian
-jinja2==3.1.2 \
-    --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
-    --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
+jinja2==3.1.4 \
+    --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
+    --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
     # via reuse
-license-expression==30.0.0 \
-    --hash=sha256:ad638292aa8493f84354909b517922cb823582c2ce2c4d880e42544a86bea8dd \
-    --hash=sha256:e95325110110eb2b7539ee7773b97a0724d5371ec563cc718c8cac0e38cc40cc
+license-expression==30.3.0 \
+    --hash=sha256:1295406f736b4f395ff069aec1cebfad53c0fcb3cf57df0f5ec58fc7b905aea5 \
+    --hash=sha256:ae0ba9a829d6909c785dc2f0131f13d10d68318e4a5f28af5ef152d6b52f9b41
     # via reuse
-markupsafe==2.1.1 \
-    --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \
-    --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \
-    --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \
-    --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \
-    --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \
-    --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \
-    --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \
-    --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \
-    --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \
-    --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \
-    --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \
-    --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \
-    --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \
-    --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \
-    --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \
-    --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \
-    --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \
-    --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \
-    --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \
-    --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \
-    --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \
-    --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \
-    --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \
-    --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \
-    --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \
-    --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \
-    --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \
-    --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \
-    --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \
-    --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \
-    --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \
-    --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \
-    --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \
-    --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \
-    --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \
-    --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \
-    --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \
-    --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \
-    --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \
-    --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7
+markupsafe==2.1.5 \
+    --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
+    --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
+    --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
+    --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
+    --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
+    --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
+    --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
+    --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
+    --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
+    --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
+    --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
+    --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
+    --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
+    --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
+    --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
+    --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
+    --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
+    --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
+    --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
+    --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
+    --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
+    --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
+    --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
+    --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
+    --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
+    --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
+    --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
+    --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
+    --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
+    --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
+    --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
+    --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
+    --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
+    --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
+    --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
+    --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
+    --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
+    --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
+    --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
+    --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
+    --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
+    --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
+    --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
+    --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
+    --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
+    --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
+    --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
+    --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
+    --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
+    --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
+    --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
+    --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
+    --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
+    --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
+    --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
+    --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
+    --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
+    --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
+    --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
+    --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
     # via jinja2
 python-debian==0.1.49 \
     --hash=sha256:880f3bc52e31599f2a9b432bd7691844286825087fccdcf2f6ffd5cd79a26f9f \
     --hash=sha256:8cf677a30dbcb4be7a99536c17e11308a827a4d22028dc59a67f6c6dd3f0f58c
     # via reuse
-reuse==1.1.0 \
-    --hash=sha256:7a054f6e372ad02d0b1b07368030fc38746b50ed45f5422a81994e7a88b52f1f \
-    --hash=sha256:b0f3fb9091ff513af04b555d14a4c529ab05f6a575ab192dd9b68244f1e0721d
+reuse==4.0.3 \
+    --hash=sha256:4f2c3e1213ec644e5febc50d8322d18982e4e1102af8a51d9493bfc2164a0eac \
+    --hash=sha256:b33e26ec1d105cfcfc2e904d103faec0d758994278feb95a4f4290a864562243
     # via -r reuse-requirements.in
-setuptools==66.0.0 \
-    --hash=sha256:a78d01d1e2c175c474884671dde039962c9d74c7223db7369771fcf6e29ceeab \
-    --hash=sha256:bd6eb2d6722568de6d14b87c44a96fac54b2a45ff5e940e639979a3d1792adb6
+tomlkit==0.13.0 \
+    --hash=sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72 \
+    --hash=sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264
     # via reuse
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index f874b2ed475..c2f5a87b123 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -40,9 +40,9 @@ WORKDIR /
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0-linux.tar.gz | \
+RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \
   tar -xz
-ENV WASI_SDK_PATH=/wasi-sdk-22.0
+ENV WASI_SDK_PATH=/wasi-sdk-23.0-x86_64-linux
 
 ENV RUST_CONFIGURE_ARGS \
   --musl-root-x86_64=/usr/local/x86_64-linux-musl \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index 53b4583166d..a5a5acc333b 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -8,6 +8,10 @@ X_PY="$1"
 
 # Try to test the toolstate-tracked tools and store the build/test success in the TOOLSTATE_FILE.
 
+# Pre-build the compiler and the library first to output a better error message when the build
+# itself fails (see https://github.com/rust-lang/rust/issues/127869 for context).
+python3 "$X_PY" build --stage 2 compiler rustdoc
+
 set +e
 python3 "$X_PY" test --stage 2 --no-fail-fast \
     src/doc/book \
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index a6e12c6ff95..638f14ad53f 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -326,6 +326,7 @@ auto:
       NO_DEBUG_ASSERTIONS: 1
       NO_OVERFLOW_CHECKS: 1
       DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-macos-m1
 
   # This target only needs to support 11.0 and up as nothing else supports the hardware
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 869f75e923d..c8201d9bcfd 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -19,7 +19,7 @@ if [ "$NO_CHANGE_USER" = "" ]; then
     # already be running with the right user.
     #
     # For NO_CHANGE_USER done in the small number of Dockerfiles affected.
-    echo -e '[safe]\n\tdirectory = *' > /home/user/gitconfig
+    echo -e '[safe]\n\tdirectory = *' > /home/user/.gitconfig
 
     exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
   fi
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 1a8ff931f01..292b6032f84 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -83,6 +83,7 @@
     - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [xtensa-\*-none-elf](platform-support/xtensa.md)
+    - [*-nuttx-\*](platform-support/nuttx.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 370dbed50fa..0c7f4e7bf1b 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -392,5 +392,17 @@ target | std | host | notes
 [`xtensa-esp32s2-espidf`](platform-support/esp-idf.md) | ✓ |  | Xtensa ESP32-S2
 [`xtensa-esp32s3-none-elf`](platform-support/xtensa.md) | * |  | Xtensa ESP32-S3
 [`xtensa-esp32s3-espidf`](platform-support/esp-idf.md) | ✓ |  | Xtensa ESP32-S3
+[`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | * |  | ARMv6M with NuttX
+[`thumbv7m-nuttx-eabi`](platform-support/nuttx.md) | * |  | ARMv7M with NuttX
+[`thumbv7em-nuttx-eabi`](platform-support/nuttx.md) | * |  | ARMv7EM with NuttX
+[`thumbv7em-nuttx-eabihf`](platform-support/nuttx.md) | * |  | ARMv7EM with NuttX, hardfloat
+[`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | * |  | ARMv8M Baseline with NuttX
+[`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | * |  | ARMv8M Mainline with NuttX
+[`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | * |  | ARMv8M Mainline with NuttX, hardfloat
+[`riscv32imc-unknown-nuttx-elf`](platform-support/nuttx.md) | * |  | RISC-V 32bit with NuttX
+[`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * |  | RISC-V 32bit with NuttX
+[`riscv32imafc-unknown-nuttx-elf`](platform-support/nuttx.md) | * |  | RISC-V 32bit with NuttX
+[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * |  | RISC-V 64bit with NuttX
+[`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | * |  | RISC-V 64bit with NuttX
 
 [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
diff --git a/src/doc/rustc/src/platform-support/nuttx.md b/src/doc/rustc/src/platform-support/nuttx.md
new file mode 100644
index 00000000000..cbbede45f52
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/nuttx.md
@@ -0,0 +1,60 @@
+# `*-nuttx-elf`
+
+**Tier: 3**
+
+Targets for the [Apache NuttX](https://github.com/apache/nuttx).
+
+Apache NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. It is scalable from 8-bit to 64-bit microcontroller environments. The primary governing standards in NuttX are POSIX and ANSI standards.
+
+NuttX adopts additional standard APIs from Unix and other common RTOSs, such as VxWorks. These APIs are used for functionality not available under the POSIX and ANSI standards. However, some APIs, like fork(), are not appropriate for deeply-embedded environments and are not implemented in NuttX.
+
+For brevity, many parts of the documentation will refer to Apache NuttX as simply NuttX.
+
+## Target maintainers
+
+- Qi Huang [@no1wudi](https://github.com/no1wudi)
+
+## Requirements
+
+The target name follow this format: `ARCH[-VENDOR]-nuttx-ABI`, where `ARCH` is the target architecture, `VENDOR` is the vendor name, and `ABI` is the ABI used.
+
+The following target names are defined:
+
+- `thumbv6m-nuttx-eal`
+- `thumbv7m-nuttx-eal`
+- `thumbv7em-nuttx-eabi`
+- `thumbv7em-nuttx-eabihf`
+- `thumbv8m.base-nuttx-eabi`
+- `thumbv8m.main-nuttx-eabi`
+- `thumbv8m.main-nuttx-eabihf`
+- `riscv32imc-unknown-nuttx-elf`
+- `riscv32imac-unknown-nuttx-elf`
+- `riscv32imafc-unknown-nuttx-elf`
+- `riscv64imac-unknown-nuttx-elf`
+- `riscv64gc-unknown-nuttx-elf`
+
+## Building the target
+
+The target can be built by enabled in the `rustc` build:
+
+```toml
+[build]
+target = "riscv32imc-unknown-nuttx-elf"
+
+[target.'riscv32imc-unknown-nuttx-elf']
+linker = "riscv-none-elf-gcc"
+```
+
+The toolchain for the target can be found in [NuttX's quick start guide](https://nuttx.apache.org/docs/latest/quickstart/install.html).
+
+
+## Testing
+
+This is a cross-compiled `no-std` target, which must be run either in a simulator
+or by programming them onto suitable hardware. It is not possible to run the
+Rust test-suite on this target.
+
+## Cross-compilation toolchains and C code
+
+This target supports C code. If interlinking with C or C++, you may need to use
+`riscv-none-elf-gcc` or `arm-none-eabi-gcc` as a linker instead of `rust-lld`.
diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md
index 4a1c0916253..c02c9aebe7e 100644
--- a/src/doc/rustdoc/src/advanced-features.md
+++ b/src/doc/rustdoc/src/advanced-features.md
@@ -38,33 +38,10 @@ they will both appear in documentation.
 Rustdoc does not have a magic way to compile documentation 'as-if' you'd run it once for each
 platform (such a magic wand has been called the ['holy grail of rustdoc'][#1998]). Instead,
 it sees *all* of your code at once, the same way the Rust compiler would if you passed it
-`--cfg doc`. However, Rustdoc has a trick up its sleeve to handle platform-specific code if it
-*does* receive it.
-
-To document your crate, Rustdoc only needs to know the public signature of your functions.
-In particular, it doesn't have to know how any of your functions are implemented, so it ignores
-all type errors and name resolution errors with function bodies. Note that this does *not*
-work for anything outside a function body: since Rustdoc documents your types, it has to
-know what those types are! For example, this code will work regardless of the platform:
-
-```rust,ignore (platform-specific,rustdoc-specific-behavior)
-pub fn f() {
-    use std::os::windows::ffi::OsStrExt;
-}
-```
-
-but this will not, because the unknown type is part of the function signature:
-
-```rust,ignore (platform-specific,rustdoc-specific-behavior)
-pub fn f() -> std::os::windows::ffi::EncodeWide<'static> {
-    unimplemented!()
-}
-```
-
-For a more realistic example of code this allows, see [the rustdoc test suite][realistic-async].
+`--cfg doc`. The main difference is that rustdoc doesn't run all the compiler passes, meaning
+that some invalid code won't emit an error.
 
 [#1998]: https://github.com/rust-lang/rust/issues/1998
-[realistic-async]: https://github.com/rust-lang/rust/blob/b146000e910ccd60bdcde89363cb6aa14ecc0d95/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs
 
 ## Add aliases for an item in documentation search
 
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 3d7ead99282..599e1e8102c 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -266,6 +266,7 @@ def get_known_directive_names():
 # To prevent duplicating the list of commmands between `compiletest` and `htmldocck`, we put
 # it into a common file which is included in rust code and parsed here.
 # FIXME: This setup is temporary until we figure out how to improve this situation.
+#        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
 KNOWN_DIRECTIVE_NAMES = get_known_directive_names()
 
 LINE_PATTERN = re.compile(r'''
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index a045be956ac..56cb5cddeea 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -4,11 +4,12 @@ version = "0.1.0"
 edition = "2021"
 publish = false
 
-[workspace]
-resolver = "1"
-
 [dependencies]
-rand = "0.8"
+indicatif = { version = "0.17.8", default-features = false }
+num = "0.4.3"
+rand = "0.8.5"
+rand_chacha = "0.3"
+rayon = "1"
 
 [lib]
 name = "test_float_parse"
diff --git a/src/etc/test-float-parse/README.md b/src/etc/test-float-parse/README.md
new file mode 100644
index 00000000000..21b20d0a072
--- /dev/null
+++ b/src/etc/test-float-parse/README.md
@@ -0,0 +1,55 @@
+# Float Parsing Tests
+
+These are tests designed to test decimal to float conversions (`dec2flt`) used
+by the standard library.
+
+It consistes of a collection of test generators that each generate a set of
+patterns intended to test a specific property. In addition, there are exhaustive
+tests (for <= `f32`) and fuzzers (for anything that can't be run exhaustively).
+
+The generators work as follows:
+
+- Each generator is a struct that lives somewhere in the `gen` module. Usually
+  it is generic over a float type.
+- These generators must implement `Iterator`, which should return a context type
+  that can be used to construct a test string (but usually not the string
+  itself).
+- They must also implement the `Generator` trait, which provides a method to
+  write test context to a string as a test case, as well as some extra metadata.
+
+  The split between context generation and string construction is so that we can
+  reuse string allocations.
+- Each generator gets registered once for each float type. Each of these
+  generators then get their iterator called, and each test case checked against
+  the float type's parse implementation.
+
+Some generators produce decimal strings, others create bit patterns that need to
+be bitcasted to the float type, which then uses its `Display` implementation to
+write to a string. For these, float to decimal (`flt2dec`) conversions also get
+tested, if unintentionally.
+
+For each test case, the following is done:
+
+- The test string is parsed to the float type using the standard library's
+  implementation.
+- The test string is parsed separately to a `BigRational`, which acts as a
+  representation with infinite precision.
+- The rational value then gets checked that it is within the float's
+  representable values (absolute value greater than the smallest number to round
+  to zero, but less less than the first value to round to infinity). If these
+  limits are exceeded, check that the parsed float reflects that.
+- For real nonzero numbers, the parsed float is converted into a rational using
+  `significand * 2^exponent`. It is then checked against the actual rational
+  value, and verified to be within half a bit's precision of the parsed value.
+  Also it is checked that ties round to even.
+
+This is all highly parallelized with `rayon`; test generators can run in
+parallel, and their tests get chunked and run in parallel.
+
+There is a simple command line that allows filtering which tests are run,
+setting the number of iterations for fuzzing tests, limiting failures, setting
+timeouts, etc. See `main.rs` or run with `--help` for options.
+
+Note that when running via `./x`, only tests that take less than a few minutes
+are run by default. Navigate to the crate (or pass `-C` to Cargo) and run it
+directly to run all tests or pass specific arguments.
diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py
deleted file mode 100755
index cc5e31a051f..00000000000
--- a/src/etc/test-float-parse/runtests.py
+++ /dev/null
@@ -1,394 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Testing dec2flt
-===============
-These are *really* extensive tests. Expect them to run for hours. Due to the
-nature of the problem (the input is a string of arbitrary length), exhaustive
-testing is not really possible. Instead, there are exhaustive tests for some
-classes of inputs for which that is feasible and a bunch of deterministic and
-random non-exhaustive tests for covering everything else.
-
-The actual tests (generating decimal strings and feeding them to dec2flt) is
-performed by a set of stand-along rust programs. This script compiles, runs,
-and supervises them. The programs report the strings they generate and the
-floating point numbers they converted those strings to, and this script
-checks that the results are correct.
-
-You can run specific tests rather than all of them by giving their names
-(without .rs extension) as command line parameters.
-
-Verification
-------------
-The tricky part is not generating those inputs but verifying the outputs.
-Comparing with the result of Python's float() does not cut it because
-(and this is apparently undocumented) although Python includes a version of
-Martin Gay's code including the decimal-to-float part, it doesn't actually use
-it for float() (only for round()) instead relying on the system scanf() which
-is not necessarily completely accurate.
-
-Instead, we take the input and compute the true value with bignum arithmetic
-(as a fraction, using the ``fractions`` module).
-
-Given an input string and the corresponding float computed via Rust, simply
-decode the float into f * 2^k (for integers f, k) and the ULP.
-We can now easily compute the error and check if it is within 0.5 ULP as it
-should be. Zero and infinites are handled similarly:
-
-- If the approximation is 0.0, the exact value should be *less or equal*
-  half the smallest denormal float: the smallest denormal floating point
-  number has an odd mantissa (00...001) and thus half of that is rounded
-  to 00...00, i.e., zero.
-- If the approximation is Inf, the exact value should be *greater or equal*
-  to the largest finite float + 0.5 ULP: the largest finite float has an odd
-  mantissa (11...11), so that plus half an ULP is rounded up to the nearest
-  even number, which overflows.
-
-Implementation details
-----------------------
-This directory contains a set of single-file Rust programs that perform
-tests with a particular class of inputs. Each is compiled and run without
-parameters, outputs (f64, f32, decimal) pairs to verify externally, and
-in any case either exits gracefully or with a panic.
-
-If a test binary writes *anything at all* to stderr or exits with an
-exit code that's not 0, the test fails.
-The output on stdout is treated as (f64, f32, decimal) record, encoded thusly:
-
-- First, the bits of the f64 encoded as an ASCII hex string.
-- Second, the bits of the f32 encoded as an ASCII hex string.
-- Then the corresponding string input, in ASCII
-- The record is terminated with a newline.
-
-Incomplete records are an error. Not-a-Number bit patterns are invalid too.
-
-The tests run serially but the validation for a single test is parallelized
-with ``multiprocessing``. Each test is launched as a subprocess.
-One thread supervises it: Accepts and enqueues records to validate, observe
-stderr, and waits for the process to exit. A set of worker processes perform
-the validation work for the outputs enqueued there. Another thread listens
-for progress updates from the workers.
-
-Known issues
-------------
-Some errors (e.g., NaN outputs) aren't handled very gracefully.
-Also, if there is an exception or the process is interrupted (at least on
-Windows) the worker processes are leaked and stick around forever.
-They're only a few megabytes each, but still, this script should not be run
-if you aren't prepared to manually kill a lot of orphaned processes.
-"""
-from __future__ import print_function
-import sys
-import os.path
-import time
-import struct
-from fractions import Fraction
-from collections import namedtuple
-from subprocess import Popen, check_call, PIPE
-from glob import glob
-import multiprocessing
-import threading
-import ctypes
-import binascii
-
-try:  # Python 3
-    import queue as Queue
-except ImportError:  # Python 2
-    import Queue
-
-NUM_WORKERS = 2
-UPDATE_EVERY_N = 50000
-INF = namedtuple('INF', '')()
-NEG_INF = namedtuple('NEG_INF', '')()
-ZERO = namedtuple('ZERO', '')()
-MAILBOX = None  # The queue for reporting errors to the main process.
-STDOUT_LOCK = threading.Lock()
-test_name = None
-child_processes = []
-exit_status = 0
-
-def msg(*args):
-    with STDOUT_LOCK:
-        print("[" + test_name + "]", *args)
-        sys.stdout.flush()
-
-
-def write_errors():
-    global exit_status
-    f = open("errors.txt", 'w')
-    have_seen_error = False
-    while True:
-        args = MAILBOX.get()
-        if args is None:
-            f.close()
-            break
-        print(*args, file=f)
-        f.flush()
-        if not have_seen_error:
-            have_seen_error = True
-            msg("Something is broken:", *args)
-            msg("Future errors will be logged to errors.txt")
-            exit_status = 101
-
-
-def cargo():
-    print("compiling tests")
-    sys.stdout.flush()
-    check_call(['cargo', 'build', '--release'])
-
-
-def run(test):
-    global test_name
-    test_name = test
-
-    t0 = time.perf_counter()
-    msg("setting up supervisor")
-    command = ['cargo', 'run', '--bin', test, '--release']
-    proc = Popen(command, bufsize=1<<20 , stdin=PIPE, stdout=PIPE, stderr=PIPE)
-    done = multiprocessing.Value(ctypes.c_bool)
-    queue = multiprocessing.Queue(maxsize=5)#(maxsize=1024)
-    workers = []
-    for n in range(NUM_WORKERS):
-        worker = multiprocessing.Process(name='Worker-' + str(n + 1),
-                                         target=init_worker,
-                                         args=[test, MAILBOX, queue, done])
-        workers.append(worker)
-        child_processes.append(worker)
-    for worker in workers:
-        worker.start()
-    msg("running test")
-    interact(proc, queue)
-    with done.get_lock():
-        done.value = True
-    for worker in workers:
-        worker.join()
-    msg("python is done")
-    assert queue.empty(), "did not validate everything"
-    dt = time.perf_counter() - t0
-    msg("took", round(dt, 3), "seconds")
-
-
-def interact(proc, queue):
-    n = 0
-    while proc.poll() is None:
-        line = proc.stdout.readline()
-        if not line:
-            continue
-        assert line.endswith(b'\n'), "incomplete line: " + repr(line)
-        queue.put(line)
-        n += 1
-        if n % UPDATE_EVERY_N == 0:
-            msg("got", str(n // 1000) + "k", "records")
-    msg("rust is done. exit code:", proc.returncode)
-    rest, stderr = proc.communicate()
-    if stderr:
-        msg("rust stderr output:", stderr)
-    for line in rest.split(b'\n'):
-        if not line:
-            continue
-        queue.put(line)
-
-
-def main():
-    global MAILBOX
-    files = glob('src/bin/*.rs')
-    basenames = [os.path.basename(i) for i in files]
-    all_tests = [os.path.splitext(f)[0] for f in basenames if not f.startswith('_')]
-    args = sys.argv[1:]
-    if args:
-        tests = [test for test in all_tests if test in args]
-    else:
-        tests = all_tests
-    if not tests:
-        print("Error: No tests to run")
-        sys.exit(1)
-    # Compile first for quicker feedback
-    cargo()
-    # Set up mailbox once for all tests
-    MAILBOX = multiprocessing.Queue()
-    mailman = threading.Thread(target=write_errors)
-    mailman.daemon = True
-    mailman.start()
-    for test in tests:
-        run(test)
-    MAILBOX.put(None)
-    mailman.join()
-
-
-# ---- Worker thread code ----
-
-
-POW2 = { e: Fraction(2) ** e for e in range(-1100, 1100) }
-HALF_ULP = { e: (Fraction(2) ** e)/2 for e in range(-1100, 1100) }
-DONE_FLAG = None
-
-
-def send_error_to_supervisor(*args):
-    MAILBOX.put(args)
-
-
-def init_worker(test, mailbox, queue, done):
-    global test_name, MAILBOX, DONE_FLAG
-    test_name = test
-    MAILBOX = mailbox
-    DONE_FLAG = done
-    do_work(queue)
-
-
-def is_done():
-    with DONE_FLAG.get_lock():
-        return DONE_FLAG.value
-
-
-def do_work(queue):
-    while True:
-        try:
-            line = queue.get(timeout=0.01)
-        except Queue.Empty:
-            if queue.empty() and is_done():
-                return
-            else:
-                continue
-        bin64, bin32, text = line.rstrip().split()
-        validate(bin64, bin32, text.decode('utf-8'))
-
-
-def decode_binary64(x):
-    """
-    Turn a IEEE 754 binary64 into (mantissa, exponent), except 0.0 and
-    infinity (positive and negative), which return ZERO, INF, and NEG_INF
-    respectively.
-    """
-    x = binascii.unhexlify(x)
-    assert len(x) == 8, repr(x)
-    [bits] = struct.unpack(b'>Q', x)
-    if bits == 0:
-        return ZERO
-    exponent = (bits >> 52) & 0x7FF
-    negative = bits >> 63
-    low_bits = bits & 0xFFFFFFFFFFFFF
-    if exponent == 0:
-        mantissa = low_bits
-        exponent += 1
-        if mantissa == 0:
-            return ZERO
-    elif exponent == 0x7FF:
-        assert low_bits == 0, "NaN"
-        if negative:
-            return NEG_INF
-        else:
-            return INF
-    else:
-        mantissa = low_bits | (1 << 52)
-    exponent -= 1023 + 52
-    if negative:
-        mantissa = -mantissa
-    return (mantissa, exponent)
-
-
-def decode_binary32(x):
-    """
-    Turn a IEEE 754 binary32 into (mantissa, exponent), except 0.0 and
-    infinity (positive and negative), which return ZERO, INF, and NEG_INF
-    respectively.
-    """
-    x = binascii.unhexlify(x)
-    assert len(x) == 4, repr(x)
-    [bits] = struct.unpack(b'>I', x)
-    if bits == 0:
-        return ZERO
-    exponent = (bits >> 23) & 0xFF
-    negative = bits >> 31
-    low_bits = bits & 0x7FFFFF
-    if exponent == 0:
-        mantissa = low_bits
-        exponent += 1
-        if mantissa == 0:
-            return ZERO
-    elif exponent == 0xFF:
-        if negative:
-            return NEG_INF
-        else:
-            return INF
-    else:
-        mantissa = low_bits | (1 << 23)
-    exponent -= 127 + 23
-    if negative:
-        mantissa = -mantissa
-    return (mantissa, exponent)
-
-
-MIN_SUBNORMAL_DOUBLE = Fraction(2) ** -1074
-MIN_SUBNORMAL_SINGLE = Fraction(2) ** -149  # XXX unsure
-MAX_DOUBLE = (2 - Fraction(2) ** -52) * (2 ** 1023)
-MAX_SINGLE = (2 - Fraction(2) ** -23) * (2 ** 127)
-MAX_ULP_DOUBLE = 1023 - 52
-MAX_ULP_SINGLE = 127 - 23
-DOUBLE_ZERO_CUTOFF = MIN_SUBNORMAL_DOUBLE / 2
-DOUBLE_INF_CUTOFF = MAX_DOUBLE + 2 ** (MAX_ULP_DOUBLE - 1)
-SINGLE_ZERO_CUTOFF = MIN_SUBNORMAL_SINGLE / 2
-SINGLE_INF_CUTOFF = MAX_SINGLE + 2 ** (MAX_ULP_SINGLE - 1)
-
-def validate(bin64, bin32, text):
-    try:
-        double = decode_binary64(bin64)
-    except AssertionError:
-        print(bin64, bin32, text)
-        raise
-    single = decode_binary32(bin32)
-    real = Fraction(text)
-
-    if double is ZERO:
-        if real > DOUBLE_ZERO_CUTOFF:
-            record_special_error(text, "f64 zero")
-    elif double is INF:
-        if real < DOUBLE_INF_CUTOFF:
-            record_special_error(text, "f64 inf")
-    elif double is NEG_INF:
-        if -real < DOUBLE_INF_CUTOFF:
-            record_special_error(text, "f64 -inf")
-    elif len(double) == 2:
-        sig, k = double
-        validate_normal(text, real, sig, k, "f64")
-    else:
-        assert 0, "didn't handle binary64"
-    if single is ZERO:
-        if real > SINGLE_ZERO_CUTOFF:
-            record_special_error(text, "f32 zero")
-    elif single is INF:
-        if real < SINGLE_INF_CUTOFF:
-            record_special_error(text, "f32 inf")
-    elif single is NEG_INF:
-        if -real < SINGLE_INF_CUTOFF:
-            record_special_error(text, "f32 -inf")
-    elif len(single) == 2:
-        sig, k = single
-        validate_normal(text, real, sig, k, "f32")
-    else:
-        assert 0, "didn't handle binary32"
-
-def record_special_error(text, descr):
-    send_error_to_supervisor(text.strip(), "wrongly rounded to", descr)
-
-
-def validate_normal(text, real, sig, k, kind):
-    approx = sig * POW2[k]
-    error = abs(approx - real)
-    if error > HALF_ULP[k]:
-        record_normal_error(text, error, k, kind)
-
-
-def record_normal_error(text, error, k, kind):
-    one_ulp = HALF_ULP[k + 1]
-    assert one_ulp == 2 * HALF_ULP[k]
-    relative_error = error / one_ulp
-    text = text.strip()
-    try:
-        err_repr = float(relative_error)
-    except ValueError:
-        err_repr = str(err_repr).replace('/', ' / ')
-    send_error_to_supervisor(err_repr, "ULP error on", text, "(" + kind + ")")
-
-
-if __name__ == '__main__':
-    main()
diff --git a/src/etc/test-float-parse/src/bin/few-ones.rs b/src/etc/test-float-parse/src/bin/few-ones.rs
deleted file mode 100644
index 6bb406a5947..00000000000
--- a/src/etc/test-float-parse/src/bin/few-ones.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    let mut pow = vec![];
-    for i in 0..63 {
-        pow.push(1u64 << i);
-    }
-    for a in &pow {
-        for b in &pow {
-            for c in &pow {
-                validate(&(a | b | c).to_string());
-            }
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/huge-pow10.rs b/src/etc/test-float-parse/src/bin/huge-pow10.rs
deleted file mode 100644
index 722a24ffcd8..00000000000
--- a/src/etc/test-float-parse/src/bin/huge-pow10.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    for e in 300..310 {
-        for i in 0..100000 {
-            validate(&format!("{}e{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/long-fractions.rs b/src/etc/test-float-parse/src/bin/long-fractions.rs
deleted file mode 100644
index c715bc1ac2b..00000000000
--- a/src/etc/test-float-parse/src/bin/long-fractions.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use std::char;
-use test_float_parse::validate;
-
-fn main() {
-    for n in 0..10 {
-        let digit = char::from_digit(n, 10).unwrap();
-        let mut s = "0.".to_string();
-        for _ in 0..400 {
-            s.push(digit);
-            if s.parse::<f64>().is_ok() {
-                validate(&s);
-            }
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/many-digits.rs b/src/etc/test-float-parse/src/bin/many-digits.rs
deleted file mode 100644
index ba166fd5607..00000000000
--- a/src/etc/test-float-parse/src/bin/many-digits.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-extern crate rand;
-
-use rand::distributions::{Range, Sample};
-use rand::{IsaacRng, Rng, SeedableRng};
-use std::char;
-use test_float_parse::{validate, SEED};
-
-fn main() {
-    let mut rnd = IsaacRng::from_seed(&SEED);
-    let mut range = Range::new(0, 10);
-    for _ in 0..5_000_000u64 {
-        let num_digits = rnd.gen_range(100, 400);
-        let digits = gen_digits(num_digits, &mut range, &mut rnd);
-        validate(&digits);
-    }
-}
-
-fn gen_digits<R: Rng>(n: u32, range: &mut Range<u32>, rnd: &mut R) -> String {
-    let mut s = String::new();
-    for _ in 0..n {
-        let digit = char::from_digit(range.sample(rnd), 10).unwrap();
-        s.push(digit);
-    }
-    s
-}
diff --git a/src/etc/test-float-parse/src/bin/rand-f64.rs b/src/etc/test-float-parse/src/bin/rand-f64.rs
deleted file mode 100644
index 6991e8be15e..00000000000
--- a/src/etc/test-float-parse/src/bin/rand-f64.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-extern crate rand;
-
-use rand::{IsaacRng, Rng, SeedableRng};
-use std::mem::transmute;
-use test_float_parse::{validate, SEED};
-
-fn main() {
-    let mut rnd = IsaacRng::from_seed(&SEED);
-    let mut i = 0;
-    while i < 10_000_000 {
-        let bits = rnd.next_u64();
-        let x: f64 = unsafe { transmute(bits) };
-        if x.is_finite() {
-            validate(&format!("{:e}", x));
-            i += 1;
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/short-decimals.rs b/src/etc/test-float-parse/src/bin/short-decimals.rs
deleted file mode 100644
index 49084eb35e8..00000000000
--- a/src/etc/test-float-parse/src/bin/short-decimals.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    // Skip e = 0 because small-u32 already does those.
-    for e in 1..301 {
-        for i in 0..10000 {
-            // If it ends in zeros, the parser will strip those (and adjust the exponent),
-            // which almost always (except for exponents near +/- 300) result in an input
-            // equivalent to something we already generate in a different way.
-            if i % 10 == 0 {
-                continue;
-            }
-            validate(&format!("{}e{}", i, e));
-            validate(&format!("{}e-{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/subnorm.rs b/src/etc/test-float-parse/src/bin/subnorm.rs
deleted file mode 100644
index ac88747eacd..00000000000
--- a/src/etc/test-float-parse/src/bin/subnorm.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use std::mem::transmute;
-use test_float_parse::validate;
-
-fn main() {
-    for bits in 0u32..(1 << 21) {
-        let single: f32 = unsafe { transmute(bits) };
-        validate(&format!("{:e}", single));
-        let double: f64 = unsafe { transmute(bits as u64) };
-        validate(&format!("{:e}", double));
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/tiny-pow10.rs b/src/etc/test-float-parse/src/bin/tiny-pow10.rs
deleted file mode 100644
index fb6ba166380..00000000000
--- a/src/etc/test-float-parse/src/bin/tiny-pow10.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    for e in 301..327 {
-        for i in 0..100000 {
-            validate(&format!("{}e-{}", i, e));
-        }
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/u32-small.rs b/src/etc/test-float-parse/src/bin/u32-small.rs
deleted file mode 100644
index 5ec9d1eea5f..00000000000
--- a/src/etc/test-float-parse/src/bin/u32-small.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    for i in 0..(1 << 19) {
-        validate(&i.to_string());
-    }
-}
diff --git a/src/etc/test-float-parse/src/bin/u64-pow2.rs b/src/etc/test-float-parse/src/bin/u64-pow2.rs
deleted file mode 100644
index 984e49200cd..00000000000
--- a/src/etc/test-float-parse/src/bin/u64-pow2.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use test_float_parse::validate;
-
-fn main() {
-    for exp in 19..64 {
-        let power: u64 = 1 << exp;
-        validate(&power.to_string());
-        for offset in 1..123 {
-            validate(&(power + offset).to_string());
-            validate(&(power - offset).to_string());
-        }
-    }
-    for offset in 0..123 {
-        validate(&(u64::MAX - offset).to_string());
-    }
-}
diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen/exhaustive.rs
new file mode 100644
index 00000000000..5d4b6df8e59
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/exhaustive.rs
@@ -0,0 +1,43 @@
+use std::fmt::Write;
+use std::ops::RangeInclusive;
+
+use crate::{Float, Generator, Int};
+
+/// Test every possible bit pattern. This is infeasible to run on any float types larger than
+/// `f32` (which takes about an hour).
+pub struct Exhaustive<F: Float> {
+    iter: RangeInclusive<F::Int>,
+}
+
+impl<F: Float> Generator<F> for Exhaustive<F>
+where
+    RangeInclusive<F::Int>: Iterator<Item = F::Int>,
+{
+    const NAME: &'static str = "exhaustive";
+    const SHORT_NAME: &'static str = "exhaustive";
+
+    type WriteCtx = F;
+
+    fn total_tests() -> u64 {
+        F::Int::MAX.try_into().unwrap_or(u64::MAX)
+    }
+
+    fn new() -> Self {
+        Self { iter: F::Int::ZERO..=F::Int::MAX }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx:e}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for Exhaustive<F>
+where
+    RangeInclusive<F::Int>: Iterator<Item = F::Int>,
+{
+    type Item = F;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        Some(F::from_bits(self.iter.next()?))
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen/exponents.rs
new file mode 100644
index 00000000000..3748e9d380c
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/exponents.rs
@@ -0,0 +1,95 @@
+use std::fmt::Write;
+use std::ops::RangeInclusive;
+
+use crate::traits::BoxGenIter;
+use crate::{Float, Generator};
+
+const SMALL_COEFF_MAX: i32 = 10_000;
+const SMALL_EXP_MAX: i32 = 300;
+
+const SMALL_COEFF_RANGE: RangeInclusive<i32> = (-SMALL_COEFF_MAX)..=SMALL_COEFF_MAX;
+const SMALL_EXP_RANGE: RangeInclusive<i32> = (-SMALL_EXP_MAX)..=SMALL_EXP_MAX;
+
+const LARGE_COEFF_RANGE: RangeInclusive<u32> = 0..=100_000;
+const LARGE_EXP_RANGE: RangeInclusive<u32> = 300..=350;
+
+/// Check exponential values around zero.
+pub struct SmallExponents<F: Float> {
+    iter: BoxGenIter<Self, F>,
+}
+
+impl<F: Float> Generator<F> for SmallExponents<F> {
+    const NAME: &'static str = "small exponents";
+    const SHORT_NAME: &'static str = "small exp";
+
+    /// `(coefficient, exponent)`
+    type WriteCtx = (i32, i32);
+
+    fn total_tests() -> u64 {
+        ((1 + SMALL_COEFF_RANGE.end() - SMALL_COEFF_RANGE.start())
+            * (1 + SMALL_EXP_RANGE.end() - SMALL_EXP_RANGE.start()))
+        .try_into()
+        .unwrap()
+    }
+
+    fn new() -> Self {
+        let iter = SMALL_EXP_RANGE.flat_map(|exp| SMALL_COEFF_RANGE.map(move |coeff| (coeff, exp)));
+
+        Self { iter: Box::new(iter) }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        let (coeff, exp) = ctx;
+        write!(s, "{coeff}e{exp}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for SmallExponents<F> {
+    type Item = (i32, i32);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next()
+    }
+}
+
+/// Check exponential values further from zero.
+pub struct LargeExponents<F: Float> {
+    iter: BoxGenIter<Self, F>,
+}
+
+impl<F: Float> Generator<F> for LargeExponents<F> {
+    const NAME: &'static str = "large positive exponents";
+    const SHORT_NAME: &'static str = "large exp";
+
+    /// `(coefficient, exponent, is_positive)`
+    type WriteCtx = (u32, u32, bool);
+
+    fn total_tests() -> u64 {
+        ((1 + LARGE_EXP_RANGE.end() - LARGE_EXP_RANGE.start())
+            * (1 + LARGE_COEFF_RANGE.end() - LARGE_COEFF_RANGE.start())
+            * 2)
+        .into()
+    }
+
+    fn new() -> Self {
+        let iter = LARGE_EXP_RANGE
+            .flat_map(|exp| LARGE_COEFF_RANGE.map(move |coeff| (coeff, exp)))
+            .flat_map(|(coeff, exp)| [(coeff, exp, false), (coeff, exp, true)]);
+
+        Self { iter: Box::new(iter) }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        let (coeff, exp, is_positive) = ctx;
+        let sign = if is_positive { "" } else { "-" };
+        write!(s, "{sign}{coeff}e{exp}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for LargeExponents<F> {
+    type Item = (u32, u32, bool);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next()
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen/fuzz.rs
new file mode 100644
index 00000000000..213bcfc64af
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/fuzz.rs
@@ -0,0 +1,88 @@
+use std::any::{type_name, TypeId};
+use std::collections::BTreeMap;
+use std::fmt::Write;
+use std::marker::PhantomData;
+use std::ops::Range;
+use std::sync::Mutex;
+
+use rand::distributions::{Distribution, Standard};
+use rand::Rng;
+use rand_chacha::rand_core::SeedableRng;
+use rand_chacha::ChaCha8Rng;
+
+use crate::{Float, Generator, Int, SEED};
+
+/// Mapping of float types to the number of iterations that should be run.
+///
+/// We could probably make `Generator::new` take an argument instead of the global state,
+/// but we only load this once so it works.
+static FUZZ_COUNTS: Mutex<BTreeMap<TypeId, u64>> = Mutex::new(BTreeMap::new());
+
+/// Generic fuzzer; just tests deterministic random bit patterns N times.
+pub struct Fuzz<F> {
+    iter: Range<u64>,
+    rng: ChaCha8Rng,
+    /// Allow us to use generics in `Iterator`.
+    marker: PhantomData<F>,
+}
+
+impl<F: Float> Fuzz<F> {
+    /// Register how many iterations the fuzzer should run for a type. Uses some logic by
+    /// default, but if `from_cfg` is `Some`, that will be used instead.
+    pub fn set_iterations(from_cfg: Option<u64>) {
+        let count = if let Some(cfg_count) = from_cfg {
+            cfg_count
+        } else if F::BITS <= crate::MAX_BITS_FOR_EXHAUUSTIVE {
+            // If we run exhaustively, still fuzz but only do half as many bits. The only goal here is
+            // to catch failures from e.g. high bit patterns before exhaustive tests would get to them.
+            (F::Int::MAX >> (F::BITS / 2)).try_into().unwrap()
+        } else {
+            // Eveything bigger gets a fuzz test with as many iterations as `f32` exhaustive.
+            u32::MAX.into()
+        };
+
+        let _ = FUZZ_COUNTS.lock().unwrap().insert(TypeId::of::<F>(), count);
+    }
+}
+
+impl<F: Float> Generator<F> for Fuzz<F>
+where
+    Standard: Distribution<<F as Float>::Int>,
+{
+    const NAME: &'static str = "fuzz";
+    const SHORT_NAME: &'static str = "fuzz";
+
+    type WriteCtx = F;
+
+    fn total_tests() -> u64 {
+        *FUZZ_COUNTS
+            .lock()
+            .unwrap()
+            .get(&TypeId::of::<F>())
+            .unwrap_or_else(|| panic!("missing fuzz count for {}", type_name::<F>()))
+    }
+
+    fn new() -> Self {
+        let rng = ChaCha8Rng::from_seed(SEED);
+
+        Self { iter: 0..Self::total_tests(), rng, marker: PhantomData }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx:e}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for Fuzz<F>
+where
+    Standard: Distribution<<F as Float>::Int>,
+{
+    type Item = <Self as Generator<F>>::WriteCtx;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let _ = self.iter.next()?;
+        let i: F::Int = self.rng.gen();
+
+        Some(F::from_bits(i))
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen/integers.rs
new file mode 100644
index 00000000000..070d188e88c
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/integers.rs
@@ -0,0 +1,104 @@
+use std::fmt::Write;
+use std::ops::{Range, RangeInclusive};
+
+use crate::traits::BoxGenIter;
+use crate::{Float, Generator};
+
+const SMALL_MAX_POW2: u32 = 19;
+
+/// All values up to the max power of two
+const SMALL_VALUES: RangeInclusive<i32> = {
+    let max = 1i32 << SMALL_MAX_POW2;
+    (-max)..=max
+};
+
+/// Large values only get tested around powers of two
+const LARGE_POWERS: Range<u32> = SMALL_MAX_POW2..128;
+
+/// We perturbe each large value around these ranges
+const LARGE_PERTURBATIONS: RangeInclusive<i128> = -256..=256;
+
+/// Test all integers up to `2 ^ MAX_POW2`
+pub struct SmallInt {
+    iter: RangeInclusive<i32>,
+}
+
+impl<F: Float> Generator<F> for SmallInt {
+    const NAME: &'static str = "small integer values";
+    const SHORT_NAME: &'static str = "int small";
+
+    type WriteCtx = i32;
+
+    fn total_tests() -> u64 {
+        (SMALL_VALUES.end() + 1 - SMALL_VALUES.start()).try_into().unwrap()
+    }
+
+    fn new() -> Self {
+        Self { iter: SMALL_VALUES }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx}").unwrap();
+    }
+}
+
+impl Iterator for SmallInt {
+    type Item = i32;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next()
+    }
+}
+
+/// Test much bigger integers than [`SmallInt`].
+pub struct LargeInt<F: Float> {
+    iter: BoxGenIter<Self, F>,
+}
+
+impl<F: Float> LargeInt<F> {
+    const EDGE_CASES: [i128; 7] = [
+        i32::MIN as i128,
+        i32::MAX as i128,
+        i64::MIN as i128,
+        i64::MAX as i128,
+        u64::MAX as i128,
+        i128::MIN,
+        i128::MAX,
+    ];
+}
+
+impl<F: Float> Generator<F> for LargeInt<F> {
+    const NAME: &'static str = "large integer values";
+    const SHORT_NAME: &'static str = "int large";
+
+    type WriteCtx = i128;
+
+    fn total_tests() -> u64 {
+        u64::try_from(
+            (i128::from(LARGE_POWERS.end - LARGE_POWERS.start)
+                + i128::try_from(Self::EDGE_CASES.len()).unwrap())
+                * (LARGE_PERTURBATIONS.end() + 1 - LARGE_PERTURBATIONS.start()),
+        )
+        .unwrap()
+    }
+
+    fn new() -> Self {
+        let iter = LARGE_POWERS
+            .map(|pow| 1i128 << pow)
+            .chain(Self::EDGE_CASES)
+            .flat_map(|base| LARGE_PERTURBATIONS.map(move |perturb| base.saturating_add(perturb)));
+
+        Self { iter: Box::new(iter) }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx}").unwrap();
+    }
+}
+impl<F: Float> Iterator for LargeInt<F> {
+    type Item = i128;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next()
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen/long_fractions.rs
new file mode 100644
index 00000000000..b75148b779c
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/long_fractions.rs
@@ -0,0 +1,58 @@
+use std::char;
+use std::fmt::Write;
+
+use crate::{Float, Generator};
+
+/// Number of decimal digits to check (all of them).
+const MAX_DIGIT: u32 = 9;
+/// Test with this many decimals in the string.
+const MAX_DECIMALS: usize = 410;
+const PREFIX: &str = "0.";
+
+/// Test e.g. `0.1`, `0.11`, `0.111`, `0.1111`, ..., `0.2`, `0.22`, ...
+pub struct RepeatingDecimal {
+    digit: u32,
+    buf: String,
+}
+
+impl<F: Float> Generator<F> for RepeatingDecimal {
+    const NAME: &'static str = "repeating decimal";
+    const SHORT_NAME: &'static str = "dec rep";
+
+    type WriteCtx = String;
+
+    fn total_tests() -> u64 {
+        u64::from(MAX_DIGIT + 1) * u64::try_from(MAX_DECIMALS + 1).unwrap() + 1
+    }
+
+    fn new() -> Self {
+        Self { digit: 0, buf: PREFIX.to_owned() }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        *s = ctx;
+    }
+}
+
+impl Iterator for RepeatingDecimal {
+    type Item = String;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.digit > MAX_DIGIT {
+            return None;
+        }
+
+        let digit = self.digit;
+        let inc_digit = self.buf.len() - PREFIX.len() > MAX_DECIMALS;
+
+        if inc_digit {
+            // Reset the string
+            self.buf.clear();
+            self.digit += 1;
+            self.buf.write_str(PREFIX).unwrap();
+        }
+
+        self.buf.push(char::from_digit(digit, 10).unwrap());
+        Some(self.buf.clone())
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen/many_digits.rs
new file mode 100644
index 00000000000..aab8d5d704b
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/many_digits.rs
@@ -0,0 +1,84 @@
+use std::char;
+use std::fmt::Write;
+use std::marker::PhantomData;
+use std::ops::{Range, RangeInclusive};
+
+use rand::distributions::{Distribution, Uniform};
+use rand::{Rng, SeedableRng};
+use rand_chacha::ChaCha8Rng;
+
+use crate::{Float, Generator, SEED};
+
+/// Total iterations
+const ITERATIONS: u64 = 5_000_000;
+
+/// Possible lengths of the string, excluding decimals and exponents
+const POSSIBLE_NUM_DIGITS: RangeInclusive<usize> = 100..=400;
+
+/// Range of possible exponents
+const EXP_RANGE: Range<i32> = -4500..4500;
+
+/// Try strings of random digits.
+pub struct RandDigits<F> {
+    rng: ChaCha8Rng,
+    iter: Range<u64>,
+    uniform: Uniform<u32>,
+    /// Allow us to use generics in `Iterator`.
+    marker: PhantomData<F>,
+}
+
+impl<F: Float> Generator<F> for RandDigits<F> {
+    const NAME: &'static str = "random digits";
+
+    const SHORT_NAME: &'static str = "rand digits";
+
+    type WriteCtx = String;
+
+    fn total_tests() -> u64 {
+        ITERATIONS
+    }
+
+    fn new() -> Self {
+        let rng = ChaCha8Rng::from_seed(SEED);
+        let range = Uniform::from(0..10);
+
+        Self { rng, iter: 0..ITERATIONS, uniform: range, marker: PhantomData }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        *s = ctx;
+    }
+}
+
+impl<F: Float> Iterator for RandDigits<F> {
+    type Item = String;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let _ = self.iter.next()?;
+        let num_digits = self.rng.gen_range(POSSIBLE_NUM_DIGITS);
+        let has_decimal = self.rng.gen_bool(0.2);
+        let has_exp = self.rng.gen_bool(0.2);
+
+        let dec_pos = if has_decimal { Some(self.rng.gen_range(0..num_digits)) } else { None };
+
+        let mut s = String::with_capacity(num_digits);
+
+        for pos in 0..num_digits {
+            let digit = char::from_digit(self.uniform.sample(&mut self.rng), 10).unwrap();
+            s.push(digit);
+
+            if let Some(dec_pos) = dec_pos {
+                if pos == dec_pos {
+                    s.push('.');
+                }
+            }
+        }
+
+        if has_exp {
+            let exp = self.rng.gen_range(EXP_RANGE);
+            write!(s, "e{exp}").unwrap();
+        }
+
+        Some(s)
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen/sparse.rs
new file mode 100644
index 00000000000..389b71056a3
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/sparse.rs
@@ -0,0 +1,100 @@
+use std::fmt::Write;
+
+use crate::traits::BoxGenIter;
+use crate::{Float, Generator};
+
+const POWERS_OF_TWO: [u128; 128] = make_powers_of_two();
+
+const fn make_powers_of_two() -> [u128; 128] {
+    let mut ret = [0; 128];
+    let mut i = 0;
+    while i < 128 {
+        ret[i] = 1 << i;
+        i += 1;
+    }
+
+    ret
+}
+
+/// Can't clone this result because of lifetime errors, just use a macro.
+macro_rules! pow_iter {
+    () => {
+        (0..F::BITS).map(|i| F::Int::try_from(POWERS_OF_TWO[i as usize]).unwrap())
+    };
+}
+
+/// Test all numbers that include three 1s in the binary representation as integers.
+pub struct FewOnesInt<F: Float>
+where
+    FewOnesInt<F>: Generator<F>,
+{
+    iter: BoxGenIter<Self, F>,
+}
+
+impl<F: Float> Generator<F> for FewOnesInt<F>
+where
+    <F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
+{
+    const NAME: &'static str = "few ones int";
+    const SHORT_NAME: &'static str = "few ones int";
+
+    type WriteCtx = F::Int;
+
+    fn total_tests() -> u64 {
+        u64::from(F::BITS).pow(3)
+    }
+
+    fn new() -> Self {
+        let iter = pow_iter!()
+            .flat_map(move |a| pow_iter!().map(move |b| (a, b)))
+            .flat_map(move |(a, b)| pow_iter!().map(move |c| (a, b, c)))
+            .map(|(a, b, c)| a | b | c);
+
+        Self { iter: Box::new(iter) }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for FewOnesInt<F> {
+    type Item = F::Int;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next()
+    }
+}
+
+/// Similar to `FewOnesInt` except test those bit patterns as a float.
+pub struct FewOnesFloat<F: Float>(FewOnesInt<F>);
+
+impl<F: Float> Generator<F> for FewOnesFloat<F>
+where
+    <F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
+{
+    const NAME: &'static str = "few ones float";
+    const SHORT_NAME: &'static str = "few ones float";
+
+    type WriteCtx = F;
+
+    fn total_tests() -> u64 {
+        FewOnesInt::<F>::total_tests()
+    }
+
+    fn new() -> Self {
+        Self(FewOnesInt::new())
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx:e}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for FewOnesFloat<F> {
+    type Item = F;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next().map(|i| F::from_bits(i))
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen/spot_checks.rs
new file mode 100644
index 00000000000..18691f9d6cf
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/spot_checks.rs
@@ -0,0 +1,101 @@
+use std::fmt::Write;
+
+use crate::traits::{Float, Generator};
+
+const SPECIAL: &[&str] = &[
+    "inf", "Inf", "iNf", "INF", "-inf", "-Inf", "-iNf", "-INF", "+inf", "+Inf", "+iNf", "+INF",
+    "nan", "NaN", "NAN", "nAn", "-nan", "-NaN", "-NAN", "-nAn", "+nan", "+NaN", "+NAN", "+nAn",
+    "1", "-1", "+1", "1e1", "-1e1", "+1e1", "1e-1", "-1e-1", "+1e-1", "1e+1", "-1e+1", "+1e+1",
+    "1E1", "-1E1", "+1E1", "1E-1", "-1E-1", "+1E-1", "1E+1", "-1E+1", "+1E+1", "0", "-0", "+0",
+];
+
+/// Check various non-numeric special strings.
+pub struct Special {
+    iter: std::slice::Iter<'static, &'static str>,
+}
+
+impl<F: Float> Generator<F> for Special {
+    const NAME: &'static str = "special values";
+
+    const SHORT_NAME: &'static str = "special";
+
+    type WriteCtx = &'static str;
+
+    fn total_tests() -> u64 {
+        SPECIAL.len().try_into().unwrap()
+    }
+
+    fn new() -> Self {
+        Self { iter: SPECIAL.iter() }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        s.write_str(ctx).unwrap();
+    }
+}
+
+impl Iterator for Special {
+    type Item = &'static str;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next().copied()
+    }
+}
+
+/// Strings that we know have failed in the past
+const REGRESSIONS: &[&str] = &[
+    // From <https://github.com/rust-lang/rust/issues/31407>
+    "1234567890123456789012345678901234567890e-340",
+    "2.225073858507201136057409796709131975934819546351645648023426109724822222021076945516529523908135087914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630666655994938275772572015763062690663332647565300009245888316433037779791869612049497390377829704905051080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884423900265498198385487948292206894721689831099698365846814022854243330660339850886445804001034933970427567186443383770486037861622771738545623065874679014086723327636718749999999999999999999999999999999999999e-308",
+    "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308",
+    "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222507385850720138309023271733240406421921598046233183055332741688720443481391819585428315901251102056406733973103581100515243416155346010885601238537771882113077799353200233047961014744258363607192156504694250373420837525080665061665815894872049117996859163964850063590877011830487479978088775374994945158045160505091539985658247081864511353793580499211598108576605199243335211435239014879569960959128889160299264151106346631339366347758651302937176204732563178148566435087212282863764204484681140761391147706280168985324411002416144742161856716615054015428508471675290190316132277889672970737312333408698898317506783884692609277397797285865965494109136909540613646756870239867831529068098461721092462539672851562500000000000000001",
+    "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999",
+    "2.47032822920623272e-324",
+    "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316",
+    "3.237883913302901289588352412501532174863037669423108059901297049552301970670676565786835742587799557860615776559838283435514391084153169252689190564396459577394618038928365305143463955100356696665629202017331344031730044369360205258345803431471660032699580731300954848363975548690010751530018881758184174569652173110473696022749934638425380623369774736560008997404060967498028389191878963968575439222206416981462690113342524002724385941651051293552601421155333430225237291523843322331326138431477823591142408800030775170625915670728657003151953664260769822494937951845801530895238439819708403389937873241463484205608000027270531106827387907791444918534771598750162812548862768493201518991668028251730299953143924168545708663913273994694463908672332763671875E-319",
+    "6.953355807847677105972805215521891690222119817145950754416205607980030131549636688806115726399441880065386399864028691275539539414652831584795668560082999889551357784961446896042113198284213107935110217162654939802416034676213829409720583759540476786936413816541621287843248433202369209916612249676005573022703244799714622116542188837770376022371172079559125853382801396219552418839469770514904192657627060319372847562301074140442660237844114174497210955449896389180395827191602886654488182452409583981389442783377001505462015745017848754574668342161759496661766020028752888783387074850773192997102997936619876226688096314989645766000479009083731736585750335262099860150896718774401964796827166283225641992040747894382698751809812609536720628966577351093292236328125E-310",
+    "3.339068557571188581835713701280943911923401916998521771655656997328440314559615318168849149074662609099998113009465566426808170378434065722991659642619467706034884424989741080790766778456332168200464651593995817371782125010668346652995912233993254584461125868481633343674905074271064409763090708017856584019776878812425312008812326260363035474811532236853359905334625575404216060622858633280744301892470300555678734689978476870369853549413277156622170245846166991655321535529623870646888786637528995592800436177901746286272273374471701452991433047257863864601424252024791567368195056077320885329384322332391564645264143400798619665040608077549162173963649264049738362290606875883456826586710961041737908872035803481241600376705491726170293986797332763671875E-319",
+    "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324",
+    "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324",
+    "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324",
+    "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324",
+    "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324",
+    "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324",
+    "94393431193180696942841837085033647913224148539854e-358",
+    "104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075",
+    "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281249",
+    "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251",
+];
+
+/// Check items that failed in the past.
+pub struct RegressionCheck {
+    iter: std::slice::Iter<'static, &'static str>,
+}
+
+impl<F: Float> Generator<F> for RegressionCheck {
+    const NAME: &'static str = "regression check";
+
+    const SHORT_NAME: &'static str = "regression";
+
+    type WriteCtx = &'static str;
+
+    fn total_tests() -> u64 {
+        REGRESSIONS.len().try_into().unwrap()
+    }
+
+    fn new() -> Self {
+        Self { iter: REGRESSIONS.iter() }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        s.write_str(ctx).unwrap();
+    }
+}
+
+impl Iterator for RegressionCheck {
+    type Item = &'static str;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next().copied()
+    }
+}
diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen/subnorm.rs
new file mode 100644
index 00000000000..4fe3b90a3dd
--- /dev/null
+++ b/src/etc/test-float-parse/src/gen/subnorm.rs
@@ -0,0 +1,103 @@
+use std::cmp::min;
+use std::fmt::Write;
+use std::ops::RangeInclusive;
+
+use crate::{Float, Generator, Int};
+
+/// Spot check some edge cases for subnormals.
+pub struct SubnormEdgeCases<F: Float> {
+    cases: [F::Int; 6],
+    index: usize,
+}
+
+impl<F: Float> SubnormEdgeCases<F> {
+    /// Shorthand
+    const I1: F::Int = F::Int::ONE;
+
+    fn edge_cases() -> [F::Int; 6] {
+        // Comments use an 8-bit mantissa as a demo
+        [
+            // 0b00000001
+            Self::I1,
+            // 0b10000000
+            Self::I1 << (F::MAN_BITS - 1),
+            // 0b00001000
+            Self::I1 << ((F::MAN_BITS / 2) - 1),
+            // 0b00001111
+            Self::I1 << ((F::MAN_BITS / 2) - 1),
+            // 0b00001111
+            Self::I1 << ((F::MAN_BITS / 2) - 1),
+            // 0b11111111
+            F::MAN_MASK,
+        ]
+    }
+}
+
+impl<F: Float> Generator<F> for SubnormEdgeCases<F> {
+    const NAME: &'static str = "subnormal edge cases";
+    const SHORT_NAME: &'static str = "subnorm edge";
+
+    type WriteCtx = F;
+
+    fn new() -> Self {
+        Self { cases: Self::edge_cases(), index: 0 }
+    }
+
+    fn total_tests() -> u64 {
+        Self::edge_cases().len().try_into().unwrap()
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx:e}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for SubnormEdgeCases<F> {
+    type Item = F;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let i = self.cases.get(self.index)?;
+        self.index += 1;
+
+        Some(F::from_bits(*i))
+    }
+}
+
+/// Test all subnormals up to `1 << 22`.
+pub struct SubnormComplete<F: Float> {
+    iter: RangeInclusive<F::Int>,
+}
+
+impl<F: Float> Generator<F> for SubnormComplete<F>
+where
+    RangeInclusive<F::Int>: Iterator<Item = F::Int>,
+{
+    const NAME: &'static str = "subnormal";
+    const SHORT_NAME: &'static str = "subnorm ";
+
+    type WriteCtx = F;
+
+    fn total_tests() -> u64 {
+        let iter = Self::new().iter;
+        (F::Int::ONE + *iter.end() - *iter.start()).try_into().unwrap()
+    }
+
+    fn new() -> Self {
+        Self { iter: F::Int::ZERO..=min(F::Int::ONE << 22, F::MAN_BITS.try_into().unwrap()) }
+    }
+
+    fn write_string(s: &mut String, ctx: Self::WriteCtx) {
+        write!(s, "{ctx:e}").unwrap();
+    }
+}
+
+impl<F: Float> Iterator for SubnormComplete<F>
+where
+    RangeInclusive<F::Int>: Iterator<Item = F::Int>,
+{
+    type Item = F;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        Some(F::from_bits(self.iter.next()?))
+    }
+}
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index 9cbad5486b4..f36e3928d26 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -1,16 +1,526 @@
-use std::io;
-use std::io::prelude::*;
-use std::mem::transmute;
-
-// Nothing up my sleeve: Just (PI - 3) in base 16.
-#[allow(dead_code)]
-pub const SEED: [u32; 3] = [0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e];
-
-pub fn validate(text: &str) {
-    let mut out = io::stdout();
-    let x: f64 = text.parse().unwrap();
-    let f64_bytes: u64 = unsafe { transmute(x) };
-    let x: f32 = text.parse().unwrap();
-    let f32_bytes: u32 = unsafe { transmute(x) };
-    writeln!(&mut out, "{:016x} {:08x} {}", f64_bytes, f32_bytes, text).unwrap();
+mod traits;
+mod ui;
+mod validate;
+
+use std::any::{type_name, TypeId};
+use std::cmp::min;
+use std::ops::RangeInclusive;
+use std::process::ExitCode;
+use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::{mpsc, OnceLock};
+use std::{fmt, time};
+
+use indicatif::{MultiProgress, ProgressBar};
+use rand::distributions::{Distribution, Standard};
+use rayon::prelude::*;
+use time::{Duration, Instant};
+use traits::{Float, Generator, Int};
+
+/// Test generators.
+mod gen {
+    pub mod exhaustive;
+    pub mod exponents;
+    pub mod fuzz;
+    pub mod integers;
+    pub mod long_fractions;
+    pub mod many_digits;
+    pub mod sparse;
+    pub mod spot_checks;
+    pub mod subnorm;
+}
+
+/// How many failures to exit after if unspecified.
+const DEFAULT_MAX_FAILURES: u64 = 20;
+
+/// Register exhaustive tests only for <= 32 bits. No more because it would take years.
+const MAX_BITS_FOR_EXHAUUSTIVE: u32 = 32;
+
+/// If there are more tests than this threashold, the test will be defered until after all
+/// others run (so as to avoid thread pool starvation). They also can be excluded with
+/// `--skip-huge`.
+const HUGE_TEST_CUTOFF: u64 = 5_000_000;
+
+/// Seed for tests that use a deterministic RNG.
+const SEED: [u8; 32] = *b"3.141592653589793238462643383279";
+
+/// Global configuration
+#[derive(Debug)]
+pub struct Config {
+    pub timeout: Duration,
+    /// Failures per test
+    pub max_failures: u64,
+    pub disable_max_failures: bool,
+    /// If `None`, the default will be used
+    pub fuzz_count: Option<u64>,
+    pub skip_huge: bool,
+}
+
+impl Default for Config {
+    fn default() -> Self {
+        Self {
+            timeout: Duration::from_secs(60 * 60 * 3),
+            max_failures: DEFAULT_MAX_FAILURES,
+            disable_max_failures: false,
+            fuzz_count: None,
+            skip_huge: false,
+        }
+    }
+}
+
+/// Collect, filter, and launch all tests.
+pub fn run(cfg: Config, include: &[String], exclude: &[String]) -> ExitCode {
+    // With default parallelism, the CPU doesn't saturate. We don't need to be nice to
+    // other processes, so do 1.5x to make sure we use all available resources.
+    let threads = std::thread::available_parallelism().map(Into::into).unwrap_or(0) * 3 / 2;
+    rayon::ThreadPoolBuilder::new().num_threads(threads).build_global().unwrap();
+
+    let mut tests = register_tests(&cfg);
+    println!("registered");
+    let initial_tests: Vec<_> = tests.iter().map(|t| t.name.clone()).collect();
+
+    let unmatched: Vec<_> = include
+        .iter()
+        .chain(exclude.iter())
+        .filter(|filt| !tests.iter().any(|t| t.matches(filt)))
+        .collect();
+
+    assert!(
+        unmatched.is_empty(),
+        "filters were provided that have no matching tests: {unmatched:#?}"
+    );
+
+    tests.retain(|test| !exclude.iter().any(|exc| test.matches(exc)));
+
+    if cfg.skip_huge {
+        tests.retain(|test| !test.is_huge_test());
+    }
+
+    if !include.is_empty() {
+        tests.retain(|test| include.iter().any(|inc| test.matches(inc)));
+    }
+
+    for exc in initial_tests.iter().filter(|orig_name| !tests.iter().any(|t| t.name == **orig_name))
+    {
+        println!("Skipping test '{exc}'");
+    }
+
+    println!("launching");
+    let elapsed = launch_tests(&mut tests, &cfg);
+    ui::finish(&tests, elapsed, &cfg)
+}
+
+/// Enumerate tests to run but don't actaully run them.
+pub fn register_tests(cfg: &Config) -> Vec<TestInfo> {
+    let mut tests = Vec::new();
+
+    // Register normal generators for all floats.
+    register_float::<f32>(&mut tests, cfg);
+    register_float::<f64>(&mut tests, cfg);
+
+    tests.sort_unstable_by_key(|t| (t.float_name, t.gen_name));
+    for i in 0..(tests.len() - 1) {
+        if tests[i].gen_name == tests[i + 1].gen_name {
+            panic!("dupliate test name {}", tests[i].gen_name);
+        }
+    }
+
+    tests
+}
+
+/// Register all generators for a single float.
+fn register_float<F: Float>(tests: &mut Vec<TestInfo>, cfg: &Config)
+where
+    RangeInclusive<F::Int>: Iterator<Item = F::Int>,
+    <F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
+    Standard: Distribution<<F as traits::Float>::Int>,
+{
+    if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
+        // Only run exhaustive tests if there is a chance of completion.
+        TestInfo::register::<F, gen::exhaustive::Exhaustive<F>>(tests);
+    }
+
+    gen::fuzz::Fuzz::<F>::set_iterations(cfg.fuzz_count);
+
+    TestInfo::register::<F, gen::exponents::LargeExponents<F>>(tests);
+    TestInfo::register::<F, gen::exponents::SmallExponents<F>>(tests);
+    TestInfo::register::<F, gen::fuzz::Fuzz<F>>(tests);
+    TestInfo::register::<F, gen::integers::LargeInt<F>>(tests);
+    TestInfo::register::<F, gen::integers::SmallInt>(tests);
+    TestInfo::register::<F, gen::long_fractions::RepeatingDecimal>(tests);
+    TestInfo::register::<F, gen::many_digits::RandDigits<F>>(tests);
+    TestInfo::register::<F, gen::sparse::FewOnesFloat<F>>(tests);
+    TestInfo::register::<F, gen::sparse::FewOnesInt<F>>(tests);
+    TestInfo::register::<F, gen::spot_checks::RegressionCheck>(tests);
+    TestInfo::register::<F, gen::spot_checks::Special>(tests);
+    TestInfo::register::<F, gen::subnorm::SubnormComplete<F>>(tests);
+    TestInfo::register::<F, gen::subnorm::SubnormEdgeCases<F>>(tests);
+}
+
+/// Configuration for a single test.
+#[derive(Debug)]
+pub struct TestInfo {
+    pub name: String,
+    /// Tests are identified by the type ID of `(F, G)` (tuple of the float and generator type).
+    /// This gives an easy way to associate messages with tests.
+    id: TypeId,
+    float_name: &'static str,
+    gen_name: &'static str,
+    /// Name for display in the progress bar.
+    short_name: String,
+    total_tests: u64,
+    /// Function to launch this test.
+    launch: fn(&mpsc::Sender<Msg>, &TestInfo, &Config),
+    /// Progress bar to be updated.
+    pb: Option<ProgressBar>,
+    /// Once completed, this will be set.
+    completed: OnceLock<Completed>,
+}
+
+impl TestInfo {
+    /// Check if either the name or short name is a match, for filtering.
+    fn matches(&self, pat: &str) -> bool {
+        self.short_name.contains(pat) || self.name.contains(pat)
+    }
+
+    /// Create a `TestInfo` for a given float and generator, then add it to a list.
+    fn register<F: Float, G: Generator<F>>(v: &mut Vec<Self>) {
+        let f_name = type_name::<F>();
+        let gen_name = G::NAME;
+        let gen_short_name = G::SHORT_NAME;
+
+        let info = TestInfo {
+            id: TypeId::of::<(F, G)>(),
+            float_name: f_name,
+            gen_name,
+            pb: None,
+            name: format!("{f_name} {gen_name}"),
+            short_name: format!("{f_name} {gen_short_name}"),
+            launch: test_runner::<F, G>,
+            total_tests: G::total_tests(),
+            completed: OnceLock::new(),
+        };
+        v.push(info);
+    }
+
+    /// Pad the short name to a common width for progress bar use.
+    fn short_name_padded(&self) -> String {
+        format!("{:18}", self.short_name)
+    }
+
+    /// Create a progress bar for this test within a multiprogress bar.
+    fn register_pb(&mut self, mp: &MultiProgress, drop_bars: &mut Vec<ProgressBar>) {
+        self.pb = Some(ui::create_pb(mp, self.total_tests, &self.short_name_padded(), drop_bars));
+    }
+
+    /// When the test is finished, update progress bar messages and finalize.
+    fn finalize_pb(&self, c: &Completed) {
+        let pb = self.pb.as_ref().unwrap();
+        ui::finalize_pb(pb, &self.short_name_padded(), c);
+    }
+
+    /// True if this should be run after all others.
+    fn is_huge_test(&self) -> bool {
+        self.total_tests >= HUGE_TEST_CUTOFF
+    }
+}
+
+/// A message sent from test runner threads to the UI/log thread.
+#[derive(Clone, Debug)]
+struct Msg {
+    id: TypeId,
+    update: Update,
+}
+
+impl Msg {
+    /// Wrap an `Update` into a message for the specified type. We use the `TypeId` of `(F, G)` to
+    /// identify which test a message in the channel came from.
+    fn new<F: Float, G: Generator<F>>(u: Update) -> Self {
+        Self { id: TypeId::of::<(F, G)>(), update: u }
+    }
+
+    /// Get the matching test from a list. Panics if not found.
+    fn find_test<'a>(&self, tests: &'a [TestInfo]) -> &'a TestInfo {
+        tests.iter().find(|t| t.id == self.id).unwrap()
+    }
+
+    /// Update UI as needed for a single message received from the test runners.
+    fn handle(self, tests: &[TestInfo], mp: &MultiProgress) {
+        let test = self.find_test(tests);
+        let pb = test.pb.as_ref().unwrap();
+
+        match self.update {
+            Update::Started => {
+                mp.println(format!("Testing '{}'", test.name)).unwrap();
+            }
+            Update::Progress { executed, failures } => {
+                pb.set_message(format! {"{failures}"});
+                pb.set_position(executed);
+            }
+            Update::Failure { fail, input, float_res } => {
+                mp.println(format!(
+                    "Failure in '{}': {fail}. parsing '{input}'. Parsed as: {float_res}",
+                    test.name
+                ))
+                .unwrap();
+            }
+            Update::Completed(c) => {
+                test.finalize_pb(&c);
+
+                let prefix = match c.result {
+                    Ok(FinishedAll) => "Completed tests for",
+                    Err(EarlyExit::Timeout) => "Timed out",
+                    Err(EarlyExit::MaxFailures) => "Max failures reached for",
+                };
+
+                mp.println(format!(
+                    "{prefix} generator '{}' in {:?}. {} tests run, {} failures",
+                    test.name, c.elapsed, c.executed, c.failures
+                ))
+                .unwrap();
+                test.completed.set(c).unwrap();
+            }
+        };
+    }
+}
+
+/// Status sent with a message.
+#[derive(Clone, Debug)]
+enum Update {
+    /// Starting a new test runner.
+    Started,
+    /// Completed a out of b tests.
+    Progress { executed: u64, failures: u64 },
+    /// Received a failed test.
+    Failure {
+        fail: CheckFailure,
+        /// String for which parsing was attempted.
+        input: Box<str>,
+        /// The parsed & decomposed `FloatRes`, aleady stringified so we don't need generics here.
+        float_res: Box<str>,
+    },
+    /// Exited with an unexpected condition.
+    Completed(Completed),
+}
+
+/// Result of an input did not parsing successfully.
+#[derive(Clone, Debug)]
+enum CheckFailure {
+    /// Above the zero cutoff but got rounded to zero.
+    UnexpectedZero,
+    /// Below the infinity cutoff but got rounded to infinity.
+    UnexpectedInf,
+    /// Above the negative infinity cutoff but got rounded to negative infinity.
+    UnexpectedNegInf,
+    /// Got a `NaN` when none was expected.
+    UnexpectedNan,
+    /// Expected `NaN`, got none.
+    ExpectedNan,
+    /// Expected infinity, got finite.
+    ExpectedInf,
+    /// Expected negative infinity, got finite.
+    ExpectedNegInf,
+    /// The value exceeded its error tolerance.
+    InvalidReal {
+        /// Error from the expected value, as a float.
+        error_float: Option<f64>,
+        /// Error as a rational string (since it can't always be represented as a float).
+        error_str: Box<str>,
+        /// True if the error was caused by not rounding to even at the midpoint between
+        /// two representable values.
+        incorrect_midpoint_rounding: bool,
+    },
+}
+
+impl fmt::Display for CheckFailure {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            CheckFailure::UnexpectedZero => {
+                write!(f, "incorrectly rounded to 0 (expected nonzero)")
+            }
+            CheckFailure::UnexpectedInf => {
+                write!(f, "incorrectly rounded to +inf (expected finite)")
+            }
+            CheckFailure::UnexpectedNegInf => {
+                write!(f, "incorrectly rounded to -inf (expected finite)")
+            }
+            CheckFailure::UnexpectedNan => write!(f, "got a NaN where none was expected"),
+            CheckFailure::ExpectedNan => write!(f, "expected a NaN but did not get it"),
+            CheckFailure::ExpectedInf => write!(f, "expected +inf but did not get it"),
+            CheckFailure::ExpectedNegInf => write!(f, "expected -inf but did not get it"),
+            CheckFailure::InvalidReal { error_float, error_str, incorrect_midpoint_rounding } => {
+                if *incorrect_midpoint_rounding {
+                    write!(
+                        f,
+                        "midpoint between two representable values did not correctly \
+                        round to even; error: {error_str}"
+                    )?;
+                } else {
+                    write!(f, "real number did not parse correctly; error: {error_str}")?;
+                }
+
+                if let Some(float) = error_float {
+                    write!(f, " ({float})")?;
+                }
+                Ok(())
+            }
+        }
+    }
+}
+
+/// Information about a completed test generator.
+#[derive(Clone, Debug)]
+struct Completed {
+    /// Finished tests (both successful and failed).
+    executed: u64,
+    /// Failed tests.
+    failures: u64,
+    /// Extra exit information if unsuccessful.
+    result: Result<FinishedAll, EarlyExit>,
+    /// If there is something to warn about (e.g bad estimate), leave it here.
+    warning: Option<Box<str>>,
+    /// Total time to run the test.
+    elapsed: Duration,
+}
+
+/// Marker for completing all tests (used in `Result` types).
+#[derive(Clone, Debug)]
+struct FinishedAll;
+
+/// Reasons for exiting early.
+#[derive(Clone, Debug)]
+enum EarlyExit {
+    Timeout,
+    MaxFailures,
+}
+
+/// Run all tests in `tests`.
+///
+/// This launches a main thread that receives messages and handlees UI updates, and uses the
+/// rest of the thread pool to execute the tests.
+fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
+    // Run shorter tests first
+    tests.sort_unstable_by_key(|test| test.total_tests);
+
+    for test in tests.iter() {
+        println!("Launching test '{}'", test.name);
+    }
+
+    // Configure progress bars
+    let mut all_progress_bars = Vec::new();
+    let mp = MultiProgress::new();
+    mp.set_move_cursor(true);
+    for test in tests.iter_mut() {
+        test.register_pb(&mp, &mut all_progress_bars);
+    }
+
+    ui::set_panic_hook(all_progress_bars);
+
+    let (tx, rx) = mpsc::channel::<Msg>();
+    let start = Instant::now();
+
+    rayon::scope(|scope| {
+        // Thread that updates the UI
+        scope.spawn(|_scope| {
+            let rx = rx; // move rx
+
+            loop {
+                if tests.iter().all(|t| t.completed.get().is_some()) {
+                    break;
+                }
+
+                let msg = rx.recv().unwrap();
+                msg.handle(tests, &mp);
+            }
+
+            // All tests completed; finish things up
+            drop(mp);
+            assert_eq!(rx.try_recv().unwrap_err(), mpsc::TryRecvError::Empty);
+        });
+
+        // Don't let the thread pool be starved by huge tests. Run faster tests first in parallel,
+        // then parallelize only within the rest of the tests.
+        let (huge_tests, normal_tests): (Vec<_>, Vec<_>) =
+            tests.iter().partition(|t| t.is_huge_test());
+
+        // Run the actual tests
+        normal_tests.par_iter().for_each(|test| ((test.launch)(&tx, test, cfg)));
+
+        huge_tests.par_iter().for_each(|test| ((test.launch)(&tx, test, cfg)));
+    });
+
+    start.elapsed()
+}
+
+/// Test runer for a single generator.
+///
+/// This calls the generator's iterator multiple times (in parallel) and validates each output.
+fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestInfo, cfg: &Config) {
+    tx.send(Msg::new::<F, G>(Update::Started)).unwrap();
+
+    let total = G::total_tests();
+    let gen = G::new();
+    let executed = AtomicU64::new(0);
+    let failures = AtomicU64::new(0);
+
+    let checks_per_update = min(total, 1000);
+    let started = Instant::now();
+
+    // Function to execute for a single test iteration.
+    let check_one = |buf: &mut String, ctx: G::WriteCtx| {
+        let executed = executed.fetch_add(1, Ordering::Relaxed);
+        buf.clear();
+        G::write_string(buf, ctx);
+
+        match validate::validate::<F>(buf) {
+            Ok(()) => (),
+            Err(e) => {
+                tx.send(Msg::new::<F, G>(e)).unwrap();
+                let f = failures.fetch_add(1, Ordering::Relaxed);
+                // End early if the limit is exceeded.
+                if f >= cfg.max_failures {
+                    return Err(EarlyExit::MaxFailures);
+                }
+            }
+        };
+
+        // Send periodic updates
+        if executed % checks_per_update == 0 {
+            let failures = failures.load(Ordering::Relaxed);
+
+            tx.send(Msg::new::<F, G>(Update::Progress { executed, failures })).unwrap();
+
+            if started.elapsed() > cfg.timeout {
+                return Err(EarlyExit::Timeout);
+            }
+        }
+
+        Ok(())
+    };
+
+    // Run the test iterations in parallel. Each thread gets a string buffer to write
+    // its check values to.
+    let res = gen.par_bridge().try_for_each_init(|| String::with_capacity(100), check_one);
+
+    let elapsed = started.elapsed();
+    let executed = executed.into_inner();
+    let failures = failures.into_inner();
+
+    // Warn about bad estimates if relevant.
+    let warning = if executed != total && res.is_ok() {
+        let msg = format!("executed tests != estimated ({executed} != {total}) for {}", G::NAME);
+
+        Some(msg.into())
+    } else {
+        None
+    };
+
+    let result = res.map(|()| FinishedAll);
+    tx.send(Msg::new::<F, G>(Update::Completed(Completed {
+        executed,
+        failures,
+        result,
+        warning,
+        elapsed,
+    })))
+    .unwrap();
 }
diff --git a/src/etc/test-float-parse/src/main.rs b/src/etc/test-float-parse/src/main.rs
new file mode 100644
index 00000000000..9c6cad7324f
--- /dev/null
+++ b/src/etc/test-float-parse/src/main.rs
@@ -0,0 +1,129 @@
+use std::process::ExitCode;
+use std::time::Duration;
+
+use test_float_parse as tfp;
+
+static HELP: &str = r#"Usage:
+
+  ./test-float-parse [--timeout x] [--exclude x] [--max-failures x] [INCLUDE ...]
+  ./test-float-parse [--fuzz-count x] [INCLUDE ...]
+  ./test-float-parse [--skip-huge] [INCLUDE ...]
+  ./test-float-parse --list
+
+Args:
+
+  INCLUDE                  Include only tests with names containing these
+                           strings. If this argument is not specified, all tests
+                           are run.
+  --timeout N              Exit after this amount of time (in seconds).
+  --exclude FILTER         Skip tests containing this string. May be specified
+                           more than once.
+  --list                   List available tests.
+  --max-failures N         Limit to N failures per test. Defaults to 20. Pass
+                           "--max-failures none" to remove this limit.
+  --fuzz-count N           Run the fuzzer with N iterations. Only has an effect
+                           if fuzz tests are enabled. Pass `--fuzz-count none`
+                           to remove this limit.
+  --skip-huge              Skip tests that run for a long time.
+  --all                    Reset previous `--exclude`, `--skip-huge`, and
+                           `INCLUDE` arguments (useful for running all tests
+                           via `./x`).
+"#;
+
+enum ArgMode {
+    Any,
+    Timeout,
+    Exclude,
+    FuzzCount,
+    MaxFailures,
+}
+
+fn main() -> ExitCode {
+    if cfg!(debug_assertions) {
+        println!(
+            "WARNING: running in debug mode. Release mode is recommended to reduce test duration."
+        );
+        std::thread::sleep(Duration::from_secs(2));
+    }
+
+    let args: Vec<_> = std::env::args().skip(1).collect();
+    if args.iter().any(|arg| arg == "--help" || arg == "-h") {
+        println!("{HELP}");
+        return ExitCode::SUCCESS;
+    }
+
+    if args.iter().any(|arg| arg == "--list") {
+        let tests = tfp::register_tests(&tfp::Config::default());
+        println!("Available tests:");
+        for t in tests {
+            println!("{}", t.name);
+        }
+
+        return ExitCode::SUCCESS;
+    }
+
+    let (cfg, include, exclude) = parse_args(args);
+
+    tfp::run(cfg, &include, &exclude)
+}
+
+/// Simple command argument parser
+fn parse_args(args: Vec<String>) -> (tfp::Config, Vec<String>, Vec<String>) {
+    let mut cfg = tfp::Config::default();
+
+    let mut mode = ArgMode::Any;
+    let mut include = Vec::new();
+    let mut exclude = Vec::new();
+
+    for arg in args {
+        mode = match mode {
+            ArgMode::Any if arg == "--timeout" => ArgMode::Timeout,
+            ArgMode::Any if arg == "--exclude" => ArgMode::Exclude,
+            ArgMode::Any if arg == "--max-failures" => ArgMode::MaxFailures,
+            ArgMode::Any if arg == "--fuzz-count" => ArgMode::FuzzCount,
+            ArgMode::Any if arg == "--skip-huge" => {
+                cfg.skip_huge = true;
+                ArgMode::Any
+            }
+            ArgMode::Any if arg == "--all" => {
+                cfg.skip_huge = false;
+                include.clear();
+                exclude.clear();
+                ArgMode::Any
+            }
+            ArgMode::Any if arg.starts_with('-') => {
+                panic!("Unknown argument {arg}. Usage:\n{HELP}")
+            }
+            ArgMode::Any => {
+                include.push(arg);
+                ArgMode::Any
+            }
+            ArgMode::Timeout => {
+                cfg.timeout = Duration::from_secs(arg.parse().unwrap());
+                ArgMode::Any
+            }
+            ArgMode::MaxFailures => {
+                if arg == "none" {
+                    cfg.disable_max_failures = true;
+                } else {
+                    cfg.max_failures = arg.parse().unwrap();
+                }
+                ArgMode::Any
+            }
+            ArgMode::FuzzCount => {
+                if arg == "none" {
+                    cfg.fuzz_count = Some(u64::MAX);
+                } else {
+                    cfg.fuzz_count = Some(arg.parse().unwrap());
+                }
+                ArgMode::Any
+            }
+            ArgMode::Exclude => {
+                exclude.push(arg);
+                ArgMode::Any
+            }
+        }
+    }
+
+    (cfg, include, exclude)
+}
diff --git a/src/etc/test-float-parse/src/traits.rs b/src/etc/test-float-parse/src/traits.rs
new file mode 100644
index 00000000000..dc009ea235f
--- /dev/null
+++ b/src/etc/test-float-parse/src/traits.rs
@@ -0,0 +1,202 @@
+//! Interfaces used throughout this crate.
+
+use std::str::FromStr;
+use std::{fmt, ops};
+
+use num::bigint::ToBigInt;
+use num::Integer;
+
+use crate::validate::Constants;
+
+/// Integer types.
+#[allow(dead_code)] // Some functions only used for testing
+pub trait Int:
+    Clone
+    + Copy
+    + fmt::Debug
+    + fmt::Display
+    + fmt::LowerHex
+    + ops::Add<Output = Self>
+    + ops::Sub<Output = Self>
+    + ops::Shl<u32, Output = Self>
+    + ops::Shr<u32, Output = Self>
+    + ops::BitAnd<Output = Self>
+    + ops::BitOr<Output = Self>
+    + ops::Not<Output = Self>
+    + ops::AddAssign
+    + ops::BitAndAssign
+    + ops::BitOrAssign
+    + From<u8>
+    + TryFrom<i8>
+    + TryFrom<u32, Error: fmt::Debug>
+    + TryFrom<u64, Error: fmt::Debug>
+    + TryFrom<u128, Error: fmt::Debug>
+    + TryInto<u64, Error: fmt::Debug>
+    + TryInto<u32, Error: fmt::Debug>
+    + ToBigInt
+    + PartialOrd
+    + Integer
+    + Send
+    + 'static
+{
+    type Signed: Int;
+    type Bytes: Default + AsMut<[u8]>;
+
+    const BITS: u32;
+    const ZERO: Self;
+    const ONE: Self;
+    const MAX: Self;
+
+    fn to_signed(self) -> Self::Signed;
+    fn wrapping_neg(self) -> Self;
+    fn trailing_zeros(self) -> u32;
+
+    fn hex(self) -> String {
+        format!("{self:x}")
+    }
+}
+
+macro_rules! impl_int {
+    ($($uty:ty, $sty:ty);+) => {
+        $(
+            impl Int for $uty {
+                type Signed = $sty;
+                type Bytes = [u8; Self::BITS as usize / 8];
+                const BITS: u32 = Self::BITS;
+                const ZERO: Self = 0;
+                const ONE: Self = 1;
+                const MAX: Self = Self::MAX;
+                fn to_signed(self) -> Self::Signed {
+                    self.try_into().unwrap()
+                }
+                fn wrapping_neg(self) -> Self {
+                    self.wrapping_neg()
+                }
+                fn trailing_zeros(self) -> u32 {
+                    self.trailing_zeros()
+                }
+            }
+
+            impl Int for $sty {
+                type Signed = Self;
+                type Bytes = [u8; Self::BITS as usize / 8];
+                const BITS: u32 = Self::BITS;
+                const ZERO: Self = 0;
+                const ONE: Self = 1;
+                const MAX: Self = Self::MAX;
+                fn to_signed(self) -> Self::Signed {
+                    self
+                }
+                fn wrapping_neg(self) -> Self {
+                    self.wrapping_neg()
+                }
+                fn trailing_zeros(self) -> u32 {
+                    self.trailing_zeros()
+                }
+            }
+        )+
+    }
+}
+
+impl_int!(u32, i32; u64, i64);
+
+/// Floating point types.
+pub trait Float:
+    Copy + fmt::Debug + fmt::LowerExp + FromStr<Err: fmt::Display> + Sized + Send + 'static
+{
+    /// Unsigned integer of same width
+    type Int: Int<Signed = Self::SInt>;
+    type SInt: Int;
+
+    /// Total bits
+    const BITS: u32;
+
+    /// (Stored) bits in the mantissa)
+    const MAN_BITS: u32;
+
+    /// Bits in the exponent
+    const EXP_BITS: u32 = Self::BITS - Self::MAN_BITS - 1;
+
+    /// A saturated exponent (all ones)
+    const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
+
+    /// The exponent bias, also its maximum value
+    const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
+
+    const MAN_MASK: Self::Int;
+    const SIGN_MASK: Self::Int;
+
+    fn from_bits(i: Self::Int) -> Self;
+    fn to_bits(self) -> Self::Int;
+
+    /// Rational constants associated with this float type.
+    fn constants() -> &'static Constants;
+
+    fn is_sign_negative(self) -> bool {
+        (self.to_bits() & Self::SIGN_MASK) > Self::Int::ZERO
+    }
+
+    /// Exponent without adjustment for bias.
+    fn exponent(self) -> u32 {
+        ((self.to_bits() >> Self::MAN_BITS) & Self::EXP_SAT.try_into().unwrap()).try_into().unwrap()
+    }
+
+    fn mantissa(self) -> Self::Int {
+        self.to_bits() & Self::MAN_MASK
+    }
+}
+
+macro_rules! impl_float {
+    ($($fty:ty, $ity:ty, $bits:literal);+) => {
+        $(
+            impl Float for $fty {
+                type Int = $ity;
+                type SInt = <Self::Int as Int>::Signed;
+                const BITS: u32 = $bits;
+                const MAN_BITS: u32 = Self::MANTISSA_DIGITS - 1;
+                const MAN_MASK: Self::Int = (Self::Int::ONE << Self::MAN_BITS) - Self::Int::ONE;
+                const SIGN_MASK: Self::Int = Self::Int::ONE << (Self::BITS-1);
+                fn from_bits(i: Self::Int) -> Self { Self::from_bits(i) }
+                fn to_bits(self) -> Self::Int { self.to_bits() }
+                fn constants() -> &'static Constants {
+                    use std::sync::LazyLock;
+                    static CONSTANTS: LazyLock<Constants> = LazyLock::new(Constants::new::<$fty>);
+                    &CONSTANTS
+                }
+            }
+        )+
+    }
+}
+
+impl_float!(f32, u32, 32; f64, u64, 64);
+
+/// A test generator. Should provide an iterator that produces unique patterns to parse.
+///
+/// The iterator needs to provide a `WriteCtx` (could be anything), which is then used to
+/// write the string at a later step. This is done separately so that we can reuse string
+/// allocations (which otherwise turn out to be a pretty expensive part of these tests).
+pub trait Generator<F: Float>: Iterator<Item = Self::WriteCtx> + Send + 'static {
+    /// Full display and filtering name
+    const NAME: &'static str;
+
+    /// Name for display with the progress bar
+    const SHORT_NAME: &'static str;
+
+    /// The context needed to create a test string.
+    type WriteCtx: Send;
+
+    /// Number of tests that will be run.
+    fn total_tests() -> u64;
+
+    /// Constructor for this test generator.
+    fn new() -> Self;
+
+    /// Create a test string given write context, which was produced as a step from the iterator.
+    ///
+    /// `s` will be provided empty.
+    fn write_string(s: &mut String, ctx: Self::WriteCtx);
+}
+
+/// For tests that use iterator combinators, it is easier to just to box the iterator than trying
+/// to specify its type. This is a shorthand for the usual type.
+pub type BoxGenIter<This, F> = Box<dyn Iterator<Item = <This as Generator<F>>::WriteCtx> + Send>;
diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs
new file mode 100644
index 00000000000..f333bd4a55d
--- /dev/null
+++ b/src/etc/test-float-parse/src/ui.rs
@@ -0,0 +1,132 @@
+//! Progress bars and such.
+
+use std::io::{self, Write};
+use std::process::ExitCode;
+use std::time::Duration;
+
+use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
+
+use crate::{Completed, Config, EarlyExit, FinishedAll, TestInfo};
+
+/// Templates for progress bars.
+const PB_TEMPLATE: &str = "[{elapsed:3} {percent:3}%] {bar:20.cyan/blue} NAME ({pos}/{len}, {msg} f, {per_sec}, eta {eta})";
+const PB_TEMPLATE_FINAL: &str =
+    "[{elapsed:3} {percent:3}%] NAME ({pos}/{len}, {msg:.COLOR}, {per_sec}, {elapsed_precise})";
+
+/// Create a new progress bar within a multiprogress bar.
+pub fn create_pb(
+    mp: &MultiProgress,
+    total_tests: u64,
+    short_name_padded: &str,
+    all_bars: &mut Vec<ProgressBar>,
+) -> ProgressBar {
+    let pb = mp.add(ProgressBar::new(total_tests));
+    let pb_style = ProgressStyle::with_template(&PB_TEMPLATE.replace("NAME", short_name_padded))
+        .unwrap()
+        .progress_chars("##-");
+
+    pb.set_style(pb_style.clone());
+    pb.set_message("0");
+    all_bars.push(pb.clone());
+    pb
+}
+
+/// Removes the status bar and replace it with a message.
+pub fn finalize_pb(pb: &ProgressBar, short_name_padded: &str, c: &Completed) {
+    let f = c.failures;
+
+    // Use a tuple so we can use colors
+    let (color, msg, finish_pb): (&str, String, fn(&ProgressBar, String)) = match &c.result {
+        Ok(FinishedAll) if f > 0 => {
+            ("red", format!("{f} f (finished with errors)",), ProgressBar::finish_with_message)
+        }
+        Ok(FinishedAll) => {
+            ("green", format!("{f} f (finished successfully)",), ProgressBar::finish_with_message)
+        }
+        Err(EarlyExit::Timeout) => {
+            ("red", format!("{f} f (timed out)"), ProgressBar::abandon_with_message)
+        }
+        Err(EarlyExit::MaxFailures) => {
+            ("red", format!("{f} f (failure limit)"), ProgressBar::abandon_with_message)
+        }
+    };
+
+    let pb_style = ProgressStyle::with_template(
+        &PB_TEMPLATE_FINAL.replace("NAME", short_name_padded).replace("COLOR", color),
+    )
+    .unwrap();
+
+    pb.set_style(pb_style);
+    finish_pb(pb, msg);
+}
+
+/// Print final messages after all tests are complete.
+pub fn finish(tests: &[TestInfo], total_elapsed: Duration, cfg: &Config) -> ExitCode {
+    println!("\n\nResults:");
+
+    let mut failed_generators = 0;
+    let mut stopped_generators = 0;
+
+    for t in tests {
+        let Completed { executed, failures, elapsed, warning, result } = t.completed.get().unwrap();
+
+        let stat = if result.is_err() {
+            stopped_generators += 1;
+            "STOPPED"
+        } else if *failures > 0 {
+            failed_generators += 1;
+            "FAILURE"
+        } else {
+            "SUCCESS"
+        };
+
+        println!(
+            "    {stat} for generator '{name}'. {passed}/{executed} passed in {elapsed:?}",
+            name = t.name,
+            passed = executed - failures,
+        );
+
+        if let Some(warning) = warning {
+            println!("      warning: {warning}");
+        }
+
+        match result {
+            Ok(FinishedAll) => (),
+            Err(EarlyExit::Timeout) => {
+                println!("      exited early; exceded {:?} timeout", cfg.timeout)
+            }
+            Err(EarlyExit::MaxFailures) => {
+                println!("      exited early; exceeded {:?} max failures", cfg.max_failures)
+            }
+        }
+    }
+
+    println!(
+        "{passed}/{} tests succeeded in {total_elapsed:?} ({passed} passed, {} failed, {} stopped)",
+        tests.len(),
+        failed_generators,
+        stopped_generators,
+        passed = tests.len() - failed_generators - stopped_generators,
+    );
+
+    if failed_generators > 0 || stopped_generators > 0 {
+        ExitCode::FAILURE
+    } else {
+        ExitCode::SUCCESS
+    }
+}
+
+/// indicatif likes to eat panic messages. This workaround isn't ideal, but it improves things.
+/// <https://github.com/console-rs/indicatif/issues/121>.
+pub fn set_panic_hook(drop_bars: Vec<ProgressBar>) {
+    let hook = std::panic::take_hook();
+    std::panic::set_hook(Box::new(move |info| {
+        for bar in &drop_bars {
+            bar.abandon();
+            println!();
+            io::stdout().flush().unwrap();
+            io::stderr().flush().unwrap();
+        }
+        hook(info);
+    }));
+}
diff --git a/src/etc/test-float-parse/src/validate.rs b/src/etc/test-float-parse/src/validate.rs
new file mode 100644
index 00000000000..1eb3699cfb9
--- /dev/null
+++ b/src/etc/test-float-parse/src/validate.rs
@@ -0,0 +1,364 @@
+//! Everything related to verifying that parsed outputs are correct.
+
+use std::any::type_name;
+use std::collections::BTreeMap;
+use std::ops::RangeInclusive;
+use std::str::FromStr;
+use std::sync::LazyLock;
+
+use num::bigint::ToBigInt;
+use num::{BigInt, BigRational, FromPrimitive, Signed, ToPrimitive};
+
+use crate::{CheckFailure, Float, Int, Update};
+
+/// Powers of two that we store for constants. Account for binary128 which has a 15-bit exponent.
+const POWERS_OF_TWO_RANGE: RangeInclusive<i32> = (-(2 << 15))..=(2 << 15);
+
+/// Powers of ten that we cache. Account for binary128, which can fit +4932/-4931
+const POWERS_OF_TEN_RANGE: RangeInclusive<i32> = -5_000..=5_000;
+
+/// Cached powers of 10 so we can look them up rather than recreating.
+static POWERS_OF_TEN: LazyLock<BTreeMap<i32, BigRational>> = LazyLock::new(|| {
+    POWERS_OF_TEN_RANGE.map(|exp| (exp, BigRational::from_u32(10).unwrap().pow(exp))).collect()
+});
+
+/// Rational property-related constants for a specific float type.
+#[allow(dead_code)]
+#[derive(Debug)]
+pub struct Constants {
+    /// The minimum positive value (a subnormal).
+    min_subnormal: BigRational,
+    /// The maximum possible finite value.
+    max: BigRational,
+    /// Cutoff between rounding to zero and rounding to the minimum value (min subnormal).
+    zero_cutoff: BigRational,
+    /// Cutoff between rounding to the max value and rounding to infinity.
+    inf_cutoff: BigRational,
+    /// Opposite of `inf_cutoff`
+    neg_inf_cutoff: BigRational,
+    /// The powers of two for all relevant integers.
+    powers_of_two: BTreeMap<i32, BigRational>,
+    /// Half of each power of two. ULP = "unit in last position".
+    ///
+    /// This is a mapping from integers to half the precision available at that exponent. In other
+    /// words, `0.5 * 2^n` = `2^(n-1)`, which is half the distance between `m * 2^n` and
+    /// `(m + 1) * 2^n`, m ∈ ℤ.
+    ///
+    /// So, this is the maximum error from a real number to its floating point representation,
+    /// assuming the float type can represent the exponent.
+    half_ulp: BTreeMap<i32, BigRational>,
+    /// Handy to have around so we don't need to reallocate for it
+    two: BigInt,
+}
+
+impl Constants {
+    pub fn new<F: Float>() -> Self {
+        let two_int = &BigInt::from_u32(2).unwrap();
+        let two = &BigRational::from_integer(2.into());
+
+        // The minimum subnormal (aka minimum positive) value. Most negative power of two is the
+        // minimum exponent (bias - 1) plus the extra from shifting within the mantissa bits.
+        let min_subnormal = two.pow(-(F::EXP_BIAS + F::MAN_BITS - 1).to_signed());
+
+        // The maximum value is the maximum exponent with a fully saturated mantissa. This
+        // is easiest to calculate by evaluating what the next value up would be if representable
+        // (zeroed mantissa, exponent increments by one, i.e. `2^(bias + 1)`), and subtracting
+        // a single LSB (`2 ^ (-mantissa_bits)`).
+        let max = (two - two.pow(-F::MAN_BITS.to_signed())) * (two.pow(F::EXP_BIAS.to_signed()));
+        let zero_cutoff = &min_subnormal / two_int;
+
+        let inf_cutoff = &max + two_int.pow(F::EXP_BIAS - F::MAN_BITS - 1);
+        let neg_inf_cutoff = -&inf_cutoff;
+
+        let powers_of_two: BTreeMap<i32, _> =
+            (POWERS_OF_TWO_RANGE).map(|n| (n, two.pow(n))).collect();
+        let mut half_ulp = powers_of_two.clone();
+        half_ulp.iter_mut().for_each(|(_k, v)| *v = &*v / two_int);
+
+        Self {
+            min_subnormal,
+            max,
+            zero_cutoff,
+            inf_cutoff,
+            neg_inf_cutoff,
+            powers_of_two,
+            half_ulp,
+            two: two_int.clone(),
+        }
+    }
+}
+
+/// Validate that a string parses correctly
+pub fn validate<F: Float>(input: &str) -> Result<(), Update> {
+    let parsed: F = input
+        .parse()
+        .unwrap_or_else(|e| panic!("parsing failed for {}: {e}. Input: {input}", type_name::<F>()));
+
+    // Parsed float, decoded into significand and exponent
+    let decoded = decode(parsed);
+
+    // Float parsed separately into a rational
+    let rational = Rational::parse(input);
+
+    // Verify that the values match
+    decoded.check(rational, input)
+}
+
+/// The result of parsing a string to a float type.
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum FloatRes<F: Float> {
+    Inf,
+    NegInf,
+    Zero,
+    Nan,
+    /// A real number with significand and exponent. Value is `sig * 2 ^ exp`.
+    Real {
+        sig: F::SInt,
+        exp: i32,
+    },
+}
+
+impl<F: Float> FloatRes<F> {
+    /// Given a known exact rational, check that this representation is accurate within the
+    /// limits of the float representation. If not, construct a failure `Update` to send.
+    fn check(self, expected: Rational, input: &str) -> Result<(), Update> {
+        let consts = F::constants();
+        // let bool_helper = |cond: bool, err| cond.then_some(()).ok_or(err);
+
+        let res = match (expected, self) {
+            // Easy correct cases
+            (Rational::Inf, FloatRes::Inf)
+            | (Rational::NegInf, FloatRes::NegInf)
+            | (Rational::Nan, FloatRes::Nan) => Ok(()),
+
+            // Easy incorrect cases
+            (
+                Rational::Inf,
+                FloatRes::NegInf | FloatRes::Zero | FloatRes::Nan | FloatRes::Real { .. },
+            ) => Err(CheckFailure::ExpectedInf),
+            (
+                Rational::NegInf,
+                FloatRes::Inf | FloatRes::Zero | FloatRes::Nan | FloatRes::Real { .. },
+            ) => Err(CheckFailure::ExpectedNegInf),
+            (
+                Rational::Nan,
+                FloatRes::Inf | FloatRes::NegInf | FloatRes::Zero | FloatRes::Real { .. },
+            ) => Err(CheckFailure::ExpectedNan),
+            (Rational::Finite(_), FloatRes::Nan) => Err(CheckFailure::UnexpectedNan),
+
+            // Cases near limits
+            (Rational::Finite(r), FloatRes::Zero) => {
+                if r <= consts.zero_cutoff {
+                    Ok(())
+                } else {
+                    Err(CheckFailure::UnexpectedZero)
+                }
+            }
+            (Rational::Finite(r), FloatRes::Inf) => {
+                if r >= consts.inf_cutoff {
+                    Ok(())
+                } else {
+                    Err(CheckFailure::UnexpectedInf)
+                }
+            }
+            (Rational::Finite(r), FloatRes::NegInf) => {
+                if r <= consts.neg_inf_cutoff {
+                    Ok(())
+                } else {
+                    Err(CheckFailure::UnexpectedNegInf)
+                }
+            }
+
+            // Actual numbers
+            (Rational::Finite(r), FloatRes::Real { sig, exp }) => Self::validate_real(r, sig, exp),
+        };
+
+        res.map_err(|fail| Update::Failure {
+            fail,
+            input: input.into(),
+            float_res: format!("{self:?}").into(),
+        })
+    }
+
+    /// Check that `sig * 2^exp` is the same as `rational`, within the float's error margin.
+    fn validate_real(rational: BigRational, sig: F::SInt, exp: i32) -> Result<(), CheckFailure> {
+        let consts = F::constants();
+
+        // `2^exp`. Use cached powers of two to be faster.
+        let two_exp = consts
+            .powers_of_two
+            .get(&exp)
+            .unwrap_or_else(|| panic!("missing exponent {exp} for {}", type_name::<F>()));
+
+        // Rational from the parsed value, `sig * 2^exp`
+        let parsed_rational = two_exp * sig.to_bigint().unwrap();
+        let error = (parsed_rational - &rational).abs();
+
+        // Determine acceptable error at this exponent, which is halfway between this value
+        // (`sig * 2^exp`) and the next value up (`(sig+1) * 2^exp`).
+        let half_ulp = consts.half_ulp.get(&exp).unwrap();
+
+        // If we are within one error value (but not equal) then we rounded correctly.
+        if &error < half_ulp {
+            return Ok(());
+        }
+
+        // For values where we are exactly between two representable values, meaning that the error
+        // is exactly one half of the precision at that exponent, we need to round to an even
+        // binary value (i.e. mantissa ends in 0).
+        let incorrect_midpoint_rounding = if &error == half_ulp {
+            if sig & F::SInt::ONE == F::SInt::ZERO {
+                return Ok(());
+            }
+
+            // We rounded to odd rather than even; failing based on midpoint rounding.
+            true
+        } else {
+            // We are out of spec for some other reason.
+            false
+        };
+
+        let one_ulp = consts.half_ulp.get(&(exp + 1)).unwrap();
+        assert_eq!(one_ulp, &(half_ulp * &consts.two), "ULP values are incorrect");
+
+        let relative_error = error / one_ulp;
+
+        Err(CheckFailure::InvalidReal {
+            error_float: relative_error.to_f64(),
+            error_str: relative_error.to_string().into(),
+            incorrect_midpoint_rounding,
+        })
+    }
+
+    /// Remove trailing zeros in the significand and adjust the exponent
+    #[cfg(test)]
+    fn normalize(self) -> Self {
+        use std::cmp::min;
+
+        match self {
+            Self::Real { sig, exp } => {
+                // If there are trailing zeroes, remove them and increment the exponent instead
+                let shift = min(sig.trailing_zeros(), exp.wrapping_neg().try_into().unwrap());
+                Self::Real { sig: sig >> shift, exp: exp + i32::try_from(shift).unwrap() }
+            }
+            _ => self,
+        }
+    }
+}
+
+/// Decompose a float into its integral components. This includes the implicit bit.
+///
+/// If `allow_nan` is `false`, panic if `NaN` values are reached.
+fn decode<F: Float>(f: F) -> FloatRes<F> {
+    let ione = F::SInt::ONE;
+    let izero = F::SInt::ZERO;
+
+    let mut exponent_biased = f.exponent();
+    let mut mantissa = f.mantissa().to_signed();
+
+    if exponent_biased == 0 {
+        if mantissa == izero {
+            return FloatRes::Zero;
+        }
+
+        exponent_biased += 1;
+    } else if exponent_biased == F::EXP_SAT {
+        if mantissa != izero {
+            return FloatRes::Nan;
+        }
+
+        if f.is_sign_negative() {
+            return FloatRes::NegInf;
+        }
+
+        return FloatRes::Inf;
+    } else {
+        // Set implicit bit
+        mantissa |= ione << F::MAN_BITS;
+    }
+
+    let mut exponent = i32::try_from(exponent_biased).unwrap();
+
+    // Adjust for bias and the rnage of the mantissa
+    exponent -= i32::try_from(F::EXP_BIAS + F::MAN_BITS).unwrap();
+
+    if f.is_sign_negative() {
+        mantissa = mantissa.wrapping_neg();
+    }
+
+    FloatRes::Real { sig: mantissa, exp: exponent }
+}
+
+/// A rational or its unrepresentable values.
+#[derive(Clone, Debug, PartialEq)]
+enum Rational {
+    Inf,
+    NegInf,
+    Nan,
+    Finite(BigRational),
+}
+
+impl Rational {
+    /// Turn a string into a rational. `None` if `NaN`.
+    fn parse(s: &str) -> Rational {
+        let mut s = s; // lifetime rules
+
+        if s.strip_prefix('+').unwrap_or(s).eq_ignore_ascii_case("nan")
+            || s.eq_ignore_ascii_case("-nan")
+        {
+            return Rational::Nan;
+        }
+
+        if s.strip_prefix('+').unwrap_or(s).eq_ignore_ascii_case("inf") {
+            return Rational::Inf;
+        }
+
+        if s.eq_ignore_ascii_case("-inf") {
+            return Rational::NegInf;
+        }
+
+        // Fast path; no decimals or exponents ot parse
+        if s.bytes().all(|b| b.is_ascii_digit() || b == b'-') {
+            return Rational::Finite(BigRational::from_str(s).unwrap());
+        }
+
+        let mut ten_exp: i32 = 0;
+
+        // Remove and handle e.g. `e-4`, `e+10`, `e5` suffixes
+        if let Some(pos) = s.bytes().position(|b| b == b'e' || b == b'E') {
+            let (dec, exp) = s.split_at(pos);
+            s = dec;
+            ten_exp = exp[1..].parse().unwrap();
+        }
+
+        // Remove the decimal and instead change our exponent
+        // E.g. "12.3456" becomes "123456 * 10^-4"
+        let mut s_owned;
+        if let Some(pos) = s.bytes().position(|b| b == b'.') {
+            ten_exp = ten_exp.checked_sub((s.len() - pos - 1).try_into().unwrap()).unwrap();
+            s_owned = s.to_owned();
+            s_owned.remove(pos);
+            s = &s_owned;
+        }
+
+        // let pow = BigRational::from_u32(10).unwrap().pow(ten_exp);
+        let pow =
+            POWERS_OF_TEN.get(&ten_exp).unwrap_or_else(|| panic!("missing power of ten {ten_exp}"));
+        let r = pow
+            * BigInt::from_str(s)
+                .unwrap_or_else(|e| panic!("`BigInt::from_str(\"{s}\")` failed with {e}"));
+        Rational::Finite(r)
+    }
+
+    #[cfg(test)]
+    fn expect_finite(self) -> BigRational {
+        let Self::Finite(r) = self else {
+            panic!("got non rational: {self:?}");
+        };
+
+        r
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/etc/test-float-parse/src/validate/tests.rs b/src/etc/test-float-parse/src/validate/tests.rs
new file mode 100644
index 00000000000..ab0e7d8a7ba
--- /dev/null
+++ b/src/etc/test-float-parse/src/validate/tests.rs
@@ -0,0 +1,149 @@
+use num::ToPrimitive;
+
+use super::*;
+
+#[test]
+fn test_parse_rational() {
+    assert_eq!(Rational::parse("1234").expect_finite(), BigRational::new(1234.into(), 1.into()));
+    assert_eq!(
+        Rational::parse("-1234").expect_finite(),
+        BigRational::new((-1234).into(), 1.into())
+    );
+    assert_eq!(Rational::parse("1e+6").expect_finite(), BigRational::new(1000000.into(), 1.into()));
+    assert_eq!(Rational::parse("1e-6").expect_finite(), BigRational::new(1.into(), 1000000.into()));
+    assert_eq!(
+        Rational::parse("10.4e6").expect_finite(),
+        BigRational::new(10400000.into(), 1.into())
+    );
+    assert_eq!(
+        Rational::parse("10.4e+6").expect_finite(),
+        BigRational::new(10400000.into(), 1.into())
+    );
+    assert_eq!(
+        Rational::parse("10.4e-6").expect_finite(),
+        BigRational::new(13.into(), 1250000.into())
+    );
+    assert_eq!(
+        Rational::parse("10.4243566462342456234124").expect_finite(),
+        BigRational::new(104243566462342456234124_i128.into(), 10000000000000000000000_i128.into())
+    );
+    assert_eq!(Rational::parse("inf"), Rational::Inf);
+    assert_eq!(Rational::parse("+inf"), Rational::Inf);
+    assert_eq!(Rational::parse("-inf"), Rational::NegInf);
+    assert_eq!(Rational::parse("NaN"), Rational::Nan);
+}
+
+#[test]
+fn test_decode() {
+    assert_eq!(decode(0f32), FloatRes::Zero);
+    assert_eq!(decode(f32::INFINITY), FloatRes::Inf);
+    assert_eq!(decode(f32::NEG_INFINITY), FloatRes::NegInf);
+    assert_eq!(decode(1.0f32).normalize(), FloatRes::Real { sig: 1, exp: 0 });
+    assert_eq!(decode(-1.0f32).normalize(), FloatRes::Real { sig: -1, exp: 0 });
+    assert_eq!(decode(100.0f32).normalize(), FloatRes::Real { sig: 100, exp: 0 });
+    assert_eq!(decode(100.5f32).normalize(), FloatRes::Real { sig: 201, exp: -1 });
+    assert_eq!(decode(-4.004f32).normalize(), FloatRes::Real { sig: -8396997, exp: -21 });
+    assert_eq!(decode(0.0004f32).normalize(), FloatRes::Real { sig: 13743895, exp: -35 });
+    assert_eq!(decode(f32::from_bits(0x1)).normalize(), FloatRes::Real { sig: 1, exp: -149 });
+}
+
+#[test]
+fn test_validate() {
+    validate::<f32>("0").unwrap();
+    validate::<f32>("-0").unwrap();
+    validate::<f32>("1").unwrap();
+    validate::<f32>("-1").unwrap();
+    validate::<f32>("1.1").unwrap();
+    validate::<f32>("-1.1").unwrap();
+    validate::<f32>("1e10").unwrap();
+    validate::<f32>("1e1000").unwrap();
+    validate::<f32>("-1e1000").unwrap();
+    validate::<f32>("1e-1000").unwrap();
+    validate::<f32>("-1e-1000").unwrap();
+}
+
+#[test]
+fn test_validate_real() {
+    // Most of the arbitrary values come from checking against <http://weitz.de/ieee/>.
+    let r = &BigRational::from_float(10.0).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 10, 0).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 10, -1).unwrap_err();
+    FloatRes::<f32>::validate_real(r.clone(), 10, 1).unwrap_err();
+
+    let r = &BigRational::from_float(0.25).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 1, -2).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 2, -2).unwrap_err();
+
+    let r = &BigRational::from_float(1234.5678).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 0b100110100101001000101011, -13).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), 0b100110100101001000101010, -13).unwrap_err();
+    FloatRes::<f32>::validate_real(r.clone(), 0b100110100101001000101100, -13).unwrap_err();
+
+    let r = &BigRational::from_float(-1234.5678).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), -0b100110100101001000101011, -13).unwrap();
+    FloatRes::<f32>::validate_real(r.clone(), -0b100110100101001000101010, -13).unwrap_err();
+    FloatRes::<f32>::validate_real(r.clone(), -0b100110100101001000101100, -13).unwrap_err();
+}
+
+#[test]
+#[allow(unused)]
+fn test_validate_real_rounding() {
+    // Check that we catch when values don't round to even.
+
+    // For f32, the cutoff between 1.0 and the next value up (1.0000001) is
+    // 1.000000059604644775390625. Anything below it should round down, anything above it should
+    // round up, and the value itself should round _down_ because `1.0` has an even significand but
+    // 1.0000001 is odd.
+    let v1_low_down = Rational::parse("1.00000005960464477539062499999").expect_finite();
+    let v1_mid_down = Rational::parse("1.000000059604644775390625").expect_finite();
+    let v1_high_up = Rational::parse("1.00000005960464477539062500001").expect_finite();
+
+    let exp = -(f32::MAN_BITS as i32);
+    let v1_down_sig = 1 << f32::MAN_BITS;
+    let v1_up_sig = (1 << f32::MAN_BITS) | 0b1;
+
+    FloatRes::<f32>::validate_real(v1_low_down.clone(), v1_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(v1_mid_down.clone(), v1_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(v1_high_up.clone(), v1_up_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v1_low_down.clone(), -v1_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v1_mid_down.clone(), -v1_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v1_high_up.clone(), -v1_up_sig, exp).unwrap();
+
+    // 1.000000178813934326171875 is between 1.0000001 and the next value up, 1.0000002. The middle
+    // value here should round _up_ since 1.0000002 has an even mantissa.
+    let v2_low_down = Rational::parse("1.00000017881393432617187499999").expect_finite();
+    let v2_mid_up = Rational::parse("1.000000178813934326171875").expect_finite();
+    let v2_high_up = Rational::parse("1.00000017881393432617187500001").expect_finite();
+
+    let v2_down_sig = v1_up_sig;
+    let v2_up_sig = (1 << f32::MAN_BITS) | 0b10;
+
+    FloatRes::<f32>::validate_real(v2_low_down.clone(), v2_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(v2_mid_up.clone(), v2_up_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(v2_high_up.clone(), v2_up_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v2_low_down.clone(), -v2_down_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v2_mid_up.clone(), -v2_up_sig, exp).unwrap();
+    FloatRes::<f32>::validate_real(-v2_high_up.clone(), -v2_up_sig, exp).unwrap();
+
+    // Rounding the wrong direction should error
+    for res in [
+        FloatRes::<f32>::validate_real(v1_mid_down.clone(), v1_up_sig, exp),
+        FloatRes::<f32>::validate_real(v2_mid_up.clone(), v2_down_sig, exp),
+        FloatRes::<f32>::validate_real(-v1_mid_down.clone(), -v1_up_sig, exp),
+        FloatRes::<f32>::validate_real(-v2_mid_up.clone(), -v2_down_sig, exp),
+    ] {
+        let e = res.unwrap_err();
+        let CheckFailure::InvalidReal { incorrect_midpoint_rounding: true, .. } = e else {
+            panic!("{e:?}");
+        };
+    }
+}
+
+/// Just a quick check that the constants are what we expect.
+#[test]
+fn check_constants() {
+    assert_eq!(f32::constants().max.to_f32().unwrap(), f32::MAX);
+    assert_eq!(f32::constants().min_subnormal.to_f32().unwrap(), f32::from_bits(0x1));
+    assert_eq!(f64::constants().max.to_f64().unwrap(), f64::MAX);
+    assert_eq!(f64::constants().min_subnormal.to_f64().unwrap(), f64::from_bits(0x1));
+}
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 51fb126cb34..fe531f0ff59 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -8,7 +8,7 @@ path = "lib.rs"
 
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
-askama = { version = "0.12", default-features = false, features = ["config"] }
+rinja = { version = "0.2", default-features = false, features = ["config"] }
 base64 = "0.21.7"
 itertools = "0.12"
 indexmap = "2"
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e3c4602212c..2cd9b6fcd38 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -468,13 +468,7 @@ fn clean_projection<'tcx>(
     def_id: Option<DefId>,
 ) -> Type {
     if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
-        let bounds = cx
-            .tcx
-            .explicit_item_bounds(ty.skip_binder().def_id)
-            .iter_instantiated_copied(cx.tcx, ty.skip_binder().args)
-            .map(|(pred, _)| pred)
-            .collect::<Vec<_>>();
-        return clean_middle_opaque_bounds(cx, bounds);
+        return clean_middle_opaque_bounds(cx, ty.skip_binder().def_id, ty.skip_binder().args);
     }
 
     let trait_ = clean_trait_ref_with_constraints(
@@ -2260,13 +2254,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                 // by looking up the bounds associated with the def_id.
-                let bounds = cx
-                    .tcx
-                    .explicit_item_bounds(def_id)
-                    .iter_instantiated_copied(cx.tcx, args)
-                    .map(|(bound, _)| bound)
-                    .collect::<Vec<_>>();
-                let ty = clean_middle_opaque_bounds(cx, bounds);
+                let ty = clean_middle_opaque_bounds(cx, def_id, args);
                 if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
                     *count -= 1;
                     if *count == 0 {
@@ -2289,12 +2277,20 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
 fn clean_middle_opaque_bounds<'tcx>(
     cx: &mut DocContext<'tcx>,
-    bounds: Vec<ty::Clause<'tcx>>,
+    impl_trait_def_id: DefId,
+    args: ty::GenericArgsRef<'tcx>,
 ) -> Type {
     let mut has_sized = false;
+
+    let bounds: Vec<_> = cx
+        .tcx
+        .explicit_item_bounds(impl_trait_def_id)
+        .iter_instantiated_copied(cx.tcx, args)
+        .collect();
+
     let mut bounds = bounds
         .iter()
-        .filter_map(|bound| {
+        .filter_map(|(bound, _)| {
             let bound_predicate = bound.kind();
             let trait_ref = match bound_predicate.skip_binder() {
                 ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
@@ -2313,7 +2309,7 @@ fn clean_middle_opaque_bounds<'tcx>(
 
             let bindings: ThinVec<_> = bounds
                 .iter()
-                .filter_map(|bound| {
+                .filter_map(|(bound, _)| {
                     if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
                         if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
                             Some(AssocItemConstraint {
@@ -2353,6 +2349,10 @@ fn clean_middle_opaque_bounds<'tcx>(
         bounds.insert(0, GenericBound::sized(cx));
     }
 
+    if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
+        bounds.push(GenericBound::Use(args.to_vec()));
+    }
+
     ImplTrait(bounds)
 }
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 9b0b2571ec1..055781f7fed 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -850,7 +850,7 @@ fn resolved_path<'cx>(
         }
     }
     if w.alternate() {
-        write!(w, "{}{:#}", &last.name, last.args.print(cx))?;
+        write!(w, "{}{:#}", last.name, last.args.print(cx))?;
     } else {
         let path = if use_absolute {
             if let Ok((_, _, fqp)) = href(did, cx) {
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index d4b4db0f3fd..22576b76e41 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -6,7 +6,7 @@ use crate::externalfiles::ExternalHtml;
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
-use askama::Template;
+use rinja::Template;
 
 use super::static_files::{StaticFiles, STATIC_FILES};
 
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index db1119eca1d..7718413c956 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -36,7 +36,7 @@ use crate::html::url_parts_builder::UrlPartsBuilder;
 use crate::html::{layout, sources, static_files};
 use crate::scrape_examples::AllCallLocations;
 use crate::try_err;
-use askama::Template;
+use rinja::Template;
 
 /// Major driving force in all rustdoc rendering. This contains information
 /// about where in the tree-like hierarchy rendering is occurring and controls
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 877a00e206d..5b9ef67109c 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -46,7 +46,7 @@ use std::path::PathBuf;
 use std::rc::Rc;
 use std::str;
 
-use askama::Template;
+use rinja::Template;
 use rustc_attr::{ConstStability, DeprecatedSince, Deprecation, StabilityLevel, StableSince};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 00973865915..a04313b4b79 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -36,10 +36,10 @@ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
 use crate::html::render::{document_full, document_item_info};
 use crate::html::url_parts_builder::UrlPartsBuilder;
 
-use askama::Template;
 use itertools::Itertools;
+use rinja::Template;
 
-/// Generates an Askama template struct for rendering items with common methods.
+/// Generates a Rinja template struct for rendering items with common methods.
 ///
 /// Usage:
 /// ```ignore (illustrative)
@@ -309,7 +309,7 @@ fn toggle_close(mut w: impl fmt::Write) {
     w.write_str("</details>").unwrap();
 }
 
-trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display {
+trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
     fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
 }
 
@@ -2062,16 +2062,23 @@ pub(super) fn item_path(ty: ItemType, name: &str) -> String {
 
 fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> String {
     let mut bounds = String::new();
-    if !t_bounds.is_empty() {
-        if !trait_alias {
+    if t_bounds.is_empty() {
+        return bounds;
+    }
+    let has_lots_of_bounds = t_bounds.len() > 2;
+    let inter_str = if has_lots_of_bounds { "\n    + " } else { " + " };
+    if !trait_alias {
+        if has_lots_of_bounds {
+            bounds.push_str(":\n    ");
+        } else {
             bounds.push_str(": ");
         }
-        for (i, p) in t_bounds.iter().enumerate() {
-            if i > 0 {
-                bounds.push_str(" + ");
-            }
-            bounds.push_str(&p.print(cx).to_string());
+    }
+    for (i, p) in t_bounds.iter().enumerate() {
+        if i > 0 {
+            bounds.push_str(inter_str);
         }
+        bounds.push_str(&p.print(cx).to_string());
     }
     bounds
 }
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 3d28937eb99..e5bc2ace203 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,6 +1,6 @@
 use std::{borrow::Cow, rc::Rc};
 
-use askama::Template;
+use rinja::Template;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::{def::CtorKind, def_id::DefIdSet};
 use rustc_middle::ty::{self, TyCtxt};
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index a27e327f235..35a38d5375f 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -1,4 +1,4 @@
-use askama::Template;
+use rinja::Template;
 
 use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index d4b1da71b40..7b4d1fa5305 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -8,7 +8,7 @@ use crate::html::layout;
 use crate::html::render::Context;
 use crate::visit::DocVisitor;
 
-use askama::Template;
+use rinja::Template;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index a305335e0b3..41c506f33dc 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -675,7 +675,6 @@ ul.block, .block li {
 	border-top: solid 16px transparent;
 	box-sizing: content-box;
 	position: relative;
-	background-color: var(--sidebar-background-color);
 	background-clip: border-box;
 	z-index: 1;
 }
@@ -832,6 +831,10 @@ pre, .rustdoc.src .example-wrap {
 	background: var(--table-alt-row-background-color);
 }
 
+.docblock .stab, .docblock-short .stab {
+	display: inline-block;
+}
+
 /* "where ..." clauses with block display are also smaller */
 div.where {
 	white-space: pre-wrap;
@@ -954,6 +957,7 @@ table,
 	display: table;
 	padding: 0;
 	margin: 0;
+	width: 100%;
 }
 .item-table > li {
 	display: table-row;
@@ -2179,7 +2183,6 @@ in src-script.js and main.js
 		width: 33%;
 	}
 	.item-table > li > div {
-		padding-bottom: 5px;
 		word-break: break-all;
 	}
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 64c35660778..9506bc9ed22 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -529,11 +529,13 @@ function preLoadCss(cssUrl) {
                 }
                 const link = document.createElement("a");
                 link.href = path;
-                if (path === current_page) {
-                    link.className = "current";
-                }
                 link.textContent = name;
                 const li = document.createElement("li");
+                // Don't "optimize" this to just use `path`.
+                // We want the browser to normalize this into an absolute URL.
+                if (link.href === current_page) {
+                    li.classList.add("current");
+                }
                 li.appendChild(link);
                 ul.appendChild(li);
             }
diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md
index 38aac2a60e9..32bacb11475 100644
--- a/src/librustdoc/html/templates/STYLE.md
+++ b/src/librustdoc/html/templates/STYLE.md
@@ -1,15 +1,13 @@
 # Style for Templates
 
-This directory has templates in the [Tera templating language][teradoc], which is very
-similar to [Jinja2][jinjadoc] and [Django][djangodoc] templates, and also to [Askama][askamadoc].
+This directory has templates in the [Rinja templating language][rinjadoc], which is very
+similar to [Jinja2][jinjadoc].
 
-[teradoc]: https://tera.netlify.app/docs/#templates
 [jinjadoc]: https://jinja.palletsprojects.com/en/3.1.x/templates/
-[djangodoc]: https://docs.djangoproject.com/en/4.1/topics/templates/
-[askamadoc]: https://docs.rs/askama/latest/askama/
+[rinjadoc]: https://docs.rs/rinja/latest/rinja/
 
 We want our rendered output to have as little unnecessary whitespace as
-possible, so that pages load quickly. To achieve that we use Tera's
+possible, so that pages load quickly. To achieve that we use Rinja's
 [whitespace control] features. By default, whitespace characters are removed
 around jinja tags (`{% %}` for example). At the end of most lines, we put an
 empty comment tag: `{# #}`. This causes all whitespace between the end of the
@@ -20,7 +18,7 @@ remove following whitespace but not preceding. We also use the whitespace
 control characters in most instances of tags with control flow, for example
 `{% if foo %}`.
 
-[whitespace control]: https://tera.netlify.app/docs/#whitespace-control
+[whitespace control]: https://rinja.readthedocs.io/en/stable/configuration.html#whitespace-control
 
 We want our templates to be readable, so we use indentation and newlines
 liberally. We indent by four spaces after opening an HTML tag _or_ a Jinja
@@ -28,11 +26,11 @@ tag. In most cases an HTML tag should be followed by a newline, but if the
 tag has simple contents and fits with its close tag on a single line, the
 contents don't necessarily need a new line.
 
-Askama templates support quite sophisticated control flow. To keep our templates
+Rinja templates support quite sophisticated control flow. To keep our templates
 simple and understandable, we use only a subset: `if` and `for`. In particular
-we avoid [assignments in the template logic][assignments] and [Askama
+we avoid [assignments in the template logic][assignments] and [Rinja
 macros][macros]. This also may make things easier if we switch to a different
 Jinja-style template system in the future.
 
-[assignments]: https://djc.github.io/askama/template_syntax.html#assignments
-[macros]: https://djc.github.io/askama/template_syntax.html#macros
+[assignments]: https://rinja.readthedocs.io/en/stable/template_syntax.html#assignments
+[macros]: https://rinja.readthedocs.io/en/stable/template_syntax.html#macros
diff --git a/src/librustdoc/askama.toml b/src/librustdoc/rinja.toml
index 2732c4bc61e..2732c4bc61e 100644
--- a/src/librustdoc/askama.toml
+++ b/src/librustdoc/rinja.toml
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index a2e7907b532..e0bea5f053d 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -157,6 +157,7 @@ static TARGETS: &[&str] = &[
     "wasm32-wasi",
     "wasm32-wasip1",
     "wasm32-wasip1-threads",
+    "wasm32-wasip2",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
     "x86_64-fortanix-unknown-sgx",
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
index b4522de6897..8be38dc855f 100644
--- a/src/tools/build_helper/src/git.rs
+++ b/src/tools/build_helper/src/git.rs
@@ -7,7 +7,7 @@ pub struct GitConfig<'a> {
 }
 
 /// Runs a command and returns the output
-fn output_result(cmd: &mut Command) -> Result<String, String> {
+pub fn output_result(cmd: &mut Command) -> Result<String, String> {
     let output = match cmd.stderr(Stdio::inherit()).output() {
         Ok(status) => status,
         Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject a2b58c3dad4d554ba01ed6c45c41ff85390560f
+Subproject 5f6b9a92201d78af75dc24f14662c3e2dacbbbe
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index d2a34c75583..0ed7859418b 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                                 // 'cuz currently nothing changes after deleting this check.
                                 local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
                             }) {
-                                match cx.tcx.infer_ctxt().build().type_implements_fn_trait(
+                                match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
                                     cx.param_env,
                                     Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
                                     ty::PredicatePolarity::Positive,
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index cce8617821e..b179d7b5249 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -16,6 +16,7 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 
 use core::ops::ControlFlow;
 
@@ -117,11 +118,11 @@ fn check_needless_must_use(
         // Ignore async functions unless Future::Output type is a must_use type
         if sig.header.is_async() {
             let infcx = cx.tcx.infer_ctxt().build();
-            if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
+            if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
                 && !is_must_use_ty(cx, future_ty)
             {
                 return;
-            }
+            };
         }
 
         span_lint_and_help(
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 1fd8faf3ea8..e6506709774 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index 95ae591884b..0d3786dad4b 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -56,19 +56,18 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
         let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
             return;
         };
-        let inherent_impls = cx
-            .tcx
-            .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
 
-        for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
-            impls.len() > 1
+        for (&id, impl_ids) in &impls.inherent_impls {
+            if impl_ids.len() < 2
             // Check for `#[allow]` on the type definition
-            && !is_lint_allowed(
+            || is_lint_allowed(
                 cx,
                 MULTIPLE_INHERENT_IMPL,
                 cx.tcx.local_def_id_to_hir_id(id),
-            )
-        }) {
+            ) {
+                continue;
+            }
+
             for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
                 let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity();
                 match type_map.entry(impl_ty) {
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 0ecfa7baa72..9d326c06eff 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use std::ops::Deref;
 
 declare_clippy_lint! {
@@ -159,7 +160,7 @@ impl NoEffect {
                                 // Remove `impl Future<Output = T>` to get `T`
                                 if cx.tcx.ty_is_opaque_future(ret_ty)
                                     && let Some(true_ret_ty) =
-                                        cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+                                        cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
                                 {
                                     ret_ty = true_ret_ty;
                                 }
diff --git a/src/tools/clippy/tests/ui/track-diagnostics.stderr b/src/tools/clippy/tests/ui/track-diagnostics.stderr
index 3c7577dd003..83451fb658d 100644
--- a/src/tools/clippy/tests/ui/track-diagnostics.stderr
+++ b/src/tools/clippy/tests/ui/track-diagnostics.stderr
@@ -3,7 +3,7 @@ error[E0308]: mismatched types
    |
 LL | const S: A = B;
    |              ^ expected `A`, found `B`
--Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs
index cbe94af3510..ca2a6f4b8c8 100644
--- a/src/tools/collect-license-metadata/src/main.rs
+++ b/src/tools/collect-license-metadata/src/main.rs
@@ -6,16 +6,6 @@ use crate::licenses::LicensesInterner;
 use anyhow::Error;
 use std::path::PathBuf;
 
-// Some directories have too many slight license differences that'd result in a
-// huge report, and could be considered a standalone project anyway. Those
-// directories are "condensed" into a single licensing block for ease of
-// reading, merging the licensing information.
-//
-// For every `(dir, file)``, every file in `dir` is considered to have the
-// license info of `file`.
-const CONDENSED_DIRECTORIES: &[(&str, &str)] =
-    &[("./src/llvm-project/", "./src/llvm-project/README.md")];
-
 fn main() -> Result<(), Error> {
     let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
     let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs
index fc8756d9a2e..b27fb7f9225 100644
--- a/src/tools/collect-license-metadata/src/path_tree.rs
+++ b/src/tools/collect-license-metadata/src/path_tree.rs
@@ -4,7 +4,7 @@
 //! passes over the tree to remove redundant information.
 
 use crate::licenses::{License, LicenseId, LicensesInterner};
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::BTreeMap;
 use std::path::{Path, PathBuf};
 
 #[derive(serde::Serialize)]
@@ -12,7 +12,6 @@ use std::path::{Path, PathBuf};
 pub(crate) enum Node<L> {
     Root { children: Vec<Node<L>> },
     Directory { name: PathBuf, children: Vec<Node<L>>, license: Option<L> },
-    CondensedDirectory { name: PathBuf, licenses: Vec<L> },
     File { name: PathBuf, license: L },
     Group { files: Vec<PathBuf>, directories: Vec<PathBuf>, license: L },
     Empty,
@@ -59,8 +58,6 @@ impl Node<LicenseId> {
                             directories.entry(name).or_insert_with(Vec::new).append(&mut children);
                         }
                         file @ Node::File { .. } => files.push(file),
-                        // Propagate condensed directories as-is.
-                        condensed @ Node::CondensedDirectory { .. } => files.push(condensed),
                         Node::Empty => {}
                         Node::Root { .. } => {
                             panic!("can't have a root inside another element");
@@ -87,7 +84,6 @@ impl Node<LicenseId> {
             }
             Node::Empty => {}
             Node::File { .. } => {}
-            Node::CondensedDirectory { .. } => {}
             Node::Group { .. } => {
                 panic!("Group should not be present at this stage");
             }
@@ -134,7 +130,6 @@ impl Node<LicenseId> {
                 }
             }
             Node::File { .. } => {}
-            Node::CondensedDirectory { .. } => {}
             Node::Group { .. } => panic!("group should not be present at this stage"),
             Node::Empty => {}
         }
@@ -177,9 +172,6 @@ impl Node<LicenseId> {
                             Node::Directory { name: child_child_name, .. } => {
                                 *child_child_name = child_name.join(&child_child_name);
                             }
-                            Node::CondensedDirectory { name: child_child_name, .. } => {
-                                *child_child_name = child_name.join(&child_child_name);
-                            }
                             Node::File { name: child_child_name, .. } => {
                                 *child_child_name = child_name.join(&child_child_name);
                             }
@@ -194,7 +186,6 @@ impl Node<LicenseId> {
             }
             Node::Empty => {}
             Node::File { .. } => {}
-            Node::CondensedDirectory { .. } => {}
             Node::Group { .. } => panic!("Group should not be present at this stage"),
         }
     }
@@ -262,7 +253,6 @@ impl Node<LicenseId> {
                 }
             }
             Node::File { .. } => {}
-            Node::CondensedDirectory { .. } => {}
             Node::Group { .. } => panic!("FileGroup should not be present at this stage"),
             Node::Empty => {}
         }
@@ -278,7 +268,6 @@ impl Node<LicenseId> {
                 }
                 children.retain(|child| !matches!(child, Node::Empty));
             }
-            Node::CondensedDirectory { .. } => {}
             Node::Group { .. } => {}
             Node::File { .. } => {}
             Node::Empty => {}
@@ -302,24 +291,7 @@ pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
     // Ensure reproducibility of all future steps.
     input.sort();
 
-    let mut condensed_directories = BTreeMap::new();
-    'outer: for (path, license) in input {
-        // Files in condensed directories are handled separately.
-        for (condensed_directory, allowed_file) in super::CONDENSED_DIRECTORIES {
-            if path.starts_with(condensed_directory) {
-                if path.as_path() == Path::new(allowed_file) {
-                    // The licence on our allowed file is used to represent the entire directory
-                    condensed_directories
-                        .entry(*condensed_directory)
-                        .or_insert_with(BTreeSet::new)
-                        .insert(license);
-                } else {
-                    // don't add the file
-                }
-                continue 'outer;
-            }
-        }
-
+    for (path, license) in input {
         let mut node = Node::File { name: path.file_name().unwrap().into(), license };
         for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
             node = Node::Directory {
@@ -332,22 +304,6 @@ pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node<LicenseId> {
         children.push(node);
     }
 
-    for (path, licenses) in condensed_directories {
-        let path = Path::new(path);
-        let mut node = Node::CondensedDirectory {
-            name: path.file_name().unwrap().into(),
-            licenses: licenses.iter().copied().collect(),
-        };
-        for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() {
-            node = Node::Directory {
-                name: component.as_os_str().into(),
-                children: vec![node],
-                license: None,
-            };
-        }
-        children.push(node);
-    }
-
     Node::Root { children }
 }
 
@@ -376,10 +332,6 @@ pub(crate) fn expand_interned_licenses(
         Node::Group { files, directories, license } => {
             Node::Group { files, directories, license: interner.resolve(license) }
         }
-        Node::CondensedDirectory { name, licenses } => Node::CondensedDirectory {
-            name,
-            licenses: licenses.into_iter().map(|license| interner.resolve(license)).collect(),
-        },
         Node::Empty => Node::Empty,
     }
 }
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index da7f03441e7..bc66dcbfb94 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -760,8 +760,14 @@ pub fn output_testname_unique(
 /// test/revision should reside. Example:
 ///   /path/to/build/host-triple/test/ui/relative/testname.revision.mode/
 pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
-    output_relative_path(config, &testpaths.relative_dir)
-        .join(output_testname_unique(config, testpaths, revision))
+    // In run-make tests, constructing a relative path + unique testname causes a double layering
+    // since revisions are not supported, causing unnecessary nesting.
+    if config.mode == Mode::RunMake {
+        output_relative_path(config, &testpaths.relative_dir)
+    } else {
+        output_relative_path(config, &testpaths.relative_dir)
+            .join(output_testname_unique(config, testpaths, revision))
+    }
 }
 
 /// Absolute path to the base filename used as output for the given
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 7f5d4f4b416..3afb5e27547 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -723,12 +723,13 @@ pub fn line_directive<'line>(
     }
 }
 
-// To prevent duplicating the list of commmands between `compiletest` and `htmldocck`, we put
-// it into a common file which is included in rust code and parsed here.
+// To prevent duplicating the list of commmands between `compiletest`,`htmldocck` and `jsondocck`,
+// we put it into a common file which is included in rust code and parsed here.
 // FIXME: This setup is temporary until we figure out how to improve this situation.
+//        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
 include!("command-list.rs");
 
-const KNOWN_RUSTDOC_DIRECTIVE_NAMES: &[&str] = &[
+const KNOWN_HTMLDOCCK_DIRECTIVE_NAMES: &[&str] = &[
     "count",
     "!count",
     "files",
@@ -747,6 +748,9 @@ const KNOWN_RUSTDOC_DIRECTIVE_NAMES: &[&str] = &[
     "!snapshot",
 ];
 
+const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] =
+    &["count", "!count", "has", "!has", "is", "!is", "ismany", "!ismany", "set", "!set"];
+
 /// The broken-down contents of a line containing a test header directive,
 /// which [`iter_header`] passes to its callback function.
 ///
@@ -783,7 +787,7 @@ pub(crate) struct CheckDirectiveResult<'ln> {
 
 pub(crate) fn check_directive<'a>(
     directive_ln: &'a str,
-    is_rustdoc: bool,
+    mode: Mode,
     original_line: &str,
 ) -> CheckDirectiveResult<'a> {
     let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, ""));
@@ -791,9 +795,18 @@ pub(crate) fn check_directive<'a>(
     let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post);
     let is_known = |s: &str| {
         KNOWN_DIRECTIVE_NAMES.contains(&s)
-            || (is_rustdoc
-                && original_line.starts_with("//@")
-                && KNOWN_RUSTDOC_DIRECTIVE_NAMES.contains(&s))
+            || match mode {
+                Mode::Rustdoc | Mode::RustdocJson => {
+                    original_line.starts_with("//@")
+                        && match mode {
+                            Mode::Rustdoc => KNOWN_HTMLDOCCK_DIRECTIVE_NAMES,
+                            Mode::RustdocJson => KNOWN_JSONDOCCK_DIRECTIVE_NAMES,
+                            _ => unreachable!(),
+                        }
+                        .contains(&s)
+                }
+                _ => false,
+            }
     };
     let trailing_directive = {
         // 1. is the directive name followed by a space? (to exclude `:`)
@@ -875,7 +888,7 @@ fn iter_header(
                 let directive_ln = non_revisioned_directive_line.trim();
 
                 let CheckDirectiveResult { is_known_directive, trailing_directive, .. } =
-                    check_directive(directive_ln, mode == Mode::Rustdoc, ln);
+                    check_directive(directive_ln, mode, ln);
 
                 if !is_known_directive {
                     *poisoned = true;
@@ -928,7 +941,7 @@ fn iter_header(
             let rest = rest.trim_start();
 
             let CheckDirectiveResult { is_known_directive, directive_name, .. } =
-                check_directive(rest, mode == Mode::Rustdoc, ln);
+                check_directive(rest, mode, ln);
 
             if is_known_directive {
                 *poisoned = true;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 1a4101e4de8..78c06551ff2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -82,24 +82,22 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
 }
 
 /// The platform-specific library name
-fn get_lib_name(lib: &str, aux_type: AuxType) -> Option<String> {
+fn get_lib_name(name: &str, aux_type: AuxType) -> Option<String> {
     match aux_type {
         AuxType::Bin => None,
         // In some cases (e.g. MUSL), we build a static
         // library, rather than a dynamic library.
         // In this case, the only path we can pass
         // with '--extern-meta' is the '.rlib' file
-        AuxType::Lib => Some(format!("lib{}.rlib", lib)),
-        AuxType::Dylib => Some(if cfg!(windows) {
-            format!("{}.dll", lib)
-        } else if cfg!(target_vendor = "apple") {
-            format!("lib{}.dylib", lib)
-        } else {
-            format!("lib{}.so", lib)
-        }),
+        AuxType::Lib => Some(format!("lib{name}.rlib")),
+        AuxType::Dylib => Some(dylib_name(name)),
     }
 }
 
+fn dylib_name(name: &str) -> String {
+    format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION)
+}
+
 pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
     match &*config.target {
         "arm-linux-androideabi"
@@ -3380,6 +3378,7 @@ impl<'test> TestCx<'test> {
             cmd.env("IS_MSVC", "1")
                 .env("IS_WINDOWS", "1")
                 .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
+                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
                 .env("CC", format!("'{}' {}", self.config.cc, cflags))
                 .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
         } else {
@@ -3431,29 +3430,51 @@ impl<'test> TestCx<'test> {
 
     fn run_rmake_v2_test(&self) {
         // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
-        // (`rmake.rs`) to run the actual tests. The support library is already built as a tool
-        // dylib and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
+        // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
+        // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
         //
-        // 1. We need to build the recipe `rmake.rs` and link in the support library.
-        // 2. We need to run the recipe to build and run the tests.
-        let cwd = env::current_dir().unwrap();
-        let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
-        let src_root = cwd.join(&src_root);
-        let build_root = self.config.build_base.parent().unwrap().parent().unwrap();
-        let build_root = cwd.join(&build_root);
+        // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
+        //    library.
+        // 2. We need to run the recipe binary.
+
+        // So we assume the rust-lang/rust project setup looks like the following (our `.` is the
+        // top-level directory, irrelevant entries to our purposes omitted):
+        //
+        // ```
+        // .                               // <- `source_root`
+        // ├── build/                      // <- `build_root`
+        // ├── compiler/
+        // ├── library/
+        // ├── src/
+        // │  └── tools/
+        // │     └── run_make_support/
+        // └── tests
+        //    └── run-make/
+        // ```
+
+        // `source_root` is the top-level directory containing the rust-lang/rust checkout.
+        let source_root =
+            self.config.find_rust_src_root().expect("could not determine rust source root");
+        // `self.config.build_base` is actually the build base folder + "test" + test suite name, it
+        // looks like `build/<host_triple>/test/run-make`. But we want `build/<host_triple>/`. Note
+        // that the `build` directory does not need to be called `build`, nor does it need to be
+        // under `source_root`, so we must compute it based off of `self.config.build_base`.
+        let build_root =
+            self.config.build_base.parent().and_then(Path::parent).unwrap().to_path_buf();
 
         // We construct the following directory tree for each rmake.rs test:
         // ```
-        // base_dir/
+        // <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.
+        // having the recipe executable separate from the output artifacts directory allows the
+        // recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
+        // a currently running executable because the recipe 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());
+        let base_dir = self.output_base_name();
         if base_dir.exists() {
             self.aggressive_rm_rf(&base_dir).unwrap();
         }
@@ -3475,120 +3496,186 @@ impl<'test> TestCx<'test> {
             }
         }
 
-        // HACK: assume stageN-target, we only want stageN.
+        // `self.config.stage_id` looks like `stage1-<target_triple>`, but we only want
+        // the `stage1` part as that is what the output directories of bootstrap are prefixed with.
+        // Note that this *assumes* build layout from bootstrap is produced as:
+        //
+        // ```
+        // build/<target_triple>/          // <- this is `build_root`
+        // ├── stage0
+        // ├── stage0-bootstrap-tools
+        // ├── stage0-codegen
+        // ├── stage0-rustc
+        // ├── stage0-std
+        // ├── stage0-sysroot
+        // ├── stage0-tools
+        // ├── stage0-tools-bin
+        // ├── stage1
+        // ├── stage1-std
+        // ├── stage1-tools
+        // ├── stage1-tools-bin
+        // └── test
+        // ```
+        // FIXME(jieyouxu): improve the communication between bootstrap and compiletest here so
+        // we don't have to hack out a `stageN`.
         let stage = self.config.stage_id.split('-').next().unwrap();
 
-        // First, we construct the path to the built support library.
-        let mut support_lib_path = PathBuf::new();
-        support_lib_path.push(&build_root);
-        support_lib_path.push(format!("{}-tools-bin", stage));
-        support_lib_path.push("librun_make_support.rlib");
+        // In order to link in the support library as a rlib when compiling recipes, we need three
+        // paths:
+        // 1. Path of the built support library rlib itself.
+        // 2. Path of the built support library's dependencies directory.
+        // 3. Path of the built support library's dependencies' dependencies directory.
+        //
+        // The paths look like
+        //
+        // ```
+        // build/<target_triple>/
+        // ├── stageN-tools-bin/
+        // │   └── librun_make_support.rlib       // <- support rlib itself
+        // ├── stageN-tools/
+        // │   ├── release/deps/                  // <- deps of deps
+        // │   └── <host_triple>/release/deps/    // <- deps
+        // ```
+        //
+        // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
+        // support lib and its deps are organized, can't we copy them to the tools-bin dir as
+        // well?), but this seems to work for now.
 
-        let mut stage_std_path = PathBuf::new();
-        stage_std_path.push(&build_root);
-        stage_std_path.push(&stage);
-        stage_std_path.push("lib");
+        let stage_tools_bin = build_root.join(format!("{stage}-tools-bin"));
+        let support_lib_path = stage_tools_bin.join("librun_make_support.rlib");
 
-        // Then, we need to build the recipe `rmake.rs` and link in the support library.
-        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);
-        support_lib_deps.push(format!("{}-tools", stage));
-        support_lib_deps.push(&self.config.host);
-        support_lib_deps.push("release");
-        support_lib_deps.push("deps");
-
-        let mut support_lib_deps_deps = PathBuf::new();
-        support_lib_deps_deps.push(&build_root);
-        support_lib_deps_deps.push(format!("{}-tools", stage));
-        support_lib_deps_deps.push("release");
-        support_lib_deps_deps.push("deps");
-
-        debug!(?support_lib_deps);
-        debug!(?support_lib_deps_deps);
-
-        let orig_dylib_env_paths =
+        let stage_tools = build_root.join(format!("{stage}-tools"));
+        let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps");
+        let support_lib_deps_deps = stage_tools.join("release").join("deps");
+
+        // To compile the recipe with rustc, we need to provide suitable dynamic library search
+        // paths to rustc. This includes both:
+        // 1. The "base" dylib search paths that was provided to compiletest, e.g. `LD_LIBRARY_PATH`
+        //    on some linux distros.
+        // 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
+
+        let base_dylib_search_paths =
             Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
 
-        let mut host_dylib_env_paths = Vec::new();
-        host_dylib_env_paths.push(cwd.join(&self.config.compile_lib_path));
-        host_dylib_env_paths.extend(orig_dylib_env_paths.iter().cloned());
-        let host_dylib_env_paths = env::join_paths(host_dylib_env_paths).unwrap();
+        let host_dylib_search_paths = {
+            let mut paths = vec![self.config.compile_lib_path.clone()];
+            paths.extend(base_dylib_search_paths.iter().cloned());
+            paths
+        };
+
+        // Calculate the paths of the recipe binary. As previously discussed, this is placed at
+        // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
+        // platform.
+        let recipe_bin = {
+            let mut p = base_dir.join("rmake");
+            p.set_extension(env::consts::EXE_EXTENSION);
+            p
+        };
 
-        let mut cmd = Command::new(&self.config.rustc_path);
-        cmd.arg("-o")
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc
+            .arg("-o")
             .arg(&recipe_bin)
+            // Specify library search paths for `run_make_support`.
             .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
             .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
             .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
+            // Provide `run_make_support` as extern prelude, so test writers don't need to write
+            // `extern run_make_support;`.
             .arg("--extern")
             .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
             .arg("--edition=2021")
             .arg(&self.testpaths.file.join("rmake.rs"))
-            .env("TARGET", &self.config.target)
-            .env("PYTHON", &self.config.python)
-            .env("RUST_BUILD_STAGE", &self.config.stage_id)
-            .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-            .env(dylib_env_var(), &host_dylib_env_paths)
-            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
-            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-            .env("LLVM_COMPONENTS", &self.config.llvm_components);
+            // Provide necessary library search paths for rustc.
+            .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
 
         // In test code we want to be very pedantic about values being silently discarded that are
         // annotated with `#[must_use]`.
-        cmd.arg("-Dunused_must_use");
-
+        rustc.arg("-Dunused_must_use");
+
+        // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
+        // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
+        // > compiled using the bootstrap rustc wrapper which sets `--sysroot
+        // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
+        // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
+        // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
+        //
+        // The gist here is that we have to pass the proper stage0 sysroot if we want
+        //
+        // ```
+        // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
+        // ```
+        //
+        // to work correctly.
+        //
+        // See <https://github.com/rust-lang/rust/pull/122248> for more background.
         if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
-            let mut stage0_sysroot = build_root.clone();
-            stage0_sysroot.push("stage0-sysroot");
-            debug!(?stage0_sysroot);
-            debug!(exists = stage0_sysroot.exists());
-
-            cmd.arg("--sysroot").arg(&stage0_sysroot);
+            let stage0_sysroot = build_root.join("stage0-sysroot");
+            rustc.arg("--sysroot").arg(&stage0_sysroot);
         }
 
-        let res = self.run_command_to_procres(&mut cmd);
+        // Now run rustc to build the recipe.
+        let res = self.run_command_to_procres(&mut rustc);
         if !res.status.success() {
             self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
         }
 
-        // Finally, we need to run the recipe binary to build and run the actual tests.
-        debug!(?recipe_bin);
+        // To actually run the recipe, we have to provide the recipe with a bunch of information
+        // provided through env vars.
 
-        let mut dylib_env_paths = orig_dylib_env_paths.clone();
-        dylib_env_paths.push(support_lib_path.parent().unwrap().to_path_buf());
-        dylib_env_paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
-        let dylib_env_paths = env::join_paths(dylib_env_paths).unwrap();
+        // Compute stage-specific standard library paths.
+        let stage_std_path = build_root.join(&stage).join("lib");
 
-        let mut target_rpath_env_path = Vec::new();
-        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();
+        // Compute dynamic library search paths for recipes.
+        let recipe_dylib_search_paths = {
+            let mut paths = base_dylib_search_paths.clone();
+            paths.push(support_lib_path.parent().unwrap().to_path_buf());
+            paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
+            paths
+        };
 
+        // Compute runtime library search paths for recipes. This is target-specific.
+        let target_runtime_dylib_search_paths = {
+            let mut paths = vec![rmake_out_dir.clone()];
+            paths.extend(base_dylib_search_paths.iter().cloned());
+            paths
+        };
+
+        // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
+        // `TARGET_RPATH_DIR`, it is **extremely** confusing!
         let mut cmd = Command::new(&recipe_bin);
         cmd.current_dir(&rmake_out_dir)
             .stdout(Stdio::piped())
             .stderr(Stdio::piped())
+            // Provide the target-specific env var that is used to record dylib search paths. For
+            // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
             .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-            .env("TARGET_RPATH_ENV", &target_rpath_env_path)
-            .env(dylib_env_var(), &dylib_env_paths)
+            // Provide the dylib search paths.
+            .env(dylib_env_var(), &env::join_paths(recipe_dylib_search_paths).unwrap())
+            // Provide runtime dylib search paths.
+            .env("TARGET_RPATH_ENV", &env::join_paths(target_runtime_dylib_search_paths).unwrap())
+            // Provide the target.
             .env("TARGET", &self.config.target)
+            // Some tests unfortunately still need Python, so provide path to a Python interpreter.
             .env("PYTHON", &self.config.python)
-            .env("SOURCE_ROOT", &src_root)
-            .env("RUST_BUILD_STAGE", &self.config.stage_id)
-            .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
-            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
+            // Provide path to checkout root. This is the top-level directory containing
+            // rust-lang/rust checkout.
+            .env("SOURCE_ROOT", &source_root)
+            // Provide path to stage-corresponding rustc.
+            .env("RUSTC", &self.config.rustc_path)
+            // Provide the directory to libraries that are needed to run the *compiler*. This is not
+            // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
+            // recipe wants to invoke rustc.
+            .env("HOST_RPATH_DIR", &self.config.compile_lib_path)
+            // Provide the directory to libraries that might be needed to run compiled binaries
+            // (further compiled by the recipe!).
+            .env("TARGET_RPATH_DIR", &self.config.run_lib_path)
+            // Provide which LLVM components are available (e.g. which LLVM components are provided
+            // through a specific CI runner).
             .env("LLVM_COMPONENTS", &self.config.llvm_components);
 
         if let Some(ref rustdoc) = self.config.rustdoc_path {
-            cmd.env("RUSTDOC", cwd.join(rustdoc));
+            cmd.env("RUSTDOC", source_root.join(rustdoc));
         }
 
         if let Some(ref node) = self.config.nodejs {
@@ -3662,6 +3749,7 @@ impl<'test> TestCx<'test> {
             cmd.env("IS_MSVC", "1")
                 .env("IS_WINDOWS", "1")
                 .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
+                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
                 // Note: we diverge from legacy run_make and don't lump `CC` the compiler and
                 // default flags together.
                 .env("CC_DEFAULT_FLAGS", &cflags)
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
index 558e87290b0..d91b258162e 100644
--- a/src/tools/generate-copyright/src/main.rs
+++ b/src/tools/generate-copyright/src/main.rs
@@ -1,5 +1,4 @@
 use anyhow::Error;
-use std::collections::BTreeSet;
 use std::io::Write;
 use std::path::PathBuf;
 
@@ -27,7 +26,7 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
             }
         }
         Node::Directory { name, children, license } => {
-            render_license(&prefix, std::iter::once(name), license.iter(), buffer)?;
+            render_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?;
             if !children.is_empty() {
                 writeln!(buffer, "{prefix}")?;
                 writeln!(buffer, "{prefix}*Exceptions:*")?;
@@ -37,19 +36,11 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
                 }
             }
         }
-        Node::CondensedDirectory { name, licenses } => {
-            render_license(&prefix, std::iter::once(name), licenses.iter(), buffer)?;
-        }
         Node::Group { files, directories, license } => {
-            render_license(
-                &prefix,
-                directories.iter().chain(files.iter()),
-                std::iter::once(license),
-                buffer,
-            )?;
+            render_license(&prefix, directories.iter().chain(files.iter()), Some(license), buffer)?;
         }
         Node::File { name, license } => {
-            render_license(&prefix, std::iter::once(name), std::iter::once(license), buffer)?;
+            render_license(&prefix, std::iter::once(name), Some(license), buffer)?;
         }
     }
 
@@ -59,27 +50,17 @@ fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(
 fn render_license<'a>(
     prefix: &str,
     names: impl Iterator<Item = &'a String>,
-    licenses: impl Iterator<Item = &'a License>,
+    license: Option<&License>,
     buffer: &mut Vec<u8>,
 ) -> Result<(), Error> {
-    let mut spdxs = BTreeSet::new();
-    let mut copyrights = BTreeSet::new();
-    for license in licenses {
-        spdxs.insert(&license.spdx);
-        for copyright in &license.copyright {
-            copyrights.insert(copyright);
-        }
-    }
-
     for name in names {
         writeln!(buffer, "{prefix}**`{name}`**  ")?;
     }
-    for spdx in spdxs.iter() {
-        writeln!(buffer, "{prefix}License: `{spdx}`  ")?;
-    }
-    for (i, copyright) in copyrights.iter().enumerate() {
-        let suffix = if i == copyrights.len() - 1 { "" } else { "  " };
-        writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?;
+    if let Some(license) = license {
+        writeln!(buffer, "{prefix}License: `{}`", license.spdx)?;
+        for copyright in license.copyright.iter() {
+            writeln!(buffer, "{prefix}Copyright: {copyright}")?;
+        }
     }
 
     Ok(())
@@ -95,7 +76,6 @@ struct Metadata {
 pub(crate) enum Node {
     Root { children: Vec<Node> },
     Directory { name: String, children: Vec<Node>, license: Option<License> },
-    CondensedDirectory { name: String, licenses: Vec<License> },
     File { name: String, license: License },
     Group { files: Vec<String>, directories: Vec<String>, license: License },
 }
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 429c6151796..de94990b53e 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -66,14 +66,17 @@ impl CommandKind {
         };
 
         if !count {
-            print_err(&format!("Incorrect number of arguments to `@{}`", self), lineno);
+            print_err(&format!("Incorrect number of arguments to `{}`", self), lineno);
             return false;
         }
 
         if let CommandKind::Count = self {
             if args[1].parse::<usize>().is_err() {
                 print_err(
-                    &format!("Second argument to @count must be a valid usize (got `{}`)", args[1]),
+                    &format!(
+                        "Second argument to `count` must be a valid usize (got `{}`)",
+                        args[1]
+                    ),
                     lineno,
                 );
                 return false;
@@ -101,7 +104,8 @@ static LINE_PATTERN: OnceLock<Regex> = OnceLock::new();
 fn line_pattern() -> Regex {
     RegexBuilder::new(
         r#"
-        \s(?P<invalid>!?)@(?P<negated>!?)
+        //@\s+
+        (?P<negated>!?)
         (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
         (?P<args>.*)$
     "#,
@@ -116,6 +120,10 @@ fn print_err(msg: &str, lineno: usize) {
     eprintln!("Invalid command: {} on line {}", msg, lineno)
 }
 
+// FIXME: This setup is temporary until we figure out how to improve this situation.
+//        See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
+include!(concat!(env!("CARGO_MANIFEST_DIR"), "/../compiletest/src/command-list.rs"));
+
 /// Get a list of commands from a file. Does the work of ensuring the commands
 /// are syntactically valid.
 fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
@@ -132,36 +140,22 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
         };
 
         let negated = cap.name("negated").unwrap().as_str() == "!";
-        let cmd = cap.name("cmd").unwrap().as_str();
 
-        let cmd = match cmd {
+        let cmd = match cap.name("cmd").unwrap().as_str() {
             "has" => CommandKind::Has,
             "count" => CommandKind::Count,
             "is" => CommandKind::Is,
             "ismany" => CommandKind::IsMany,
             "set" => CommandKind::Set,
-            _ => {
-                print_err(&format!("Unrecognized command name `@{}`", cmd), lineno);
+            // FIXME: See the comment above the `include!(...)`.
+            cmd if KNOWN_DIRECTIVE_NAMES.contains(&cmd) => continue,
+            cmd => {
+                print_err(&format!("Unrecognized command name `{cmd}`"), lineno);
                 errors = true;
                 continue;
             }
         };
 
-        if let Some(m) = cap.name("invalid") {
-            if m.as_str() == "!" {
-                print_err(
-                    &format!(
-                        "`!@{0}{1}`, (help: try with `@!{1}`)",
-                        if negated { "!" } else { "" },
-                        cmd,
-                    ),
-                    lineno,
-                );
-                errors = true;
-                continue;
-            }
-        }
-
         let args = cap.name("args").map_or(Some(vec![]), |m| shlex::split(m.as_str()));
 
         let args = match args {
@@ -197,19 +191,19 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
     let result = match command.kind {
         CommandKind::Has => {
             match command.args.len() {
-                // @has <jsonpath> = check path exists
+                // `has <jsonpath>`: Check that `jsonpath` exists.
                 1 => {
                     let val = cache.value();
                     let results = select(val, &command.args[0]).unwrap();
                     !results.is_empty()
                 }
-                // @has <jsonpath> <value> = check *any* item matched by path equals value
+                // `has <jsonpath> <value>`: Check *any* item matched by `jsonpath` equals `value`.
                 2 => {
                     let val = cache.value().clone();
                     let results = select(&val, &command.args[0]).unwrap();
                     let pat = string_to_value(&command.args[1], cache);
                     let has = results.contains(&pat.as_ref());
-                    // Give better error for when @has check fails
+                    // Give better error for when `has` check fails.
                     if !command.negated && !has {
                         return Err(CkError::FailedCheck(
                             format!(
@@ -227,8 +221,9 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 _ => unreachable!(),
             }
         }
+        // `ismany <path> <jsonpath> <value...>`
         CommandKind::IsMany => {
-            // @ismany <path> <jsonpath> <value>...
+            assert!(!command.negated, "`ismany` may not be negated");
             let (query, values) = if let [query, values @ ..] = &command.args[..] {
                 (query, values)
             } else {
@@ -236,7 +231,6 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             };
             let val = cache.value();
             let got_values = select(val, &query).unwrap();
-            assert!(!command.negated, "`@!ismany` is not supported");
 
             // Serde json doesn't implement Ord or Hash for Value, so we must
             // use a Vec here. While in theory that makes setwize equality
@@ -265,8 +259,8 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             }
             true
         }
+        // `count <jsonpath> <count>`: Check that `jsonpath` matches exactly `count` times.
         CommandKind::Count => {
-            // @count <jsonpath> <count> = Check that the jsonpath matches exactly [count] times
             assert_eq!(command.args.len(), 2);
             let expected: usize = command.args[1].parse().unwrap();
             let val = cache.value();
@@ -287,8 +281,8 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 eq
             }
         }
+        // `has <jsonpath> <value>`: Check` *exactly one* item matched by `jsonpath`, and it equals `value`.
         CommandKind::Is => {
-            // @has <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
             assert_eq!(command.args.len(), 2);
             let val = cache.value().clone();
             let results = select(&val, &command.args[0]).unwrap();
@@ -308,8 +302,9 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 is
             }
         }
+        // `set <name> = <jsonpath>`
         CommandKind::Set => {
-            // @set <name> = <jsonpath>
+            assert!(!command.negated, "`set` may not be negated");
             assert_eq!(command.args.len(), 3);
             assert_eq!(command.args[1], "=", "Expected an `=`");
             let val = cache.value().clone();
@@ -317,7 +312,7 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
             assert_eq!(
                 results.len(),
                 1,
-                "Expected 1 match for `{}` (because of @set): matched to {:?}",
+                "Expected 1 match for `{}` (because of `set`): matched to {:?}",
                 command.args[2],
                 results
             );
@@ -330,7 +325,7 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
                 }
                 _ => {
                     panic!(
-                        "Got multiple results in `@set` for `{}`: {:?}",
+                        "Got multiple results in `set` for `{}`: {:?}",
                         &command.args[2], results,
                     );
                 }
@@ -341,18 +336,14 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
     if result == command.negated {
         if command.negated {
             Err(CkError::FailedCheck(
-                format!(
-                    "`@!{} {}` matched when it shouldn't",
-                    command.kind,
-                    command.args.join(" ")
-                ),
+                format!("`!{} {}` matched when it shouldn't", command.kind, command.args.join(" ")),
                 command,
             ))
         } else {
             // FIXME: In the future, try 'peeling back' each step, and see at what level the match failed
             Err(CkError::FailedCheck(
                 format!(
-                    "`@{} {}` didn't match when it should",
+                    "`{} {}` didn't match when it should",
                     command.kind,
                     command.args.join(" ")
                 ),
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 9eaa234bfaf..0d827ab2e72 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -24,6 +24,7 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
         "keyword-idents",
         "Lints that detect identifiers which will be come keywords in later editions",
     ),
+    ("deprecated-safe", "Lints for functions which were erroneously marked as safe in the past"),
 ];
 
 type LintGroups = BTreeMap<String, BTreeSet<String>>;
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
index 1d6b6777032..85d7582d112 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
@@ -59,8 +59,10 @@ impl Baz for i32 {
 }
 
 fn main() {
-    let baz: &dyn Baz = &1;
-    let baz_fake: *const dyn Bar = unsafe { std::mem::transmute(baz) };
-    let _err = baz_fake as *const dyn Foo;
-    //~^ERROR: using vtable for trait `Baz` but trait `Bar` was expected
+    unsafe {
+        let baz: &dyn Baz = &1;
+        let baz_fake: *const dyn Bar = std::mem::transmute(baz);
+        let _err = baz_fake as *const dyn Foo;
+        //~^ERROR: using vtable for trait `Baz` but trait `Bar` was expected
+    }
 }
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
index 6a2415cf57e..87b1361c3e5 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: using vtable for trait `Baz` but trait `Bar` was expected
   --> $DIR/dyn-upcast-trait-mismatch.rs:LL:CC
    |
-LL |     let _err = baz_fake as *const dyn Foo;
-   |                ^^^^^^^^ using vtable for trait `Baz` but trait `Bar` was expected
+LL |         let _err = baz_fake as *const dyn Foo;
+   |                    ^^^^^^^^ using vtable for trait `Baz` but trait `Bar` was expected
    |
    = 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/extern_static.rs b/src/tools/miri/tests/fail/extern_static.rs
index f8805db8d14..0cbf1646be9 100644
--- a/src/tools/miri/tests/fail/extern_static.rs
+++ b/src/tools/miri/tests/fail/extern_static.rs
@@ -5,5 +5,5 @@ extern "C" {
 }
 
 fn main() {
-    let _val = unsafe { std::ptr::addr_of!(FOO) }; //~ ERROR: is not supported by Miri
+    let _val = std::ptr::addr_of!(FOO); //~ ERROR: is not supported by Miri
 }
diff --git a/src/tools/miri/tests/fail/extern_static.stderr b/src/tools/miri/tests/fail/extern_static.stderr
index 21759f96019..c7ab128e2fe 100644
--- a/src/tools/miri/tests/fail/extern_static.stderr
+++ b/src/tools/miri/tests/fail/extern_static.stderr
@@ -1,8 +1,8 @@
 error: unsupported operation: extern static `FOO` is not supported by Miri
   --> $DIR/extern_static.rs:LL:CC
    |
-LL |     let _val = unsafe { std::ptr::addr_of!(FOO) };
-   |                                            ^^^ extern static `FOO` is not supported by Miri
+LL |     let _val = std::ptr::addr_of!(FOO);
+   |                                   ^^^ extern static `FOO` is not supported by Miri
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs
index 1b416cc4e9b..4488b5a09d5 100644
--- a/src/tools/miri/tests/pass/static_mut.rs
+++ b/src/tools/miri/tests/pass/static_mut.rs
@@ -2,7 +2,7 @@ use std::ptr::addr_of;
 
 static mut FOO: i32 = 42;
 
-static BAR: Foo = Foo(unsafe { addr_of!(FOO) });
+static BAR: Foo = Foo(addr_of!(FOO));
 
 #[allow(dead_code)]
 struct Foo(*const i32);
diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs
index a2c58f4e4b6..bc6ec7566e5 100644
--- a/src/tools/run-make-support/src/artifact_names.rs
+++ b/src/tools/run-make-support/src/artifact_names.rs
@@ -1,7 +1,9 @@
 //! A collection of helpers to construct artifact names, such as names of dynamic or static
 //! librarys which are target-dependent.
 
-use crate::targets::{is_darwin, is_msvc, is_windows};
+// FIXME(jieyouxu): convert these to return `PathBuf`s instead of strings!
+
+use crate::targets::is_msvc;
 
 /// Construct the static library name based on the target.
 #[must_use]
@@ -31,41 +33,15 @@ pub fn static_lib_name(name: &str) -> String {
 /// Construct the dynamic library name based on the target.
 #[must_use]
 pub fn dynamic_lib_name(name: &str) -> String {
-    // See tools.mk (irrelevant lines omitted):
-    //
-    // ```makefile
-    // ifeq ($(UNAME),Darwin)
-    //     DYLIB = $(TMPDIR)/lib$(1).dylib
-    // else
-    //     ifdef IS_WINDOWS
-    //         DYLIB = $(TMPDIR)/$(1).dll
-    //     else
-    //         DYLIB = $(TMPDIR)/lib$(1).so
-    //     endif
-    // endif
-    // ```
     assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
 
-    let extension = dynamic_lib_extension();
-    if is_darwin() {
-        format!("lib{name}.{extension}")
-    } else if is_windows() {
-        format!("{name}.{extension}")
-    } else {
-        format!("lib{name}.{extension}")
-    }
+    format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION)
 }
 
 /// Construct the dynamic library extension based on the target.
 #[must_use]
 pub fn dynamic_lib_extension() -> &'static str {
-    if is_darwin() {
-        "dylib"
-    } else if is_windows() {
-        "dll"
-    } else {
-        "so"
-    }
+    std::env::consts::DLL_EXTENSION
 }
 
 /// Construct the name of a rust library (rlib).
@@ -77,5 +53,5 @@ pub fn rust_lib_name(name: &str) -> String {
 /// Construct the binary (executable) name based on the target.
 #[must_use]
 pub fn bin_name(name: &str) -> String {
-    if is_windows() { format!("{name}.exe") } else { name.to_string() }
+    format!("{name}{}", std::env::consts::EXE_SUFFIX)
 }
diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index 5e8ad7ed312..b116bd08e3a 100644
--- a/src/tools/run-make-support/src/external_deps/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -229,6 +229,8 @@ impl LlvmAr {
         Self { cmd }
     }
 
+    /// Automatically pass the commonly used arguments `rcus`, used for combining one or more
+    /// input object files into one output static library file.
     pub fn obj_to_ar(&mut self) -> &mut Self {
         self.cmd.arg("rcus");
         self
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index e6a45f57de6..b85191970de 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -3,6 +3,10 @@
 //! notably is built via cargo: this means that if your test wants some non-trivial utility, such
 //! as `object` or `wasmparser`, they can be re-exported and be made available through this library.
 
+// We want to control use declaration ordering and spacing (and preserve use group comments), so
+// skip rustfmt on this file.
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
 mod command;
 mod macros;
 mod util;
@@ -18,6 +22,8 @@ pub mod scoped_run;
 pub mod string;
 pub mod targets;
 
+// Internally we call our fs-related support module as `fs`, but re-export its content as `rfs`
+// to tests to avoid colliding with commonly used `use std::fs;`.
 mod fs;
 
 /// [`std::fs`] wrappers and assorted filesystem-related helpers. Public to tests as `rfs` to not be
diff --git a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs
index cf3d85b4da3..4ec74c0742a 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/panic_context.rs
@@ -21,6 +21,7 @@ impl PanicContext {
     #[allow(clippy::print_stderr)]
     fn init() {
         let default_hook = panic::take_hook();
+        #[allow(deprecated)]
         let hook = move |panic_info: &panic::PanicInfo<'_>| {
             with_ctx(|ctx| {
                 if !ctx.is_empty() {
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
new file mode 100644
index 00000000000..75b89a162e9
--- /dev/null
+++ b/src/tools/rustbook/Cargo.lock
@@ -0,0 +1,1762 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ammonia"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
+dependencies = [
+ "html5ever",
+ "maplit",
+ "once_cell",
+ "tendril",
+ "url",
+]
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bstr"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+dependencies = [
+ "memchr",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "cc"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "num-traits",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+ "terminal_size",
+]
+
+[[package]]
+name = "clap_complete"
+version = "4.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b4be9c4c4b1f30b78d8a750e0822b6a6102d97e62061c583a6c1dea2dfb33ae"
+dependencies = [
+ "clap",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "dbus"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
+dependencies = [
+ "libc",
+ "libdbus-sys",
+ "winapi",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "elasticlunr-rs"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571"
+dependencies = [
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+]
+
+[[package]]
+name = "env_filter"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "humantime",
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
+name = "flate2"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futf"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
+dependencies = [
+ "mac",
+ "new_debug_unreachable",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getopts"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "handlebars"
+version = "5.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b"
+dependencies = [
+ "log",
+ "pest",
+ "pest_derive",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "html5ever"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
+dependencies = [
+ "log",
+ "mac",
+ "markup5ever",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.155"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+
+[[package]]
+name = "libdbus-sys"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
+name = "linereader"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d921fea6860357575519aca014c6e22470585accdd543b370c404a8a72d0dd1d"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "mac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
+name = "markup5ever"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
+dependencies = [
+ "log",
+ "phf",
+ "phf_codegen",
+ "string_cache",
+ "string_cache_codegen",
+ "tendril",
+]
+
+[[package]]
+name = "mdbook"
+version = "0.4.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5"
+dependencies = [
+ "ammonia",
+ "anyhow",
+ "chrono",
+ "clap",
+ "clap_complete",
+ "elasticlunr-rs",
+ "env_logger",
+ "handlebars",
+ "log",
+ "memchr",
+ "once_cell",
+ "opener",
+ "pulldown-cmark",
+ "regex",
+ "serde",
+ "serde_json",
+ "shlex",
+ "tempfile",
+ "toml 0.5.11",
+ "topological-sort",
+]
+
+[[package]]
+name = "mdbook-i18n-helpers"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c8f972ab672d366c3dad77ea5aa7bae68db2d25fbeb889849f97469d7b658e4"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "mdbook",
+ "polib",
+ "pulldown-cmark",
+ "pulldown-cmark-to-cmark",
+ "regex",
+ "semver",
+ "serde_json",
+ "syntect",
+ "textwrap",
+]
+
+[[package]]
+name = "mdbook-trpl-listing"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "mdbook",
+ "pulldown-cmark",
+ "pulldown-cmark-to-cmark",
+ "serde_json",
+ "thiserror",
+ "toml 0.8.14",
+ "xmlparser",
+]
+
+[[package]]
+name = "mdbook-trpl-note"
+version = "1.0.0"
+dependencies = [
+ "clap",
+ "mdbook",
+ "pulldown-cmark",
+ "pulldown-cmark-to-cmark",
+ "serde_json",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
+
+[[package]]
+name = "normpath"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "onig"
+version = "6.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+ "once_cell",
+ "onig_sys",
+]
+
+[[package]]
+name = "onig_sys"
+version = "69.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
+name = "opener"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0"
+dependencies = [
+ "bstr",
+ "dbus",
+ "normpath",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pest"
+version = "2.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95"
+dependencies = [
+ "memchr",
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_shared 0.11.2",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+dependencies = [
+ "phf_generator 0.11.2",
+ "phf_shared 0.11.2",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
+dependencies = [
+ "phf_shared 0.10.0",
+ "rand",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared 0.11.2",
+ "rand",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
+[[package]]
+name = "plist"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
+dependencies = [
+ "base64",
+ "indexmap",
+ "quick-xml",
+ "serde",
+ "time",
+]
+
+[[package]]
+name = "polib"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b393b155cf9be86249cba1b56cc81be0e6212c66d94ac0d76d37a1761f3bb1b"
+dependencies = [
+ "linereader",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "pulldown-cmark"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
+dependencies = [
+ "bitflags 2.6.0",
+ "getopts",
+ "memchr",
+ "pulldown-cmark-escape",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark-escape"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3"
+
+[[package]]
+name = "pulldown-cmark-to-cmark"
+version = "13.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b"
+dependencies = [
+ "pulldown-cmark",
+]
+
+[[package]]
+name = "quick-xml"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+
+[[package]]
+name = "rustbook"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "env_logger",
+ "mdbook",
+ "mdbook-i18n-helpers",
+ "mdbook-trpl-listing",
+ "mdbook-trpl-note",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags 2.6.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
+[[package]]
+name = "serde"
+version = "1.0.204"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.204"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.120"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "string_cache"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
+dependencies = [
+ "new_debug_unreachable",
+ "once_cell",
+ "parking_lot",
+ "phf_shared 0.10.0",
+ "precomputed-hash",
+ "serde",
+]
+
+[[package]]
+name = "string_cache_codegen"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
+dependencies = [
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syntect"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
+dependencies = [
+ "bincode",
+ "bitflags 1.3.2",
+ "flate2",
+ "fnv",
+ "once_cell",
+ "onig",
+ "plist",
+ "regex-syntax",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "thiserror",
+ "walkdir",
+ "yaml-rust",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "tendril"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
+dependencies = [
+ "futf",
+ "mac",
+ "utf-8",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
+dependencies = [
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+
+[[package]]
+name = "thiserror"
+version = "1.0.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "time"
+version = "0.3.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "topological-sort"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
+
+[[package]]
+name = "unicase"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+
+[[package]]
+name = "url"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+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 = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "winnow"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xmlparser"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 95f1a5d6e1d..51ba58483c5 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -1,3 +1,5 @@
+[workspace]
+
 [package]
 name = "rustbook"
 version = "0.1.0"
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 745f00c4f52..4042bac8dac 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,16 +1,10 @@
-run-make/archive-duplicate-names/Makefile
 run-make/branch-protection-check-IBT/Makefile
 run-make/c-dynamic-dylib/Makefile
 run-make/c-dynamic-rlib/Makefile
-run-make/c-static-dylib/Makefile
-run-make/c-static-rlib/Makefile
 run-make/c-unwind-abi-catch-lib-panic/Makefile
-run-make/c-unwind-abi-catch-panic/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
-run-make/compiler-lookup-paths-2/Makefile
 run-make/compiler-rt-works-on-mingw/Makefile
-run-make/crate-hash-rustc-version/Makefile
 run-make/cross-lang-lto-clang/Makefile
 run-make/cross-lang-lto-pgo-smoketest/Makefile
 run-make/cross-lang-lto-upstream-rlibs/Makefile
@@ -23,9 +17,7 @@ run-make/emit-to-stdout/Makefile
 run-make/export-executable-symbols/Makefile
 run-make/extern-diff-internal-name/Makefile
 run-make/extern-flag-disambiguates/Makefile
-run-make/extern-fn-generic/Makefile
 run-make/extern-fn-reachable/Makefile
-run-make/extern-fn-with-union/Makefile
 run-make/extern-multiple-copies/Makefile
 run-make/extern-multiple-copies2/Makefile
 run-make/fmt-write-bloat/Makefile
@@ -35,48 +27,29 @@ run-make/foreign-rust-exceptions/Makefile
 run-make/incr-add-rust-src-component/Makefile
 run-make/incr-foreign-head-span/Makefile
 run-make/interdependent-c-libraries/Makefile
-run-make/issue-107094/Makefile
-run-make/issue-14698/Makefile
-run-make/issue-15460/Makefile
-run-make/issue-22131/Makefile
-run-make/issue-26006/Makefile
-run-make/issue-28595/Makefile
-run-make/issue-33329/Makefile
 run-make/issue-35164/Makefile
 run-make/issue-36710/Makefile
 run-make/issue-47551/Makefile
 run-make/issue-69368/Makefile
 run-make/issue-84395-lto-embed-bitcode/Makefile
 run-make/issue-88756-default-output/Makefile
-run-make/issue-97463-abi-param-passing/Makefile
 run-make/jobserver-error/Makefile
 run-make/libs-through-symlinks/Makefile
 run-make/libtest-json/Makefile
 run-make/libtest-junit/Makefile
 run-make/libtest-thread-limit/Makefile
 run-make/link-cfg/Makefile
-run-make/link-framework/Makefile
-run-make/link-path-order/Makefile
-run-make/linkage-attr-on-static/Makefile
 run-make/long-linker-command-lines-cmd-exe/Makefile
 run-make/long-linker-command-lines/Makefile
-run-make/lto-linkage-used-attr/Makefile
-run-make/lto-no-link-whole-rlib/Makefile
-run-make/lto-smoke-c/Makefile
 run-make/macos-deployment-target/Makefile
-run-make/macos-fat-archive/Makefile
-run-make/manual-link/Makefile
 run-make/min-global-align/Makefile
 run-make/native-link-modifier-bundle/Makefile
 run-make/native-link-modifier-whole-archive/Makefile
 run-make/no-alloc-shim/Makefile
 run-make/no-builtins-attribute/Makefile
-run-make/no-duplicate-libs/Makefile
 run-make/panic-abort-eh_frame/Makefile
-run-make/pass-non-c-like-enum-to-c/Makefile
 run-make/pdb-buildinfo-cl-cmd/Makefile
 run-make/pgo-gen-lto/Makefile
-run-make/pgo-gen-no-imp-symbols/Makefile
 run-make/pgo-indirect-call-promotion/Makefile
 run-make/pointer-auth-link-with-c/Makefile
 run-make/print-calling-conventions/Makefile
@@ -90,9 +63,7 @@ run-make/redundant-libs/Makefile
 run-make/remap-path-prefix-dwarf/Makefile
 run-make/reproducible-build-2/Makefile
 run-make/reproducible-build/Makefile
-run-make/return-non-c-like-enum-from-c/Makefile
 run-make/rlib-format-packed-bundled-libs-2/Makefile
-run-make/rlib-format-packed-bundled-libs-3/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/sanitizer-cdylib-link/Makefile
 run-make/sanitizer-dylib-link/Makefile
@@ -102,12 +73,10 @@ run-make/simd-ffi/Makefile
 run-make/split-debuginfo/Makefile
 run-make/stable-symbol-names/Makefile
 run-make/static-dylib-by-default/Makefile
-run-make/staticlib-blank-lib/Makefile
 run-make/staticlib-dylib-linkage/Makefile
 run-make/symbol-mangling-hashed/Makefile
 run-make/symbol-visibility/Makefile
 run-make/sysroot-crates-are-unstable/Makefile
-run-make/test-benches/Makefile
 run-make/thumb-none-cortex-m/Makefile
 run-make/thumb-none-qemu/Makefile
 run-make/translation/Makefile
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index f9bf04626f7..ea03662c584 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -65,11 +65,12 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
     //("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo
     ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None),
     ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None),
-    //("src/etc/test-float-parse", &[], None), // FIXME uncomment once all deps are vendored
+    ("src/etc/test-float-parse", EXCEPTIONS, None),
     ("src/tools/cargo", EXCEPTIONS_CARGO, None),
     //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
     //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
     ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
+    ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None),
     ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None),
     ("src/tools/x", &[], None),
     // tidy-alphabetical-end
@@ -167,6 +168,13 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[
     // tidy-alphabetical-end
 ];
 
+const EXCEPTIONS_RUSTBOOK: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("mdbook", "MPL-2.0"),
+    ("ryu", "Apache-2.0 OR BSL-1.0"),
+    // tidy-alphabetical-end
+];
+
 const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-start
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
diff --git a/src/tools/tier-check/src/main.rs b/src/tools/tier-check/src/main.rs
index c74d37c61e8..91b96117db0 100644
--- a/src/tools/tier-check/src/main.rs
+++ b/src/tools/tier-check/src/main.rs
@@ -47,8 +47,14 @@ fn main() {
     // Check target names for unwanted characters like `.` that can cause problems e.g. in Cargo.
     // See also Tier 3 target policy.
     // If desired, target names can ignore this check.
-    let ignore_target_names =
-        vec!["thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf"];
+    let ignore_target_names = vec![
+        "thumbv8m.base-none-eabi",
+        "thumbv8m.main-none-eabi",
+        "thumbv8m.main-none-eabihf",
+        "thumbv8m.base-nuttx-eabi",
+        "thumbv8m.main-nuttx-eabi",
+        "thumbv8m.main-nuttx-eabihf",
+    ];
     let mut invalid_target_name_found = false;
     for target in &target_list {
         if !ignore_target_names.contains(target)
diff --git a/src/version b/src/version
index dbd41264aa9..71fae54fb27 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.81.0
+1.82.0
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index 32cce3839dc..762df40a44b 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -576,6 +576,42 @@
 //@ revisions: x86_64_wrs_vxworks
 //@ [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks
 //@ [x86_64_wrs_vxworks] needs-llvm-components: x86
+//@ revisions: thumbv6m_nuttx_eabi
+//@ [thumbv6m_nuttx_eabi] compile-flags: --target thumbv6m-nuttx-eabi
+//@ [thumbv6m_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7m_nuttx_eabi
+//@ [thumbv7m_nuttx_eabi] compile-flags: --target thumbv7m-nuttx-eabi
+//@ [thumbv7m_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_nuttx_eabi
+//@ [thumbv7em_nuttx_eabi] compile-flags: --target thumbv7em-nuttx-eabi
+//@ [thumbv7em_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv7em_nuttx_eabihf
+//@ [thumbv7em_nuttx_eabihf] compile-flags: --target thumbv7em-nuttx-eabihf
+//@ [thumbv7em_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: thumbv8m_base_nuttx_eabi
+//@ [thumbv8m_base_nuttx_eabi] compile-flags: --target thumbv8m.base-nuttx-eabi
+//@ [thumbv8m_base_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_nuttx_eabi
+//@ [thumbv8m_main_nuttx_eabi] compile-flags: --target thumbv8m.main-nuttx-eabi
+//@ [thumbv8m_main_nuttx_eabi] needs-llvm-components: arm
+//@ revisions: thumbv8m_main_nuttx_eabihf
+//@ [thumbv8m_main_nuttx_eabihf] compile-flags: --target thumbv8m.main-nuttx-eabihf
+//@ [thumbv8m_main_nuttx_eabihf] needs-llvm-components: arm
+//@ revisions: riscv32imc_unknown_nuttx_elf
+//@ [riscv32imc_unknown_nuttx_elf] compile-flags: --target riscv32imc-unknown-nuttx-elf
+//@ [riscv32imc_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imac_unknown_nuttx_elf
+//@ [riscv32imac_unknown_nuttx_elf] compile-flags: --target riscv32imac-unknown-nuttx-elf
+//@ [riscv32imac_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv32imafc_unknown_nuttx_elf
+//@ [riscv32imafc_unknown_nuttx_elf] compile-flags: --target riscv32imafc-unknown-nuttx-elf
+//@ [riscv32imafc_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv64imac_unknown_nuttx_elf
+//@ [riscv64imac_unknown_nuttx_elf] compile-flags: --target riscv64imac-unknown-nuttx-elf
+//@ [riscv64imac_unknown_nuttx_elf] needs-llvm-components: riscv
+//@ revisions: riscv64gc_unknown_nuttx_elf
+//@ [riscv64gc_unknown_nuttx_elf] compile-flags: --target riscv64gc-unknown-nuttx-elf
+//@ [riscv64gc_unknown_nuttx_elf] needs-llvm-components: riscv
 // FIXME: disabled since it requires a custom LLVM until the upstream LLVM adds support for the target (https://github.com/espressif/llvm-project/issues/4)
 /*
     revisions: xtensa_esp32_none_elf
diff --git a/tests/codegen/generic-debug.rs b/tests/codegen/generic-debug.rs
index 3423abe7187..0ad0b074657 100644
--- a/tests/codegen/generic-debug.rs
+++ b/tests/codegen/generic-debug.rs
@@ -1,4 +1,3 @@
-//@ ignore-windows
 //@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
diff --git a/tests/codegen/issues/issue-58881.rs b/tests/codegen/issues/issue-58881.rs
index 759e3b70baa..ba6285f3972 100644
--- a/tests/codegen/issues/issue-58881.rs
+++ b/tests/codegen/issues/issue-58881.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: -C no-prepopulate-passes -Copt-level=0
 //
 //@ only-x86_64
-//@ ignore-windows
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/mainsubprogram.rs b/tests/codegen/mainsubprogram.rs
index 12b24c90229..ce3fe3c8608 100644
--- a/tests/codegen/mainsubprogram.rs
+++ b/tests/codegen/mainsubprogram.rs
@@ -1,7 +1,6 @@
 // This test depends on a patch that was committed to upstream LLVM
 // before 4.0, formerly backported to the Rust LLVM fork.
 
-//@ ignore-windows
 //@ ignore-apple
 //@ ignore-wasi
 
diff --git a/tests/codegen/mainsubprogramstart.rs b/tests/codegen/mainsubprogramstart.rs
index 20741791db5..0bcb311644d 100644
--- a/tests/codegen/mainsubprogramstart.rs
+++ b/tests/codegen/mainsubprogramstart.rs
@@ -1,4 +1,3 @@
-//@ ignore-windows
 //@ ignore-apple
 //@ ignore-wasi wasi codegens the main symbol differently
 
diff --git a/tests/codegen/nounwind.rs b/tests/codegen/nounwind.rs
index 464bc2535c2..c910644458a 100644
--- a/tests/codegen/nounwind.rs
+++ b/tests/codegen/nounwind.rs
@@ -1,6 +1,5 @@
 //@ aux-build:nounwind.rs
 //@ compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a
-//@ ignore-windows
 //@ ignore-android
 
 #![crate_type = "lib"]
diff --git a/tests/crashes/119299.rs b/tests/crashes/119299.rs
deleted file mode 100644
index c8c10546d94..00000000000
--- a/tests/crashes/119299.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #119299
-#![feature(adt_const_params)]
-#![allow(incomplete_features)]
-
-use std::marker::ConstParamTy;
-
-#[derive(Eq, PartialEq)]
-struct ConstStrU(*const u8, usize);
-
-impl ConstParamTy for &'static ConstStrU {}
-
-impl ConstStrU {
-  const fn from_bytes(bytes: &'static [u8]) -> Self {
-    Self(bytes.as_ptr(), bytes.len())
-  }
-}
-
-const fn chars_s<const S: &'static ConstStrU>() -> [char; 3] {
-  ['a','b','c']
-}
-
-fn main() {
-  const A: &'static ConstStrU = &ConstStrU::from_bytes(b"abc");
-  chars_s::<A>();
-}
diff --git a/tests/crashes/127009.rs b/tests/crashes/127009.rs
deleted file mode 100644
index 74ca14393e4..00000000000
--- a/tests/crashes/127009.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #127009
-
-#![feature(non_lifetime_binders)]
-
-fn b()
-where
-    for<const C: usize> [(); C]: Copy,
-{
-}
-
-fn main() {}
diff --git a/tests/crashes/127351.rs b/tests/crashes/127351.rs
new file mode 100644
index 00000000000..e3f41594885
--- /dev/null
+++ b/tests/crashes/127351.rs
@@ -0,0 +1,17 @@
+//@ known-bug: #127351
+#![feature(lazy_type_alias)]
+#![allow(incomplete_features)]
+
+struct Outer0<'a, T>(ExplicitTypeOutlives<'a, T>);
+type ExplicitTypeOutlives<'a, T: 'a> = (&'a (), T);
+
+pub struct Warns {
+    _significant_drop: ExplicitTypeOutlives,
+    field: String,
+}
+
+pub fn test(w: Warns) {
+    _ = || drop(w.field);
+}
+
+fn main() {}
diff --git a/tests/crashes/127353.rs b/tests/crashes/127353.rs
new file mode 100644
index 00000000000..9bcb90b5c57
--- /dev/null
+++ b/tests/crashes/127353.rs
@@ -0,0 +1,18 @@
+//@ known-bug: #127353
+#![feature(type_alias_impl_trait)]
+trait Trait<T> {}
+type Alias<'a, U> = impl Trait<U>;
+
+fn f<'a>() -> Alias<'a, ()> {}
+
+pub enum UninhabitedVariants {
+    Tuple(Alias),
+}
+
+struct A;
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+    match x {}
+}
+
+fn main() {}
diff --git a/tests/crashes/127628.rs b/tests/crashes/127628.rs
new file mode 100644
index 00000000000..f11ab3f7e8d
--- /dev/null
+++ b/tests/crashes/127628.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #127628
+//@ compile-flags: -Zpolonius=next
+
+use std::io::{self, Read};
+
+pub struct Container<'a> {
+    reader: &'a mut dyn Read,
+}
+
+impl<'a> Container {
+    pub fn wrap<'s>(reader: &'s mut dyn io::Read) -> Container<'s> {
+        Container { reader: reader }
+    }
+}
diff --git a/tests/crashes/127643.rs b/tests/crashes/127643.rs
new file mode 100644
index 00000000000..a4db9397bde
--- /dev/null
+++ b/tests/crashes/127643.rs
@@ -0,0 +1,18 @@
+//@ known-bug: #127643
+
+#![feature(associated_const_equality)]
+
+fn user() -> impl Owner<dyn Sized, C = 0> {}
+
+trait Owner<K> {
+    const C: K;
+}
+impl<K: ConstDefault> Owner<K> for () {
+    const C: K = K::DEFAULT;
+}
+
+trait ConstDefault {
+    const DEFAULT: Self;
+}
+
+fn main() {}
diff --git a/tests/crashes/127676.rs b/tests/crashes/127676.rs
new file mode 100644
index 00000000000..81149c2ef84
--- /dev/null
+++ b/tests/crashes/127676.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #127676
+//@ edition:2018
+
+#![feature(dyn_star,const_async_blocks)]
+
+static S: dyn* Send + Sync = async { 42 };
+
+pub fn main() {}
diff --git a/tests/crashes/127737.rs b/tests/crashes/127737.rs
new file mode 100644
index 00000000000..2ee8c769858
--- /dev/null
+++ b/tests/crashes/127737.rs
@@ -0,0 +1,21 @@
+//@ known-bug: #127737
+//@ compile-flags: -Zmir-opt-level=5 --crate-type lib
+
+pub trait TestTrait {
+    type MyType;
+    fn func() -> Option<Self>
+    where
+        Self: Sized;
+}
+
+impl<T> dyn TestTrait<MyType = T>
+where
+    Self: Sized,
+{
+    pub fn other_func() -> Option<Self> {
+        match Self::func() {
+            Some(me) => Some(me),
+            None => None,
+        }
+    }
+}
diff --git a/tests/crashes/127742.rs b/tests/crashes/127742.rs
new file mode 100644
index 00000000000..24add454135
--- /dev/null
+++ b/tests/crashes/127742.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #127742
+struct Vtable(dyn Cap);  // missing lifetime
+
+trait Cap<'a> {}
+
+union Transmute {
+    t: u64,  // ICEs with u64, u128, or usize. Correctly errors with u32.
+    u: &'static Vtable,
+}
+
+const G: &'static Vtable = unsafe { Transmute { t: 1 }.u };
diff --git a/tests/crashes/127880.rs b/tests/crashes/127880.rs
new file mode 100644
index 00000000000..6c625eac691
--- /dev/null
+++ b/tests/crashes/127880.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #127880
+//@ compile-flags: -Cinstrument-coverage
+
+#[coverage]
+fn main() {}
diff --git a/tests/crashes/127916.rs b/tests/crashes/127916.rs
new file mode 100644
index 00000000000..295c88df857
--- /dev/null
+++ b/tests/crashes/127916.rs
@@ -0,0 +1,16 @@
+//@ known-bug: #127916
+
+trait Trait {
+    fn foo(&self) -> u32 { 0 }
+}
+
+struct F;
+struct S;
+
+mod to_reuse {
+    pub fn foo(&self) -> u32 {}
+}
+
+impl Trait  S {
+    reuse to_reuse::foo { self }
+}
diff --git a/tests/crashes/127972.rs b/tests/crashes/127972.rs
new file mode 100644
index 00000000000..d0764f875db
--- /dev/null
+++ b/tests/crashes/127972.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #127962
+#![feature(generic_const_exprs)]
+
+fn zero_init<const usize: usize>() -> Substs1<{ (N) }> {
+    Substs1([0; { (usize) }])
+}
diff --git a/tests/crashes/128016.rs b/tests/crashes/128016.rs
new file mode 100644
index 00000000000..d23721ae14e
--- /dev/null
+++ b/tests/crashes/128016.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #128016
+macro_rules! len {
+    () => {
+        target
+    };
+}
+
+fn main() {
+    let val: [str; len!()] = [];
+}
diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs
index 91ee36ae2c5..b59103792bf 100644
--- a/tests/mir-opt/const_prop/invalid_constant.rs
+++ b/tests/mir-opt/const_prop/invalid_constant.rs
@@ -3,7 +3,7 @@
 //@ compile-flags: -Zmir-enable-passes=+RemoveZsts
 // Verify that we can pretty print invalid constants.
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 #[derive(Copy, Clone)]
diff --git a/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff
index 1aeaaff21dc..3b739a25cb8 100644
--- a/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/aggregate_copy.foo.DataflowConstProp.diff
@@ -57,9 +57,7 @@
           StorageDead(_1);
           return;
       }
-+ }
-+ 
-+ ALLOC0 (size: 8, align: 4) {
-+     05 00 00 00 03 00 00 00                         │ ........
   }
++ 
++ ALLOC0 (size: 8, align: 4) { .. }
   
diff --git a/tests/mir-opt/dataflow-const-prop/aggregate_copy.rs b/tests/mir-opt/dataflow-const-prop/aggregate_copy.rs
index aca5f047222..9cd485813bc 100644
--- a/tests/mir-opt/dataflow-const-prop/aggregate_copy.rs
+++ b/tests/mir-opt/dataflow-const-prop/aggregate_copy.rs
@@ -1,6 +1,7 @@
 //! Verify that we manage to propagate the value of aggregate `a` even without directly mentioning
 //! the contained scalars.
 //@ test-mir-pass: DataflowConstProp
+//@ compile-flags: -Zdump-mir-exclude-alloc-bytes
 
 const Foo: (u32, u32) = (5, 3);
 
diff --git a/tests/mir-opt/issue_99325.rs b/tests/mir-opt/issue_99325.rs
index 2638b69e2ee..4cee4f20b31 100644
--- a/tests/mir-opt/issue_99325.rs
+++ b/tests/mir-opt/issue_99325.rs
@@ -1,7 +1,7 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {
diff --git a/tests/run-make/archive-duplicate-names/Makefile b/tests/run-make/archive-duplicate-names/Makefile
deleted file mode 100644
index 207eee39299..00000000000
--- a/tests/run-make/archive-duplicate-names/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# When two object archives with the same filename are present, an iterator is supposed to inspect each object, recognize the duplication and extract each one to a different directory.
-# This test checks that this duplicate handling behaviour has not been broken.
-# See https://github.com/rust-lang/rust/pull/24439
-
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	mkdir $(TMPDIR)/a
-	mkdir $(TMPDIR)/b
-	$(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c)
-	$(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c)
-	$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
-	$(RUSTC) foo.rs
-	$(RUSTC) bar.rs
-	$(call RUN,bar)
diff --git a/tests/run-make/archive-duplicate-names/rmake.rs b/tests/run-make/archive-duplicate-names/rmake.rs
new file mode 100644
index 00000000000..62a35566199
--- /dev/null
+++ b/tests/run-make/archive-duplicate-names/rmake.rs
@@ -0,0 +1,37 @@
+// When two object archives with the same filename are present, an iterator is supposed to
+// inspect each object, recognize the duplication and extract each one to a different directory.
+// This test checks that this duplicate handling behaviour has not been broken.
+// See https://github.com/rust-lang/rust/pull/24439
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{cc, is_msvc, llvm_ar, rfs, run, rustc};
+
+fn main() {
+    rfs::create_dir("a");
+    rfs::create_dir("b");
+    compile_obj_force_foo("a", "foo");
+    compile_obj_force_foo("b", "bar");
+    let mut ar = llvm_ar();
+    ar.obj_to_ar().arg("libfoo.a");
+    if is_msvc() {
+        ar.arg("a/foo.obj").arg("b/foo.obj").run();
+    } else {
+        ar.arg("a/foo.o").arg("b/foo.o").run();
+    }
+    rustc().input("foo.rs").run();
+    rustc().input("bar.rs").run();
+    run("bar");
+}
+
+#[track_caller]
+pub fn compile_obj_force_foo(dir: &str, lib_name: &str) {
+    let obj_file = if is_msvc() { format!("{dir}/foo") } else { format!("{dir}/foo.o") };
+    let src = format!("{lib_name}.c");
+    if is_msvc() {
+        cc().arg("-c").out_exe(&obj_file).input(src).run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
+    };
+}
diff --git a/tests/run-make/c-static-dylib/Makefile b/tests/run-make/c-static-dylib/Makefile
deleted file mode 100644
index 05da1743c83..00000000000
--- a/tests/run-make/c-static-dylib/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# This test checks that static Rust linking with C does not encounter any errors, with dynamic dependencies given preference over static.
-# See https://github.com/rust-lang/rust/issues/10434
-
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,cfoo)
-	$(RUSTC) foo.rs -C prefer-dynamic
-	$(RUSTC) bar.rs
-	rm $(call NATIVE_STATICLIB,cfoo)
-	$(call RUN,bar)
-	$(call REMOVE_DYLIBS,foo)
-	$(call FAIL,bar)
diff --git a/tests/run-make/c-static-dylib/rmake.rs b/tests/run-make/c-static-dylib/rmake.rs
new file mode 100644
index 00000000000..12ec06c8199
--- /dev/null
+++ b/tests/run-make/c-static-dylib/rmake.rs
@@ -0,0 +1,20 @@
+// This test checks that static Rust linking with C does not encounter any errors,
+// with dynamic dependencies given preference over static.
+// See https://github.com/rust-lang/rust/issues/10434
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{
+    build_native_static_lib, dynamic_lib_name, rfs, run, run_fail, rustc, static_lib_name,
+};
+
+fn main() {
+    build_native_static_lib("cfoo");
+    rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
+    rustc().input("bar.rs").run();
+    rfs::remove_file(static_lib_name("cfoo"));
+    run("bar");
+    rfs::remove_file(dynamic_lib_name("foo"));
+    run_fail("bar");
+}
diff --git a/tests/run-make/c-static-rlib/Makefile b/tests/run-make/c-static-rlib/Makefile
deleted file mode 100644
index 298e432cdb8..00000000000
--- a/tests/run-make/c-static-rlib/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# This test checks that static Rust linking with C does not encounter any errors, with static dependencies given preference over dynamic. (This is the default behaviour.)
-# See https://github.com/rust-lang/rust/issues/10434
-
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,cfoo)
-	$(RUSTC) foo.rs
-	$(RUSTC) bar.rs
-	$(call REMOVE_RLIBS,foo)
-	rm $(call NATIVE_STATICLIB,cfoo)
-	$(call RUN,bar)
diff --git a/tests/run-make/c-static-rlib/rmake.rs b/tests/run-make/c-static-rlib/rmake.rs
new file mode 100644
index 00000000000..447e29a14f6
--- /dev/null
+++ b/tests/run-make/c-static-rlib/rmake.rs
@@ -0,0 +1,17 @@
+// This test checks that static Rust linking with C does not encounter any errors,
+// with static dependencies given preference over dynamic. (This is the default behaviour.)
+// See https://github.com/rust-lang/rust/issues/10434
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, rfs, run, rust_lib_name, rustc, static_lib_name};
+
+fn main() {
+    build_native_static_lib("cfoo");
+    rustc().input("foo.rs").run();
+    rustc().input("bar.rs").run();
+    rfs::remove_file(rust_lib_name("foo"));
+    rfs::remove_file(static_lib_name("cfoo"));
+    run("bar");
+}
diff --git a/tests/run-make/c-unwind-abi-catch-panic/Makefile b/tests/run-make/c-unwind-abi-catch-panic/Makefile
deleted file mode 100644
index 0a38d838e32..00000000000
--- a/tests/run-make/c-unwind-abi-catch-panic/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# Exercise unwinding a panic. This catches a panic across an FFI boundary and downcasts it into an integer. The Rust code that panics is in the same directory.
-# See https://github.com/rust-lang/rust/commit/baf227ea0c1e07fc54395a51e4b3881d701180cb
-
-# ignore-cross-compile
-# needs-unwind
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,add)
-	$(RUSTC) main.rs
-	$(call RUN,main) || exit 1
diff --git a/tests/run-make/c-unwind-abi-catch-panic/rmake.rs b/tests/run-make/c-unwind-abi-catch-panic/rmake.rs
new file mode 100644
index 00000000000..a99dbd18ec6
--- /dev/null
+++ b/tests/run-make/c-unwind-abi-catch-panic/rmake.rs
@@ -0,0 +1,18 @@
+// A test for calling `C-unwind` functions across foreign function boundaries (FFI).
+// This test triggers a panic when calling a foreign function that calls *back* into Rust.
+// This catches a panic across an FFI boundary and downcasts it into an integer.
+// The Rust code that panics is in the same directory, unlike `c-unwind-abi-catch-lib-panic`.
+// See https://github.com/rust-lang/rust/pull/76570
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+//@ needs-unwind
+// Reason: this test exercises panic unwinding
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("add");
+    rustc().input("main.rs").run();
+    run("main");
+}
diff --git a/tests/run-make/compiler-lookup-paths-2/Makefile b/tests/run-make/compiler-lookup-paths-2/Makefile
deleted file mode 100644
index ecc0577384a..00000000000
--- a/tests/run-make/compiler-lookup-paths-2/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# This test checks that extern crate declarations in Cargo without a corresponding declaration in the manifest of a dependency are NOT allowed.
-# See https://github.com/rust-lang/rust/pull/21113
-
-include ../tools.mk
-
-all:
-	mkdir -p $(TMPDIR)/a $(TMPDIR)/b
-	$(RUSTC) a.rs && mv $(TMPDIR)/liba.rlib $(TMPDIR)/a
-	$(RUSTC) b.rs -L $(TMPDIR)/a && mv $(TMPDIR)/libb.rlib $(TMPDIR)/b
-	$(RUSTC) c.rs -L crate=$(TMPDIR)/b -L dependency=$(TMPDIR)/a \
-		&& exit 1 || exit 0
diff --git a/tests/run-make/compiler-lookup-paths-2/rmake.rs b/tests/run-make/compiler-lookup-paths-2/rmake.rs
new file mode 100644
index 00000000000..99efb157b53
--- /dev/null
+++ b/tests/run-make/compiler-lookup-paths-2/rmake.rs
@@ -0,0 +1,20 @@
+// This test checks that extern crate declarations in Cargo without a corresponding declaration
+// in the manifest of a dependency are NOT allowed. The last rustc call does it anyways, which
+// should result in a compilation failure.
+// See https://github.com/rust-lang/rust/pull/21113
+
+use run_make_support::{path, rfs, rust_lib_name, rustc};
+
+fn main() {
+    rfs::create_dir("a");
+    rfs::create_dir("b");
+    rustc().input("a.rs").run();
+    rfs::rename(rust_lib_name("a"), path("a").join(rust_lib_name("a")));
+    rustc().input("b.rs").library_search_path("a").run();
+    rfs::rename(rust_lib_name("b"), path("b").join(rust_lib_name("b")));
+    rustc()
+        .input("c.rs")
+        .library_search_path("crate=b")
+        .library_search_path("dependency=a")
+        .run_fail();
+}
diff --git a/tests/run-make/crate-hash-rustc-version/Makefile b/tests/run-make/crate-hash-rustc-version/Makefile
deleted file mode 100644
index 6bf504bf01b..00000000000
--- a/tests/run-make/crate-hash-rustc-version/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Ensure that crates compiled with different rustc versions cannot
-# be dynamically linked.
-
-FLAGS := -Cprefer-dynamic -Csymbol-mangling-version=v0
-UNAME := $(shell uname)
-ifeq ($(UNAME),Linux)
-  EXT=".so"
-  NM_CMD := nm -D
-endif
-ifeq ($(UNAME),Darwin)
-  EXT=".dylib"
-  NM_CMD := nm
-endif
-
-ifndef NM_CMD
-all:
-	exit 0
-else
-all:
-	# a.rs is a dylib
-	$(RUSTC) a.rs --crate-type=dylib $(FLAGS)
-	# Write symbols to disk.
-	$(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsbefore
-	# b.rs is a binary
-	$(RUSTC) b.rs --extern a=$(TMPDIR)/liba$(EXT) --crate-type=bin -Crpath $(FLAGS)
-	$(call RUN,b)
-	# Now re-compile a.rs with another rustc version
-	RUSTC_FORCE_RUSTC_VERSION=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS)
-	# After compiling with a different rustc version, write symbols to disk again.
-	$(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsafter
-	# As a sanity check, test if the symbols changed:
-	# If the symbols are identical, there's been an error.
-	if diff $(TMPDIR)/symbolsbefore $(TMPDIR)/symbolsafter; then exit 1; fi
-	$(call FAIL,b)
-endif
diff --git a/tests/run-make/crate-hash-rustc-version/rmake.rs b/tests/run-make/crate-hash-rustc-version/rmake.rs
new file mode 100644
index 00000000000..97b3dd3931e
--- /dev/null
+++ b/tests/run-make/crate-hash-rustc-version/rmake.rs
@@ -0,0 +1,57 @@
+// Ensure that crates compiled with different rustc versions cannot
+// be dynamically linked.
+
+//@ ignore-cross-compile
+//@ only-unix
+
+use run_make_support::llvm;
+use run_make_support::{diff, dynamic_lib_name, is_darwin, run, run_fail, rustc};
+
+fn llvm_readobj() -> llvm::LlvmReadobj {
+    let mut cmd = llvm::llvm_readobj();
+    if is_darwin() {
+        cmd.symbols();
+    } else {
+        cmd.dynamic_table();
+    }
+    cmd
+}
+
+fn main() {
+    let flags = ["-Cprefer-dynamic", "-Csymbol-mangling-version=v0"];
+
+    // a.rs is compiled to a dylib
+    rustc().input("a.rs").crate_type("dylib").args(&flags).run();
+
+    // Store symbols
+    let symbols_before = llvm_readobj().arg(dynamic_lib_name("a")).run().stdout_utf8();
+
+    // b.rs is compiled to a binary
+    rustc()
+        .input("b.rs")
+        .extern_("a", dynamic_lib_name("a"))
+        .crate_type("bin")
+        .arg("-Crpath")
+        .args(&flags)
+        .run();
+    run("b");
+
+    // Now re-compile a.rs with another rustc version
+    rustc()
+        .env("RUSTC_FORCE_RUSTC_VERSION", "deadfeed")
+        .input("a.rs")
+        .crate_type("dylib")
+        .args(&flags)
+        .run();
+
+    // After compiling with a different rustc version, store symbols again.
+    let symbols_after = llvm_readobj().arg(dynamic_lib_name("a")).run().stdout_utf8();
+
+    // As a sanity check, test if the symbols changed:
+    // If the symbols are identical, there's been an error.
+    diff()
+        .expected_text("symbols_before", symbols_before)
+        .actual_text("symbols_after", symbols_after)
+        .run_fail();
+    run_fail("b");
+}
diff --git a/tests/run-make/extern-fn-generic/Makefile b/tests/run-make/extern-fn-generic/Makefile
deleted file mode 100644
index 7dceea6cb88..00000000000
--- a/tests/run-make/extern-fn-generic/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) testcrate.rs
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-generic/rmake.rs b/tests/run-make/extern-fn-generic/rmake.rs
new file mode 100644
index 00000000000..05de839a1b0
--- /dev/null
+++ b/tests/run-make/extern-fn-generic/rmake.rs
@@ -0,0 +1,16 @@
+// Generic types in foreign-function interfaces were introduced in #15831 - this
+// test simply runs a Rust program containing generics that is also reliant on
+// a C library, and checks that compilation and execution are successful.
+// See https://github.com/rust-lang/rust/pull/15831
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("test");
+    rustc().input("testcrate.rs").run();
+    rustc().input("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/extern-fn-with-union/Makefile b/tests/run-make/extern-fn-with-union/Makefile
deleted file mode 100644
index e6c8c993679..00000000000
--- a/tests/run-make/extern-fn-with-union/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,ctest)
-	$(RUSTC) testcrate.rs
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-with-union/rmake.rs b/tests/run-make/extern-fn-with-union/rmake.rs
new file mode 100644
index 00000000000..200602eabeb
--- /dev/null
+++ b/tests/run-make/extern-fn-with-union/rmake.rs
@@ -0,0 +1,16 @@
+// If an external function from foreign-function interface was called upon,
+// its attributes would only be passed to LLVM if and only if it was called in the same crate.
+// This caused passing around unions to be incorrect.
+// See https://github.com/rust-lang/rust/pull/14191
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("ctest");
+    rustc().input("testcrate.rs").run();
+    rustc().input("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/invalid-symlink-search-path/in/bar/lib.rs b/tests/run-make/invalid-symlink-search-path/in/bar/lib.rs
new file mode 100644
index 00000000000..58c3e33bb6c
--- /dev/null
+++ b/tests/run-make/invalid-symlink-search-path/in/bar/lib.rs
@@ -0,0 +1,5 @@
+extern crate foo;
+
+pub fn main() {
+    let _ = foo::hello_world();
+}
diff --git a/tests/run-make/invalid-symlink-search-path/in/foo/lib.rs b/tests/run-make/invalid-symlink-search-path/in/foo/lib.rs
new file mode 100644
index 00000000000..07b66f8ca45
--- /dev/null
+++ b/tests/run-make/invalid-symlink-search-path/in/foo/lib.rs
@@ -0,0 +1,3 @@
+pub fn hello_world() -> i32 {
+    42
+}
diff --git a/tests/run-make/invalid-symlink-search-path/rmake.rs b/tests/run-make/invalid-symlink-search-path/rmake.rs
new file mode 100644
index 00000000000..ed2cd9c4bd2
--- /dev/null
+++ b/tests/run-make/invalid-symlink-search-path/rmake.rs
@@ -0,0 +1,33 @@
+// In this test, the symlink created is invalid (valid relative to the root, but not
+// relatively to where it is located), and used to cause an internal
+// compiler error (ICE) when passed as a library search path. This was fixed in #26044,
+// and this test checks that the invalid symlink is instead simply ignored.
+// See https://github.com/rust-lang/rust/issues/26006
+
+//@ needs-symlink
+//Reason: symlink requires elevated permission in Windows
+
+use run_make_support::{rfs, rustc};
+
+fn main() {
+    // We create two libs: `bar` which depends on `foo`. We need to compile `foo` first.
+    rfs::create_dir("out");
+    rfs::create_dir("out/foo");
+    rustc()
+        .input("in/foo/lib.rs")
+        .crate_name("foo")
+        .crate_type("lib")
+        .metadata("foo")
+        .output("out/foo/libfoo.rlib")
+        .run();
+    rfs::create_dir("out/bar");
+    rfs::create_dir("out/bar/deps");
+    rfs::create_symlink("out/foo/libfoo.rlib", "out/bar/deps/libfoo.rlib");
+    // Check that the invalid symlink does not cause an ICE
+    rustc()
+        .input("in/bar/lib.rs")
+        .library_search_path("dependency=out/bar/deps")
+        .run_fail()
+        .assert_exit_code(1)
+        .assert_stderr_not_contains("internal compiler error");
+}
diff --git a/tests/run-make/issue-14698/foo.rs b/tests/run-make/invalid-tmpdir-env-var/foo.rs
index f328e4d9d04..f328e4d9d04 100644
--- a/tests/run-make/issue-14698/foo.rs
+++ b/tests/run-make/invalid-tmpdir-env-var/foo.rs
diff --git a/tests/run-make/invalid-tmpdir-env-var/rmake.rs b/tests/run-make/invalid-tmpdir-env-var/rmake.rs
new file mode 100644
index 00000000000..db44debb319
--- /dev/null
+++ b/tests/run-make/invalid-tmpdir-env-var/rmake.rs
@@ -0,0 +1,20 @@
+// When the TMP (on Windows) or TMPDIR (on Unix) variable is set to an invalid
+// or non-existing directory, this used to cause an internal compiler error (ICE). After the
+// addition of proper error handling in #28430, this test checks that the expected message is
+// printed.
+// See https://github.com/rust-lang/rust/issues/14698
+
+use run_make_support::{is_windows, rustc};
+
+// NOTE: This is not a UI test despite its simplicity, as the error message contains a path
+// with some variability that is difficult to normalize
+
+fn main() {
+    let mut rustc = rustc();
+    if is_windows() {
+        rustc.env("TMP", "fake");
+    } else {
+        rustc.env("TMPDIR", "fake");
+    }
+    rustc.input("foo.rs").run_fail().assert_stderr_contains("couldn't create a temp dir");
+}
diff --git a/tests/run-make/issue-107094/Makefile b/tests/run-make/issue-107094/Makefile
deleted file mode 100644
index d614e3e1055..00000000000
--- a/tests/run-make/issue-107094/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# needs-git-hash
-
-include ../tools.mk
-
-all:
-	$(BARE_RUSTC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
-	$(BARE_RUSTDOC) --version --verbose | $(CGREP) -i -e "commit-hash: [0-9a-f]{40}" "commit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"
diff --git a/tests/run-make/issue-14698/Makefile b/tests/run-make/issue-14698/Makefile
deleted file mode 100644
index a1cfb5abab5..00000000000
--- a/tests/run-make/issue-14698/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
-	TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | $(CGREP) "couldn't create a temp dir:"
diff --git a/tests/run-make/issue-15460/Makefile b/tests/run-make/issue-15460/Makefile
deleted file mode 100644
index a36a085fa6f..00000000000
--- a/tests/run-make/issue-15460/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,foo)
-	$(RUSTC) foo.rs -C extra-filename=-383hf8 -C prefer-dynamic
-	$(RUSTC) bar.rs
-	$(call RUN,bar)
diff --git a/tests/run-make/issue-22131/Makefile b/tests/run-make/issue-22131/Makefile
deleted file mode 100644
index 4f33a4659cc..00000000000
--- a/tests/run-make/issue-22131/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: foo.rs
-	$(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs
-	$(RUSTDOC) --test --cfg 'feature="bar"' \
-		-L $(TMPDIR) foo.rs |\
-		$(CGREP) 'foo.rs - foo (line 1) ... ok'
diff --git a/tests/run-make/issue-26006/Makefile b/tests/run-make/issue-26006/Makefile
deleted file mode 100644
index b679c121530..00000000000
--- a/tests/run-make/issue-26006/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows
-
-OUT := $(TMPDIR)/out
-
-all: time
-
-time: libc
-	mkdir -p $(OUT)/time $(OUT)/time/deps
-	ln -sf $(OUT)/libc/liblibc.rlib $(OUT)/time/deps/
-	$(RUSTC) in/time/lib.rs -Ldependency=$(OUT)/time/deps/
-
-libc:
-	mkdir -p $(OUT)/libc
-	$(RUSTC) in/libc/lib.rs --crate-name=libc -Cmetadata=foo -o $(OUT)/libc/liblibc.rlib
diff --git a/tests/run-make/issue-26006/in/libc/lib.rs b/tests/run-make/issue-26006/in/libc/lib.rs
deleted file mode 100644
index bad155a99bd..00000000000
--- a/tests/run-make/issue-26006/in/libc/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type = "rlib"]
-
-pub fn something() {}
diff --git a/tests/run-make/issue-26006/in/time/lib.rs b/tests/run-make/issue-26006/in/time/lib.rs
deleted file mode 100644
index 51ed27cd713..00000000000
--- a/tests/run-make/issue-26006/in/time/lib.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![feature(rustc_private)]
-extern crate libc;
-
-fn main() {}
diff --git a/tests/run-make/issue-28595/Makefile b/tests/run-make/issue-28595/Makefile
deleted file mode 100644
index 258f9788aaf..00000000000
--- a/tests/run-make/issue-28595/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,a) $(call NATIVE_STATICLIB,b)
-	$(RUSTC) a.rs
-	$(RUSTC) b.rs
-	$(call RUN,b)
diff --git a/tests/run-make/issue-33329/Makefile b/tests/run-make/issue-33329/Makefile
deleted file mode 100644
index 9c149440d8e..00000000000
--- a/tests/run-make/issue-33329/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) --target x86_64_unknown-linux-musl main.rs 2>&1 | $(CGREP) \
-		"error: Error loading target specification: Could not find specification for target"
diff --git a/tests/run-make/issue-33329/main.rs b/tests/run-make/issue-33329/main.rs
deleted file mode 100644
index f328e4d9d04..00000000000
--- a/tests/run-make/issue-33329/main.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn main() {}
diff --git a/tests/run-make/issue-97463-abi-param-passing/Makefile b/tests/run-make/issue-97463-abi-param-passing/Makefile
deleted file mode 100644
index 7ce7aaeec57..00000000000
--- a/tests/run-make/issue-97463-abi-param-passing/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-msvc
-
-# The issue exercised by this test, rust-lang/rust#97463, explicitly needs `-O`
-# flags (like `-O3`) to reproduce. Thus, we call $(CC) instead of nicer
-# alternatives provided by tools.mk like using `COMPILE_OBJ` or using a
-# `NATIVE_STATICLIB` dependency.
-
-all:
-	$(CC) -c -O3 -o $(TMPDIR)/bad.o bad.c
-	$(AR) rcs $(TMPDIR)/libbad.a $(TMPDIR)/bad.o
-	$(RUSTC) param_passing.rs -L$(TMPDIR) -lbad -C opt-level=3
-	$(call RUN,param_passing)
diff --git a/tests/run-make/link-framework/Makefile b/tests/run-make/link-framework/Makefile
deleted file mode 100644
index 96d832ad4a8..00000000000
--- a/tests/run-make/link-framework/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# only-apple
-#
-# Check that linking to a framework actually makes it to the linker.
-
-include ../tools.mk
-
-all:
-	$(RUSTC) dep-link-framework.rs
-	$(RUSTC) dep-link-weak-framework.rs
-
-	$(RUSTC) empty.rs
-	otool -L $(TMPDIR)/no-link | $(CGREP) -v CoreFoundation
-
-	$(RUSTC) link-framework.rs
-	otool -L $(TMPDIR)/link-framework | $(CGREP) CoreFoundation | $(CGREP) -v weak
-
-	$(RUSTC) link-weak-framework.rs
-	otool -L $(TMPDIR)/link-weak-framework | $(CGREP) CoreFoundation | $(CGREP) weak
-
-# When linking the framework both normally, and weakly, the weak linking takes preference
-
-	$(RUSTC) link-both.rs
-	otool -L $(TMPDIR)/link-both | $(CGREP) CoreFoundation | $(CGREP) weak
diff --git a/tests/run-make/link-framework/rmake.rs b/tests/run-make/link-framework/rmake.rs
new file mode 100644
index 00000000000..e5df93b181a
--- /dev/null
+++ b/tests/run-make/link-framework/rmake.rs
@@ -0,0 +1,38 @@
+// Check that linking to a framework actually makes it to the linker.
+
+//@ only-apple
+
+use run_make_support::{cmd, rustc};
+
+fn main() {
+    rustc().input("dep-link-framework.rs").run();
+    rustc().input("dep-link-weak-framework.rs").run();
+
+    rustc().input("empty.rs").run();
+    cmd("otool").arg("-L").arg("no-link").run_fail().assert_stdout_not_contains("CoreFoundation");
+
+    rustc().input("link-framework.rs").run();
+    cmd("otool")
+        .arg("-L")
+        .arg("link-framework")
+        .run()
+        .assert_stdout_contains("CoreFoundation")
+        .assert_stdout_not_contains("weak");
+
+    rustc().input("link-weak-framework.rs").run();
+    cmd("otool")
+        .arg("-L")
+        .arg("link-weak-framework")
+        .run()
+        .assert_stdout_contains("CoreFoundation")
+        .assert_stdout_contains("weak");
+
+    // When linking the framework both normally, and weakly, the weak linking takes preference.
+    rustc().input("link-both.rs").run();
+    cmd("otool")
+        .arg("-L")
+        .arg("link-both")
+        .run()
+        .assert_stdout_contains("CoreFoundation")
+        .assert_stdout_contains("weak");
+}
diff --git a/tests/run-make/issue-15460/bar.rs b/tests/run-make/link-native-static-lib-to-dylib/bar.rs
index e66aeb6bd39..e66aeb6bd39 100644
--- a/tests/run-make/issue-15460/bar.rs
+++ b/tests/run-make/link-native-static-lib-to-dylib/bar.rs
diff --git a/tests/run-make/issue-15460/foo.c b/tests/run-make/link-native-static-lib-to-dylib/foo.c
index fdf595b574e..fdf595b574e 100644
--- a/tests/run-make/issue-15460/foo.c
+++ b/tests/run-make/link-native-static-lib-to-dylib/foo.c
diff --git a/tests/run-make/issue-15460/foo.rs b/tests/run-make/link-native-static-lib-to-dylib/foo.rs
index b4eaa0b31c5..b4eaa0b31c5 100644
--- a/tests/run-make/issue-15460/foo.rs
+++ b/tests/run-make/link-native-static-lib-to-dylib/foo.rs
diff --git a/tests/run-make/link-native-static-lib-to-dylib/rmake.rs b/tests/run-make/link-native-static-lib-to-dylib/rmake.rs
new file mode 100644
index 00000000000..0746c396314
--- /dev/null
+++ b/tests/run-make/link-native-static-lib-to-dylib/rmake.rs
@@ -0,0 +1,14 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/15460>.
+
+//@ ignore-cross-compile
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("foo");
+
+    rustc().input("foo.rs").extra_filename("-383hf8").arg("-Cprefer-dynamic").run();
+    rustc().input("bar.rs").run();
+
+    run("bar");
+}
diff --git a/tests/run-make/link-path-order/Makefile b/tests/run-make/link-path-order/Makefile
deleted file mode 100644
index a3831a63ac7..00000000000
--- a/tests/run-make/link-path-order/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Verifies that the -L arguments given to the linker is in the same order
-# as the -L arguments on the rustc command line.
-
-CORRECT_DIR=$(TMPDIR)/correct
-WRONG_DIR=$(TMPDIR)/wrong
-
-F := $(call NATIVE_STATICLIB_FILE,foo)
-
-all: $(call NATIVE_STATICLIB,correct) $(call NATIVE_STATICLIB,wrong)
-	mkdir -p $(CORRECT_DIR) $(WRONG_DIR)
-	mv $(call NATIVE_STATICLIB,correct) $(CORRECT_DIR)/$(F)
-	mv $(call NATIVE_STATICLIB,wrong) $(WRONG_DIR)/$(F)
-	$(RUSTC) main.rs -o $(TMPDIR)/should_succeed -L $(CORRECT_DIR) -L $(WRONG_DIR)
-	$(call RUN,should_succeed)
-	$(RUSTC) main.rs -o $(TMPDIR)/should_fail -L $(WRONG_DIR) -L $(CORRECT_DIR)
-	$(call FAIL,should_fail)
diff --git a/tests/run-make/link-path-order/rmake.rs b/tests/run-make/link-path-order/rmake.rs
new file mode 100644
index 00000000000..c8e41b2bcf8
--- /dev/null
+++ b/tests/run-make/link-path-order/rmake.rs
@@ -0,0 +1,33 @@
+// The order in which "library search path" `-L` arguments are given to the command line rustc
+// is important. These arguments must match the order of the linker's arguments. In this test,
+// fetching the Wrong library before the Correct one causes a function to return 0 instead of the
+// expected 1, causing a runtime panic, as expected.
+// See https://github.com/rust-lang/rust/pull/16904
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, path, rfs, run, run_fail, rustc, static_lib_name};
+
+fn main() {
+    build_native_static_lib("correct");
+    build_native_static_lib("wrong");
+    rfs::create_dir("correct");
+    rfs::create_dir("wrong");
+    rfs::rename(static_lib_name("correct"), path("correct").join(static_lib_name("foo")));
+    rfs::rename(static_lib_name("wrong"), path("wrong").join(static_lib_name("foo")));
+    rustc()
+        .input("main.rs")
+        .output("should_succeed")
+        .library_search_path("correct")
+        .library_search_path("wrong")
+        .run();
+    run("should_succeed");
+    rustc()
+        .input("main.rs")
+        .output("should_fail")
+        .library_search_path("wrong")
+        .library_search_path("correct")
+        .run();
+    run_fail("should_fail");
+}
diff --git a/tests/run-make/linkage-attr-on-static/Makefile b/tests/run-make/linkage-attr-on-static/Makefile
deleted file mode 100644
index ef50a7ef9f1..00000000000
--- a/tests/run-make/linkage-attr-on-static/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,foo)
-	$(RUSTC) bar.rs
-	$(call RUN,bar) || exit 1
diff --git a/tests/run-make/linkage-attr-on-static/rmake.rs b/tests/run-make/linkage-attr-on-static/rmake.rs
new file mode 100644
index 00000000000..cd85542e958
--- /dev/null
+++ b/tests/run-make/linkage-attr-on-static/rmake.rs
@@ -0,0 +1,15 @@
+// #[linkage] is a useful attribute which can be applied to statics to allow
+// external linkage, something which was not possible before #18890. This test
+// checks that using this new feature results in successful compilation and execution.
+// See https://github.com/rust-lang/rust/pull/18890
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("foo");
+    rustc().input("bar.rs").run();
+    run("bar");
+}
diff --git a/tests/run-make/lto-linkage-used-attr/Makefile b/tests/run-make/lto-linkage-used-attr/Makefile
deleted file mode 100644
index fed41a00f84..00000000000
--- a/tests/run-make/lto-linkage-used-attr/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-# Verify that the impl_* symbols are preserved. #108030
-# only-x86_64-unknown-linux-gnu
-
-all:
-	$(RUSTC) -Cdebuginfo=0 -Copt-level=3 lib.rs
-	$(RUSTC) -Clto=fat -Cdebuginfo=0 -Copt-level=3 main.rs
diff --git a/tests/run-make/lto-linkage-used-attr/rmake.rs b/tests/run-make/lto-linkage-used-attr/rmake.rs
new file mode 100644
index 00000000000..12463b79a75
--- /dev/null
+++ b/tests/run-make/lto-linkage-used-attr/rmake.rs
@@ -0,0 +1,15 @@
+// Link time optimizations (LTO) used to snip away some important symbols
+// when setting optimization level to 3 or higher.
+// This is an LLVM, not a rustc bug, fixed here: https://reviews.llvm.org/D145293
+// This test checks that the impl_* symbols are preserved as they should.
+// See https://github.com/rust-lang/rust/issues/108030
+
+//@ only-x86_64-unknown-linux-gnu
+// Reason: some of the inline assembly directives are architecture-specific.
+
+use run_make_support::rustc;
+
+fn main() {
+    rustc().arg("-Cdebuginfo=0").opt_level("3").input("lib.rs").run();
+    rustc().arg("-Clto=fat").arg("-Cdebuginfo=0").opt_level("3").input("main.rs").run();
+}
diff --git a/tests/run-make/lto-no-link-whole-rlib/Makefile b/tests/run-make/lto-no-link-whole-rlib/Makefile
deleted file mode 100644
index 3e82322e72d..00000000000
--- a/tests/run-make/lto-no-link-whole-rlib/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
-	$(RUSTC) lib1.rs
-	$(RUSTC) lib2.rs
-	$(RUSTC) main.rs -Clto
-	$(call RUN,main)
-
diff --git a/tests/run-make/lto-no-link-whole-rlib/rmake.rs b/tests/run-make/lto-no-link-whole-rlib/rmake.rs
new file mode 100644
index 00000000000..8cd653d5f08
--- /dev/null
+++ b/tests/run-make/lto-no-link-whole-rlib/rmake.rs
@@ -0,0 +1,18 @@
+// In order to improve linking performance, entire rlibs will only be linked if a dylib is being
+// created. Otherwise, an executable will only link one rlib as usual. Linking will fail in this
+// test should this optimization be reverted.
+// See https://github.com/rust-lang/rust/pull/31460
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("foo");
+    build_native_static_lib("bar");
+    rustc().input("lib1.rs").run();
+    rustc().input("lib2.rs").run();
+    rustc().input("main.rs").arg("-Clto").run();
+    run("main");
+}
diff --git a/tests/run-make/lto-smoke-c/Makefile b/tests/run-make/lto-smoke-c/Makefile
deleted file mode 100644
index f1ba3d95da2..00000000000
--- a/tests/run-make/lto-smoke-c/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Apparently older versions of GCC segfault if -g is passed...
-CC := $(CC:-g=)
-
-all:
-	$(RUSTC) foo.rs -C lto
-	$(CC) bar.c $(call STATICLIB,foo) \
-		$(call OUT_EXE,bar) \
-		$(EXTRACFLAGS) $(EXTRACXXFLAGS)
-	$(call RUN,bar)
diff --git a/tests/run-make/lto-smoke-c/rmake.rs b/tests/run-make/lto-smoke-c/rmake.rs
new file mode 100644
index 00000000000..70760f730c0
--- /dev/null
+++ b/tests/run-make/lto-smoke-c/rmake.rs
@@ -0,0 +1,20 @@
+// LLVM's link-time-optimization (LTO) is a useful feature added to Rust in response
+// to #10741. This test uses this feature with `-C lto` alongside a native C library,
+// and checks that compilation and execution is successful.
+// See https://github.com/rust-lang/rust/issues/10741
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib_name};
+
+fn main() {
+    rustc().input("foo.rs").arg("-Clto").run();
+    cc().input("bar.c")
+        .arg(static_lib_name("foo"))
+        .out_exe("bar")
+        .args(extra_c_flags())
+        .args(extra_cxx_flags())
+        .run();
+    run("bar");
+}
diff --git a/tests/run-make/macos-fat-archive/Makefile b/tests/run-make/macos-fat-archive/Makefile
deleted file mode 100644
index 0feb39a23cb..00000000000
--- a/tests/run-make/macos-fat-archive/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# only-apple
-
-include ../tools.mk
-
-"$(TMPDIR)"/libnative-library.a: native-library.c
-	$(CC) -arch arm64 -arch x86_64 native-library.c -c -o "$(TMPDIR)"/native-library.o
-	$(AR) crs "$(TMPDIR)"/libnative-library.a "$(TMPDIR)"/native-library.o
-
-all: "$(TMPDIR)"/libnative-library.a
-	$(RUSTC) lib.rs --crate-type=lib -L "native=$(TMPDIR)" -l static=native-library
diff --git a/tests/run-make/macos-fat-archive/rmake.rs b/tests/run-make/macos-fat-archive/rmake.rs
new file mode 100644
index 00000000000..c9f0fa07693
--- /dev/null
+++ b/tests/run-make/macos-fat-archive/rmake.rs
@@ -0,0 +1,20 @@
+// macOS (and iOS) has a concept of universal (fat) binaries which contain code for multiple CPU
+// architectures in the same file. Apple is migrating from x86_64 to aarch64 CPUs,
+// so for the next few years it will be important for macOS developers to
+// build "fat" binaries (executables and cdylibs).
+
+// Rustc used to be unable to handle these special libraries, which was fixed in #98736. If
+// compilation in this test is successful, the native fat library was successfully linked to.
+// See https://github.com/rust-lang/rust/issues/55235
+
+//@ only-apple
+
+use run_make_support::{cc, llvm_ar, rustc};
+
+fn main() {
+    cc().args(&["-arch", "arm64", "-arch", "x86_64", "native-library.c", "-c"])
+        .out_exe("native-library.o")
+        .run();
+    llvm_ar().obj_to_ar().output_input("libnative-library.a", "native-library.o").run();
+    rustc().input("lib.rs").crate_type("lib").arg("-lstatic=native-library").run();
+}
diff --git a/tests/run-make/manual-link/Makefile b/tests/run-make/manual-link/Makefile
deleted file mode 100644
index 8dbf0460fff..00000000000
--- a/tests/run-make/manual-link/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(TMPDIR)/libbar.a
-	$(RUSTC) foo.rs -lstatic=bar
-	$(RUSTC) main.rs
-	$(call RUN,main)
diff --git a/tests/run-make/manual-link/rmake.rs b/tests/run-make/manual-link/rmake.rs
new file mode 100644
index 00000000000..1d362172263
--- /dev/null
+++ b/tests/run-make/manual-link/rmake.rs
@@ -0,0 +1,16 @@
+// A smoke test for the `-l` command line rustc flag, which manually links to the selected
+// library. Useful for native libraries, this is roughly equivalent to `#[link]` in Rust code.
+// If compilation succeeds, the flag successfully linked the native library.
+// See https://github.com/rust-lang/rust/pull/18470
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("bar");
+    rustc().input("foo.rs").arg("-lstatic=bar").run();
+    rustc().input("main.rs").run();
+    run("main");
+}
diff --git a/tests/run-make/issue-28595/a.c b/tests/run-make/native-lib-load-order/a.c
index 7bfd83cca21..7bfd83cca21 100644
--- a/tests/run-make/issue-28595/a.c
+++ b/tests/run-make/native-lib-load-order/a.c
diff --git a/tests/run-make/issue-28595/a.rs b/tests/run-make/native-lib-load-order/a.rs
index 07863cf64d6..07863cf64d6 100644
--- a/tests/run-make/issue-28595/a.rs
+++ b/tests/run-make/native-lib-load-order/a.rs
diff --git a/tests/run-make/issue-28595/b.c b/tests/run-make/native-lib-load-order/b.c
index 6aecb5f9e04..6aecb5f9e04 100644
--- a/tests/run-make/issue-28595/b.c
+++ b/tests/run-make/native-lib-load-order/b.c
diff --git a/tests/run-make/issue-28595/b.rs b/tests/run-make/native-lib-load-order/b.rs
index 1f389859fad..1f389859fad 100644
--- a/tests/run-make/issue-28595/b.rs
+++ b/tests/run-make/native-lib-load-order/b.rs
diff --git a/tests/run-make/native-lib-load-order/rmake.rs b/tests/run-make/native-lib-load-order/rmake.rs
new file mode 100644
index 00000000000..ffe20a64168
--- /dev/null
+++ b/tests/run-make/native-lib-load-order/rmake.rs
@@ -0,0 +1,16 @@
+// An old compiler bug from 2015 caused native libraries to be loaded in the
+// wrong order, causing `b` to be loaded before `a` in this test. If the compilation
+// is successful, the libraries were loaded in the correct order.
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("a");
+    build_native_static_lib("b");
+    rustc().input("a.rs").run();
+    rustc().input("b.rs").run();
+    run("b");
+}
diff --git a/tests/run-make/no-duplicate-libs/Makefile b/tests/run-make/no-duplicate-libs/Makefile
deleted file mode 100644
index 4be8c026294..00000000000
--- a/tests/run-make/no-duplicate-libs/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-ifdef IS_MSVC
-# FIXME(#27979)
-all:
-else
-all: $(call STATICLIB,foo) $(call STATICLIB,bar)
-	$(RUSTC) main.rs
-	$(call RUN,main)
-endif
diff --git a/tests/run-make/no-duplicate-libs/rmake.rs b/tests/run-make/no-duplicate-libs/rmake.rs
new file mode 100644
index 00000000000..469348e266c
--- /dev/null
+++ b/tests/run-make/no-duplicate-libs/rmake.rs
@@ -0,0 +1,22 @@
+// The rust compiler used to try to detect duplicated libraries in
+// the linking order and remove the duplicates... but certain edge cases,
+// such as the one presented in `foo` and `bar` in this test, demand precise
+// control over the link order, including duplicates. As the anti-duplication
+// filter was removed, this test should now successfully see main be compiled
+// and executed.
+// See https://github.com/rust-lang/rust/pull/12688
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+//@ ignore-msvc
+// Reason: native compilation results in an unresolved external symbol
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("foo");
+    build_native_static_lib("bar");
+    rustc().input("main.rs").run();
+    run("main");
+}
diff --git a/tests/run-make/pass-non-c-like-enum-to-c/Makefile b/tests/run-make/pass-non-c-like-enum-to-c/Makefile
deleted file mode 100644
index bd441d321bf..00000000000
--- a/tests/run-make/pass-non-c-like-enum-to-c/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) nonclike.rs -L$(TMPDIR) -ltest
-	$(call RUN,nonclike)
diff --git a/tests/run-make/pass-non-c-like-enum-to-c/rmake.rs b/tests/run-make/pass-non-c-like-enum-to-c/rmake.rs
new file mode 100644
index 00000000000..c706e82f4a0
--- /dev/null
+++ b/tests/run-make/pass-non-c-like-enum-to-c/rmake.rs
@@ -0,0 +1,19 @@
+// Similar to the `return-non-c-like-enum-from-c` test, where
+// the C code is the library, and the Rust code compiles
+// into the executable. Once again, enum variants should be treated
+// like an union of structs, which should prevent segfaults or
+// unexpected results. The only difference with the aforementioned
+// test is that the structs are passed into C directly through the
+// `tt_add` and `t_add` function calls.
+// See https://github.com/rust-lang/rust/issues/68190
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("test");
+    rustc().input("nonclike.rs").arg("-ltest").run();
+    run("nonclike");
+}
diff --git a/tests/run-make/pgo-gen-no-imp-symbols/Makefile b/tests/run-make/pgo-gen-no-imp-symbols/Makefile
deleted file mode 100644
index d2baa145ba5..00000000000
--- a/tests/run-make/pgo-gen-no-imp-symbols/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../tools.mk
-
-COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" -Zno-profiler-runtime
-
-all:
-	$(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs
-	# We expect symbols starting with "__llvm_profile_".
-	$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
-	# We do NOT expect the "__imp_" version of these symbols.
-	$(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit
-	$(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit
diff --git a/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs
new file mode 100644
index 00000000000..85ade7885ce
--- /dev/null
+++ b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs
@@ -0,0 +1,27 @@
+// LLVM's profiling instrumentation adds a few symbols that are used by the profiler runtime.
+// Since these show up as globals in the LLVM IR, the compiler generates dllimport-related
+// __imp_ stubs for them. This can lead to linker errors because the instrumentation
+// symbols have weak linkage or are in a comdat section, but the __imp_ stubs aren't.
+// Since profiler-related symbols were excluded from stub-generation in #59812, this has
+// been fixed, and this test checks that the llvm profile symbol appear, but without the
+// anomalous __imp_ stubs.
+// See https://github.com/rust-lang/rust/pull/59812
+
+use run_make_support::{cwd, rfs, rustc};
+
+fn main() {
+    rustc()
+        .input("test.rs")
+        .emit("llvm-ir")
+        .opt()
+        .codegen_units(1)
+        .profile_generate(cwd())
+        .arg("-Zno-profiler-runtime")
+        .run();
+    let out = rfs::read_to_string("test.ll");
+    // We expect symbols starting with "__llvm_profile_".
+    assert!(out.contains("__llvm_profile_"));
+    // We do NOT expect the "__imp_" version of these symbols.
+    assert!(!out.contains("__imp___llvm_profile_")); // 64 bit
+    assert!(!out.contains("__imp____llvm_profile_")); // 32 bit
+}
diff --git a/tests/run-make/return-non-c-like-enum-from-c/Makefile b/tests/run-make/return-non-c-like-enum-from-c/Makefile
deleted file mode 100644
index bd441d321bf..00000000000
--- a/tests/run-make/return-non-c-like-enum-from-c/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) nonclike.rs -L$(TMPDIR) -ltest
-	$(call RUN,nonclike)
diff --git a/tests/run-make/return-non-c-like-enum-from-c/rmake.rs b/tests/run-make/return-non-c-like-enum-from-c/rmake.rs
new file mode 100644
index 00000000000..f24bd6d5fc7
--- /dev/null
+++ b/tests/run-make/return-non-c-like-enum-from-c/rmake.rs
@@ -0,0 +1,17 @@
+// A reversed version of the `return-non-c-like-enum` test, though
+// this time, the C code is the library, and the Rust code compiles
+// into the executable. Once again, enum variants should be treated
+// like an union of structs, which should prevent segfaults or
+// unexpected results.
+// See https://github.com/rust-lang/rust/issues/68190
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib, run, rustc};
+
+fn main() {
+    build_native_static_lib("test");
+    rustc().input("nonclike.rs").arg("-ltest").run();
+    run("nonclike");
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile
deleted file mode 100644
index 9ba077b1854..00000000000
--- a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-# only-linux
-
-# Make sure -Zpacked_bundled_libs-like behavior activates with +bundle,+whole-archive.
-
-# We're using the llvm-nm instead of the system nm to ensure it is compatible
-# with the LLVM bitcode generated by rustc.
-NM = "$(LLVM_BIN_DIR)"/llvm-nm
-
-all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) $(call NATIVE_STATICLIB,native_dep_4)
-	# test cfg with packed bundle
-	$(RUSTC) rust_dep_cfg.rs --crate-type=rlib
-	$(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep_cfg.rlib --crate-type=staticlib --cfg should_add
-	$(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_1.a"
-	$(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_2.a"
-	$(AR) t $(TMPDIR)/libmain.a | $(CGREP) -e "libnative_dep_1.o"
-	$(AR) t $(TMPDIR)/libmain.a | $(CGREP) -ev "libnative_dep_2.o"
-
-
-	# test bundle with whole_archive
-	$(RUSTC) rust_dep.rs --crate-type=rlib
-	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_1"
-	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_3"
-	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_2"
-	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_4"
-
-	# Make sure compiler doesn't use files, that it shouldn't know about.
-	rm $(TMPDIR)/libnative_dep_1.a
-	rm $(TMPDIR)/libnative_dep_3.a
-
-	$(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib --print link-args > $(TMPDIR)/link_args
-	cat $(TMPDIR)/link_args | $(CGREP) -ev "native_dep_3"
-	cat $(TMPDIR)/link_args | $(CGREP) -e "--whole-archive.*native_dep_1.*--whole-archive.*lnative_dep_2.*no-whole-archive.*lnative_dep_4"
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs
new file mode 100644
index 00000000000..d152047600f
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs
@@ -0,0 +1,84 @@
+// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler
+// only require a native library and no supplementary object files to compile.
+// #105601 made it possible to have this behaviour without an unstable flag by
+// passing +bundle in modifiers, and this test checks that this feature successfully
+// compiles and includes only the static libraries, with no object files.
+// See https://github.com/rust-lang/rust/pull/105601
+
+use run_make_support::{
+    build_native_static_lib, is_msvc, llvm_ar, regex, rfs, rust_lib_name, rustc, static_lib_name,
+};
+
+//@ ignore-cross-compile
+// Reason: Invalid library format (not ELF) causes compilation failure
+// in the final `rustc` call.
+
+//@ only-linux
+// Reason: differences in the native lib compilation process causes differences
+// in the --print link-args output
+
+fn main() {
+    build_native_static_lib("native_dep_1");
+    build_native_static_lib("native_dep_2");
+    build_native_static_lib("native_dep_3");
+    build_native_static_lib("native_dep_4");
+    // Test cfg with packed bundle.
+    rustc().input("rust_dep_cfg.rs").crate_type("rlib").run();
+    rustc()
+        .input("main.rs")
+        .extern_("rust_dep", rust_lib_name("rust_dep_cfg"))
+        .crate_type("staticlib")
+        .cfg("should_add")
+        .run();
+    // Only static libraries should appear, no object files at all.
+    llvm_ar()
+        .arg("t")
+        .arg(rust_lib_name("rust_dep_cfg"))
+        .run()
+        .assert_stdout_contains(static_lib_name("native_dep_1"));
+    llvm_ar()
+        .arg("t")
+        .arg(rust_lib_name("rust_dep_cfg"))
+        .run()
+        .assert_stdout_contains(static_lib_name("native_dep_2"));
+    llvm_ar().arg("t").arg(static_lib_name("main")).run().assert_stdout_contains("native_dep_1.o");
+    llvm_ar()
+        .arg("t")
+        .arg(static_lib_name("main"))
+        .run()
+        .assert_stdout_not_contains("native_dep_2.o");
+
+    // Test bundle with whole archive.
+    rustc().input("rust_dep.rs").crate_type("rlib").run();
+    // Only deps with `+bundle` should appear.
+    llvm_ar().arg("t").arg(rust_lib_name("rust_dep")).run().assert_stdout_contains("native_dep_1");
+    llvm_ar().arg("t").arg(rust_lib_name("rust_dep")).run().assert_stdout_contains("native_dep_3");
+    llvm_ar()
+        .arg("t")
+        .arg(rust_lib_name("rust_dep"))
+        .run()
+        .assert_stdout_not_contains("native_dep_2");
+    llvm_ar()
+        .arg("t")
+        .arg(rust_lib_name("rust_dep"))
+        .run()
+        .assert_stdout_not_contains("native_dep_4");
+
+    // The compiler shouldn't use files which it doesn't know about.
+    rfs::remove_file(static_lib_name("native_dep_1"));
+    rfs::remove_file(static_lib_name("native_dep_3"));
+
+    let out = rustc()
+        .input("main.rs")
+        .extern_("rust_dep", rust_lib_name("rust_dep"))
+        .print("link-args")
+        .run()
+        .assert_stdout_not_contains("native_dep_3")
+        .stdout_utf8();
+
+    let re = regex::Regex::new(
+"--whole-archive.*native_dep_1.*--whole-archive.*lnative_dep_2.*no-whole-archive.*lnative_dep_4"
+    ).unwrap();
+
+    assert!(re.is_match(&out));
+}
diff --git a/tests/run-make/issue-22131/foo.rs b/tests/run-make/rustdoc-cfgspec-parsing/foo.rs
index 7b955a07b97..7b955a07b97 100644
--- a/tests/run-make/issue-22131/foo.rs
+++ b/tests/run-make/rustdoc-cfgspec-parsing/foo.rs
diff --git a/tests/run-make/rustdoc-cfgspec-parsing/rmake.rs b/tests/run-make/rustdoc-cfgspec-parsing/rmake.rs
new file mode 100644
index 00000000000..9c8c71b19a6
--- /dev/null
+++ b/tests/run-make/rustdoc-cfgspec-parsing/rmake.rs
@@ -0,0 +1,21 @@
+// A rustdoc bug caused the `feature=bar` syntax for the cfg flag to be interpreted
+// wrongly, with `feature=bar` instead of just `bar` being understood as the feature name.
+// After this was fixed in #22135, this test checks that this bug does not make a resurgence.
+// See https://github.com/rust-lang/rust/issues/22131
+
+//@ ignore-cross-compile
+// Reason: rustdoc fails to find the "foo" crate
+
+use run_make_support::{cwd, rustc, rustdoc};
+
+fn main() {
+    rustc().cfg(r#"feature="bar""#).crate_type("lib").input("foo.rs").run();
+    rustdoc()
+        .arg("--test")
+        .arg("--cfg")
+        .arg(r#"feature="bar""#)
+        .library_search_path(cwd())
+        .input("foo.rs")
+        .run()
+        .assert_stdout_contains("foo.rs - foo (line 1) ... ok");
+}
diff --git a/tests/run-make/split-debuginfo/Makefile b/tests/run-make/split-debuginfo/Makefile
index cb2439093b6..5f463ffe8cd 100644
--- a/tests/run-make/split-debuginfo/Makefile
+++ b/tests/run-make/split-debuginfo/Makefile
@@ -1,4 +1,6 @@
 # ignore-cross-compile
+# ignore-riscv64 On this platform only `-Csplit-debuginfo=off` is supported, see #120518
+
 include ../tools.mk
 
 all: off packed unpacked
diff --git a/tests/run-make/staticlib-blank-lib/Makefile b/tests/run-make/staticlib-blank-lib/Makefile
deleted file mode 100644
index fcbf87758fb..00000000000
--- a/tests/run-make/staticlib-blank-lib/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-
-all:
-	$(AR) crus $(TMPDIR)/libfoo.a foo.rs
-	$(AR) d $(TMPDIR)/libfoo.a foo.rs
-	$(RUSTC) foo.rs
diff --git a/tests/run-make/staticlib-blank-lib/rmake.rs b/tests/run-make/staticlib-blank-lib/rmake.rs
new file mode 100644
index 00000000000..11a85d102aa
--- /dev/null
+++ b/tests/run-make/staticlib-blank-lib/rmake.rs
@@ -0,0 +1,13 @@
+// In this test, the static library foo is made blank, which used to cause
+// a compilation error. As the compiler now returns Ok upon encountering a blank
+// staticlib as of #12379, this test checks that compilation is successful despite
+// the blank staticlib.
+// See https://github.com/rust-lang/rust/pull/12379
+
+use run_make_support::{llvm_ar, rustc, static_lib_name};
+
+fn main() {
+    llvm_ar().obj_to_ar().output_input(static_lib_name("foo"), "foo.rs").run();
+    llvm_ar().arg("d").output_input(static_lib_name("foo"), "foo.rs").run();
+    rustc().input("foo.rs").run();
+}
diff --git a/tests/run-make/test-benches/Makefile b/tests/run-make/test-benches/Makefile
deleted file mode 100644
index 11aed2e4c79..00000000000
--- a/tests/run-make/test-benches/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-# needs-unwind #[bench] and -Zpanic-abort-tests can't be combined
-
-all:
-	# Smoke-test that `#[bench]` isn't entirely broken.
-	$(RUSTC) --test smokebench.rs -O
-	$(call RUN,smokebench --bench)
-	$(call RUN,smokebench --bench noiter)
-	$(call RUN,smokebench --bench yesiter)
-	$(call RUN,smokebench)
diff --git a/tests/run-make/test-benches/rmake.rs b/tests/run-make/test-benches/rmake.rs
new file mode 100644
index 00000000000..1458fb8c990
--- /dev/null
+++ b/tests/run-make/test-benches/rmake.rs
@@ -0,0 +1,22 @@
+// #[bench] is a Rust feature to run benchmarks on performance-critical
+// code, which previously experienced a runtime panic bug in #103794.
+// In order to ensure future breakages of this feature are detected, this
+// smoke test was created, using the benchmarking feature with various
+// runtime flags.
+// See https://github.com/rust-lang/rust/issues/103794
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+//@ needs-unwind
+// Reason: #[bench] and -Zpanic-abort-tests can't be combined
+
+use run_make_support::{run, run_with_args, rustc};
+
+fn main() {
+    // Smoke-test that #[bench] isn't entirely broken.
+    rustc().arg("--test").input("smokebench.rs").opt().run();
+    run_with_args("smokebench", &["--bench"]);
+    run_with_args("smokebench", &["--bench", "noiter"]);
+    run_with_args("smokebench", &["--bench", "yesiter"]);
+    run("smokebench");
+}
diff --git a/tests/run-make/version-verbose-commit-hash/rmake.rs b/tests/run-make/version-verbose-commit-hash/rmake.rs
new file mode 100644
index 00000000000..733c0e2cdb1
--- /dev/null
+++ b/tests/run-make/version-verbose-commit-hash/rmake.rs
@@ -0,0 +1,20 @@
+// `--version --verbose` should display the git-commit hashes of rustc and rustdoc, but this
+// functionality was lost due to #104184. After this feature was returned by #109981, this
+// test ensures it will not be broken again.
+// See https://github.com/rust-lang/rust/issues/107094
+
+//@ needs-git-hash
+
+use run_make_support::{bare_rustc, bare_rustdoc, regex};
+
+fn main() {
+    let out_rustc =
+        bare_rustc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
+    let out_rustdoc =
+        bare_rustdoc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
+    let re =
+        regex::Regex::new(r#"commit-hash: [0-9a-f]{40}\ncommit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"#)
+            .unwrap();
+    assert!(re.is_match(&out_rustc));
+    assert!(re.is_match(&out_rustdoc));
+}
diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs
index 8d0944ed98d..e69fbac9635 100644
--- a/tests/run-make/wasm-panic-small/rmake.rs
+++ b/tests/run-make/wasm-panic-small/rmake.rs
@@ -13,7 +13,14 @@ fn main() {
 fn test(cfg: &str) {
     eprintln!("running cfg {cfg:?}");
 
-    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().cfg(cfg).run();
+    rustc()
+        .input("foo.rs")
+        .target("wasm32-wasip1")
+        .arg("-Clto")
+        .arg("-Cstrip=debuginfo")
+        .opt()
+        .cfg(cfg)
+        .run();
 
     let bytes = rfs::read("foo.wasm");
     println!("{}", bytes.len());
diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs
index 93eb38b0987..c0448c59c03 100644
--- a/tests/run-make/wasm-stringify-ints-small/rmake.rs
+++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs
@@ -4,7 +4,13 @@
 use run_make_support::{rfs, rustc};
 
 fn main() {
-    rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
+    rustc()
+        .input("foo.rs")
+        .target("wasm32-wasip1")
+        .arg("-Clto")
+        .arg("-Cstrip=debuginfo")
+        .opt()
+        .run();
 
     let bytes = rfs::read("foo.wasm");
     println!("{}", bytes.len());
diff --git a/tests/run-make/issue-97463-abi-param-passing/bad.c b/tests/run-make/zero-extend-abi-param-passing/bad.c
index 013314ab20d..013314ab20d 100644
--- a/tests/run-make/issue-97463-abi-param-passing/bad.c
+++ b/tests/run-make/zero-extend-abi-param-passing/bad.c
diff --git a/tests/run-make/issue-97463-abi-param-passing/param_passing.rs b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs
index c11f3cc72bd..c11f3cc72bd 100644
--- a/tests/run-make/issue-97463-abi-param-passing/param_passing.rs
+++ b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs
diff --git a/tests/run-make/zero-extend-abi-param-passing/rmake.rs b/tests/run-make/zero-extend-abi-param-passing/rmake.rs
new file mode 100644
index 00000000000..aed27f7f5ab
--- /dev/null
+++ b/tests/run-make/zero-extend-abi-param-passing/rmake.rs
@@ -0,0 +1,25 @@
+// This test was created in response to an obscure miscompilation bug, only
+// visible with the -O3 flag passed to the cc compiler when trying to obtain
+// a native static library for the sake of foreign function interface. This
+// flag could cause certain integer types to fail to be zero-extended, resulting
+// in type casting errors. After the fix in #97800, this test attempts integer casting
+// while simultaneously interfacing with a C library and using the -O3 flag.
+// See https://github.com/rust-lang/rust/issues/97463
+
+//@ ignore-msvc
+// Reason: the rustc compilation fails due to an unresolved external symbol
+
+//@ ignore-cross-compile
+// Reason: The compiled binary is executed.
+
+use run_make_support::{cc, is_msvc, llvm_ar, run, rustc, static_lib_name};
+
+fn main() {
+    // The issue exercised by this test specifically needs needs `-O`
+    // flags (like `-O3`) to reproduce. Thus, we call `cc()` instead of
+    // the nicer `build_native_static_lib`.
+    cc().arg("-c").arg("-O3").out_exe("bad.o").input("bad.c").run();
+    llvm_ar().obj_to_ar().output_input(static_lib_name("bad"), "bad.o").run();
+    rustc().input("param_passing.rs").arg("-lbad").opt_level("3").run();
+    run("param_passing");
+}
diff --git a/tests/rustdoc-gui/item-name-wrap.goml b/tests/rustdoc-gui/item-name-wrap.goml
new file mode 100644
index 00000000000..825c16ac5b8
--- /dev/null
+++ b/tests/rustdoc-gui/item-name-wrap.goml
@@ -0,0 +1,23 @@
+// This test ensures that the item name's width is not wrapped.
+go-to: "file://" + |DOC_PATH| + "/test_docs/short_docs/index.html"
+set-window-size: (1000, 600)
+
+// First we ensure that there is only one `item-table`...
+assert-count: ("ul.item-table", 1)
+// And only two items in it.
+assert-count: ("ul.item-table li", 2)
+
+// If they don't have the same height, then it means one of the two is on two lines whereas it
+// shouldn't!
+compare-elements-size: (
+    ".item-table .item-name a[href='fn.mult_vec_num.html']",
+    ".item-table .item-name a[href='fn.subt_vec_num.html']",
+    ["height"],
+)
+
+// We also check that the `item-table` is taking the full width.
+compare-elements-size: (
+    "#functions",
+    "ul.item-table",
+    ["width"],
+)
diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml
index 56453517a55..e499c159c6c 100644
--- a/tests/rustdoc-gui/sidebar.goml
+++ b/tests/rustdoc-gui/sidebar.goml
@@ -72,6 +72,7 @@ click: "#structs + .item-table .item-name > a"
 assert-count: (".sidebar .sidebar-crate", 1)
 assert-count: (".sidebar .location", 1)
 assert-count: (".sidebar h2", 3)
+assert-text: (".sidebar-elems ul.block > li.current > a", "Foo")
 // We check that there is no crate listed outside of the top level.
 assert-false: ".sidebar-elems > .crate"
 
@@ -110,6 +111,7 @@ click: "#functions + .item-table .item-name > a"
 assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
 assert-count: (".sidebar .location", 0)
 assert-count: (".sidebar h2", 1)
+assert-text: (".sidebar-elems ul.block > li.current > a", "foobar")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
@@ -118,6 +120,7 @@ assert-property: (".sidebar", {"clientWidth": "200"})
 assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
 assert-text: (".sidebar > .location", "Module module")
 assert-count: (".sidebar .location", 1)
+assert-text: (".sidebar-elems ul.block > li.current > a", "module")
 // Module page requires three headings:
 //   - Presistent crate branding (name and version)
 //   - Module name, followed by TOC for module headings
@@ -138,6 +141,7 @@ assert-text: (".sidebar > .sidebar-elems > h2", "In lib2::module::sub_module")
 assert-property: (".sidebar > .sidebar-elems > h2 > a", {
     "href": "/module/sub_module/index.html",
 }, ENDS_WITH)
+assert-text: (".sidebar-elems ul.block > li.current > a", "sub_sub_module")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems .crate"
 assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml
index 35f338ea328..31ab281d6ce 100644
--- a/tests/rustdoc-gui/source-code-page-code-scroll.goml
+++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml
@@ -2,7 +2,7 @@
 go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 set-window-size: (800, 1000)
 // "scrollWidth" should be superior than "clientWidth".
-assert-property: ("body", {"scrollWidth": 1047, "clientWidth": 800})
+assert-property: ("body", {"scrollWidth": 1114, "clientWidth": 800})
 
 // Both properties should be equal (ie, no scroll on the code block).
-assert-property: (".example-wrap .rust", {"scrollWidth": 933, "clientWidth": 933})
+assert-property: (".example-wrap .rust", {"scrollWidth": 1000, "clientWidth": 1000})
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 7e34178e56f..7397992c0ab 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -20,10 +20,10 @@ Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated
 Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
 Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
 
-Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
-</span>.
-Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
-</span>.
+Finally, you can use `quz` only on <span class="stab portability" data-span="1"><code>Unix or x86-64
+</code></span>.
+Finally, you can use `quz` only on <span class="stab portability" data-span="2"><code>Unix or x86-64
+</code></span>.
 */
 
 use std::convert::AsRef;
@@ -614,3 +614,17 @@ pub mod private {
         B,
     }
 }
+
+pub mod trait_bounds {
+    pub trait OneBound: Sized {}
+    pub trait TwoBounds: Sized + Copy {}
+    pub trait ThreeBounds: Sized + Copy + Eq {}
+}
+
+pub mod short_docs {
+    /// mult_vec_num(x: &[f64], y: f64)
+    pub fn mult_vec_num() {}
+
+    /// subt_vec_num(x: &[f64], y: f64)
+    pub fn subt_vec_num() {}
+}
diff --git a/tests/rustdoc-gui/stab-in-doc.goml b/tests/rustdoc-gui/stab-in-doc.goml
new file mode 100644
index 00000000000..6a03a51fe9f
--- /dev/null
+++ b/tests/rustdoc-gui/stab-in-doc.goml
@@ -0,0 +1,9 @@
+// This test ensure that `stab` elements if used in doc blocks are not breaking the text layout.
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// We make the window wide enough for the two stabs who are looking into to be on the same line.
+set-window-size: (1100, 600)
+compare-elements-position: (
+    ".top-doc .docblock span[data-span='1']",
+    ".top-doc .docblock span[data-span='2']",
+    ["y"],
+)
diff --git a/tests/rustdoc-gui/trait-with-bounds.goml b/tests/rustdoc-gui/trait-with-bounds.goml
new file mode 100644
index 00000000000..f076bdd4707
--- /dev/null
+++ b/tests/rustdoc-gui/trait-with-bounds.goml
@@ -0,0 +1,35 @@
+// Check that if a trait has more than 2 bounds, they are displayed on different lines.
+
+// It tries to load a JS for each trait but there are none since they're not implemented.
+fail-on-request-error: false
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait_bounds/trait.OneBound.html"
+// They should have the same Y position.
+compare-elements-position: (
+    ".item-decl code",
+    ".item-decl a.trait[title='trait core::marker::Sized']",
+    ["y"],
+)
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait_bounds/trait.TwoBounds.html"
+// They should have the same Y position.
+compare-elements-position: (
+    ".item-decl code",
+    ".item-decl a.trait[title='trait core::marker::Copy']",
+    ["y"],
+)
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait_bounds/trait.ThreeBounds.html"
+// All on their own line.
+compare-elements-position-false: (
+    ".item-decl code",
+    ".item-decl a.trait[title='trait core::marker::Sized']",
+    ["y"],
+)
+compare-elements-position-false: (
+    ".item-decl a.trait[title='trait core::marker::Sized']",
+    ".item-decl a.trait[title='trait core::marker::Copy']",
+    ["y"],
+)
+compare-elements-position-false: (
+    ".item-decl a.trait[title='trait core::marker::Copy']",
+    ".item-decl a.trait[title='trait core::cmp::Eq']",
+    ["y"],
+)
diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml
index fdf84c3fd29..8df946c6f39 100644
--- a/tests/rustdoc-gui/type-declation-overflow.goml
+++ b/tests/rustdoc-gui/type-declation-overflow.goml
@@ -8,34 +8,38 @@ fail-on-request-error: false
 
 go-to: "file://" + |DOC_PATH| + "/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html"
 // We set a fixed size so there is no chance of "random" resize.
-set-window-size: (1100, 800)
+set-window-size: (710, 800)
 // Logically, the <body> scroll width should be the width of the window.
-assert-property: ("body", {"scrollWidth": "1100"})
-// However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
+assert-property: ("body", {"scrollWidth": "710"})
+// We now check that the section width hasn't grown because of it.
+assert-property: ("#main-content", {"scrollWidth": "450"})
+// However, since there is overflow in the type declaration, its scroll width is bigger that "#main-content".
+assert-property: ("pre.item-decl", {"scrollWidth": "585"})
 
 // In the table-ish view on the module index, the name should not be wrapped more than necessary.
 go-to: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
 
 // We'll ensure that items with short documentation have the same width.
 store-property: ("//*[@class='item-table']//*[@class='struct']/..", {"offsetWidth": offset_width})
-assert: |offset_width| == "277"
+assert: |offset_width| == "149"
 assert-property: ("//*[@class='item-table']//*[@class='constant']/..", {"offsetWidth": |offset_width|})
 
 // We now make the same check on type declaration...
 go-to: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"
-assert-property: ("body", {"scrollWidth": "1100"})
+assert-property: ("body", {"scrollWidth": "710"})
+// Getting the width of the "<main>" element.
+assert-property: ("main", {"scrollWidth": "510"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "450"})
 // And now checking that it has scrollable content.
 assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
 
 // ... and constant.
 // On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
 go-to: "file://" + |DOC_PATH| + "/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html"
-assert-property: ("body", {"scrollWidth": "1100"})
+assert-property: ("body", {"scrollWidth": "710"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "450"})
 // And now checking that it has scrollable content.
 assert-property: ("pre.item-decl", {"scrollWidth": "950"})
 
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index 05c2d428393..7fd0fe2b898 100644
--- a/tests/rustdoc-json/assoc_items.rs
+++ b/tests/rustdoc-json/assoc_items.rs
@@ -3,32 +3,32 @@
 pub struct Simple;
 
 impl Simple {
-    // @has "$.index[*][?(@.name=='CONSTANT')].inner.assoc_const"
+    //@ has "$.index[*][?(@.name=='CONSTANT')].inner.assoc_const"
     pub const CONSTANT: usize = 0;
 }
 
 pub trait EasyToImpl {
-    // @has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
+    //@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
+    //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
+    //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
     /// ToDeclare trait
     type ToDeclare;
-    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
+    //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
     /// AN_ATTRIBUTE trait
     const AN_ATTRIBUTE: usize;
 }
 
 impl EasyToImpl for Simple {
-    // @has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
+    //@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
+    //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
     /// ToDeclare impl
     type ToDeclare = usize;
 
-    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
+    //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
     /// AN_ATTRIBUTE impl
     const AN_ATTRIBUTE: usize = 12;
 }
diff --git a/tests/rustdoc-json/assoc_type.rs b/tests/rustdoc-json/assoc_type.rs
index edc1f73c866..43b4d387d92 100644
--- a/tests/rustdoc-json/assoc_type.rs
+++ b/tests/rustdoc-json/assoc_type.rs
@@ -1,9 +1,9 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/98547>.
 
-// @has "$.index[*][?(@.name=='Trait')]"
-// @has "$.index[*][?(@.name=='AssocType')]"
-// @has "$.index[*][?(@.name=='S')]"
-// @has "$.index[*][?(@.name=='S2')]"
+//@ has "$.index[*][?(@.name=='Trait')]"
+//@ has "$.index[*][?(@.name=='AssocType')]"
+//@ has "$.index[*][?(@.name=='S')]"
+//@ has "$.index[*][?(@.name=='S2')]"
 
 pub trait Trait {
     type AssocType;
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index a2a5c4a7146..bc2c98dcbb7 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -2,7 +2,7 @@
 
 #![no_std]
 
-// @has "$.index[*][?(@.name=='Error')].inner.assoc_type"
-// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
-// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs
index e2ce66c99e4..249e35b7243 100644
--- a/tests/rustdoc-json/doc_hidden_failure.rs
+++ b/tests/rustdoc-json/doc_hidden_failure.rs
@@ -11,8 +11,8 @@ mod auto {
     }
 }
 
-// @count "$.index[*][?(@.name=='builders')]" 1
-// @has "$.index[*][?(@.name == 'ActionRowBuilder')"]
+//@ count "$.index[*][?(@.name=='builders')]" 1
+//@ has "$.index[*][?(@.name == 'ActionRowBuilder')"]
 pub use auto::*;
 
 pub mod builders {
diff --git a/tests/rustdoc-json/enums/discriminant/basic.rs b/tests/rustdoc-json/enums/discriminant/basic.rs
index dbfc5c2cf6b..06a240404fb 100644
--- a/tests/rustdoc-json/enums/discriminant/basic.rs
+++ b/tests/rustdoc-json/enums/discriminant/basic.rs
@@ -1,12 +1,12 @@
 #[repr(i8)]
 pub enum Ordering {
-    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"'
-    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.value" '"-1"'
+    //@ is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"'
+    //@ is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.value" '"-1"'
     Less = -1,
-    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"'
-    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.value" '"0"'
+    //@ is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"'
+    //@ is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.value" '"0"'
     Equal = 0,
-    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"'
-    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.value" '"1"'
+    //@ is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"'
+    //@ is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.value" '"1"'
     Greater = 1,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/expr.rs b/tests/rustdoc-json/enums/discriminant/expr.rs
index ddcad58a550..bf2bce85108 100644
--- a/tests/rustdoc-json/enums/discriminant/expr.rs
+++ b/tests/rustdoc-json/enums/discriminant/expr.rs
@@ -1,30 +1,30 @@
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"'
+    //@ is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.value" '"0"'
+    //@ is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"'
     Addition = 0 + 0,
-    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.value" '"1"'
-    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"'
+    //@ is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.value" '"1"'
+    //@ is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"'
     Bin = 0b1,
-    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.value" '"2"'
-    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"'
+    //@ is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.value" '"2"'
+    //@ is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"'
     Oct = 0o2,
-    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"'
-    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"'
+    //@ is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"'
+    //@ is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"'
     PubConst = THREE,
-    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.value" '"4"'
-    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"'
+    //@ is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.value" '"4"'
+    //@ is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"'
     Hex = 0x4,
-    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.value" '"5"'
-    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"'
+    //@ is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.value" '"5"'
+    //@ is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"'
     Cast = 5 as isize,
-    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"'
-    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"'
+    //@ is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"'
+    //@ is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PubCall = six(),
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"'
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"'
+    //@ is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"'
+    //@ is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PrivCall = seven(),
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"'
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"'
+    //@ is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"'
+    //@ is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"'
     PrivConst = EIGHT,
 }
 
diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs
index 47fb7040896..a023c9fbf6e 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -4,40 +4,40 @@
 
 #[repr(u64)]
 pub enum U64 {
-    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"'
+    //@ is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"'
+    //@ is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"'
     U64Min = u64::MIN,
-    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"'
-    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"'
+    //@ is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"'
+    //@ is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"'
     U64Max = u64::MAX,
 }
 
 #[repr(i64)]
 pub enum I64 {
-    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"'
-    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"'
+    //@ is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"'
+    //@ is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"'
     I64Min = i64::MIN,
-    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"'
-    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"'
+    //@ is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"'
+    //@ is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"'
     I64Max = i64::MAX,
 }
 
 #[repr(u128)]
 pub enum U128 {
-    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"'
+    //@ is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"'
+    //@ is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"'
     U128Min = u128::MIN,
-    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"'
-    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"'
+    //@ is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"'
+    //@ is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"'
     U128Max = u128::MAX,
 }
 
 #[repr(i128)]
 pub enum I128 {
-    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"'
-    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"'
+    //@ is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"'
+    //@ is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"'
     I128Min = i128::MIN,
-    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"'
-    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"'
+    //@ is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"'
+    //@ is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"'
     I128Max = i128::MAX,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
index 9c3db81c663..f16a74d638b 100644
--- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
+++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
@@ -2,16 +2,16 @@
 
 #[repr(u32)]
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"'
+    //@ is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"'
+    //@ is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"'
     Basic = 0,
-    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"'
-    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"'
+    //@ is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"'
+    //@ is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"'
     Suffix = 10u32,
-    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"'
-    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"'
+    //@ is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"'
+    //@ is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"'
     Underscore = 1_0_0,
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"'
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"'
+    //@ is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"'
+    //@ is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"'
     SuffixUnderscore = 1_0_0_0u32,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
index 38ba1caf140..522545d34d0 100644
--- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
+++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
@@ -1,12 +1,12 @@
 // ignore-tidy-linelength
 
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}'
+    //@ is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}'
     Has = 0,
-    // @is "$.index[*][?(@.name=='Doesnt')].inner.variant.discriminant" null
+    //@ is "$.index[*][?(@.name=='Doesnt')].inner.variant.discriminant" null
     Doesnt,
-    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null
+    //@ is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null
     AlsoDoesnt,
-    // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}'
+    //@ is "$.index[*][?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}'
     AlsoHas = 44,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index c4b087c3635..0ac40cda733 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -1,15 +1,15 @@
 // ignore-tidy-linelength
 
 #[repr(i32)]
-// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
-    // @count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
+    //@ is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
+    //@ count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
     Struct {},
-    // @is    "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}'
-    // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1
+    //@ is    "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}'
+    //@ count "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1
     StructWithDiscr { x: i32 } = 42,
-    // @is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.discriminant"  '{"expr": "0x42", "value": "66"}'
-    // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2
+    //@ is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.discriminant"  '{"expr": "0x42", "value": "66"}'
+    //@ count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2
     StructWithHexDiscr { x: i32, y: bool } = 0x42,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index 7da82ec8ea4..fbff5aacd67 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -1,15 +1,15 @@
 // ignore-tidy-linelength
 
 #[repr(u32)]
-// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
-    // @count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
+    //@ is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
+    //@ count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
     Tuple(),
-    // @is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}'
-    // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1
+    //@ is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}'
+    //@ count "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1
     TupleWithDiscr(i32) = 1,
-    // @is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}'
-    // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2
+    //@ is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}'
+    //@ count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2
     TupleWithBinDiscr(i32, i32) = 0b10,
 }
diff --git a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
index 784a93c893a..6aec6960b5f 100644
--- a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
+++ b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
@@ -5,7 +5,7 @@
 extern crate color;
 use color::Color::Red;
 
-// @set red = "$.index[*][?(@.inner.module.is_crate)].links.Red"
+//@ set red = "$.index[*][?(@.inner.module.is_crate)].links.Red"
 
-// @!has "$.index[*][?(@.name == 'Red')]"
-// @!has "$.index[*][?(@.name == 'Color')]"
+//@ !has "$.index[*][?(@.name == 'Red')]"
+//@ !has "$.index[*][?(@.name == 'Color')]"
diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs
index 74d96248d5c..b353678ac92 100644
--- a/tests/rustdoc-json/enums/field_hidden.rs
+++ b/tests/rustdoc-json/enums/field_hidden.rs
@@ -1,9 +1,9 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/100529>.
 
-// @has "$.index[*][?(@.name=='ParseError')]"
-// @has "$.index[*][?(@.name=='UnexpectedEndTag')]"
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null]
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null
+//@ has "$.index[*][?(@.name=='ParseError')]"
+//@ has "$.index[*][?(@.name=='UnexpectedEndTag')]"
+//@ is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null]
+//@ is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null
 
 pub enum ParseError {
     UnexpectedEndTag(#[doc(hidden)] u32),
diff --git a/tests/rustdoc-json/enums/field_order.rs b/tests/rustdoc-json/enums/field_order.rs
index e89add9cbbd..a78be200b41 100644
--- a/tests/rustdoc-json/enums/field_order.rs
+++ b/tests/rustdoc-json/enums/field_order.rs
@@ -17,24 +17,24 @@ pub enum Whatever {
     },
 }
 
-// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
-// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
-// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
-// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
-// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
-// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
-// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
-// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
-// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
-// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+//@ set 0 = '$.index[*][?(@.name == "ews_0")].id'
+//@ set 1 = '$.index[*][?(@.name == "dik_1")].id'
+//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+//@ set 3 = '$.index[*][?(@.name == "djt_3")].id'
+//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+//@ set 6 = '$.index[*][?(@.name == "bja_6")].id'
+//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+//@ set 9 = '$.index[*][?(@.name == "vll_9")].id'
 
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[0]' $0
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[1]' $1
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[2]' $2
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[3]' $3
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[4]' $4
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[5]' $5
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[6]' $6
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[7]' $7
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[8]' $8
-// @is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[9]' $9
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[0]' $0
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[1]' $1
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[2]' $2
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[3]' $3
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[4]' $4
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[5]' $5
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[6]' $6
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[7]' $7
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[8]' $8
+//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[9]' $9
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index 68483683464..ef3d9363d64 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -1,29 +1,29 @@
 // ignore-tidy-linelength
 
 pub enum Foo {
-    // @set Unit = "$.index[*][?(@.name=='Unit')].id"
-    // @is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
+    //@ set Unit = "$.index[*][?(@.name=='Unit')].id"
+    //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
     Unit,
-    // @set Named = "$.index[*][?(@.name=='Named')].id"
-    // @is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
+    //@ set Named = "$.index[*][?(@.name=='Named')].id"
+    //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
     Named {},
-    // @set Tuple = "$.index[*][?(@.name=='Tuple')].id"
-    // @is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
+    //@ set Tuple = "$.index[*][?(@.name=='Tuple')].id"
+    //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
     Tuple(),
-    // @set NamedField = "$.index[*][?(@.name=='NamedField')].id"
-    // @set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
-    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
-    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
+    //@ set NamedField = "$.index[*][?(@.name=='NamedField')].id"
+    //@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
+    //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
+    //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
     NamedField { x: i32 },
-    // @set TupleField = "$.index[*][?(@.name=='TupleField')].id"
-    // @set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
-    // @is "$.index[*][?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field
+    //@ set TupleField = "$.index[*][?(@.name=='TupleField')].id"
+    //@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
+    //@ is "$.index[*][?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field
     TupleField(i32),
 }
 
-// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[0]" $Unit
-// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[1]" $Named
-// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[2]" $Tuple
-// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[3]" $NamedField
-// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[4]" $TupleField
-// @count "$.index[*][?(@.name=='Foo')].inner.enum.variants[*]" 5
+//@ is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[0]" $Unit
+//@ is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[1]" $Named
+//@ is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[2]" $Tuple
+//@ is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[3]" $NamedField
+//@ is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[4]" $TupleField
+//@ count "$.index[*][?(@.name=='Foo')].inner.enum.variants[*]" 5
diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs
index 2676c4e4157..b724f9abb71 100644
--- a/tests/rustdoc-json/enums/struct_field_hidden.rs
+++ b/tests/rustdoc-json/enums/struct_field_hidden.rs
@@ -2,15 +2,15 @@ pub enum Foo {
     Variant {
         #[doc(hidden)]
         a: i32,
-        // @set b = "$.index[*][?(@.name=='b')].id"
+        //@ set b = "$.index[*][?(@.name=='b')].id"
         b: i32,
         #[doc(hidden)]
         x: i32,
-        // @set y = "$.index[*][?(@.name=='y')].id"
+        //@ set y = "$.index[*][?(@.name=='y')].id"
         y: i32,
     },
-    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
-    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
-    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
-    // @count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
+    //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
+    //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
+    //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
+    //@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
 }
diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
index 53cdf83ffa6..3ac7a3ce0fc 100644
--- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs
+++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
@@ -1,80 +1,80 @@
-// @set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id"
-// @set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id"
-// @set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id"
-// @set 2.2.1 = "$.index[*][?(@.docs=='2.2.1')].id"
-// @set 2.3.0 = "$.index[*][?(@.docs=='2.3.0')].id"
-// @set 3.1.1 = "$.index[*][?(@.docs=='3.1.1')].id"
-// @set 3.1.2 = "$.index[*][?(@.docs=='3.1.2')].id"
-// @set 3.2.0 = "$.index[*][?(@.docs=='3.2.0')].id"
-// @set 3.2.2 = "$.index[*][?(@.docs=='3.2.2')].id"
-// @set 3.3.0 = "$.index[*][?(@.docs=='3.3.0')].id"
-// @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id"
+//@ set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id"
+//@ set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id"
+//@ set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id"
+//@ set 2.2.1 = "$.index[*][?(@.docs=='2.2.1')].id"
+//@ set 2.3.0 = "$.index[*][?(@.docs=='2.3.0')].id"
+//@ set 3.1.1 = "$.index[*][?(@.docs=='3.1.1')].id"
+//@ set 3.1.2 = "$.index[*][?(@.docs=='3.1.2')].id"
+//@ set 3.2.0 = "$.index[*][?(@.docs=='3.2.0')].id"
+//@ set 3.2.2 = "$.index[*][?(@.docs=='3.2.2')].id"
+//@ set 3.3.0 = "$.index[*][?(@.docs=='3.3.0')].id"
+//@ set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id"
 
 pub enum EnumWithStrippedTupleVariants {
-    // @count "$.index[*][?(@.name=='None')].inner.variant.kind.tuple[*]" 0
+    //@ count "$.index[*][?(@.name=='None')].inner.variant.kind.tuple[*]" 0
     None(),
 
-    // @count "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0
+    //@ count "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[*]" 1
+    //@ is    "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0
     One(/** 1.1.0*/ bool),
-    // @count "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null
+    //@ count "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1
+    //@ is    "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null
     OneHidden(#[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0
-    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1
+    //@ count "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[*]" 2
+    //@ is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0
+    //@ is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1
     Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1
+    //@ count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2
+    //@ is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null
+    //@ is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1
     TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null
+    //@ count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2
+    //@ is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0
+    //@ is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null
     TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool),
-    // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null
+    //@ count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2
+    //@ is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null
+    //@ is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null
     TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1
-    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2
+    //@ count "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3
+    //@ is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[0]" null
+    //@ is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1
+    //@ is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2
     Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0
-    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[1]" null
-    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2
+    //@ count "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3
+    //@ is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0
+    //@ is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[1]" null
+    //@ is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2
     Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0
-    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1
-    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[2]" null
+    //@ count "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3
+    //@ is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0
+    //@ is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1
+    //@ is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[2]" null
     Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool),
 }
 
-// @is "$.index[*][?(@.docs=='1.1.0')].name" '"0"'
-// @is "$.index[*][?(@.docs=='2.1.0')].name" '"0"'
-// @is "$.index[*][?(@.docs=='2.1.1')].name" '"1"'
-// @is "$.index[*][?(@.docs=='2.2.1')].name" '"1"'
-// @is "$.index[*][?(@.docs=='2.3.0')].name" '"0"'
-// @is "$.index[*][?(@.docs=='3.1.1')].name" '"1"'
-// @is "$.index[*][?(@.docs=='3.1.2')].name" '"2"'
-// @is "$.index[*][?(@.docs=='3.2.0')].name" '"0"'
-// @is "$.index[*][?(@.docs=='3.2.2')].name" '"2"'
-// @is "$.index[*][?(@.docs=='3.3.0')].name" '"0"'
-// @is "$.index[*][?(@.docs=='3.3.1')].name" '"1"'
+//@ is "$.index[*][?(@.docs=='1.1.0')].name" '"0"'
+//@ is "$.index[*][?(@.docs=='2.1.0')].name" '"0"'
+//@ is "$.index[*][?(@.docs=='2.1.1')].name" '"1"'
+//@ is "$.index[*][?(@.docs=='2.2.1')].name" '"1"'
+//@ is "$.index[*][?(@.docs=='2.3.0')].name" '"0"'
+//@ is "$.index[*][?(@.docs=='3.1.1')].name" '"1"'
+//@ is "$.index[*][?(@.docs=='3.1.2')].name" '"2"'
+//@ is "$.index[*][?(@.docs=='3.2.0')].name" '"0"'
+//@ is "$.index[*][?(@.docs=='3.2.2')].name" '"2"'
+//@ is "$.index[*][?(@.docs=='3.3.0')].name" '"0"'
+//@ is "$.index[*][?(@.docs=='3.3.1')].name" '"1"'
 
-// @is "$.index[*][?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}'
+//@ is "$.index[*][?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}'
diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs
index bec89530b05..61766d2a629 100644
--- a/tests/rustdoc-json/enums/use_glob.rs
+++ b/tests/rustdoc-json/enums/use_glob.rs
@@ -1,15 +1,15 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/104942>
 
-// @set Color = "$.index[*][?(@.name == 'Color')].id"
+//@ set Color = "$.index[*][?(@.name == 'Color')].id"
 pub enum Color {
     Red,
     Green,
     Blue,
 }
 
-// @set use_Color = "$.index[*][?(@.inner.import)].id"
-// @is "$.index[*][?(@.inner.import)].inner.import.id" $Color
-// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
+//@ set use_Color = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.import)].inner.import.id" $Color
+//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
 pub use Color::*;
 
-// @ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
+//@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs
index c7e0c21f1ef..9010d616493 100644
--- a/tests/rustdoc-json/enums/use_variant.rs
+++ b/tests/rustdoc-json/enums/use_variant.rs
@@ -1,12 +1,12 @@
-// @set AlwaysNone = "$.index[*][?(@.name == 'AlwaysNone')].id"
+//@ set AlwaysNone = "$.index[*][?(@.name == 'AlwaysNone')].id"
 pub enum AlwaysNone {
-    // @set None = "$.index[*][?(@.name == 'None')].id"
+    //@ set None = "$.index[*][?(@.name == 'None')].id"
     None,
 }
-// @is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
+//@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
 
-// @set use_None = "$.index[*][?(@.inner.import)].id"
-// @is "$.index[*][?(@.inner.import)].inner.import.id" $None
+//@ set use_None = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.import)].inner.import.id" $None
 pub use AlwaysNone::None;
 
-// @ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
+//@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs
index c42ead64461..0f3f16ff835 100644
--- a/tests/rustdoc-json/enums/use_variant_foreign.rs
+++ b/tests/rustdoc-json/enums/use_variant_foreign.rs
@@ -2,8 +2,8 @@
 
 extern crate color;
 
-// @has "$.index[*].inner.import[?(@.name == 'Red')]"
+//@ has "$.index[*].inner.import[?(@.name == 'Red')]"
 pub use color::Color::Red;
 
-// @!has "$.index[*][?(@.name == 'Red')]"
-// @!has "$.index[*][?(@.name == 'Color')]"
+//@ !has "$.index[*][?(@.name == 'Red')]"
+//@ !has "$.index[*][?(@.name == 'Color')]"
diff --git a/tests/rustdoc-json/enums/variant_order.rs b/tests/rustdoc-json/enums/variant_order.rs
index 17ca96213de..6ebe28c94ca 100644
--- a/tests/rustdoc-json/enums/variant_order.rs
+++ b/tests/rustdoc-json/enums/variant_order.rs
@@ -15,24 +15,24 @@ pub enum Foo {
     Vll9,
 }
 
-// @set 0 = '$.index[*][?(@.name == "Ews0")].id'
-// @set 1 = '$.index[*][?(@.name == "Dik1")].id'
-// @set 2 = '$.index[*][?(@.name == "Hsk2")].id'
-// @set 3 = '$.index[*][?(@.name == "Djt3")].id'
-// @set 4 = '$.index[*][?(@.name == "Jnr4")].id'
-// @set 5 = '$.index[*][?(@.name == "Dfs5")].id'
-// @set 6 = '$.index[*][?(@.name == "Bja6")].id'
-// @set 7 = '$.index[*][?(@.name == "Lyc7")].id'
-// @set 8 = '$.index[*][?(@.name == "Yqd8")].id'
-// @set 9 = '$.index[*][?(@.name == "Vll9")].id'
+//@ set 0 = '$.index[*][?(@.name == "Ews0")].id'
+//@ set 1 = '$.index[*][?(@.name == "Dik1")].id'
+//@ set 2 = '$.index[*][?(@.name == "Hsk2")].id'
+//@ set 3 = '$.index[*][?(@.name == "Djt3")].id'
+//@ set 4 = '$.index[*][?(@.name == "Jnr4")].id'
+//@ set 5 = '$.index[*][?(@.name == "Dfs5")].id'
+//@ set 6 = '$.index[*][?(@.name == "Bja6")].id'
+//@ set 7 = '$.index[*][?(@.name == "Lyc7")].id'
+//@ set 8 = '$.index[*][?(@.name == "Yqd8")].id'
+//@ set 9 = '$.index[*][?(@.name == "Vll9")].id'
 
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[0]' $0
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[1]' $1
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[2]' $2
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[3]' $3
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[4]' $4
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[5]' $5
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[6]' $6
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[7]' $7
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[8]' $8
-// @is '$.index[*][?(@.name == "Foo")].inner.enum.variants[9]' $9
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[0]' $0
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[1]' $1
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[2]' $2
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[3]' $3
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[4]' $4
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[5]' $5
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[6]' $6
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[7]' $7
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[8]' $8
+//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[9]' $9
diff --git a/tests/rustdoc-json/enums/variant_struct.rs b/tests/rustdoc-json/enums/variant_struct.rs
index fe40f1a5d5d..44a0c946711 100644
--- a/tests/rustdoc-json/enums/variant_struct.rs
+++ b/tests/rustdoc-json/enums/variant_struct.rs
@@ -1,10 +1,10 @@
-// @is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='EnumStruct')].inner.enum"
+//@ is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='EnumStruct')].inner.enum"
 pub enum EnumStruct {
-    // @has "$.index[*][?(@.name=='x')].inner.struct_field"
-    // @set x = "$.index[*][?(@.name=='x')].id"
-    // @has "$.index[*][?(@.name=='y')].inner.struct_field"
-    // @set y = "$.index[*][?(@.name=='y')].id"
-    // @ismany "$.index[*][?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y
+    //@ has "$.index[*][?(@.name=='x')].inner.struct_field"
+    //@ set x = "$.index[*][?(@.name=='x')].id"
+    //@ has "$.index[*][?(@.name=='y')].inner.struct_field"
+    //@ set y = "$.index[*][?(@.name=='y')].id"
+    //@ ismany "$.index[*][?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y
     VariantS { x: u32, y: String },
 }
diff --git a/tests/rustdoc-json/enums/variant_tuple_struct.rs b/tests/rustdoc-json/enums/variant_tuple_struct.rs
index 358fc1079cb..04f0cbb40c4 100644
--- a/tests/rustdoc-json/enums/variant_tuple_struct.rs
+++ b/tests/rustdoc-json/enums/variant_tuple_struct.rs
@@ -1,10 +1,10 @@
-// @is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='EnumTupleStruct')].inner.enum"
+//@ is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='EnumTupleStruct')].inner.enum"
 pub enum EnumTupleStruct {
-    // @has "$.index[*][?(@.name=='0')].inner.struct_field"
-    // @set f0 = "$.index[*][?(@.name=='0')].id"
-    // @has "$.index[*][?(@.name=='1')].inner.struct_field"
-    // @set f1 = "$.index[*][?(@.name=='1')].id"
-    // @ismany "$.index[*][?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1
+    //@ has "$.index[*][?(@.name=='0')].inner.struct_field"
+    //@ set f0 = "$.index[*][?(@.name=='0')].id"
+    //@ has "$.index[*][?(@.name=='1')].inner.struct_field"
+    //@ set f1 = "$.index[*][?(@.name=='1')].id"
+    //@ ismany "$.index[*][?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1
     VariantA(u32, String),
 }
diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs
index dbe316f573d..03fbb3b795d 100644
--- a/tests/rustdoc-json/fn_pointer/abi.rs
+++ b/tests/rustdoc-json/fn_pointer/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\"
+//@ is "$.index[*][?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\"
 pub type AbiRust = fn();
 
-// @is "$.index[*][?(@.name=='AbiC')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": false}}'
+//@ is "$.index[*][?(@.name=='AbiC')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": false}}'
 pub type AbiC = extern "C" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystem')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": false}}'
+//@ is "$.index[*][?(@.name=='AbiSystem')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": false}}'
 pub type AbiSystem = extern "system" fn();
 
-// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": true}}'
+//@ is "$.index[*][?(@.name=='AbiCUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": true}}'
 pub type AbiCUnwind = extern "C-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}'
+//@ is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}'
 pub type AbiSystemUnwind = extern "system-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""'
+//@ is "$.index[*][?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""'
 pub type AbiVecorcall = extern "vectorcall" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""'
+//@ is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""'
 pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn();
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index 8b3a8c0a74e..9f5d23ae421 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -1,10 +1,10 @@
 // ignore-tidy-linelength
 
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"'
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\"
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"'
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\"
+//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\"
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
 pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32;
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index 1a62eb2bae8..9c0e6c0ccf1 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,11 +1,11 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false
 pub type FnPointer = fn();
 
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false
 pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs
index d7b98b5924b..2f6413cee6f 100644
--- a/tests/rustdoc-json/fns/abi.rs
+++ b/tests/rustdoc-json/fns/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
+//@ is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
 pub fn abi_rust() {}
 
-// @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
+//@ is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
 pub extern "C" fn abi_c() {}
 
-// @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
+//@ is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
 pub extern "system" fn abi_system() {}
 
-// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
+//@ is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
 pub extern "C-unwind" fn abi_c_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
+//@ is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
 pub extern "system-unwind" fn abi_system_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
+//@ is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
 pub extern "vectorcall" fn abi_vectorcall() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
+//@ is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
 pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index 32117d73657..e029c72df21 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -5,30 +5,30 @@
 
 use std::future::Future;
 
-// @is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
-// @is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
 pub fn get_int() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
-// @is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
 pub async fn get_int_async() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive"  \"i32\"
-// @is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive"  \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
 pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
 pub async fn get_int_future_async() -> impl Future<Output = i32> {
     async { 42 }
 }
diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs
index eef9ae99eb0..defe66345e8 100644
--- a/tests/rustdoc-json/fns/extern_c_variadic.rs
+++ b/tests/rustdoc-json/fns/extern_c_variadic.rs
@@ -1,6 +1,6 @@
 extern "C" {
-    // @is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
+    //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
     pub fn not_variadic(_: i32);
-    // @is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
+    //@ is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
     pub fn variadic(_: i32, ...);
 }
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index 2f6cf3bf65a..75c5fcbb01f 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -1,60 +1,60 @@
 // ignore-tidy-linelength
 
-// @set foo = "$.index[*][?(@.name=='Foo')].id"
+//@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
-// @set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id"
+//@ set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id"
 pub trait GenericFoo<'a> {}
 
-// @is "$.index[*][?(@.name=='generics')].inner.function.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
-// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
-// @count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.where_predicates" "[]"
+//@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[*]" 1
+//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].name" '"F"'
+//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
+//@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
+//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
+//@ count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
 pub fn generics<F: Foo>(f: F) {}
 
-// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
-// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
-// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
-// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\"
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]"
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\"
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]"
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\"
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
-// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\"
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]"
 pub fn where_clase<F, G, H>(f: F, g: G, h: H)
 where
     F: Foo,
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index 8e82efef4be..07dc691b933 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -1,13 +1,13 @@
 // ignore-tidy-linelength
 
-// @count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2
+//@ count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2
 
-// @set foo = "$.index[*][?(@.name=='Foo')].id"
+//@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
-// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
-// @count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
-// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
+//@ count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
 pub fn get_foo() -> impl Foo {
     Fooer {}
 }
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index 44dc6d854aa..43fc7279ded 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -1,22 +1,22 @@
 // ignore-tidy-linelength
 
-// @set wham_id = "$.index[*][?(@.name=='Wham')].id"
+//@ set wham_id = "$.index[*][?(@.name=='Wham')].id"
 pub trait Wham {}
 
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
+//@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
 pub fn one_generic_param_fn<T: Wham>(w: T) {}
 
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
+//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
 pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs
index 55f24797ac0..3fa423bcefd 100644
--- a/tests/rustdoc-json/fns/pattern_arg.rs
+++ b/tests/rustdoc-json/fns/pattern_arg.rs
@@ -1,7 +1,7 @@
-// @is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
+//@ is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
 pub fn fst<X, Y>((x, _): (X, Y)) -> X {
     x
 }
 
-// @is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
+//@ is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
 pub fn drop_int(_: i32) {}
diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs
index 6293b811226..beb1b4ccd10 100644
--- a/tests/rustdoc-json/fns/qualifiers.rs
+++ b/tests/rustdoc-json/fns/qualifiers.rs
@@ -1,33 +1,33 @@
 //@ edition:2018
 
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const"  false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const"  false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
 pub fn nothing_fn() {}
 
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async"  false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const"  false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
 pub unsafe fn unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.async"  false
-// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.const"  true
-// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.async"  false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.const"  true
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
 pub const fn const_fn() {}
 
-// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.async"  true
-// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.const"  false
-// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.async"  true
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.const"  false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
 pub async fn async_fn() {}
 
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async"  true
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const"  false
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async"  true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const"  false
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
 pub async unsafe fn async_unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async"  false
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const"  true
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async"  false
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const"  true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
 pub const unsafe fn const_unsafe_fn() {}
 
 // It's impossible for a function to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs
index e8a7dce8b0a..67bc46a8740 100644
--- a/tests/rustdoc-json/fns/return_type_alias.rs
+++ b/tests/rustdoc-json/fns/return_type_alias.rs
@@ -1,9 +1,9 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/104851>
 
-/// @set foo = "$.index[*][?(@.name=='Foo')].id"
+///@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub type Foo = i32;
 
-// @is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
+//@ is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
 pub fn demo() -> Foo {
     42
 }
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index 56d6e7a49db..8a38230bb5d 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -3,32 +3,32 @@
 pub trait Display {}
 
 pub trait LendingIterator {
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\"
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1
+    //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1
+    //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\"
+    //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1
+    //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\"
+    //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
+    //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1
     type LendingItem<'a>: Display
     where
         Self: 'a;
 
-    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
-    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
-    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
+    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
+    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
     fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
 }
 
 pub trait Iterator {
-    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
+    //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0
+    //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0
+    //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
     type Item: Display;
 
-    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
-    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
-    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
+    //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
+    //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
     fn next<'a>(&'a self) -> Self::Item;
 }
diff --git a/tests/rustdoc-json/generic_impl.rs b/tests/rustdoc-json/generic_impl.rs
index 31f41d0f335..e7a5d2a78c1 100644
--- a/tests/rustdoc-json/generic_impl.rs
+++ b/tests/rustdoc-json/generic_impl.rs
@@ -1,8 +1,8 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/97986>.
 
-// @has "$.index[*][?(@.name=='f')]"
-// @has "$.index[*][?(@.name=='AssocTy')]"
-// @has "$.index[*][?(@.name=='AssocConst')]"
+//@ has "$.index[*][?(@.name=='f')]"
+//@ has "$.index[*][?(@.name=='AssocTy')]"
+//@ has "$.index[*][?(@.name=='AssocConst')]"
 
 pub mod m {
     pub struct S;
diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs
index 7de1ed78f2f..a67a99a37cb 100644
--- a/tests/rustdoc-json/glob_import.rs
+++ b/tests/rustdoc-json/glob_import.rs
@@ -2,8 +2,8 @@
 
 #![no_std]
 
-// @has "$.index[*][?(@.name=='glob')]"
-// @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
+//@ has "$.index[*][?(@.name=='glob')]"
+//@ has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
 
 mod m1 {
     pub fn f() {}
diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs
index bf98868d145..f9fee788ffe 100644
--- a/tests/rustdoc-json/impl-trait-precise-capturing.rs
+++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs
@@ -1,6 +1,6 @@
 #![feature(precise_capturing)]
 
-// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\"
-// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\"
-// @is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\"
 pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs
index 96c3ab08b99..84a1e6ed7d5 100644
--- a/tests/rustdoc-json/impls/auto.rs
+++ b/tests/rustdoc-json/impls/auto.rs
@@ -15,8 +15,8 @@ impl Foo {
 }
 
 // Testing spans, so all tests below code
-// @is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]"
-// @is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]"
+//@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]"
+//@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]"
 // FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91
 // is "$.index[*][?(@.inner.impl.synthetic==true)].span" null
 pub struct Foo;
diff --git a/tests/rustdoc-json/impls/blanket_with_local.rs b/tests/rustdoc-json/impls/blanket_with_local.rs
index 2fb4a84b9a6..de92dafae0b 100644
--- a/tests/rustdoc-json/impls/blanket_with_local.rs
+++ b/tests/rustdoc-json/impls/blanket_with_local.rs
@@ -1,11 +1,11 @@
 // Test for the ICE in rust/83718
 // A blanket impl plus a local type together shouldn't result in mismatched ID issues
 
-// @has "$.index[*][?(@.name=='Load')]"
+//@ has "$.index[*][?(@.name=='Load')]"
 pub trait Load {
-    // @has "$.index[*][?(@.name=='load')]"
+    //@ has "$.index[*][?(@.name=='load')]"
     fn load() {}
-    // @has "$.index[*][?(@.name=='write')]"
+    //@ has "$.index[*][?(@.name=='write')]"
     fn write(self) {}
 }
 
@@ -14,5 +14,5 @@ impl<P> Load for P {
     fn write(self) {}
 }
 
-// @has "$.index[*][?(@.name=='Wrapper')]"
+//@ has "$.index[*][?(@.name=='Wrapper')]"
 pub struct Wrapper {}
diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs
index d5265ba11bd..20690f26851 100644
--- a/tests/rustdoc-json/impls/foreign_for_local.rs
+++ b/tests/rustdoc-json/impls/foreign_for_local.rs
@@ -3,16 +3,16 @@ extern crate foreign_trait;
 
 /// ForeignTrait id hack
 pub use foreign_trait::ForeignTrait as _;
-// @set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
+//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
 
 pub struct LocalStruct;
-// @set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
+//@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
 
 /// foreign for local
 impl foreign_trait::ForeignTrait for LocalStruct {}
 
-// @set impl = "$.index[*][?(@.docs=='foreign for local')].id"
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait
+//@ set impl = "$.index[*][?(@.docs=='foreign for local')].id"
+//@ is "$.index[*][?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct
+//@ is "$.index[*][?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait
 
-// @has "$.index[*][?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl
+//@ has "$.index[*][?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl
diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs
index d3c15cd23e4..293dd965804 100644
--- a/tests/rustdoc-json/impls/impl_item_visibility.rs
+++ b/tests/rustdoc-json/impls/impl_item_visibility.rs
@@ -4,13 +4,13 @@ pub struct Foo;
 impl Foo {
     fn baz() {}
 }
-// @!has '$.index[*][?(@.docs=="impl Foo priv")]'
+//@ !has '$.index[*][?(@.docs=="impl Foo priv")]'
 
 /// impl Foo pub
 impl Foo {
     pub fn qux() {}
 }
-// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
 
 /// impl Foo hidden
 impl Foo {
@@ -18,4 +18,4 @@ impl Foo {
     pub fn __quazl() {}
 }
 // FIXME(#111564): Is this the right behaviour?
-// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
index 431220a473d..77ee717b03a 100644
--- a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
@@ -7,13 +7,13 @@ impl Foo {
     fn baz() {}
 }
 // FIXME(#111564): Is this the right behaviour?
-// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
 
 /// impl Foo pub
 impl Foo {
     pub fn qux() {}
 }
-// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
 
 /// impl Foo hidden
 impl Foo {
@@ -21,4 +21,4 @@ impl Foo {
     pub fn __quazl() {}
 }
 // FIXME(#111564): Is this the right behaviour?
-// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
index aa1eb989665..80c47eee6cb 100644
--- a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
@@ -6,13 +6,13 @@ pub struct Foo;
 impl Foo {
     fn baz() {}
 }
-// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
 
 /// impl Foo pub
 impl Foo {
     pub fn qux() {}
 }
-// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
 
 /// impl Foo hidden
 impl Foo {
@@ -20,4 +20,4 @@ impl Foo {
     pub fn __quazl() {}
 }
 // FIXME(#111564): Is this the right behaviour?
-// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
+//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs
index 3da03df2546..e386252e83b 100644
--- a/tests/rustdoc-json/impls/import_from_private.rs
+++ b/tests/rustdoc-json/impls/import_from_private.rs
@@ -1,20 +1,20 @@
 // https://github.com/rust-lang/rust/issues/100252
 
 mod bar {
-    // @set baz = "$.index[*][?(@.name == 'Baz')].id"
+    //@ set baz = "$.index[*][?(@.name == 'Baz')].id"
     pub struct Baz;
-    // @set impl = "$.index[*][?(@.docs == 'impl')].id"
+    //@ set impl = "$.index[*][?(@.docs == 'impl')].id"
     /// impl
     impl Baz {
-        // @set doit = "$.index[*][?(@.name == 'doit')].id"
+        //@ set doit = "$.index[*][?(@.name == 'doit')].id"
         pub fn doit() {}
     }
 }
 
-// @set import = "$.index[*][?(@.inner.import)].id"
+//@ set import = "$.index[*][?(@.inner.import)].id"
 pub use bar::Baz;
 
-// @is "$.index[*].inner.module.items[*]" $import
-// @is "$.index[*].inner.import.id" $baz
-// @has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl
-// @is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit
+//@ is "$.index[*].inner.module.items[*]" $import
+//@ is "$.index[*].inner.import.id" $baz
+//@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl
+//@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit
diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs
index 7857626d66e..4a313044920 100644
--- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs
+++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs
@@ -1,8 +1,8 @@
-// @has "$.index[*][?(@.docs=='Here')]"
-// @!has "$.index[*][?(@.docs=='Not Here')]"
-// @!has "$.index[*][?(@.name == 'HiddenPubStruct')]"
-// @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]"
-// @has "$.index[*][?(@.name=='PubTrait')]"
+//@ has "$.index[*][?(@.docs=='Here')]"
+//@ !has "$.index[*][?(@.docs=='Not Here')]"
+//@ !has "$.index[*][?(@.name == 'HiddenPubStruct')]"
+//@ has "$.index[*][?(@.name == 'NotHiddenPubStruct')]"
+//@ has "$.index[*][?(@.name=='PubTrait')]"
 pub trait PubTrait {}
 
 #[doc(hidden)]
diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs
index c09c916a530..d3f2180f22c 100644
--- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs
+++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs
@@ -1,8 +1,8 @@
 //@ compile-flags: --document-hidden-items
 
-// @has "$.index[*][?(@.name == 'HiddenPubStruct')]"
-// @has "$.index[*][?(@.inner.impl)]"
-// @has "$.index[*][?(@.name=='PubTrait')]"
+//@ has "$.index[*][?(@.name == 'HiddenPubStruct')]"
+//@ has "$.index[*][?(@.inner.impl)]"
+//@ has "$.index[*][?(@.name=='PubTrait')]"
 pub trait PubTrait {}
 
 #[doc(hidden)]
diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs
index 97db9c93a0f..a3f05818842 100644
--- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs
+++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs
@@ -1,21 +1,21 @@
-// @has "$.index[*][?(@.name=='PubTrait')]"
+//@ has "$.index[*][?(@.name=='PubTrait')]"
 pub trait PubTrait {}
 
 #[doc(hidden)]
 pub mod hidden {
-    // @!has "$.index[*][?(@.name == 'HiddenPubStruct')]"
+    //@ !has "$.index[*][?(@.name == 'HiddenPubStruct')]"
     pub struct HiddenPubStruct;
 
-    // @!has "$.index[*][?(@.docs == 'Not Here')]"
+    //@ !has "$.index[*][?(@.docs == 'Not Here')]"
     /// Not Here
     impl crate::PubTrait for HiddenPubStruct {}
 }
 
 pub mod not_hidden {
-    // @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]"
+    //@ has "$.index[*][?(@.name == 'NotHiddenPubStruct')]"
     pub struct NotHiddenPubStruct;
 
-    // @has "$.index[*][?(@.docs == 'Here')]"
+    //@ has "$.index[*][?(@.docs == 'Here')]"
     /// Here
     impl crate::PubTrait for NotHiddenPubStruct {}
 }
diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs
index 019f7d625cb..bd49269104f 100644
--- a/tests/rustdoc-json/impls/local_for_foreign.rs
+++ b/tests/rustdoc-json/impls/local_for_foreign.rs
@@ -3,16 +3,16 @@ extern crate foreign_struct;
 
 /// ForeignStruct id hack
 pub use foreign_struct::ForeignStruct as _;
-// @set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
+//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
 
 pub trait LocalTrait {}
-// @set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
+//@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
 
 /// local for foreign
 impl LocalTrait for foreign_struct::ForeignStruct {}
 
-// @set impl = "$.index[*][?(@.docs=='local for foreign')].id"
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct
+//@ set impl = "$.index[*][?(@.docs=='local for foreign')].id"
+//@ is "$.index[*][?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait
+//@ is "$.index[*][?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct
 
-// @is "$.index[*][?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl
+//@ is "$.index[*][?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl
diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs
index 015e89c2281..1d141d6e4de 100644
--- a/tests/rustdoc-json/impls/local_for_local.rs
+++ b/tests/rustdoc-json/impls/local_for_local.rs
@@ -1,12 +1,12 @@
-// @set struct = "$.index[*][?(@.name=='Struct')].id"
+//@ set struct = "$.index[*][?(@.name=='Struct')].id"
 pub struct Struct;
-// @set trait = "$.index[*][?(@.name=='Trait')].id"
+//@ set trait = "$.index[*][?(@.name=='Trait')].id"
 pub trait Trait {}
-// @set impl = "$.index[*][?(@.docs=='impl')].id"
+//@ set impl = "$.index[*][?(@.docs=='impl')].id"
 /// impl
 impl Trait for Struct {}
 
-// @has "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl
-// @is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl
-// @is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait
-// @is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct
+//@ has "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl
+//@ is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl
+//@ is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait
+//@ is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct
diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs
index acc3a879fe1..8c1eb044eae 100644
--- a/tests/rustdoc-json/impls/local_for_local_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs
@@ -1,18 +1,18 @@
 #![feature(rustc_attrs)]
 
-// @set Local = "$.index[*][?(@.name=='Local')].id"
+//@ set Local = "$.index[*][?(@.name=='Local')].id"
 pub trait Local {}
 
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.trait.id" $Local
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"'
+//@ is "$.index[*][?(@.docs=='Local for bool')].inner.impl.trait.id" $Local
+//@ is "$.index[*][?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"'
 /// Local for bool
 impl Local for bool {}
 
-// @set impl =  "$.index[*][?(@.docs=='Local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
+//@ set impl =  "$.index[*][?(@.docs=='Local for bool')].id"
+//@ is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 
 // FIXME(#101695): Test bool's `impls` include "Local for bool"
-// @has "$.index[*][?(@.name=='bool')]"
+//@ has "$.index[*][?(@.name=='bool')]"
 #[rustc_doc_primitive = "bool"]
 /// Boolean docs
 mod prim_bool {}
diff --git a/tests/rustdoc-json/impls/local_for_primitive.rs b/tests/rustdoc-json/impls/local_for_primitive.rs
index 85278c0e08c..56d930ca5c4 100644
--- a/tests/rustdoc-json/impls/local_for_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_primitive.rs
@@ -1,7 +1,7 @@
-// @set local = "$.index[*][?(@.name=='Local')]"
+//@ set local = "$.index[*][?(@.name=='Local')]"
 pub trait Local {}
 
-// @set impl = "$.index[*][?(@.docs=='local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
+//@ set impl = "$.index[*][?(@.docs=='local for bool')].id"
+//@ is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 /// local for bool
 impl Local for bool {}
diff --git a/tests/rustdoc-json/intra-doc-links/foreign_variant.rs b/tests/rustdoc-json/intra-doc-links/foreign_variant.rs
index 40e1f6b1f0a..251c4884fbb 100644
--- a/tests/rustdoc-json/intra-doc-links/foreign_variant.rs
+++ b/tests/rustdoc-json/intra-doc-links/foreign_variant.rs
@@ -8,6 +8,6 @@ pub struct Local;
 /// local impl
 impl enum_variant_in_trait_method::Trait for Local {}
 
-// @!has "$.index[*][?(@.name == 'Trait')]"
-// @!has "$.index[*][?(@.name == 'method')]"
-// @count "$.index[*][?(@.docs == 'local impl')].inner.items[*]" 0
+//@ !has "$.index[*][?(@.name == 'Trait')]"
+//@ !has "$.index[*][?(@.name == 'method')]"
+//@ count "$.index[*][?(@.docs == 'local impl')].inner.items[*]" 0
diff --git a/tests/rustdoc-json/intra-doc-links/non_page.rs b/tests/rustdoc-json/intra-doc-links/non_page.rs
index 73c5334bb5c..00987d93c1e 100644
--- a/tests/rustdoc-json/intra-doc-links/non_page.rs
+++ b/tests/rustdoc-json/intra-doc-links/non_page.rs
@@ -7,17 +7,17 @@
 //! [`Trait::ASSOC_CONST`]
 //! [`Trait::method`]
 
-// @set struct_field = "$.index[*][?(@.name=='struct_field')].id"
-// @set Variant = "$.index[*][?(@.name=='Variant')].id"
-// @set AssocType = "$.index[*][?(@.name=='AssocType')].id"
-// @set ASSOC_CONST = "$.index[*][?(@.name=='ASSOC_CONST')].id"
-// @set method = "$.index[*][?(@.name=='method')].id"
+//@ set struct_field = "$.index[*][?(@.name=='struct_field')].id"
+//@ set Variant = "$.index[*][?(@.name=='Variant')].id"
+//@ set AssocType = "$.index[*][?(@.name=='AssocType')].id"
+//@ set ASSOC_CONST = "$.index[*][?(@.name=='ASSOC_CONST')].id"
+//@ set method = "$.index[*][?(@.name=='method')].id"
 
-// @is "$.index[*][?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field
-// @is "$.index[*][?(@.name=='non_page')].links['`Enum::Variant`']" $Variant
-// @is "$.index[*][?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType
-// @is "$.index[*][?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST
-// @is "$.index[*][?(@.name=='non_page')].links['`Trait::method`']" $method
+//@ is "$.index[*][?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field
+//@ is "$.index[*][?(@.name=='non_page')].links['`Enum::Variant`']" $Variant
+//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType
+//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST
+//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::method`']" $method
 
 pub struct Struct {
     pub struct_field: i32,
diff --git a/tests/rustdoc-json/intra-doc-links/user_written.rs b/tests/rustdoc-json/intra-doc-links/user_written.rs
index 6871dfea44a..c3f9df95a8f 100644
--- a/tests/rustdoc-json/intra-doc-links/user_written.rs
+++ b/tests/rustdoc-json/intra-doc-links/user_written.rs
@@ -4,5 +4,5 @@
 /// To test rustdoc json
 pub fn foo() {}
 
-// @set foo = "$.index[*][?(@.name=='foo')].id"
-// @is "$.index[*][?(@.name=='user_written')].links['foo#reasons']" $foo
+//@ set foo = "$.index[*][?(@.name=='foo')].id"
+//@ is "$.index[*][?(@.name=='user_written')].links['foo#reasons']" $foo
diff --git a/tests/rustdoc-json/keyword.rs b/tests/rustdoc-json/keyword.rs
index 3446b212c56..7a820cd1487 100644
--- a/tests/rustdoc-json/keyword.rs
+++ b/tests/rustdoc-json/keyword.rs
@@ -6,15 +6,15 @@
 #![feature(rustdoc_internals)]
 #![no_std]
 
-// @!has "$.index[*][?(@.name=='match')]"
-// @has "$.index[*][?(@.name=='foo')]"
+//@ !has "$.index[*][?(@.name=='match')]"
+//@ has "$.index[*][?(@.name=='foo')]"
 
 #[doc(keyword = "match")]
 /// this is a test!
 pub mod foo {}
 
-// @!has "$.index[*][?(@.name=='hello')]"
-// @!has "$.index[*][?(@.name=='bar')]"
+//@ !has "$.index[*][?(@.name=='hello')]"
+//@ !has "$.index[*][?(@.name=='bar')]"
 #[doc(keyword = "hello")]
 /// hello
 mod bar {}
diff --git a/tests/rustdoc-json/keyword_private.rs b/tests/rustdoc-json/keyword_private.rs
index 1c2b7d02155..7a030041f7c 100644
--- a/tests/rustdoc-json/keyword_private.rs
+++ b/tests/rustdoc-json/keyword_private.rs
@@ -3,18 +3,18 @@
 //@ compile-flags: --document-private-items
 #![feature(rustdoc_internals)]
 
-// @!has "$.index[*][?(@.name=='match')]"
-// @has  "$.index[*][?(@.name=='foo')]"
-// @is   "$.index[*][?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]'
-// @is   "$.index[*][?(@.name=='foo')].docs" '"this is a test!"'
+//@ !has "$.index[*][?(@.name=='match')]"
+//@ has  "$.index[*][?(@.name=='foo')]"
+//@ is   "$.index[*][?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]'
+//@ is   "$.index[*][?(@.name=='foo')].docs" '"this is a test!"'
 #[doc(keyword = "match")]
 /// this is a test!
 pub mod foo {}
 
-// @!has "$.index[*][?(@.name=='hello')]"
-// @has "$.index[*][?(@.name=='bar')]"
-// @is   "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"hello\")]"]'
-// @is   "$.index[*][?(@.name=='bar')].docs" '"hello"'
+//@ !has "$.index[*][?(@.name=='hello')]"
+//@ has "$.index[*][?(@.name=='bar')]"
+//@ is   "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"hello\")]"]'
+//@ is   "$.index[*][?(@.name=='bar')].docs" '"hello"'
 #[doc(keyword = "hello")]
 /// hello
 mod bar {}
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index dccad41a861..39f791d2b09 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -1,26 +1,26 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name"  \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
+//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name"  \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+//@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
+//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
 
-// @count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
+//@ count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
 
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
+//@ 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 }
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index 549e4c200dc..c98555d5737 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -1,18 +1,18 @@
 // ignore-tidy-linelength
 
-// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" []
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].name" '"T"'
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
-// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
+//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" []
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].name" '"T"'
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" []
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
+//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
 pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/tests/rustdoc-json/lifetime/outlives_in_param.rs b/tests/rustdoc-json/lifetime/outlives_in_param.rs
index f6db93c9183..3eee6d9ea46 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_param.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_param.rs
@@ -1,8 +1,8 @@
 // ignore-tidy-linelength
 
-// @count '$.index[*][?(@.name=="outlives")].inner.function.generics.params[*]' 2
-// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\"
-// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' []
-// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].name' '"T"'
-// @is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].kind.type.bounds' '[{"outlives": "'\''a"}]'
+//@ count '$.index[*][?(@.name=="outlives")].inner.function.generics.params[*]' 2
+//@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\"
+//@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' []
+//@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].name' '"T"'
+//@ is    '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].kind.type.bounds' '[{"outlives": "'\''a"}]'
 pub fn outlives<'a, T: 'a>() {}
diff --git a/tests/rustdoc-json/lifetime/outlives_in_where.rs b/tests/rustdoc-json/lifetime/outlives_in_where.rs
index ca3e1a150ce..a8f88be01da 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_where.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_where.rs
@@ -1,22 +1,22 @@
 // ignore-tidy-linelength
 
-// @is '$.index[*][?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]'
+//@ is '$.index[*][?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]'
 pub fn on_lifetimes<'a, 'b, 'c, 'all>()
 where
     'all: 'a + 'b + 'c,
 {
 }
 
-// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[*]' 2
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].name' \"\'a\"
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].kind.lifetime.outlives' []
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].name' '"T"'
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
-// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[*]' 1
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.type.generic' '"T"'
-// @count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]' 1
-// @is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].outlives' \"\'a\"
+//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[*]' 2
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].name' \"\'a\"
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].kind.lifetime.outlives' []
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].name' '"T"'
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' []
+//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[*]' 1
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.type.generic' '"T"'
+//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]' 1
+//@ is    '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].outlives' \"\'a\"
 pub fn on_trait<'a, T>()
 where
     T: 'a,
diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs
index 917e9e0790c..6d33dfca373 100644
--- a/tests/rustdoc-json/methods/abi.rs
+++ b/tests/rustdoc-json/methods/abi.rs
@@ -2,51 +2,51 @@
 
 #![feature(abi_vectorcall)]
 
-// @has "$.index[*][?(@.name=='Foo')]"
+//@ has "$.index[*][?(@.name=='Foo')]"
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
+    //@ is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
     pub fn abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
+    //@ is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     pub extern "C" fn abi_c() {}
 
-    // @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
+    //@ is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     pub extern "system" fn abi_system() {}
 
-    // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
+    //@ is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     pub extern "C-unwind" fn abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
+    //@ is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     pub extern "system-unwind" fn abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
+    //@ is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     pub extern "vectorcall" fn abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
+    //@ is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
 }
 
 pub trait Bar {
-    // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\"
+    //@ is "$.index[*][?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\"
     fn trait_abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
+    //@ is "$.index[*][?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     extern "C" fn trait_abi_c() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
+    //@ is "$.index[*][?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     extern "system" fn trait_abi_system() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
+    //@ is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     extern "C-unwind" fn trait_abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
+    //@ is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     extern "system-unwind" fn trait_abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
+    //@ is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     extern "vectorcall" fn trait_abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
+    //@ is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {}
 }
diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs
index dac90b7ff6f..8de8cfd4c15 100644
--- a/tests/rustdoc-json/methods/qualifiers.rs
+++ b/tests/rustdoc-json/methods/qualifiers.rs
@@ -3,34 +3,34 @@
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
-    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.const"  true
-    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.const"  true
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
     pub const fn const_meth() {}
 
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async"  false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const"  false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
     pub fn nothing_meth() {}
 
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async"  false
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const"  false
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
     pub unsafe fn unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.async"  true
-    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.const"  false
-    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.async"  true
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.const"  false
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
     pub async fn async_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async"  true
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const"  false
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async"  true
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const"  false
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
     pub async unsafe fn async_unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async"  false
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const"  true
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async"  false
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const"  true
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
     pub const unsafe fn const_unsafe_meth() {}
 
     // It's impossible for a method to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs
index c0a47c467e3..ae2d9fe0ac5 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -1,32 +1,32 @@
 //@ edition:2018
 //@ compile-flags: --crate-version 1.0.0
 
-// @is "$.crate_version" \"1.0.0\"
-// @has "$.index[*][?(@.name=='nested')].inner.module"
-// @is "$.index[*][?(@.name=='nested')].inner.module.is_crate" true
+//@ is "$.crate_version" \"1.0.0\"
+//@ has "$.index[*][?(@.name=='nested')].inner.module"
+//@ is "$.index[*][?(@.name=='nested')].inner.module.is_crate" true
 
-// @set l1_id = "$.index[*][?(@.name=='l1')].id"
-// @ismany "$.index[*][?(@.name=='nested')].inner.module.items[*]" $l1_id
+//@ set l1_id = "$.index[*][?(@.name=='l1')].id"
+//@ ismany "$.index[*][?(@.name=='nested')].inner.module.items[*]" $l1_id
 
-// @has "$.index[*][?(@.name=='l1')].inner.module"
-// @is "$.index[*][?(@.name=='l1')].inner.module.is_crate" false
+//@ has "$.index[*][?(@.name=='l1')].inner.module"
+//@ is "$.index[*][?(@.name=='l1')].inner.module.is_crate" false
 pub mod l1 {
-    // @has "$.index[*][?(@.name=='l3')].inner.module"
-    // @is "$.index[*][?(@.name=='l3')].inner.module.is_crate" false
-    // @set l3_id = "$.index[*][?(@.name=='l3')].id"
+    //@ has "$.index[*][?(@.name=='l3')].inner.module"
+    //@ is "$.index[*][?(@.name=='l3')].inner.module.is_crate" false
+    //@ set l3_id = "$.index[*][?(@.name=='l3')].id"
     pub mod l3 {
 
-        // @has "$.index[*][?(@.name=='L4')].inner.struct"
-        // @is "$.index[*][?(@.name=='L4')].inner.struct.kind" '"unit"'
-        // @set l4_id = "$.index[*][?(@.name=='L4')].id"
-        // @ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
+        //@ has "$.index[*][?(@.name=='L4')].inner.struct"
+        //@ is "$.index[*][?(@.name=='L4')].inner.struct.kind" '"unit"'
+        //@ set l4_id = "$.index[*][?(@.name=='L4')].id"
+        //@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
         pub struct L4;
     }
-    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
-    // @is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
-    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
-    // @is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
-    // @set l4_use_id = "$.index[*][?(@.inner.import)].id"
+    //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    //@ is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
+    //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    //@ is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
+    //@ set l4_use_id = "$.index[*][?(@.inner.import)].id"
     pub use l3::L4;
 }
-// @ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
+//@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index 6f0732646ca..06f6e10aa85 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -7,11 +7,11 @@ pub trait Trait {}
 
 pub struct Wrapper<T_>(std::marker::PhantomData<T_>);
 
-// @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
-// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
-// @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 } }'
+//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
+//@ 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,
diff --git a/tests/rustdoc-json/output_generics.rs b/tests/rustdoc-json/output_generics.rs
index e9df64b79e3..3454f421636 100644
--- a/tests/rustdoc-json/output_generics.rs
+++ b/tests/rustdoc-json/output_generics.rs
@@ -2,11 +2,11 @@
 
 // This is a regression test for #98009.
 
-// @has "$.index[*][?(@.name=='this_compiles')]"
-// @has "$.index[*][?(@.name=='this_does_not')]"
-// @has "$.index[*][?(@.name=='Events')]"
-// @has "$.index[*][?(@.name=='Other')]"
-// @has "$.index[*][?(@.name=='Trait')]"
+//@ has "$.index[*][?(@.name=='this_compiles')]"
+//@ has "$.index[*][?(@.name=='this_does_not')]"
+//@ has "$.index[*][?(@.name=='Events')]"
+//@ has "$.index[*][?(@.name=='Other')]"
+//@ has "$.index[*][?(@.name=='Trait')]"
 
 struct Events<R>(R);
 
diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs
index 562c7e4d79b..b10ae45f3ec 100644
--- a/tests/rustdoc-json/primitives/local_primitive.rs
+++ b/tests/rustdoc-json/primitives/local_primitive.rs
@@ -11,11 +11,11 @@
 #[rustc_doc_primitive = "i32"]
 mod prim_i32 {}
 
-// @set local_i32 = "$.index[*][?(@.name=='i32')].id"
+//@ set local_i32 = "$.index[*][?(@.name=='i32')].id"
 
-// @has "$.index[*][?(@.name=='local_primitive')]"
-// @ismany "$.index[*][?(@.name=='local_primitive')].inner.module.items[*]" $local_i32
-// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
+//@ has "$.index[*][?(@.name=='local_primitive')]"
+//@ ismany "$.index[*][?(@.name=='local_primitive')].inner.module.items[*]" $local_i32
+//@ is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
 
 // Let's ensure the `prim_i32` module isn't present in the output JSON:
-// @!has "$.index[*][?(@.name=='prim_i32')]"
+//@ !has "$.index[*][?(@.name=='prim_i32')]"
diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs
index 4b7b7646b89..77d1d68f8e4 100644
--- a/tests/rustdoc-json/primitives/primitive_impls.rs
+++ b/tests/rustdoc-json/primitives/primitive_impls.rs
@@ -4,23 +4,23 @@
 #![no_core]
 #![rustc_coherence_is_core]
 
-// @set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id"
+//@ set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id"
 
 /// Only core can do this
 impl i32 {
-    // @set identity = "$.index[*][?(@.docs=='Do Nothing')].id"
+    //@ set identity = "$.index[*][?(@.docs=='Do Nothing')].id"
 
     /// Do Nothing
     pub fn identity(self) -> Self {
         self
     }
 
-    // @is "$.index[*][?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity
+    //@ is "$.index[*][?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity
 }
 
-// @set Trait = "$.index[*][?(@.name=='Trait')].id"
+//@ set Trait = "$.index[*][?(@.name=='Trait')].id"
 pub trait Trait {}
-// @set impl_trait_for_i32 = "$.index[*][?(@.docs=='impl Trait for i32')].id"
+//@ set impl_trait_for_i32 = "$.index[*][?(@.docs=='impl Trait for i32')].id"
 /// impl Trait for i32
 impl Trait for i32 {}
 
@@ -28,7 +28,7 @@ impl Trait for i32 {}
 #[rustc_doc_primitive = "i32"]
 mod prim_i32 {}
 
-// @set i32 = "$.index[*][?(@.docs=='i32')].id"
-// @is "$.index[*][?(@.docs=='i32')].name" '"i32"'
-// @is "$.index[*][?(@.docs=='i32')].inner.primitive.name" '"i32"'
-// @ismany "$.index[*][?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32
+//@ set i32 = "$.index[*][?(@.docs=='i32')].id"
+//@ is "$.index[*][?(@.docs=='i32')].name" '"i32"'
+//@ is "$.index[*][?(@.docs=='i32')].inner.primitive.name" '"i32"'
+//@ ismany "$.index[*][?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32
diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs
index e4ffbdf0295..5e5f3974ab3 100644
--- a/tests/rustdoc-json/primitives/primitive_overloading.rs
+++ b/tests/rustdoc-json/primitives/primitive_overloading.rs
@@ -4,8 +4,8 @@
 
 #![feature(rustc_attrs)]
 
-// @has "$.index[*][?(@.name=='usize')]"
-// @has "$.index[*][?(@.name=='prim')]"
+//@ has "$.index[*][?(@.name=='usize')]"
+//@ has "$.index[*][?(@.name=='prim')]"
 
 #[rustc_doc_primitive = "usize"]
 /// This is the built-in type `usize`.
diff --git a/tests/rustdoc-json/primitives/primitive_type.rs b/tests/rustdoc-json/primitives/primitive_type.rs
index 89c5d06c0b2..21ef5ab7196 100644
--- a/tests/rustdoc-json/primitives/primitive_type.rs
+++ b/tests/rustdoc-json/primitives/primitive_type.rs
@@ -1,17 +1,17 @@
 #![feature(never_type)]
 
-// @is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='PrimNever')].inner.type_alias.type.primitive" \"never\"
+//@ is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
+//@ is "$.index[*][?(@.name=='PrimNever')].inner.type_alias.type.primitive" \"never\"
 pub type PrimNever = !;
 
-// @is "$.index[*][?(@.name=='PrimStr')].inner.type_alias.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='PrimStr')].inner.type_alias.type.primitive" \"str\"
 pub type PrimStr = str;
 
-// @is "$.index[*][?(@.name=='PrimBool')].inner.type_alias.type.primitive" \"bool\"
+//@ is "$.index[*][?(@.name=='PrimBool')].inner.type_alias.type.primitive" \"bool\"
 pub type PrimBool = bool;
 
-// @is "$.index[*][?(@.name=='PrimChar')].inner.type_alias.type.primitive" \"char\"
+//@ is "$.index[*][?(@.name=='PrimChar')].inner.type_alias.type.primitive" \"char\"
 pub type PrimChar = char;
 
-// @is "$.index[*][?(@.name=='PrimU8')].inner.type_alias.type.primitive" \"u8\"
+//@ is "$.index[*][?(@.name=='PrimU8')].inner.type_alias.type.primitive" \"u8\"
 pub type PrimU8 = u8;
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index 7f5ffc04309..e97db42705f 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -5,16 +5,16 @@
 #[rustc_doc_primitive = "usize"]
 mod usize {}
 
-// @set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id"
+//@ set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id"
 
-// @has "$.index[*][?(@.name=='ilog10')]"
-// @!is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id
-// @has "$.index[*][?(@.name=='checked_add')]"
-// @!is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
-// @!has "$.index[*][?(@.name=='is_ascii_uppercase')]"
+//@ has "$.index[*][?(@.name=='ilog10')]"
+//@ !is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id
+//@ has "$.index[*][?(@.name=='checked_add')]"
+//@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
+//@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]"
 
-// @is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
+//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
 pub use i32 as my_i32;
 
-// @is "$.index[*].inner.import[?(@.name=='u32')].id" null
+//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null
 pub use u32;
diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
index 7326649d904..512c741798b 100644
--- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
+++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
@@ -5,7 +5,7 @@
 #[doc(inline)]
 pub extern crate enum_with_discriminant;
 
-// @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @has '$.index[*][?(@.name == "enum_with_discriminant")].inner.extern_crate'
-// @set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id'
-// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant
+//@ !has '$.index[*][?(@.docs == "Should not be inlined")]'
+//@ has '$.index[*][?(@.name == "enum_with_discriminant")].inner.extern_crate'
+//@ set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id'
+//@ is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant
diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
index a8f5500d629..6e9b5044816 100644
--- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
+++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
@@ -4,5 +4,5 @@
 
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\"
+//@ is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\"
 pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has
diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs
index 07497f6d7be..a0b4cb8ab2c 100644
--- a/tests/rustdoc-json/reexport/extern_crate_glob.rs
+++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs
@@ -5,7 +5,7 @@ extern crate enum_with_discriminant;
 #[doc(inline)]
 pub use enum_with_discriminant::*;
 
-// @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
-// @set use = '$.index[*][?(@.inner.import)].id'
-// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
+//@ !has '$.index[*][?(@.docs == "Should not be inlined")]'
+//@ is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
+//@ set use = '$.index[*][?(@.inner.import)].id'
+//@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs
index 9a75f4c0cf3..3a034afab65 100644
--- a/tests/rustdoc-json/reexport/glob_collision.rs
+++ b/tests/rustdoc-json/reexport/glob_collision.rs
@@ -1,27 +1,27 @@
 // Regression test for https://github.com/rust-lang/rust/issues/100973
 
-// @set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id"
-// @is "$.index[*][?(@.name == 'm1')].inner.module.items" []
-// @is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true
+//@ set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id"
+//@ is "$.index[*][?(@.name == 'm1')].inner.module.items" []
+//@ is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true
 mod m1 {
     pub fn f() {}
 }
-// @set m2 = "$.index[*][?(@.name == 'm2' && @.inner.module)].id"
-// @is "$.index[*][?(@.name == 'm2')].inner.module.items" []
-// @is "$.index[*][?(@.name == 'm2')].inner.module.is_stripped" true
+//@ set m2 = "$.index[*][?(@.name == 'm2' && @.inner.module)].id"
+//@ is "$.index[*][?(@.name == 'm2')].inner.module.items" []
+//@ is "$.index[*][?(@.name == 'm2')].inner.module.is_stripped" true
 mod m2 {
     pub fn f(_: u8) {}
 }
 
-// @set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
-// @is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
-// @is "$.index[*].inner.import[?(@.name=='m1')].glob" true
+//@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
+//@ is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
+//@ is "$.index[*].inner.import[?(@.name=='m1')].glob" true
 /// m1 re-export
 pub use m1::*;
-// @set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
-// @is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
-// @is "$.index[*].inner.import[?(@.name=='m2')].glob" true
+//@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
+//@ is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
+//@ is "$.index[*].inner.import[?(@.name=='m2')].glob" true
 /// m2 re-export
 pub use m2::*;
 
-// @ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use
+//@ ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use
diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs
index 8b7150c8fd7..326df5fdb61 100644
--- a/tests/rustdoc-json/reexport/glob_empty_mod.rs
+++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs
@@ -1,8 +1,8 @@
 // Regression test for https://github.com/rust-lang/rust/issues/100973
 
-// @is "$.index[*][?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true
-// @set m1 = "$.index[*][?(@.name=='m1')].id"
+//@ is "$.index[*][?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true
+//@ set m1 = "$.index[*][?(@.name=='m1')].id"
 mod m1 {}
 
-// @is "$.index[*][?(@.inner.import)].inner.import.id" $m1
+//@ is "$.index[*][?(@.inner.import)].inner.import.id" $m1
 pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index b95765410d5..ff5d986d377 100644
--- a/tests/rustdoc-json/reexport/glob_extern.rs
+++ b/tests/rustdoc-json/reexport/glob_extern.rs
@@ -1,19 +1,19 @@
 //@ edition:2018
 
-// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
+//@ is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
     extern "C" {
-        // @set public_fn_id = "$.index[*][?(@.name=='public_fn')].id"
+        //@ set public_fn_id = "$.index[*][?(@.name=='public_fn')].id"
         pub fn public_fn();
-        // @!has "$.index[*][?(@.name=='private_fn')]"
+        //@ !has "$.index[*][?(@.name=='private_fn')]"
         fn private_fn();
     }
-    // @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $public_fn_id
-    // @set mod1_id = "$.index[*][?(@.name=='mod1')].id"
+    //@ ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $public_fn_id
+    //@ set mod1_id = "$.index[*][?(@.name=='mod1')].id"
 }
 
-// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
-// @is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
-// @set use_id = "$.index[*][?(@.inner.import)].id"
-// @ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
+//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
+//@ is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
+//@ set use_id = "$.index[*][?(@.inner.import)].id"
+//@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
 pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs
index 9764b404682..0a889107592 100644
--- a/tests/rustdoc-json/reexport/glob_private.rs
+++ b/tests/rustdoc-json/reexport/glob_private.rs
@@ -1,32 +1,32 @@
 //@ edition:2018
 
-// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
+//@ is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
-    // @is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true"
+    //@ is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true"
     mod mod2 {
-        // @set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id"
+        //@ set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id"
         pub struct Mod2Public;
 
-        // @!has "$.index[*][?(@.name=='Mod2Private')]"
+        //@ !has "$.index[*][?(@.name=='Mod2Private')]"
         struct Mod2Private;
     }
 
-    // @set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
-    // @is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
+    //@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
+    //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
     /// Mod2 re-export
     pub use self::mod2::*;
 
-    // @set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id"
+    //@ set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id"
     pub struct Mod1Public;
-    // @!has "$.index[*][?(@.name=='Mod1Private')]"
+    //@ !has "$.index[*][?(@.name=='Mod1Private')]"
     struct Mod1Private;
 }
 
-// @set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
-// @is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
+//@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
+//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
 /// Mod1 re-export
 pub use mod1::*;
 
-// @ismany "$.index[*][?(@.name=='mod2')].inner.module.items[*]" $m2pub_id
-// @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id
-// @ismany "$.index[*][?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id
+//@ ismany "$.index[*][?(@.name=='mod2')].inner.module.items[*]" $m2pub_id
+//@ ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id
+//@ ismany "$.index[*][?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs
index a4133e2f0c7..f94e416c00f 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs
@@ -1,13 +1,13 @@
-// @!has "$.index[*][?(@.name=='foo')]"
+//@ !has "$.index[*][?(@.name=='foo')]"
 mod foo {
-    // @has "$.index[*][?(@.name=='Foo')]"
+    //@ has "$.index[*][?(@.name=='Foo')]"
     pub struct Foo;
 }
 
-// @has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
+//@ has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
 pub use foo::Foo;
 
 pub mod bar {
-    // @has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
+    //@ has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
     pub use crate::foo::Foo;
 }
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
index 37f7b26fc85..13dee323542 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -1,19 +1,19 @@
 pub mod foo {
-    // @set bar_id = "$.index[*][?(@.name=='Bar')].id"
-    // @ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id
+    //@ set bar_id = "$.index[*][?(@.name=='Bar')].id"
+    //@ ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id
     pub struct Bar;
 }
 
-// @set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
-// @is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
-// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
+//@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
+//@ is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
+//@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
 /// Outer re-export
 pub use foo::Bar;
 
 pub mod baz {
-    // @set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
-    // @is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
-    // @ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
+    //@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
+    //@ is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
+    //@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
     /// Inner re-export
     pub use crate::foo::Bar;
 }
diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs
index 2cca238908e..f182208c341 100644
--- a/tests/rustdoc-json/reexport/macro.rs
+++ b/tests/rustdoc-json/reexport/macro.rs
@@ -1,13 +1,13 @@
 //@ edition:2018
 
-// @set repro_id = "$.index[*][?(@.name=='repro')].id"
+//@ set repro_id = "$.index[*][?(@.name=='repro')].id"
 #[macro_export]
 macro_rules! repro {
     () => {};
 }
 
-// @set repro2_id = "$.index[*][?(@.docs=='Re-export')].id"
+//@ set repro2_id = "$.index[*][?(@.docs=='Re-export')].id"
 /// Re-export
 pub use crate::repro as repro2;
 
-// @ismany "$.index[*][?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id
+//@ ismany "$.index[*][?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id
diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs
index bc072be81a3..7e0c0118e84 100644
--- a/tests/rustdoc-json/reexport/mod_not_included.rs
+++ b/tests/rustdoc-json/reexport/mod_not_included.rs
@@ -6,6 +6,6 @@ mod m1 {
 
 pub use m1::x;
 
-// @has "$.index[*][?(@.name=='x' && @.inner.function)]"
-// @has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
-// @!has "$.index[*][?(@.name=='m1')]"
+//@ has "$.index[*][?(@.name=='x' && @.inner.function)]"
+//@ has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
+//@ !has "$.index[*][?(@.name=='m1')]"
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index 5e6a10af529..be66ad522da 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -6,19 +6,19 @@
 
 extern crate pub_struct as foo;
 #[doc(inline)]
-// @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
-// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
+//@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
+//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
 /// Hack A
 pub use foo::Foo;
 
-// @set bar_id = "$.index[*][?(@.name=='bar')].id"
+//@ set bar_id = "$.index[*][?(@.name=='bar')].id"
 pub mod bar {
-    // @is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
-    // @set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
-    // @ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
+    //@ is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
+    //@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
+    //@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
     /// Hack B
     pub use foo::Foo;
 }
 
-// @ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
-// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
+//@ ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
+//@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index e6f037eb4b3..1e5466dba5e 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -3,21 +3,21 @@
 // Test for the ICE in https://github.com/rust-lang/rust/issues/83720
 // A pub-in-private type re-exported under two different names shouldn't cause an error
 
-// @!has "$.index[*][?(@.name=='style')]"
+//@ !has "$.index[*][?(@.name=='style')]"
 mod style {
-    // @set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id"
+    //@ set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id"
     pub struct Color;
 }
 
-// @is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
-// @is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
-// @set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
+//@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
 /// First re-export
 pub use style::Color;
-// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
-// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
-// @set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
+//@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
 /// Second re-export
 pub use style::Color as Colour;
 
-// @ismany "$.index[*][?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id
+//@ ismany "$.index[*][?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id
diff --git a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs
index 15d194ef5d9..e021b51ab4b 100644
--- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs
+++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs
@@ -9,5 +9,5 @@ mod repeat_n {
 /// not here
 pub use repeat_n::RepeatN;
 
-// @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0
-// @!has "$.index[*][?(@.docs == 'not here')]"
+//@ count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0
+//@ !has "$.index[*][?(@.docs == 'not here')]"
diff --git a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
index 61075088af9..25edd5dbb28 100644
--- a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
+++ b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
@@ -1,11 +1,11 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/102583>.
 
-// @set impl_S = "$.index[*][?(@.docs=='impl S')].id"
-// @has "$.index[*][?(@.name=='S')].inner.struct.impls[*]" $impl_S
-// @set is_present = "$.index[*][?(@.name=='is_present')].id"
-// @is "$.index[*][?(@.docs=='impl S')].inner.impl.items[*]" $is_present
-// @!has "$.index[*][?(@.name=='hidden_impl')]"
-// @!has "$.index[*][?(@.name=='hidden_fn')]"
+//@ set impl_S = "$.index[*][?(@.docs=='impl S')].id"
+//@ has "$.index[*][?(@.name=='S')].inner.struct.impls[*]" $impl_S
+//@ set is_present = "$.index[*][?(@.name=='is_present')].id"
+//@ is "$.index[*][?(@.docs=='impl S')].inner.impl.items[*]" $is_present
+//@ !has "$.index[*][?(@.name=='hidden_impl')]"
+//@ !has "$.index[*][?(@.name=='hidden_fn')]"
 
 #![no_std]
 
diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
index 62c1dbff278..07ce1f5c20a 100644
--- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs
+++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: --document-hidden-items
 
-// @has "$.index[*].inner[?(@.import.name=='UsedHidden')]"
-// @has "$.index[*][?(@.name=='Hidden')]"
+//@ has "$.index[*].inner[?(@.import.name=='UsedHidden')]"
+//@ has "$.index[*][?(@.name=='Hidden')]"
 pub mod submodule {
     #[doc(hidden)]
     pub struct Hidden {}
diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs
index 433829bab30..3335d18e27b 100644
--- a/tests/rustdoc-json/reexport/rename_private.rs
+++ b/tests/rustdoc-json/reexport/rename_private.rs
@@ -1,10 +1,10 @@
 //@ edition:2018
 
-// @!has "$.index[*][?(@.name=='inner')]"
+//@ !has "$.index[*][?(@.name=='inner')]"
 mod inner {
-    // @has "$.index[*][?(@.name=='Public')]"
+    //@ has "$.index[*][?(@.name=='Public')]"
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
+//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
 pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs
index ebfa3d9f176..e534f458f93 100644
--- a/tests/rustdoc-json/reexport/rename_public.rs
+++ b/tests/rustdoc-json/reexport/rename_public.rs
@@ -1,15 +1,15 @@
 //@ edition:2018
 
-// @set inner_id = "$.index[*][?(@.name=='inner')].id"
+//@ set inner_id = "$.index[*][?(@.name=='inner')].id"
 pub mod inner {
-    // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
+    //@ set public_id = "$.index[*][?(@.name=='Public')].id"
+    //@ ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
-// @set import_id = "$.index[*][?(@.docs=='Re-export')].id"
-// @!has "$.index[*].inner[?(@.import.name=='Public')]"
-// @is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
+//@ set import_id = "$.index[*][?(@.docs=='Re-export')].id"
+//@ !has "$.index[*].inner[?(@.import.name=='Public')]"
+//@ is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
 /// Re-export
 pub use inner::Public as NewName;
 
-// @ismany "$.index[*][?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id
+//@ ismany "$.index[*][?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
index 42ba6c40019..b0a06d4ecfa 100644
--- a/tests/rustdoc-json/reexport/same_name_different_types.rs
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -1,22 +1,22 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/107677>.
 
 pub mod nested {
-    // @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id"
+    //@ set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id"
 
     /// Foo the struct
     pub struct Foo {}
 
-    // @set foo_fn = "$.index[*][?(@.docs == 'Foo the function')].id"
+    //@ set foo_fn = "$.index[*][?(@.docs == 'Foo the function')].id"
 
     #[allow(non_snake_case)]
     /// Foo the function
     pub fn Foo() {}
 }
 
-// @ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
-// @ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
 
-// @count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
+//@ count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
 pub use nested::Foo;
-// @count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
+//@ count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
 pub use Foo as Bar;
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index 1e1710e1c08..c533b9ba770 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -5,17 +5,17 @@
 #![no_std]
 
 mod inner {
-    // @set trait_id = "$.index[*][?(@.name=='Trait')].id"
+    //@ set trait_id = "$.index[*][?(@.name=='Trait')].id"
     pub trait Trait {}
 }
 
-// @set export_id = "$.index[*][?(@.docs=='First re-export')].id"
-// @is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
+//@ set export_id = "$.index[*][?(@.docs=='First re-export')].id"
+//@ is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
 /// First re-export
 pub use inner::Trait;
-// @set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
-// @is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
+//@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
+//@ is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
 /// Second re-export
 pub use inner::Trait as Reexport;
 
-// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id
+//@ ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id
diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs
index 7b6509abc8d..9af0157818b 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -1,14 +1,14 @@
 //@ edition:2018
 
-// @!has "$.index[*][?(@.name=='inner')]"
+//@ !has "$.index[*][?(@.name=='inner')]"
 mod inner {
-    // @set pub_id = "$.index[*][?(@.name=='Public')].id"
+    //@ set pub_id = "$.index[*][?(@.name=='Public')].id"
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
-// @is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
-// @set use_id = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
+//@ is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
+//@ set use_id = "$.index[*][?(@.inner.import)].id"
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
+//@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index 55d32b99951..d7b44b2f987 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -1,16 +1,16 @@
 //@ edition:2018
 
-// @set inner_id = "$.index[*][?(@.name=='inner')].id"
+//@ set inner_id = "$.index[*][?(@.name=='inner')].id"
 pub mod inner {
 
-    // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
+    //@ set public_id = "$.index[*][?(@.name=='Public')].id"
+    //@ ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
 
-// @set import_id = "$.index[*][?(@.docs=='Outer')].id"
-// @is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
+//@ set import_id = "$.index[*][?(@.docs=='Outer')].id"
+//@ is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
 /// Outer
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id
+//@ ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id
diff --git a/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs b/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs
index de67badffd5..59699e4861b 100644
--- a/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs
+++ b/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs
@@ -7,4 +7,4 @@ pub struct Local;
 
 impl trait_with_docs::HasDocs for Local {}
 
-// @!has "$.index[*][?(@.name == 'HasDocs')]"
+//@ !has "$.index[*][?(@.name == 'HasDocs')]"
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index a9301b3fe4f..4a1922e15e5 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -5,8 +5,8 @@ mod secret {
     pub struct Secret;
 }
 
-// @has "$.index[*][?(@.name=='get_secret')].inner.function"
-// @is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
+//@ has "$.index[*][?(@.name=='get_secret')].inner.function"
+//@ is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs
index d5ab1173d92..d0db9c6588b 100644
--- a/tests/rustdoc-json/stripped_modules.rs
+++ b/tests/rustdoc-json/stripped_modules.rs
@@ -1,17 +1,17 @@
-// @!has "$.index[*][?(@.name=='no_pub_inner')]"
+//@ !has "$.index[*][?(@.name=='no_pub_inner')]"
 mod no_pub_inner {
     fn priv_inner() {}
 }
 
-// @!has "$.index[*][?(@.name=='pub_inner_unreachable')]"
+//@ !has "$.index[*][?(@.name=='pub_inner_unreachable')]"
 mod pub_inner_unreachable {
-    // @!has "$.index[*][?(@.name=='pub_inner_1')]"
+    //@ !has "$.index[*][?(@.name=='pub_inner_1')]"
     pub fn pub_inner_1() {}
 }
 
-// @!has "$.index[*][?(@.name=='pub_inner_reachable')]"
+//@ !has "$.index[*][?(@.name=='pub_inner_reachable')]"
 mod pub_inner_reachable {
-    // @has "$.index[*][?(@.name=='pub_inner_2')]"
+    //@ has "$.index[*][?(@.name=='pub_inner_2')]"
     pub fn pub_inner_2() {}
 }
 
diff --git a/tests/rustdoc-json/structs/field_order.rs b/tests/rustdoc-json/structs/field_order.rs
index a8c18323d52..7e556df777f 100644
--- a/tests/rustdoc-json/structs/field_order.rs
+++ b/tests/rustdoc-json/structs/field_order.rs
@@ -15,24 +15,24 @@ pub struct Foo {
     pub vll_9: i32,
 }
 
-// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
-// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
-// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
-// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
-// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
-// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
-// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
-// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
-// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
-// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+//@ set 0 = '$.index[*][?(@.name == "ews_0")].id'
+//@ set 1 = '$.index[*][?(@.name == "dik_1")].id'
+//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+//@ set 3 = '$.index[*][?(@.name == "djt_3")].id'
+//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+//@ set 6 = '$.index[*][?(@.name == "bja_6")].id'
+//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+//@ set 9 = '$.index[*][?(@.name == "vll_9")].id'
 
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[0]' $0
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[1]' $1
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[2]' $2
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[3]' $3
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[4]' $4
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[5]' $5
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[6]' $6
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[7]' $7
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[8]' $8
-// @is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[9]' $9
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[0]' $0
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[1]' $1
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[2]' $2
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[3]' $3
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[4]' $4
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[5]' $5
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[6]' $6
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[7]' $7
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[8]' $8
+//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[9]' $9
diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs
index 777260100d6..aa53b59726a 100644
--- a/tests/rustdoc-json/structs/plain_all_pub.rs
+++ b/tests/rustdoc-json/structs/plain_all_pub.rs
@@ -3,9 +3,9 @@ pub struct Demo {
     pub y: i32,
 }
 
-// @set x = "$.index[*][?(@.name=='x')].id"
-// @set y = "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
-// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
+//@ set x = "$.index[*][?(@.name=='x')].id"
+//@ set y = "$.index[*][?(@.name=='y')].id"
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
+//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 1ff4489ef6b..39f9367cb93 100644
--- a/tests/rustdoc-json/structs/plain_doc_hidden.rs
+++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs
@@ -4,8 +4,8 @@ pub struct Demo {
     pub y: i32,
 }
 
-// @set x = "$.index[*][?(@.name=='x')].id"
-// @!has "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ set x = "$.index[*][?(@.name=='x')].id"
+//@ !has "$.index[*][?(@.name=='y')].id"
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index c037c0251b9..00b4b05ebdd 100644
--- a/tests/rustdoc-json/structs/plain_empty.rs
+++ b/tests/rustdoc-json/structs/plain_empty.rs
@@ -1,5 +1,5 @@
-// @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
+//@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
+//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
+//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
 pub struct PlainEmpty {}
diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs
index ff061be62d1..f9ab8714f81 100644
--- a/tests/rustdoc-json/structs/plain_pub_priv.rs
+++ b/tests/rustdoc-json/structs/plain_pub_priv.rs
@@ -3,7 +3,7 @@ pub struct Demo {
     y: i32,
 }
 
-// @set x = "$.index[*][?(@.name=='x')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ set x = "$.index[*][?(@.name=='x')].id"
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/tuple.rs b/tests/rustdoc-json/structs/tuple.rs
index 16ab95ed271..6c8dc79dfe2 100644
--- a/tests/rustdoc-json/structs/tuple.rs
+++ b/tests/rustdoc-json/structs/tuple.rs
@@ -1,4 +1,4 @@
-// @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Tuple')].inner.struct"
-// @is "$.index[*][?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]'
+//@ is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='Tuple')].inner.struct"
+//@ is "$.index[*][?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]'
 pub struct Tuple(u32, String);
diff --git a/tests/rustdoc-json/structs/tuple_empty.rs b/tests/rustdoc-json/structs/tuple_empty.rs
index 4d4af8558bb..137915e6c05 100644
--- a/tests/rustdoc-json/structs/tuple_empty.rs
+++ b/tests/rustdoc-json/structs/tuple_empty.rs
@@ -1,2 +1,2 @@
-// @is "$.index[*][?(@.name=='TupleUnit')].inner.struct.kind.tuple" []
+//@ is "$.index[*][?(@.name=='TupleUnit')].inner.struct.kind.tuple" []
 pub struct TupleUnit();
diff --git a/tests/rustdoc-json/structs/tuple_pub_priv.rs b/tests/rustdoc-json/structs/tuple_pub_priv.rs
index a669ba1dfcc..11af26e6ea3 100644
--- a/tests/rustdoc-json/structs/tuple_pub_priv.rs
+++ b/tests/rustdoc-json/structs/tuple_pub_priv.rs
@@ -5,9 +5,9 @@ pub struct Demo(
     #[doc(hidden)] i32,
 );
 
-// @set field = "$.index[*][?(@.docs=='field')].id"
+//@ set field = "$.index[*][?(@.docs=='field')].id"
 
-// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[0]" null
-// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field
-// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[2]" null
-// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3
+//@ is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[0]" null
+//@ is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field
+//@ is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[2]" null
+//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3
diff --git a/tests/rustdoc-json/structs/unit.rs b/tests/rustdoc-json/structs/unit.rs
index 640d3fb7865..ad6af65c0e0 100644
--- a/tests/rustdoc-json/structs/unit.rs
+++ b/tests/rustdoc-json/structs/unit.rs
@@ -1,4 +1,4 @@
-// @is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Unit')].inner.struct"
-// @is "$.index[*][?(@.name=='Unit')].inner.struct.kind" \"unit\"
+//@ is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='Unit')].inner.struct"
+//@ is "$.index[*][?(@.name=='Unit')].inner.struct.kind" \"unit\"
 pub struct Unit;
diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs
index d721cbdbe25..6e13dae9ebf 100644
--- a/tests/rustdoc-json/structs/with_generics.rs
+++ b/tests/rustdoc-json/structs/with_generics.rs
@@ -1,13 +1,13 @@
 use std::collections::HashMap;
 
-// @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
+//@ is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='WithGenerics')].inner.struct"
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\"
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
 pub struct WithGenerics<T, U> {
     stuff: Vec<T>,
     things: HashMap<U, U>,
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index e0285a9e688..2ca11b50608 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -1,11 +1,11 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
+//@ is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
 pub struct WithPrimitives<'a> {
     num: u32,
     s: &'a str,
diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs
index dc930550ef1..ca9e5edfdf7 100644
--- a/tests/rustdoc-json/trait_alias.rs
+++ b/tests/rustdoc-json/trait_alias.rs
@@ -1,18 +1,18 @@
 // ignore-tidy-linelength
 #![feature(trait_alias)]
 
-// @set StrLike = "$.index[*][?(@.name=='StrLike')].id"
-// @is "$.index[*][?(@.name=='StrLike')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='StrLike')].inner.trait_alias"
-// @is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE
+//@ set StrLike = "$.index[*][?(@.name=='StrLike')].id"
+//@ is "$.index[*][?(@.name=='StrLike')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='StrLike')].inner.trait_alias"
+//@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE
 pub trait StrLike = AsRef<str>;
 
-// @is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
 pub fn f() -> impl StrLike {
     "heya"
 }
 
-// @!is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
 pub fn g() -> impl AsRef<str> {
     "heya"
 }
diff --git a/tests/rustdoc-json/traits/has_body.rs b/tests/rustdoc-json/traits/has_body.rs
index 219e2d9bc54..95e0f97b52c 100644
--- a/tests/rustdoc-json/traits/has_body.rs
+++ b/tests/rustdoc-json/traits/has_body.rs
@@ -1,21 +1,21 @@
-// @has "$.index[*][?(@.name=='Foo')]"
+//@ has "$.index[*][?(@.name=='Foo')]"
 pub trait Foo {
-    // @is "$.index[*][?(@.name=='no_self')].inner.function.has_body" false
+    //@ is "$.index[*][?(@.name=='no_self')].inner.function.has_body" false
     fn no_self();
-    // @is "$.index[*][?(@.name=='move_self')].inner.function.has_body" false
+    //@ is "$.index[*][?(@.name=='move_self')].inner.function.has_body" false
     fn move_self(self);
-    // @is "$.index[*][?(@.name=='ref_self')].inner.function.has_body" false
+    //@ is "$.index[*][?(@.name=='ref_self')].inner.function.has_body" false
     fn ref_self(&self);
 
-    // @is "$.index[*][?(@.name=='no_self_def')].inner.function.has_body" true
+    //@ is "$.index[*][?(@.name=='no_self_def')].inner.function.has_body" true
     fn no_self_def() {}
-    // @is "$.index[*][?(@.name=='move_self_def')].inner.function.has_body" true
+    //@ is "$.index[*][?(@.name=='move_self_def')].inner.function.has_body" true
     fn move_self_def(self) {}
-    // @is "$.index[*][?(@.name=='ref_self_def')].inner.function.has_body" true
+    //@ is "$.index[*][?(@.name=='ref_self_def')].inner.function.has_body" true
     fn ref_self_def(&self) {}
 }
 
 pub trait Bar: Clone {
-    // @is "$.index[*][?(@.name=='method')].inner.function.has_body" false
+    //@ is "$.index[*][?(@.name=='method')].inner.function.has_body" false
     fn method(&self, param: usize);
 }
diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs
index c27553c7544..9fdb763b61e 100644
--- a/tests/rustdoc-json/traits/implementors.rs
+++ b/tests/rustdoc-json/traits/implementors.rs
@@ -5,14 +5,14 @@ pub struct GeorgeMichael {}
 impl Wham for GeorgeMichael {}
 
 // Find IDs.
-// @set wham = "$.index[*][?(@.name=='Wham')].id"
-// @set gmWham = "$.index[*][?(@.docs=='Wham for George Michael')].id"
-// @set gm = "$.index[*][?(@.name=='GeorgeMichael')].id"
+//@ set wham = "$.index[*][?(@.name=='Wham')].id"
+//@ set gmWham = "$.index[*][?(@.docs=='Wham for George Michael')].id"
+//@ set gm = "$.index[*][?(@.name=='GeorgeMichael')].id"
 
 // Both struct and trait point to impl.
-// @has "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham
-// @is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham
+//@ has "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham
+//@ is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham
 
 // Impl points to both struct and trait.
-// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham
-// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm
+//@ is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham
+//@ is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm
diff --git a/tests/rustdoc-json/traits/is_object_safe.rs b/tests/rustdoc-json/traits/is_object_safe.rs
index 131c5fc57a5..35c4e4eb847 100644
--- a/tests/rustdoc-json/traits/is_object_safe.rs
+++ b/tests/rustdoc-json/traits/is_object_safe.rs
@@ -1,19 +1,19 @@
 #![no_std]
 
-// @has "$.index[*][?(@.name=='FooUnsafe')]"
-// @is "$.index[*][?(@.name=='FooUnsafe')].inner.trait.is_object_safe" false
+//@ has "$.index[*][?(@.name=='FooUnsafe')]"
+//@ is "$.index[*][?(@.name=='FooUnsafe')].inner.trait.is_object_safe" false
 pub trait FooUnsafe {
     fn foo() -> Self;
 }
 
-// @has "$.index[*][?(@.name=='BarUnsafe')]"
-// @is "$.index[*][?(@.name=='BarUnsafe')].inner.trait.is_object_safe" false
+//@ has "$.index[*][?(@.name=='BarUnsafe')]"
+//@ is "$.index[*][?(@.name=='BarUnsafe')].inner.trait.is_object_safe" false
 pub trait BarUnsafe<T> {
     fn foo(i: T);
 }
 
-// @has "$.index[*][?(@.name=='FooSafe')]"
-// @is "$.index[*][?(@.name=='FooSafe')].inner.trait.is_object_safe" true
+//@ has "$.index[*][?(@.name=='FooSafe')]"
+//@ is "$.index[*][?(@.name=='FooSafe')].inner.trait.is_object_safe" true
 pub trait FooSafe {
     fn foo(&self);
 }
diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs
index 67b5a858ab7..d31b6ca4ad8 100644
--- a/tests/rustdoc-json/traits/private_supertrait.rs
+++ b/tests/rustdoc-json/traits/private_supertrait.rs
@@ -1,11 +1,11 @@
 // ignore-tidy-linelength
 
-// @!has "$.index[*][?(@.name == 'sealed')]"
+//@ !has "$.index[*][?(@.name == 'sealed')]"
 mod sealed {
-    // @set sealed_id = "$.index[*][?(@.name=='Sealed')].id"
+    //@ set sealed_id = "$.index[*][?(@.name=='Sealed')].id"
     pub trait Sealed {}
 }
 
-// @count "$.index[*][?(@.name=='Trait')].inner.trait.bounds[*]" 1
-// @is    "$.index[*][?(@.name=='Trait')].inner.trait.bounds[0].trait_bound.trait.id" $sealed_id
+//@ count "$.index[*][?(@.name=='Trait')].inner.trait.bounds[*]" 1
+//@ is    "$.index[*][?(@.name=='Trait')].inner.trait.bounds[0].trait_bound.trait.id" $sealed_id
 pub trait Trait: sealed::Sealed {}
diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs
index bbae3557cf9..e8fe82ab9cd 100644
--- a/tests/rustdoc-json/traits/supertrait.rs
+++ b/tests/rustdoc-json/traits/supertrait.rs
@@ -1,22 +1,22 @@
 // ignore-tidy-linelength
 
-// @set loud_id = "$.index[*][?(@.name=='Loud')].id"
+//@ set loud_id = "$.index[*][?(@.name=='Loud')].id"
 pub trait Loud {}
 
-// @set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id"
-// @count "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1
-// @is    "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id
+//@ set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id"
+//@ count "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1
+//@ is    "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id
 pub trait VeryLoud: Loud {}
 
-// @set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id"
+//@ set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id"
 pub trait SoundsGood {}
 
-// @count "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id
+//@ count "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[*]" 2
+//@ is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id
+//@ is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id
 pub trait MetalBand: VeryLoud + SoundsGood {}
 
-// @count "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id
+//@ count "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2
+//@ is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id
+//@ is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id
 pub trait DnabLatem: SoundsGood + VeryLoud {}
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index 4fcc26f7de2..a1ab039692b 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -3,25 +3,25 @@
 
 #![feature(trait_alias)]
 
-// @set Orig = "$.index[*][?(@.name == 'Orig')].id"
-// @has "$.index[*][?(@.name == 'Orig')].inner.trait"
+//@ set Orig = "$.index[*][?(@.name == 'Orig')].id"
+//@ has "$.index[*][?(@.name == 'Orig')].inner.trait"
 pub trait Orig<T> {}
 
-// @set Alias = "$.index[*][?(@.name == 'Alias')].id"
-// @has "$.index[*][?(@.name == 'Alias')].inner.trait_alias"
-// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}'
-// @count "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[*]" 1
-// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig
-// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"'
+//@ set Alias = "$.index[*][?(@.name == 'Alias')].id"
+//@ has "$.index[*][?(@.name == 'Alias')].inner.trait_alias"
+//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}'
+//@ count "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[*]" 1
+//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig
+//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"'
 pub trait Alias = Orig<i32>;
 
 pub struct Struct;
 
 impl Orig<i32> for Struct {}
 
-// @has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
-// @is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
-// @is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
+//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
+//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
+//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
 pub fn takes_alias(_: impl Alias) {}
 // FIXME: Should the trait be mentioned in both the decl and generics?
 
diff --git a/tests/rustdoc-json/traits/uses_extern_trait.rs b/tests/rustdoc-json/traits/uses_extern_trait.rs
index 55a51f739ab..3a93bcaefd4 100644
--- a/tests/rustdoc-json/traits/uses_extern_trait.rs
+++ b/tests/rustdoc-json/traits/uses_extern_trait.rs
@@ -1,5 +1,5 @@
 #![no_std]
 pub fn drop_default<T: core::default::Default>(_x: T) {}
 
-// @!has "$.index[*][?(@.name=='Debug')]"
-// @!has "$.index[*][?(@.name=='Default')]"
+//@ !has "$.index[*][?(@.name=='Debug')]"
+//@ !has "$.index[*][?(@.name=='Default')]"
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index 4db65b61dc6..86ea1c2b5f2 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -1,46 +1,46 @@
 // ignore-tidy-linelength
 use std::fmt::Debug;
 
-// @count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3
-// @set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id"
-// @set ref_fn       = "$.index[*][?(@.name=='RefFn')].id"
-// @set weird_order  = "$.index[*][?(@.name=='WeirdOrder')].id"
-// @ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order
+//@ count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3
+//@ set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id"
+//@ set ref_fn       = "$.index[*][?(@.name=='RefFn')].id"
+//@ set weird_order  = "$.index[*][?(@.name=='WeirdOrder')].id"
+//@ ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order
 
-// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
-// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
-// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
+//@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias"
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
+//@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
+//@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
+//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
 pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 
-// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias"
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
-// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref"
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\""
-// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait"
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
-// @count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
-// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
-// @has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
-// @is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
+//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias"
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
+//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref"
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false'
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\""
+//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait"
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
+//@ count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
+//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
 pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
 
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
+//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
+//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
 pub type WeirdOrder = Box<dyn Send + Debug>;
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index 59e099ec9fc..fda5d5ab970 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -5,5 +5,5 @@ extern "C" {
     pub type Foo;
 }
 
-// @is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
-// @is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
+//@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
+//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index 4aca303e6dc..2893b37319f 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -1,26 +1,26 @@
 // ignore-tidy-linelength
 
-// @has "$.index[*][?(@.name=='GenericFn')].inner.type_alias"
+//@ has "$.index[*][?(@.name=='GenericFn')].inner.type_alias"
 
-// @ismany "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\"
-// @has    "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime"
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ ismany "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\"
+//@ has    "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime"
+//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0
+//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0
+//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0
+//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
+//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 
 pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
 
-// @has    "$.index[*][?(@.name=='ForAll')].inner.type_alias"
-// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.params[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\"
-// @has   "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime"
-// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ has    "$.index[*][?(@.name=='ForAll')].inner.type_alias"
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.params[*]" 0
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.where_predicates[*]" 0
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*]" 1
+//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\"
+//@ has   "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime"
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
+//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 30817a42e8a..306376354ce 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -1,33 +1,33 @@
 // ignore-tidy-linelength
 
-// @set result = "$.index[*][?(@.name=='Result')].id"
+//@ set result = "$.index[*][?(@.name=='Result')].id"
 pub enum Result<T, E> {
     Ok(T),
     Err(E),
 }
 
-// @set my_error = "$.index[*][?(@.name=='MyError')].id"
+//@ set my_error = "$.index[*][?(@.name=='MyError')].id"
 pub struct MyError {}
 
-// @has    "$.index[*][?(@.name=='MyResult')].inner.type_alias"
-// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[*]" 2
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].name" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].name" \"E\"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type"
-// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.bounds[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.bounds[*]" 0
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null
-// @has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
-// @has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
-// @has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
-// @has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\"
+//@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias"
+//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.where_predicates[*]" 0
+//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[*]" 2
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].name" \"T\"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].name" \"E\"
+//@ has   "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type"
+//@ has   "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type"
+//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.bounds[*]" 0
+//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.bounds[*]" 0
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null
+//@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
+//@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
+//@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\"
 pub type MyResult<T, E = MyError> = Result<T, E>;
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index f7ac878ceaa..a28b2fddf46 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}'
-// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+//@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}'
+//@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
 pub fn genfn<F>(f: F)
 where
     for<'a, 'b> F: Fn(&'a i32, &'b i32),
@@ -10,12 +10,12 @@ where
     f(&zero, &zero);
 }
 
-// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
-// @count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
-// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+//@ count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
index f8603147951..386c7c80d7f 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -2,23 +2,23 @@
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
-// @set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id'
+//@ set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id'
 pub struct OwnerMetadata;
-// @set Owner = '$.index[*][?(@.name=="Owner")].id'
+//@ set Owner = '$.index[*][?(@.name=="Owner")].id'
 pub struct Owner;
 
 pub fn create() -> Owner::Metadata {
     OwnerMetadata
 }
-// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
-// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
-// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
+//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
+//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
 
 /// impl
 impl Owner {
     /// iat
     pub type Metadata = OwnerMetadata;
 }
-// @set iat = '$.index[*][?(@.docs=="iat")].id'
-// @is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
-// @is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
+//@ set iat = '$.index[*][?(@.docs=="iat")].id'
+//@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
+//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index 6da23c8fb4e..45fe19bf467 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -2,17 +2,17 @@
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
-// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
+//@ set Carrier = '$.index[*][?(@.name=="Carrier")].id'
 pub struct Carrier<'a>(&'a ());
 
-// @count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
-// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+//@ count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
 pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
 
 impl<'a> Carrier<'a> {
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index d12e5f4a784..9b827a98419 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -2,15 +2,15 @@
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
-// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
+//@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
 pub struct Parametrized<T>(T);
 
-// @count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
-// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
-// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
-// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
-// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
+//@ count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
+//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
 pub fn test(_: Parametrized<i32>::Proj) {}
 
 /// param_bool
@@ -25,10 +25,10 @@ impl Parametrized<i32> {
     pub type Proj = String;
 }
 
-// @set param_bool = '$.index[*][?(@.docs=="param_bool")].id'
-// @set param_i32 = '$.index[*][?(@.docs=="param_i32")].id'
-// @set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id'
-// @set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id'
+//@ set param_bool = '$.index[*][?(@.docs=="param_bool")].id'
+//@ set param_i32 = '$.index[*][?(@.docs=="param_i32")].id'
+//@ set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id'
+//@ set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id'
 
-// @is '$.index[*][?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj
-// @is '$.index[*][?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj
+//@ is '$.index[*][?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj
+//@ is '$.index[*][?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj
diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs
index 7a938c50ba0..ecf35c5987a 100644
--- a/tests/rustdoc-json/type_alias.rs
+++ b/tests/rustdoc-json/type_alias.rs
@@ -1,15 +1,15 @@
-// @set IntVec = "$.index[*][?(@.name=='IntVec')].id"
-// @is "$.index[*][?(@.name=='IntVec')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='IntVec')].inner.type_alias"
-// @is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE
+//@ set IntVec = "$.index[*][?(@.name=='IntVec')].id"
+//@ is "$.index[*][?(@.name=='IntVec')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='IntVec')].inner.type_alias"
+//@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE
 pub type IntVec = Vec<u32>;
 
-// @is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec
 pub fn f() -> IntVec {
     vec![0; 32]
 }
 
-// @!is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec
 pub fn g() -> Vec<u32> {
     vec![0; 32]
 }
diff --git a/tests/rustdoc-json/unions/field_order.rs b/tests/rustdoc-json/unions/field_order.rs
index 8a40bda0399..a1616f62751 100644
--- a/tests/rustdoc-json/unions/field_order.rs
+++ b/tests/rustdoc-json/unions/field_order.rs
@@ -15,24 +15,24 @@ pub union Foo {
     pub vll_9: i32,
 }
 
-// @set 0 = '$.index[*][?(@.name == "ews_0")].id'
-// @set 1 = '$.index[*][?(@.name == "dik_1")].id'
-// @set 2 = '$.index[*][?(@.name == "hsk_2")].id'
-// @set 3 = '$.index[*][?(@.name == "djt_3")].id'
-// @set 4 = '$.index[*][?(@.name == "jnr_4")].id'
-// @set 5 = '$.index[*][?(@.name == "dfs_5")].id'
-// @set 6 = '$.index[*][?(@.name == "bja_6")].id'
-// @set 7 = '$.index[*][?(@.name == "lyc_7")].id'
-// @set 8 = '$.index[*][?(@.name == "yqd_8")].id'
-// @set 9 = '$.index[*][?(@.name == "vll_9")].id'
+//@ set 0 = '$.index[*][?(@.name == "ews_0")].id'
+//@ set 1 = '$.index[*][?(@.name == "dik_1")].id'
+//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id'
+//@ set 3 = '$.index[*][?(@.name == "djt_3")].id'
+//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id'
+//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id'
+//@ set 6 = '$.index[*][?(@.name == "bja_6")].id'
+//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id'
+//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id'
+//@ set 9 = '$.index[*][?(@.name == "vll_9")].id'
 
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[0]' $0
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[1]' $1
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[2]' $2
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[3]' $3
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[4]' $4
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[5]' $5
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[6]' $6
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[7]' $7
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[8]' $8
-// @is '$.index[*][?(@.name == "Foo")].inner.union.fields[9]' $9
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[0]' $0
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[1]' $1
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[2]' $2
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[3]' $3
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[4]' $4
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[5]' $5
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[6]' $6
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[7]' $7
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[8]' $8
+//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[9]' $9
diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs
index 1515f7d9397..989a025f669 100644
--- a/tests/rustdoc-json/unions/impl.rs
+++ b/tests/rustdoc-json/unions/impl.rs
@@ -1,15 +1,15 @@
 #![no_std]
 
-// @is "$.index[*][?(@.name=='Ux')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Ux')].inner.union"
+//@ is "$.index[*][?(@.name=='Ux')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='Ux')].inner.union"
 pub union Ux {
     a: u32,
     b: u64,
 }
 
-// @is "$.index[*][?(@.name=='Num')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Num')].inner.trait"
+//@ is "$.index[*][?(@.name=='Num')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='Num')].inner.trait"
 pub trait Num {}
 
-// @count "$.index[*][?(@.name=='Ux')].inner.union.impls" 1
+//@ count "$.index[*][?(@.name=='Ux')].inner.union.impls" 1
 impl Num for Ux {}
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index 1089d9c4558..4a97b5d4fb8 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -1,14 +1,14 @@
-// @has "$.index[*][?(@.name=='Union')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Union')].inner.union"
-// @!has "$.index[*][?(@.name=='Union')].inner.union.struct_type"
-// @set Union = "$.index[*][?(@.name=='Union')].id"
+//@ has "$.index[*][?(@.name=='Union')].visibility" \"public\"
+//@ has "$.index[*][?(@.name=='Union')].inner.union"
+//@ !has "$.index[*][?(@.name=='Union')].inner.union.struct_type"
+//@ set Union = "$.index[*][?(@.name=='Union')].id"
 pub union Union {
     int: i32,
     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
+//@ 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 {
     Union { int }
 }
diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr
index f7f3e368a3c..3d17570a7a2 100644
--- a/tests/rustdoc-ui/track-diagnostics.stderr
+++ b/tests/rustdoc-ui/track-diagnostics.stderr
@@ -3,7 +3,7 @@ error[E0308]: mismatched types
    |
 LL | const S: A = B;
    |              ^ expected `A`, found `B`
--Ztrack-diagnostics: created at compiler/rustc_infer/src/error_reporting/infer/mod.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
 
 error: aborting due to 1 previous error
 
diff --git a/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs
index 5fa6891b23d..e1f19e7e017 100644
--- a/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs
+++ b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs
@@ -24,14 +24,14 @@ impl Foo<u32> {
 }
 
 impl<T> Bar for Foo<T> {
-    //@ has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' 'type Item = T'
+    // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' 'type Item = T'
     type Item=T;
 
     //@ has - '//*[@id="method.quux"]//h4[@class="code-header"]' 'fn quux(self)'
     fn quux(self) {}
 }
 impl<'a, T> Bar for &'a Foo<T> {
-    //@ has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item = &'a T"
+    // @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item = &'a T"
     type Item=&'a T;
 
     //@ has - '//*[@id="method.quux-1"]//h4[@class="code-header"]' 'fn quux(self)'
diff --git a/tests/rustdoc/auxiliary/precise-capturing.rs b/tests/rustdoc/auxiliary/precise-capturing.rs
new file mode 100644
index 00000000000..531d4dfdccc
--- /dev/null
+++ b/tests/rustdoc/auxiliary/precise-capturing.rs
@@ -0,0 +1,7 @@
+#![feature(precise_capturing)]
+
+pub fn cross_crate_empty() -> impl Sized + use<> {}
+
+pub fn cross_crate_missing() -> impl Sized {}
+
+pub fn cross_crate_args<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
diff --git a/tests/rustdoc/const-generics/const-impl.rs b/tests/rustdoc/const-generics/const-impl.rs
index ce536291290..279a7842254 100644
--- a/tests/rustdoc/const-generics/const-impl.rs
+++ b/tests/rustdoc/const-generics/const-impl.rs
@@ -1,5 +1,5 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![crate_name = "foo"]
 
 use std::marker::ConstParamTy;
diff --git a/tests/rustdoc/impl-trait-precise-capturing.rs b/tests/rustdoc/impl-trait-precise-capturing.rs
index d1987a555c1..a964a1f8518 100644
--- a/tests/rustdoc/impl-trait-precise-capturing.rs
+++ b/tests/rustdoc/impl-trait-precise-capturing.rs
@@ -1,6 +1,10 @@
+//@ aux-build:precise-capturing.rs
+
 #![crate_name = "foo"]
 #![feature(precise_capturing)]
 
+extern crate precise_capturing;
+
 //@ has foo/fn.two.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'b, 'a>"
 pub fn two<'a, 'b, 'c>() -> impl Sized + use<'b, 'a /* no 'c */> {}
 
@@ -12,3 +16,12 @@ pub fn none() -> impl Sized + use<> {}
 
 //@ has foo/fn.first.html '//section[@id="main-content"]//pre' "-> impl use<> + Sized"
 pub fn first() -> impl use<> + Sized {}
+
+//@ has foo/fn.cross_crate_empty.html '//section[@id="main-content"]//pre' "-> impl Sized + use<>"
+pub use precise_capturing::cross_crate_empty;
+
+//@ matches foo/fn.cross_crate_missing.html '//section[@id="main-content"]//pre' "-> impl Sized$"
+pub use precise_capturing::cross_crate_missing;
+
+//@ has foo/fn.cross_crate_args.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'a, T, N>"
+pub use precise_capturing::cross_crate_args;
diff --git a/tests/ui/asm/binary_asm_labels.stderr b/tests/ui/asm/binary_asm_labels.stderr
index 1f2943084f1..206d2da1779 100644
--- a/tests/ui/asm/binary_asm_labels.stderr
+++ b/tests/ui/asm/binary_asm_labels.stderr
@@ -4,7 +4,9 @@ error: avoid using labels containing only the digits `0` and `1` in inline assem
 LL |         asm!("0: jmp 0b");
    |               ^ use a different label that doesn't start with `0` or `1`
    |
-   = note: an LLVM bug makes these labels ambiguous with a binary literal number
+   = help: start numbering with `2` instead
+   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
    = note: `#[deny(binary_asm_labels)]` on by default
 
 error: avoid using labels containing only the digits `0` and `1` in inline assembly
@@ -13,7 +15,9 @@ error: avoid using labels containing only the digits `0` and `1` in inline assem
 LL |         asm!("1: jmp 1b");
    |               ^ use a different label that doesn't start with `0` or `1`
    |
-   = note: an LLVM bug makes these labels ambiguous with a binary literal number
+   = help: start numbering with `2` instead
+   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
 
 error: avoid using labels containing only the digits `0` and `1` in inline assembly
   --> $DIR/binary_asm_labels.rs:13:15
@@ -21,7 +25,9 @@ error: avoid using labels containing only the digits `0` and `1` in inline assem
 LL |         asm!("10: jmp 10b");
    |               ^^ use a different label that doesn't start with `0` or `1`
    |
-   = note: an LLVM bug makes these labels ambiguous with a binary literal number
+   = help: start numbering with `2` instead
+   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
 
 error: avoid using labels containing only the digits `0` and `1` in inline assembly
   --> $DIR/binary_asm_labels.rs:14:15
@@ -29,7 +35,9 @@ error: avoid using labels containing only the digits `0` and `1` in inline assem
 LL |         asm!("01: jmp 01b");
    |               ^^ use a different label that doesn't start with `0` or `1`
    |
-   = note: an LLVM bug makes these labels ambiguous with a binary literal number
+   = help: start numbering with `2` instead
+   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
 
 error: avoid using labels containing only the digits `0` and `1` in inline assembly
   --> $DIR/binary_asm_labels.rs:15:15
@@ -37,7 +45,9 @@ error: avoid using labels containing only the digits `0` and `1` in inline assem
 LL |         asm!("1001101: jmp 1001101b");
    |               ^^^^^^^ use a different label that doesn't start with `0` or `1`
    |
-   = note: an LLVM bug makes these labels ambiguous with a binary literal number
+   = help: start numbering with `2` instead
+   = note: an LLVM bug makes these labels ambiguous with a binary literal number on x86
+   = note: see <https://github.com/llvm/llvm-project/issues/99547> for more information
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/asm/binary_asm_labels_allowed.rs b/tests/ui/asm/binary_asm_labels_allowed.rs
new file mode 100644
index 00000000000..a21ab8d70f5
--- /dev/null
+++ b/tests/ui/asm/binary_asm_labels_allowed.rs
@@ -0,0 +1,17 @@
+//@ build-pass
+//@ only-aarch64
+
+// The `binary_asm_labels` lint should only be raised on `x86`. Make sure it
+// doesn't get raised on other platforms.
+
+use std::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!("0: bl 0b");
+        asm!("1: bl 1b");
+        asm!("10: bl 10b");
+        asm!("01: bl 01b");
+        asm!("1001101: bl 1001101b");
+    }
+}
diff --git a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.rs b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.rs
new file mode 100644
index 00000000000..e422026ca4a
--- /dev/null
+++ b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+
+extern "C" {
+    fn rust_interesting_average(_: i64, ...) -> f64;
+}
+
+fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
+    unsafe {
+        rust_interesting_average(
+            6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g, //~ ERROR use of moved value: `f` [E0382]
+        ) as i64
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr
new file mode 100644
index 00000000000..6997710ec89
--- /dev/null
+++ b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `f`
+  --> $DIR/move-error-suggest-clone-panic-issue-127915.rs:10:78
+   |
+LL | fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
+   |                                                       - move occurs because `f` has type `T`, which does not implement the `Copy` trait
+...
+LL |             6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g,
+   |                                       - value moved here                     ^ value used here after move
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/move-error-suggest-clone-panic-issue-127915.rs:7:9
+   |
+LL | fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
+   |         ^ consider constraining this type parameter with `Clone`
+...
+LL |             6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g,
+   |                                       - you could clone this value
+help: consider restricting type parameter `T`
+   |
+LL | fn test<T: Copy, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 {
+   |          ++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/cfg/diagnostics-cross-crate.rs b/tests/ui/cfg/diagnostics-cross-crate.rs
index 77dd91d6c28..00ac7e2fd08 100644
--- a/tests/ui/cfg/diagnostics-cross-crate.rs
+++ b/tests/ui/cfg/diagnostics-cross-crate.rs
@@ -11,12 +11,14 @@ fn main() {
     cfged_out::inner::uwu(); //~ ERROR cannot find function
     //~^ NOTE found an item that was configured out
     //~| NOTE not found in `cfged_out::inner`
+    //~| NOTE the item is gated here
 
     // The module isn't found - we would like to get a diagnostic, but currently don't due to
     // the awkward way the resolver diagnostics are currently implemented.
     cfged_out::inner::doesnt_exist::hello(); //~ ERROR failed to resolve
     //~^ NOTE could not find `doesnt_exist` in `inner`
     //~| NOTE found an item that was configured out
+    //~| NOTE the item is gated here
 
     // It should find the one in the right module, not the wrong one.
     cfged_out::inner::right::meow(); //~ ERROR cannot find function
@@ -28,4 +30,5 @@ fn main() {
     cfged_out::vanished(); //~ ERROR cannot find function
     //~^ NOTE found an item that was configured out
     //~| NOTE not found in `cfged_out`
+    //~| NOTE the item is gated here
 }
diff --git a/tests/ui/cfg/diagnostics-cross-crate.stderr b/tests/ui/cfg/diagnostics-cross-crate.stderr
index 8a238f36404..07ad4e3272d 100644
--- a/tests/ui/cfg/diagnostics-cross-crate.stderr
+++ b/tests/ui/cfg/diagnostics-cross-crate.stderr
@@ -1,5 +1,5 @@
 error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
-  --> $DIR/diagnostics-cross-crate.rs:17:23
+  --> $DIR/diagnostics-cross-crate.rs:18:23
    |
 LL |     cfged_out::inner::doesnt_exist::hello();
    |                       ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
@@ -9,6 +9,11 @@ note: found an item that was configured out
    |
 LL |     pub mod doesnt_exist {
    |             ^^^^^^^^^^^^
+note: the item is gated here
+  --> $DIR/auxiliary/cfged_out.rs:5:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `uwu` in crate `cfged_out`
   --> $DIR/diagnostics-cross-crate.rs:7:16
@@ -27,9 +32,14 @@ note: found an item that was configured out
    |
 LL |     pub fn uwu() {}
    |            ^^^
+note: the item is gated here
+  --> $DIR/auxiliary/cfged_out.rs:2:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `meow` in module `cfged_out::inner::right`
-  --> $DIR/diagnostics-cross-crate.rs:22:30
+  --> $DIR/diagnostics-cross-crate.rs:24:30
    |
 LL |     cfged_out::inner::right::meow();
    |                              ^^^^ not found in `cfged_out::inner::right`
@@ -39,10 +49,14 @@ note: found an item that was configured out
    |
 LL |         pub fn meow() {}
    |                ^^^^
-   = note: the item is gated behind the `what-a-cool-feature` feature
+note: the item is gated behind the `what-a-cool-feature` feature
+  --> $DIR/auxiliary/cfged_out.rs:16:15
+   |
+LL |         #[cfg(feature = "what-a-cool-feature")]
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `vanished` in crate `cfged_out`
-  --> $DIR/diagnostics-cross-crate.rs:28:16
+  --> $DIR/diagnostics-cross-crate.rs:30:16
    |
 LL |     cfged_out::vanished();
    |                ^^^^^^^^ not found in `cfged_out`
@@ -52,6 +66,11 @@ note: found an item that was configured out
    |
 LL | pub fn vanished() {}
    |        ^^^^^^^^
+note: the item is gated here
+  --> $DIR/auxiliary/cfged_out.rs:21:1
+   |
+LL | #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs
index 9b3208cb87c..9ae7d931fcb 100644
--- a/tests/ui/cfg/diagnostics-reexport.rs
+++ b/tests/ui/cfg/diagnostics-reexport.rs
@@ -4,7 +4,7 @@ pub mod inner {
         pub fn uwu() {}
     }
 
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
     pub use super::uwu;
     //~^ NOTE found an item that was configured out
 }
@@ -14,7 +14,7 @@ pub use a::x;
 //~| NOTE no `x` in `a`
 
 mod a {
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
     pub fn x() {}
     //~^ NOTE found an item that was configured out
 }
@@ -25,10 +25,10 @@ pub use b::{x, y};
 //~| NOTE no `y` in `b`
 
 mod b {
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
     pub fn x() {}
     //~^ NOTE found an item that was configured out
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
     pub fn y() {}
     //~^ NOTE found an item that was configured out
 }
diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr
index e25b7cf86e2..737202fdf9a 100644
--- a/tests/ui/cfg/diagnostics-reexport.stderr
+++ b/tests/ui/cfg/diagnostics-reexport.stderr
@@ -9,6 +9,11 @@ note: found an item that was configured out
    |
 LL |     pub fn x() {}
    |            ^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport.rs:17:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0432]: unresolved imports `b::x`, `b::y`
   --> $DIR/diagnostics-reexport.rs:22:13
@@ -23,11 +28,21 @@ note: found an item that was configured out
    |
 LL |     pub fn x() {}
    |            ^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport.rs:28:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 note: found an item that was configured out
   --> $DIR/diagnostics-reexport.rs:32:12
    |
 LL |     pub fn y() {}
    |            ^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport.rs:31:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `uwu` in module `inner`
   --> $DIR/diagnostics-reexport.rs:38:12
@@ -40,6 +55,11 @@ note: found an item that was configured out
    |
 LL |     pub use super::uwu;
    |                    ^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport.rs:7:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs
index b2a0fb58dd6..d6f8dd21a92 100644
--- a/tests/ui/cfg/diagnostics-same-crate.rs
+++ b/tests/ui/cfg/diagnostics-same-crate.rs
@@ -1,11 +1,13 @@
 #![allow(unexpected_cfgs)] // since we want to recognize them as unexpected
 
 pub mod inner {
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
     pub fn uwu() {}
     //~^ NOTE found an item that was configured out
 
-    #[cfg(FALSE)]
+    #[cfg(FALSE)] //~ NOTE the item is gated here
+    //~^ NOTE the item is gated here
+    //~| NOTE the item is gated here
     pub mod doesnt_exist {
         //~^ NOTE found an item that was configured out
         //~| NOTE found an item that was configured out
@@ -20,7 +22,7 @@ pub mod inner {
     }
 
     pub mod right {
-        #[cfg(feature = "what-a-cool-feature")]
+        #[cfg(feature = "what-a-cool-feature")] //~ NOTE the item is gated behind the `what-a-cool-feature` feature
         pub fn meow() {}
         //~^ NOTE found an item that was configured out
     }
@@ -55,7 +57,6 @@ fn main() {
     // It should find the one in the right module, not the wrong one.
     inner::right::meow(); //~ ERROR cannot find function
     //~| NOTE not found in `inner::right
-    //~| NOTE the item is gated behind the `what-a-cool-feature` feature
 
     // Exists in the crate root - we would generally want a diagnostic,
     // but currently don't have one.
diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr
index 86421736b8c..dd0d10c6567 100644
--- a/tests/ui/cfg/diagnostics-same-crate.stderr
+++ b/tests/ui/cfg/diagnostics-same-crate.stderr
@@ -1,41 +1,56 @@
 error[E0432]: unresolved import `super::inner::doesnt_exist`
-  --> $DIR/diagnostics-same-crate.rs:30:9
+  --> $DIR/diagnostics-same-crate.rs:32:9
    |
 LL |     use super::inner::doesnt_exist;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `doesnt_exist` in `inner`
    |
 note: found an item that was configured out
-  --> $DIR/diagnostics-same-crate.rs:9:13
+  --> $DIR/diagnostics-same-crate.rs:11:13
    |
 LL |     pub mod doesnt_exist {
    |             ^^^^^^^^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-same-crate.rs:8:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0432]: unresolved import `super::inner::doesnt_exist`
-  --> $DIR/diagnostics-same-crate.rs:33:23
+  --> $DIR/diagnostics-same-crate.rs:35:23
    |
 LL |     use super::inner::doesnt_exist::hi;
    |                       ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
    |
 note: found an item that was configured out
-  --> $DIR/diagnostics-same-crate.rs:9:13
+  --> $DIR/diagnostics-same-crate.rs:11:13
    |
 LL |     pub mod doesnt_exist {
    |             ^^^^^^^^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-same-crate.rs:8:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
-  --> $DIR/diagnostics-same-crate.rs:52:12
+  --> $DIR/diagnostics-same-crate.rs:54:12
    |
 LL |     inner::doesnt_exist::hello();
    |            ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
    |
 note: found an item that was configured out
-  --> $DIR/diagnostics-same-crate.rs:9:13
+  --> $DIR/diagnostics-same-crate.rs:11:13
    |
 LL |     pub mod doesnt_exist {
    |             ^^^^^^^^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-same-crate.rs:8:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `uwu` in module `inner`
-  --> $DIR/diagnostics-same-crate.rs:47:12
+  --> $DIR/diagnostics-same-crate.rs:49:12
    |
 LL |     inner::uwu();
    |            ^^^ not found in `inner`
@@ -45,28 +60,37 @@ note: found an item that was configured out
    |
 LL |     pub fn uwu() {}
    |            ^^^
+note: the item is gated here
+  --> $DIR/diagnostics-same-crate.rs:4:5
+   |
+LL |     #[cfg(FALSE)]
+   |     ^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `meow` in module `inner::right`
-  --> $DIR/diagnostics-same-crate.rs:56:19
+  --> $DIR/diagnostics-same-crate.rs:58:19
    |
 LL |     inner::right::meow();
    |                   ^^^^ not found in `inner::right`
    |
 note: found an item that was configured out
-  --> $DIR/diagnostics-same-crate.rs:24:16
+  --> $DIR/diagnostics-same-crate.rs:26:16
    |
 LL |         pub fn meow() {}
    |                ^^^^
-   = note: the item is gated behind the `what-a-cool-feature` feature
+note: the item is gated behind the `what-a-cool-feature` feature
+  --> $DIR/diagnostics-same-crate.rs:25:15
+   |
+LL |         #[cfg(feature = "what-a-cool-feature")]
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find function `uwu` in this scope
-  --> $DIR/diagnostics-same-crate.rs:43:5
+  --> $DIR/diagnostics-same-crate.rs:45:5
    |
 LL |     uwu();
    |     ^^^ not found in this scope
 
 error[E0425]: cannot find function `vanished` in this scope
-  --> $DIR/diagnostics-same-crate.rs:63:5
+  --> $DIR/diagnostics-same-crate.rs:64:5
    |
 LL |     vanished();
    |     ^^^^^^^^ not found in this scope
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 00a97ca1488..57cbe173c78 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra`
 LL |     cfg!(target_feature = "zebra");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 197 more
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 199 more
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 27 warnings emitted
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 78b7f0f5d99..00abb5f5e5c 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -285,7 +285,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |                   |
    |                   help: there is a expected value with a similar name: `"linux"`
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 29 warnings emitted
diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs
index b1c79db1375..10d869fcc85 100644
--- a/tests/ui/closures/binder/const-bound.rs
+++ b/tests/ui/closures/binder/const-bound.rs
@@ -3,5 +3,6 @@
 
 fn main()  {
     for<const N: i32> || -> () {};
-    //~^ ERROR late-bound const parameter not allowed on closures
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR late-bound const parameter not allowed on closures
 }
diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr
index 9c4fd95ed76..b805879f7fa 100644
--- a/tests/ui/closures/binder/const-bound.stderr
+++ b/tests/ui/closures/binder/const-bound.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/const-bound.rs:5:15
+   |
+LL |     for<const N: i32> || -> () {};
+   |               ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/const-bound.rs:1:37
    |
@@ -13,5 +19,5 @@ error: late-bound const parameter not allowed on closures
 LL |     for<const N: i32> || -> () {};
    |         ^^^^^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/closures/closure-no-fn-3.stderr b/tests/ui/closures/closure-no-fn-3.stderr
index bbf3677fb72..7711347c568 100644
--- a/tests/ui/closures/closure-no-fn-3.stderr
+++ b/tests/ui/closures/closure-no-fn-3.stderr
@@ -3,6 +3,12 @@ error[E0605]: non-primitive cast: `{closure@$DIR/closure-no-fn-3.rs:6:28: 6:30}`
    |
 LL |     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
+   |
+note: closures can only be coerced to `fn` types if they do not capture any variables
+  --> $DIR/closure-no-fn-3.rs:6:33
+   |
+LL |     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
+   |                                 ^ `b` captured here
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
new file mode 100644
index 00000000000..e6b0bf3e686
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[repr(C)]
+struct Wrapper<T>(T);
+
+struct Test<T: Copy> {
+    f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope
+    //~^ ERROR function pointer types may not have generic parameters
+    f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
+    //~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters
+    f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798]
+    f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64, //~ ERROR [E0798]
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
new file mode 100644
index 00000000000..fa68d95218c
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
@@ -0,0 +1,47 @@
+error: function pointer types may not have generic parameters
+  --> $DIR/generics.rs:15:42
+   |
+LL |     f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64,
+   |                                          ^^^^^^^^^
+
+error[E0412]: cannot find type `U` in this scope
+  --> $DIR/generics.rs:15:52
+   |
+LL | struct Test<T: Copy> {
+   |             - similarly named type parameter `T` defined here
+LL |     f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64,
+   |                                                    ^
+   |
+help: a type parameter with a similar name exists
+   |
+LL |     f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(T, u32, u32, u32) -> u64,
+   |                                                    ~
+help: you might be missing a type parameter
+   |
+LL | struct Test<T: Copy, U> {
+   |                    +++
+
+error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters
+  --> $DIR/generics.rs:17:43
+   |
+LL |     f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
+   |                                           ^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+
+error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
+  --> $DIR/generics.rs:19:9
+   |
+LL |     f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
+  --> $DIR/generics.rs:20:9
+   |
+LL |     f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0412, E0562, E0798.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs
deleted file mode 100644
index 364d0858afb..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ build-pass
-//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-//@ needs-llvm-components: arm
-#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
-#![no_core]
-#[lang="sized"]
-pub trait Sized { }
-#[lang="copy"]
-pub trait Copy { }
-impl Copy for u32 {}
-
-extern "rust-intrinsic" {
-    pub fn transmute<T, U>(e: T) -> U;
-}
-
-#[no_mangle]
-pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 {
-    let non_secure_function = unsafe {
-        transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>(
-            0x10000004,
-        )
-    };
-    non_secure_function(a, b, c, d)
-}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs
deleted file mode 100644
index c225a26c065..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//@ build-fail
-//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-//@ needs-llvm-components: arm
-#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
-#![no_core]
-#[lang="sized"]
-pub trait Sized { }
-#[lang="copy"]
-pub trait Copy { }
-impl Copy for u32 {}
-
-extern "rust-intrinsic" {
-    pub fn transmute<T, U>(e: T) -> U;
-}
-
-#[no_mangle]
-pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 {
-    let non_secure_function = unsafe {
-        transmute::<
-            usize,
-            extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32>
-        (
-            0x10000004,
-        )
-    };
-    non_secure_function(a, b, c, d, e)
-}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr
deleted file mode 100644
index a8aced2483e..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr
+++ /dev/null
@@ -1,4 +0,0 @@
-error: <unknown>:0:0: in function test i32 (i32, i32, i32, i32, i32): call to non-secure function would require passing arguments on stack
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs
new file mode 100644
index 00000000000..083a563bd7b
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[repr(C, align(16))]
+#[allow(unused)]
+pub struct AlignRelevant(u32);
+
+#[no_mangle]
+pub fn test(
+    f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32), //~ ERROR [E0798]
+    f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16),            //~ ERROR [E0798]
+    f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),                      //~ ERROR [E0798]
+    f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),                 //~ ERROR [E0798]
+    f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),                           //~ ERROR [E0798]
+) {
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr
new file mode 100644
index 00000000000..a5f5e1c3151
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr
@@ -0,0 +1,43 @@
+error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/params-via-stack.rs:17:63
+   |
+LL |     f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, x: u32, y: u32),
+   |                                                               ^^^^^^^^^^^^^^ these arguments don't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/params-via-stack.rs:18:63
+   |
+LL |     f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16),
+   |                                                               ^^^ this argument doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/params-via-stack.rs:19:53
+   |
+LL |     f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32),
+   |                                                     ^^^ this argument doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/params-via-stack.rs:20:58
+   |
+LL |     f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32),
+   |                                                          ^^^ this argument doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/params-via-stack.rs:21:43
+   |
+LL |     f5: extern "C-cmse-nonsecure-call" fn([u32; 5]),
+   |                                           ^^^^^^^^ this argument doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0798`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs
new file mode 100644
index 00000000000..e6af1d60e77
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs
@@ -0,0 +1,54 @@
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[repr(C)]
+pub struct ReprCU64(u64);
+
+#[repr(C)]
+pub struct ReprCBytes(u8, u8, u8, u8, u8);
+
+#[repr(C)]
+pub struct U64Compound(u32, u32);
+
+#[repr(C, align(16))]
+pub struct ReprCAlign16(u16);
+
+#[no_mangle]
+pub fn test(
+    f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798]
+    f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798]
+    f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798]
+    f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798]
+    f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5],  //~ ERROR [E0798]
+) {
+}
+
+#[allow(improper_ctypes_definitions)]
+struct Test {
+    u128: extern "C-cmse-nonsecure-call" fn() -> u128, //~ ERROR [E0798]
+    i128: extern "C-cmse-nonsecure-call" fn() -> i128, //~ ERROR [E0798]
+}
+
+#[repr(C)]
+pub union ReprCUnionU64 {
+    _unused: u64,
+}
+
+#[repr(Rust)]
+pub union ReprRustUnionU64 {
+    _unused: u64,
+}
+
+#[no_mangle]
+pub fn test_union(
+    f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, //~ ERROR [E0798]
+    f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64,    //~ ERROR [E0798]
+) {
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr
new file mode 100644
index 00000000000..89f7f159d6e
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr
@@ -0,0 +1,84 @@
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:35:50
+   |
+LL |     u128: extern "C-cmse-nonsecure-call" fn() -> u128,
+   |                                                  ^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:36:50
+   |
+LL |     i128: extern "C-cmse-nonsecure-call" fn() -> i128,
+   |                                                  ^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:25:48
+   |
+LL |     f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64,
+   |                                                ^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:26:48
+   |
+LL |     f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes,
+   |                                                ^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:27:48
+   |
+LL |     f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound,
+   |                                                ^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:28:48
+   |
+LL |     f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16,
+   |                                                ^^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:29:48
+   |
+LL |     f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5],
+   |                                                ^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:51:48
+   |
+LL |     f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64,
+   |                                                ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/return-via-stack.rs:52:48
+   |
+LL |     f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64,
+   |                                                ^^^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0798`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs
new file mode 100644
index 00000000000..9fda55c2a48
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs
@@ -0,0 +1,53 @@
+//@ build-pass
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[repr(transparent)]
+pub struct ReprTransparentStruct<T> {
+    _marker1: (),
+    _marker2: (),
+    field: T,
+    _marker3: (),
+}
+
+#[repr(transparent)]
+pub enum ReprTransparentEnumU64 {
+    A(u64),
+}
+
+#[repr(C)]
+pub struct U32Compound(u16, u16);
+
+#[no_mangle]
+#[allow(improper_ctypes_definitions)]
+pub fn params(
+    f1: extern "C-cmse-nonsecure-call" fn(),
+    f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32),
+    f3: extern "C-cmse-nonsecure-call" fn(u64, u64),
+    f4: extern "C-cmse-nonsecure-call" fn(u128),
+    f5: extern "C-cmse-nonsecure-call" fn(f64, f32, f32),
+    f6: extern "C-cmse-nonsecure-call" fn(ReprTransparentStruct<u64>, U32Compound),
+    f7: extern "C-cmse-nonsecure-call" fn([u32; 4]),
+) {
+}
+
+#[no_mangle]
+pub fn returns(
+    f1: extern "C-cmse-nonsecure-call" fn() -> u32,
+    f2: extern "C-cmse-nonsecure-call" fn() -> u64,
+    f3: extern "C-cmse-nonsecure-call" fn() -> i64,
+    f4: extern "C-cmse-nonsecure-call" fn() -> f64,
+    f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 4],
+    f6: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct<u64>,
+    f7: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct<ReprTransparentStruct<u64>>,
+    f8: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentEnumU64,
+    f9: extern "C-cmse-nonsecure-call" fn() -> U32Compound,
+) {
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/README.md b/tests/ui/codegen/equal-pointers-unequal/README.md
new file mode 100644
index 00000000000..343f9646a32
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/README.md
@@ -0,0 +1,22 @@
+See https://github.com/rust-lang/rust/issues/107975
+
+Basically, if you have two pointers with the same address but from two different allocations,
+the compiler gets confused whether their addresses are equal or not,
+resulting in some self-contradictory behavior of the compiled code.
+
+This folder contains some examples.
+They all boil down to allocating a variable on the stack, taking its address,
+getting rid of the variable, and then doing it all again.
+This way we end up with two addresses stored in two `usize`s (`a` and `b`).
+The addresses are (probably) equal but (definitely) come from two different allocations.
+Logically, we would expect that exactly one of the following options holds true:
+1. `a == b`
+2. `a != b`
+Sadly, the compiler does not always agree.
+
+Due to Rust having at least three meaningfully different ways
+to get a variable's address as an `usize`,
+each example is provided in three versions, each in the corresponding subfolder:
+1. `./as-cast/` for `&v as *const _ as usize`,
+2. `./strict-provenance/` for `addr_of!(v).addr()`,
+2. `./exposed-provenance/` for `addr_of!(v).expose_provenance()`.
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
new file mode 100644
index 00000000000..e2a00ce173d
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
@@ -0,0 +1,21 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+    let b: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs
new file mode 100644
index 00000000000..15434de50f7
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs
@@ -0,0 +1,22 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
+
+fn f() -> usize {
+    let v = 0;
+    &v as *const _ as usize
+}
+
+fn main() {
+    let a = f();
+    let b = f();
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
new file mode 100644
index 00000000000..d13fd4b63b3
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
@@ -0,0 +1,30 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    let b = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    assert_eq!(format!("{}", a == b), "false");
+    assert_eq!(format!("{}", cmp_in(a, b)), "false");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+    assert_eq!(a.to_string(), b.to_string());
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
new file mode 100644
index 00000000000..9a1ace86e4d
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
@@ -0,0 +1,30 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    let b = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    assert_eq!(a.to_string(), b.to_string());
+    assert_eq!(format!("{}", a == b), "true");
+    assert_eq!(format!("{}", cmp_in(a, b)), "true");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
new file mode 100644
index 00000000000..f33a9e511b6
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
@@ -0,0 +1,20 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+fn main() {
+    let a = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    let b = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+
+    assert_ne!(a, b);
+    println!("{a}"); // or b
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
new file mode 100644
index 00000000000..eda83e999a5
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
@@ -0,0 +1,23 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+fn main() {
+    let a = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+    let b = {
+        let v = 0;
+        &v as *const _ as usize
+    };
+
+    assert_ne!(a, b);
+    assert_ne!(a, b);
+    let c = a;
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
+    println!("{a} {b}");
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
new file mode 100644
index 00000000000..97a875f15bc
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
@@ -0,0 +1,63 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+use std::cell::{Ref, RefCell};
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+    let b: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+    let i: usize = b - a;
+
+    // A surprise tool that will help us later.
+    let arr = [
+        RefCell::new(Some(Box::new(1u8))),
+        RefCell::new(None),
+        RefCell::new(None),
+        RefCell::new(None),
+    ];
+
+    // `i` is not 0
+    assert_ne!(i, 0);
+
+    // Let's borrow the `i`-th element.
+    // If `i` is out of bounds, indexing will panic.
+    let r: Ref<Option<Box<u8>>> = arr[i].borrow();
+
+    // If we got here, it means `i` was in bounds.
+    // Now, two options are possible:
+    // EITHER `i` is not 0 (as we have asserted above),
+    // so the unwrap will panic, because only the 0-th element is `Some`
+    // OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
+    let r: &Box<u8> = r.as_ref().unwrap();
+
+    // If we got here, it means `i` *was* actually 0.
+    // Let's ignore the fact that the assert has lied
+    // and try to take a mutable reference to the 0-th element.
+    // `borrow_mut` should panic, because we are sill holding on
+    // to a shared `Ref` for the same `RefCell`.
+    *arr[0].borrow_mut() = None;
+
+    // But it doesn't panic!
+    // We have successfully replaced `Some(Box)` with `None`,
+    // while holding a shared reference to it.
+    // No unsafe involved.
+
+    // The `Box` has been deallocated by now, so this is a dangling reference!
+    let r: &u8 = &*r;
+    println!("{:p}", r);
+
+    // The following might segfault. Or it might not.
+    // Depends on the platform semantics
+    // and whatever happened to the pointed-to memory after deallocation.
+    // let u: u8 = *r;
+    // println!("{u}");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
new file mode 100644
index 00000000000..d1aa95a9a56
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
@@ -0,0 +1,28 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+    let b: usize = {
+        let v = 0u8;
+        &v as *const _ as usize
+    };
+
+    // So, are `a` and `b` equal?
+
+    // Let's check their difference.
+    let i: usize = a - b;
+    // It's not zero, which means `a` and `b` are not equal.
+    assert_ne!(i, 0);
+    // But it looks like zero...
+    assert_eq!(i.to_string(), "0");
+    // ...and now it *is* zero?
+    assert_eq!(i, 0);
+    // So `a` and `b` are equal after all?
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
new file mode 100644
index 00000000000..0c9df7ecd78
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
@@ -0,0 +1,25 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
new file mode 100644
index 00000000000..b188b794d1f
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
@@ -0,0 +1,26 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+fn f() -> usize {
+    let v = 0;
+    ptr::from_ref(&v).expose_provenance()
+}
+
+fn main() {
+    let a = f();
+    let b = f();
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
new file mode 100644
index 00000000000..7f64e23b9c1
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
@@ -0,0 +1,34 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    assert_eq!(format!("{}", a == b), "false");
+    assert_eq!(format!("{}", cmp_in(a, b)), "false");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+    assert_eq!(a.to_string(), b.to_string());
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
new file mode 100644
index 00000000000..3417296ce12
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
@@ -0,0 +1,34 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    assert_eq!(a.to_string(), b.to_string());
+    assert_eq!(format!("{}", a == b), "true");
+    assert_eq!(format!("{}", cmp_in(a, b)), "true");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
new file mode 100644
index 00000000000..e1e9e3f46b8
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
@@ -0,0 +1,24 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+
+    assert_ne!(a, b);
+    println!("{a}"); // or b
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
new file mode 100644
index 00000000000..8d581e8c9e9
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
@@ -0,0 +1,27 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).expose_provenance()
+    };
+
+    assert_ne!(a, b);
+    assert_ne!(a, b);
+    let c = a;
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
+    println!("{a} {b}");
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
new file mode 100644
index 00000000000..506f114cd2a
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
@@ -0,0 +1,68 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+#![feature(exposed_provenance)]
+
+use std::{
+    cell::{Ref, RefCell},
+    ptr,
+};
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let i: usize = b - a;
+
+    // A surprise tool that will help us later.
+    let arr = [
+        RefCell::new(Some(Box::new(1u8))),
+        RefCell::new(None),
+        RefCell::new(None),
+        RefCell::new(None),
+    ];
+
+    // `i` is not 0
+    assert_ne!(i, 0);
+
+    // Let's borrow the `i`-th element.
+    // If `i` is out of bounds, indexing will panic.
+    let r: Ref<Option<Box<u8>>> = arr[i].borrow();
+
+    // If we got here, it means `i` was in bounds.
+    // Now, two options are possible:
+    // EITHER `i` is not 0 (as we have asserted above),
+    // so the unwrap will panic, because only the 0-th element is `Some`
+    // OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
+    let r: &Box<u8> = r.as_ref().unwrap();
+
+    // If we got here, it means `i` *was* actually 0.
+    // Let's ignore the fact that the assert has lied
+    // and try to take a mutable reference to the 0-th element.
+    // `borrow_mut` should panic, because we are sill holding on
+    // to a shared `Ref` for the same `RefCell`.
+    *arr[0].borrow_mut() = None;
+
+    // But it doesn't panic!
+    // We have successfully replaced `Some(Box)` with `None`,
+    // while holding a shared reference to it.
+    // No unsafe involved.
+
+    // The `Box` has been deallocated by now, so this is a dangling reference!
+    let r: &u8 = &*r;
+    println!("{:p}", r);
+
+    // The following might segfault. Or it might not.
+    // Depends on the platform semantics
+    // and whatever happened to the pointed-to memory after deallocation.
+    // let u: u8 = *r;
+    // println!("{u}");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
new file mode 100644
index 00000000000..603db5e08f4
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
@@ -0,0 +1,32 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+#![feature(exposed_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).expose_provenance()
+    };
+
+    // So, are `a` and `b` equal?
+
+    // Let's check their difference.
+    let i: usize = a - b;
+    // It's not zero, which means `a` and `b` are not equal.
+    assert_ne!(i, 0);
+    // But it looks like zero...
+    assert_eq!(i.to_string(), "0");
+    // ...and now it *is* zero?
+    assert_eq!(i, 0);
+    // So `a` and `b` are equal after all?
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
new file mode 100644
index 00000000000..0243c2bfe95
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
@@ -0,0 +1,25 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
new file mode 100644
index 00000000000..29758036a21
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
@@ -0,0 +1,26 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn f() -> usize {
+    let v = 0;
+    ptr::from_ref(&v).addr()
+}
+
+fn main() {
+    let a = f();
+    let b = f();
+
+    // `a` and `b` are not equal.
+    assert_ne!(a, b);
+    // But they are the same number.
+    assert_eq!(format!("{a}"), format!("{b}"));
+    // And they are equal.
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
new file mode 100644
index 00000000000..11925261a65
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
@@ -0,0 +1,34 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    assert_eq!(format!("{}", a == b), "false");
+    assert_eq!(format!("{}", cmp_in(a, b)), "false");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+    assert_eq!(a.to_string(), b.to_string());
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
new file mode 100644
index 00000000000..e628bb90faa
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
@@ -0,0 +1,34 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+#[inline(never)]
+fn cmp(a: usize, b: usize) -> bool {
+    a == b
+}
+
+#[inline(always)]
+fn cmp_in(a: usize, b: usize) -> bool {
+    a == b
+}
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    assert_eq!(a.to_string(), b.to_string());
+    assert_eq!(format!("{}", a == b), "true");
+    assert_eq!(format!("{}", cmp_in(a, b)), "true");
+    assert_eq!(format!("{}", cmp(a, b)), "true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
new file mode 100644
index 00000000000..075e3475a32
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
@@ -0,0 +1,24 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+
+    assert_ne!(a, b);
+    println!("{a}"); // or b
+    assert_eq!(a, b);
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
new file mode 100644
index 00000000000..6d7b6fa33e0
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
@@ -0,0 +1,27 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0;
+        ptr::from_ref(&v).addr()
+    };
+
+    assert_ne!(a, b);
+    assert_ne!(a, b);
+    let c = a;
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
+    println!("{a} {b}");
+    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
new file mode 100644
index 00000000000..67660d285a4
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
@@ -0,0 +1,68 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+#![feature(strict_provenance)]
+
+use std::{
+    cell::{Ref, RefCell},
+    ptr,
+};
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+    let i: usize = b - a;
+
+    // A surprise tool that will help us later.
+    let arr = [
+        RefCell::new(Some(Box::new(1u8))),
+        RefCell::new(None),
+        RefCell::new(None),
+        RefCell::new(None),
+    ];
+
+    // `i` is not 0
+    assert_ne!(i, 0);
+
+    // Let's borrow the `i`-th element.
+    // If `i` is out of bounds, indexing will panic.
+    let r: Ref<Option<Box<u8>>> = arr[i].borrow();
+
+    // If we got here, it means `i` was in bounds.
+    // Now, two options are possible:
+    // EITHER `i` is not 0 (as we have asserted above),
+    // so the unwrap will panic, because only the 0-th element is `Some`
+    // OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
+    let r: &Box<u8> = r.as_ref().unwrap();
+
+    // If we got here, it means `i` *was* actually 0.
+    // Let's ignore the fact that the assert has lied
+    // and try to take a mutable reference to the 0-th element.
+    // `borrow_mut` should panic, because we are sill holding on
+    // to a shared `Ref` for the same `RefCell`.
+    *arr[0].borrow_mut() = None;
+
+    // But it doesn't panic!
+    // We have successfully replaced `Some(Box)` with `None`,
+    // while holding a shared reference to it.
+    // No unsafe involved.
+
+    // The `Box` has been deallocated by now, so this is a dangling reference!
+    let r: &u8 = &*r;
+    println!("{:p}", r);
+
+    // The following might segfault. Or it might not.
+    // Depends on the platform semantics
+    // and whatever happened to the pointed-to memory after deallocation.
+    // let u: u8 = *r;
+    // println!("{u}");
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
new file mode 100644
index 00000000000..a89310f9930
--- /dev/null
+++ b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
@@ -0,0 +1,32 @@
+//@ known-bug: #107975
+//@ compile-flags: -Copt-level=2
+//@ run-pass
+
+// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
+
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let a: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+    let b: usize = {
+        let v = 0u8;
+        ptr::from_ref(&v).addr()
+    };
+
+    // So, are `a` and `b` equal?
+
+    // Let's check their difference.
+    let i: usize = a - b;
+    // It's not zero, which means `a` and `b` are not equal.
+    assert_ne!(i, 0);
+    // But it looks like zero...
+    assert_eq!(i.to_string(), "0");
+    // ...and now it *is* zero?
+    assert_eq!(i, 0);
+    // So `a` and `b` are equal after all?
+}
diff --git a/tests/ui/coherence/negative-coherence/regions-in-canonical.rs b/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
index 6c2a11e0135..f0424e72434 100644
--- a/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
+++ b/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
@@ -1,13 +1,12 @@
 //@ check-pass
 
-#![feature(adt_const_params)]
-//~^ WARN the feature `adt_const_params` is incomplete
+#![feature(adt_const_params, unsized_const_params)]
+//~^ WARN the feature `unsized_const_params` is incomplete
 #![feature(with_negative_coherence, negative_impls)]
 
 pub trait A<const K: &'static str> {}
 pub trait C {}
 
-
 struct W<T>(T);
 
 // Negative coherence:
diff --git a/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr b/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr
index dc8c926f182..72044915294 100644
--- a/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr
+++ b/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr
@@ -1,8 +1,8 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/regions-in-canonical.rs:3:12
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/regions-in-canonical.rs:3:30
    |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
    = note: `#[warn(incomplete_features)]` on by default
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
index 8035fce0914..e90426ec0c7 100644
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
+++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 #![feature(adt_const_params, lazy_type_alias)]
-//~^ WARN: the feature `adt_const_params` is incomplete
-//~| WARN: the feature `lazy_type_alias` is incomplete
+//~^ WARN: the feature `lazy_type_alias` is incomplete
 
 pub type Matrix = [usize; 1];
 const EMPTY_MATRIX: Matrix = [0; 1];
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr
index 5c6981077b2..4f5133474c6 100644
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr
+++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr
@@ -1,12 +1,3 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/alias_const_param_ty-1.rs:2:12
-   |
-LL | #![feature(adt_const_params, lazy_type_alias)]
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/alias_const_param_ty-1.rs:2:30
    |
@@ -14,6 +5,7 @@ LL | #![feature(adt_const_params, lazy_type_alias)]
    |                              ^^^^^^^^^^^^^^^
    |
    = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = note: `#[warn(incomplete_features)]` on by default
 
-warning: 2 warnings emitted
+warning: 1 warning emitted
 
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs
index a576b75341c..961e1a9cfbf 100644
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs
+++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 #![feature(adt_const_params)]
-//~^ WARN: the feature `adt_const_params` is incomplete
 
 const EMPTY_MATRIX: <Type as Trait>::Matrix = [0; 1];
 
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr
deleted file mode 100644
index dbc8ab71636..00000000000
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/alias_const_param_ty-2.rs:2:12
-   |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs b/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs
new file mode 100644
index 00000000000..e2ba459f8dd
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/auxiliary/unsized_const_param.rs
@@ -0,0 +1,7 @@
+#![feature(adt_const_params, unsized_const_params)]
+
+#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+pub struct Foo([u8]);
+
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+pub struct GenericNotUnsizedParam<T>(T);
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
index c4d2d02ba70..35539193a27 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs
@@ -1,13 +1,13 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
-fn check(_: impl std::marker::ConstParamTy) {}
+fn check(_: impl std::marker::UnsizedConstParamTy) {}
 
 fn main() {
-    check(main);               //~ error: `fn() {main}` can't be used as a const parameter type
-    check(|| {});              //~ error: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as a const parameter type
-    check(main as fn());       //~ error: `fn()` can't be used as a const parameter type
-    check(&mut ());            //~ error: `&mut ()` can't be used as a const parameter type
+    check(main); //~ error: `fn() {main}` can't be used as a const parameter type
+    check(|| {}); //~ error: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as a const parameter type
+    check(main as fn()); //~ error: `fn()` can't be used as a const parameter type
+    check(&mut ()); //~ error: `&mut ()` can't be used as a const parameter type
     check(&mut () as *mut ()); //~ error: `*mut ()` can't be used as a const parameter type
-    check(&() as *const ());   //~ error: `*const ()` can't be used as a const parameter type
+    check(&() as *const ()); //~ error: `*const ()` can't be used as a const parameter type
 }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
index d96491f4f20..694f5a5c1a9 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
@@ -2,15 +2,15 @@ error[E0277]: `fn() {main}` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:7:11
    |
 LL |     check(main);
-   |     ----- ^^^^ the trait `ConstParamTy` is not implemented for fn item `fn() {main}`
+   |     ----- ^^^^ the trait `UnsizedConstParamTy` is not implemented for fn item `fn() {main}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this function
    |
 LL |     check(main());
@@ -20,15 +20,15 @@ error[E0277]: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as
   --> $DIR/const_param_ty_bad.rs:8:11
    |
 LL |     check(|| {});
-   |     ----- ^^^^^ the trait `ConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
+   |     ----- ^^^^^ the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this closure
    |
 LL |     check(|| {}());
@@ -38,15 +38,15 @@ error[E0277]: `fn()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:9:11
    |
 LL |     check(main as fn());
-   |     ----- ^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `fn()`
+   |     ----- ^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `fn()`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this function pointer
    |
 LL |     check(main as fn()());
@@ -56,16 +56,16 @@ error[E0277]: `&mut ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:10:11
    |
 LL |     check(&mut ());
-   |     ----- ^^^^^^^ the trait `ConstParamTy` is not implemented for `&mut ()`
+   |     ----- ^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `&mut ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = note: `ConstParamTy` is implemented for `&()`, but not for `&mut ()`
+   = note: `UnsizedConstParamTy` is implemented for `&()`, but not for `&mut ()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: consider removing the leading `&`-reference
    |
 LL -     check(&mut ());
@@ -76,31 +76,31 @@ error[E0277]: `*mut ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:11:11
    |
 LL |     check(&mut () as *mut ());
-   |     ----- ^^^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*mut ()`
+   |     ----- ^^^^^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `*mut ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `ConstParamTy` is implemented for `()`
+   = help: the trait `UnsizedConstParamTy` is implemented for `()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `*const ()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:12:11
    |
 LL |     check(&() as *const ());
-   |     ----- ^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*const ()`
+   |     ----- ^^^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `*const ()`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `ConstParamTy` is implemented for `()`
+   = help: the trait `UnsizedConstParamTy` is implemented for `()`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad.rs:4:18
    |
-LL | fn check(_: impl std::marker::ConstParamTy) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs
index b0e3b13cc1e..2008a96310a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs
@@ -1,10 +1,10 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 #[derive(PartialEq, Eq)]
 struct NotParam;
 
-fn check<T: std::marker::ConstParamTy>() {}
+fn check<T: std::marker::ConstParamTy_>() {}
 
 fn main() {
     check::<[NotParam; 0]>();
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
index 771d661f615..9852e181b9a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr
@@ -2,14 +2,14 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad_empty_array.rs:10:13
    |
 LL |     check::<[NotParam; 0]>();
-   |             ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 0]: ConstParamTy`
+   |             ^^^^^^^^^^^^^ the trait `ConstParamTy_` is not implemented for `NotParam`, which is required by `[NotParam; 0]: ConstParamTy_`
    |
-   = note: required for `[NotParam; 0]` to implement `ConstParamTy`
+   = note: required for `[NotParam; 0]` to implement `ConstParamTy_`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_bad_empty_array.rs:7:13
    |
-LL | fn check<T: std::marker::ConstParamTy>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::ConstParamTy_>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
index e4dc76703a2..7ffdafa33e9 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs
@@ -1,13 +1,13 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 #[derive(PartialEq, Eq)]
 struct NotParam;
 
-fn check<T: std::marker::ConstParamTy + ?Sized>() {}
+fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
 
 fn main() {
-    check::<&NotParam>();      //~ error: `NotParam` can't be used as a const parameter type
-    check::<[NotParam]>();     //~ error: `NotParam` can't be used as a const parameter type
+    check::<&NotParam>(); //~ error: `NotParam` can't be used as a const parameter type
+    check::<[NotParam]>(); //~ error: `NotParam` can't be used as a const parameter type
     check::<[NotParam; 17]>(); //~ error: `NotParam` can't be used as a const parameter type
 }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
index 83c34c41f10..e63ae582fd5 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr
@@ -2,40 +2,40 @@ error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13
    |
 LL |     check::<&NotParam>();
-   |             ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `&NotParam: ConstParamTy`
+   |             ^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `&NotParam: UnsizedConstParamTy`
    |
-   = note: required for `&NotParam` to implement `ConstParamTy`
+   = note: required for `&NotParam` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13
    |
 LL |     check::<[NotParam]>();
-   |             ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam]: ConstParamTy`
+   |             ^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam]: UnsizedConstParamTy`
    |
-   = note: required for `[NotParam]` to implement `ConstParamTy`
+   = note: required for `[NotParam]` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: `NotParam` can't be used as a const parameter type
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13
    |
 LL |     check::<[NotParam; 17]>();
-   |             ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 17]: ConstParamTy`
+   |             ^^^^^^^^^^^^^^ the trait `UnsizedConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 17]: UnsizedConstParamTy`
    |
-   = note: required for `[NotParam; 17]` to implement `ConstParamTy`
+   = note: required for `[NotParam; 17]` to implement `UnsizedConstParamTy`
 note: required by a bound in `check`
   --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13
    |
-LL | fn check<T: std::marker::ConstParamTy + ?Sized>() {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+LL | fn check<T: std::marker::UnsizedConstParamTy + ?Sized>() {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
index bce24059de8..98a8eb6ee95 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
@@ -1,7 +1,9 @@
 //@ check-pass
+
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
-use std::marker::ConstParamTy;
+
+use std::marker::UnsizedConstParamTy;
 
 #[derive(PartialEq, Eq)]
 struct S<T> {
@@ -9,16 +11,15 @@ struct S<T> {
     gen: T,
 }
 
-impl<T: ConstParamTy> ConstParamTy for S<T> {}
+impl<T: UnsizedConstParamTy> UnsizedConstParamTy for S<T> {}
 
-#[derive(PartialEq, Eq, ConstParamTy)]
+#[derive(PartialEq, Eq, UnsizedConstParamTy)]
 struct D<T> {
     field: u8,
     gen: T,
 }
 
-
-fn check<T: ConstParamTy + ?Sized>() {}
+fn check<T: UnsizedConstParamTy + ?Sized>() {}
 
 fn main() {
     check::<u8>();
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
index 74283a37afc..8b3d0546010 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
@@ -1,5 +1,5 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 #[derive(PartialEq, Eq)]
 struct NotParam;
@@ -7,11 +7,11 @@ struct NotParam;
 #[derive(PartialEq, Eq)]
 struct CantParam(NotParam);
 
-impl std::marker::ConstParamTy for CantParam {}
-//~^ error: the trait `ConstParamTy` cannot be implemented for this type
+impl std::marker::UnsizedConstParamTy for CantParam {}
+//~^ error: the trait `ConstParamTy_` cannot be implemented for this type
 
-#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
-//~^ error: the trait `ConstParamTy` cannot be implemented for this type
+#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+//~^ error: the trait `ConstParamTy_` cannot be implemented for this type
 struct CantParamDerive(NotParam);
 
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
index 52b65d6061a..808a569fcad 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
@@ -1,22 +1,22 @@
-error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
-  --> $DIR/const_param_ty_impl_bad_field.rs:10:36
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/const_param_ty_impl_bad_field.rs:10:43
    |
 LL | struct CantParam(NotParam);
-   |                  -------- this field does not implement `ConstParamTy`
+   |                  -------- this field does not implement `ConstParamTy_`
 LL |
-LL | impl std::marker::ConstParamTy for CantParam {}
-   |                                    ^^^^^^^^^
+LL | impl std::marker::UnsizedConstParamTy for CantParam {}
+   |                                           ^^^^^^^^^
 
-error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
   --> $DIR/const_param_ty_impl_bad_field.rs:13:10
    |
-LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | struct CantParamDerive(NotParam);
-   |                        -------- this field does not implement `ConstParamTy`
+   |                        -------- this field does not implement `ConstParamTy_`
    |
-   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index dfb8a36ec53..761a6387a24 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -1,22 +1,22 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 #[derive(PartialEq, Eq)]
 struct ImplementsConstParamTy;
-impl std::marker::ConstParamTy for ImplementsConstParamTy {}
+impl std::marker::UnsizedConstParamTy for ImplementsConstParamTy {}
 
 struct CantParam(ImplementsConstParamTy);
 
-impl std::marker::ConstParamTy for CantParam {}
+impl std::marker::UnsizedConstParamTy for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(PartialEq)]`
 //~| the trait bound `CantParam: Eq` is not satisfied
 
-#[derive(std::marker::ConstParamTy)]
+#[derive(std::marker::UnsizedConstParamTy)]
 //~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]`
 //~| the trait bound `CantParamDerive: Eq` is not satisfied
 struct CantParamDerive(ImplementsConstParamTy);
 
-fn check<T: std::marker::ConstParamTy>() {}
+fn check<T: std::marker::UnsizedConstParamTy>() {}
 
 fn main() {
     check::<ImplementsConstParamTy>();
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index e213808cf7b..80d9942c591 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -1,10 +1,10 @@
 error[E0277]: the trait bound `CantParam: Eq` is not satisfied
-  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:43
    |
-LL | impl std::marker::ConstParamTy for CantParam {}
-   |                                    ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam`
+LL | impl std::marker::UnsizedConstParamTy for CantParam {}
+   |                                           ^^^^^^^^^ the trait `Eq` is not implemented for `CantParam`
    |
-note: required by a bound in `ConstParamTy`
+note: required by a bound in `UnsizedConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 help: consider annotating `CantParam` with `#[derive(Eq)]`
    |
@@ -13,23 +13,23 @@ LL | struct CantParam(ImplementsConstParamTy);
    |
 
 error[E0277]: the type `CantParam` does not `#[derive(PartialEq)]`
-  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:43
    |
-LL | impl std::marker::ConstParamTy for CantParam {}
-   |                                    ^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParam`
+LL | impl std::marker::UnsizedConstParamTy for CantParam {}
+   |                                           ^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParam`
    |
-note: required by a bound in `ConstParamTy`
+note: required by a bound in `UnsizedConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
 error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
    |
-LL | #[derive(std::marker::ConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
+LL | #[derive(std::marker::UnsizedConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive`
    |
-note: required by a bound in `ConstParamTy`
+note: required by a bound in `UnsizedConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `CantParamDerive` with `#[derive(Eq)]`
    |
 LL + #[derive(Eq)]
@@ -39,12 +39,12 @@ LL | struct CantParamDerive(ImplementsConstParamTy);
 error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]`
   --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10
    |
-LL | #[derive(std::marker::ConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive`
+LL | #[derive(std::marker::UnsizedConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralPartialEq` is not implemented for `CantParamDerive`
    |
-note: required by a bound in `ConstParamTy`
+note: required by a bound in `UnsizedConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
-   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
index f2986f9cc60..236b3bc162a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
@@ -1,5 +1,5 @@
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 union Union {
     a: u8,
@@ -12,10 +12,10 @@ impl PartialEq for Union {
 }
 impl Eq for Union {}
 
-impl std::marker::ConstParamTy for Union {}
-//~^ ERROR the type `Union` does not `#[derive(PartialEq)]`
+impl std::marker::UnsizedConstParamTy for Union {}
+//~^ ERROR the trait `ConstParamTy` may not be implemented for this type
 
-#[derive(std::marker::ConstParamTy)]
+#[derive(std::marker::UnsizedConstParamTy)]
 //~^ ERROR this trait cannot be derived for unions
 union UnionDerive {
     a: u8,
@@ -28,5 +28,4 @@ impl PartialEq for UnionDerive {
 }
 impl Eq for UnionDerive {}
 
-
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
index 4c937db6c3a..837c289c924 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
@@ -1,18 +1,14 @@
 error: this trait cannot be derived for unions
   --> $DIR/const_param_ty_impl_union.rs:18:10
    |
-LL | #[derive(std::marker::ConstParamTy)]
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[derive(std::marker::UnsizedConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the type `Union` does not `#[derive(PartialEq)]`
-  --> $DIR/const_param_ty_impl_union.rs:15:36
+error: the trait `ConstParamTy` may not be implemented for this type
+  --> $DIR/const_param_ty_impl_union.rs:15:43
    |
-LL | impl std::marker::ConstParamTy for Union {}
-   |                                    ^^^^^ the trait `StructuralPartialEq` is not implemented for `Union`
-   |
-note: required by a bound in `ConstParamTy`
-  --> $SRC_DIR/core/src/marker.rs:LL:COL
+LL | impl std::marker::UnsizedConstParamTy for Union {}
+   |                                           ^^^^^ type is not a structure or enumeration
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs
new file mode 100644
index 00000000000..6a553c2e085
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs
@@ -0,0 +1,12 @@
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::{ConstParamTy_, UnsizedConstParamTy};
+
+fn foo(a: &dyn ConstParamTy_) {}
+//~^ ERROR: the trait `ConstParamTy_`
+
+fn bar(a: &dyn UnsizedConstParamTy) {}
+//~^ ERROR: the trait `UnsizedConstParamTy`
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr
new file mode 100644
index 00000000000..ba38f63d5df
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr
@@ -0,0 +1,33 @@
+error[E0038]: the trait `ConstParamTy_` cannot be made into an object
+  --> $DIR/const_param_ty_object_safety.rs:6:12
+   |
+LL | fn foo(a: &dyn ConstParamTy_) {}
+   |            ^^^^^^^^^^^^^^^^^ `ConstParamTy_` 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>
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | fn foo(a: &impl ConstParamTy_) {}
+   |            ~~~~
+
+error[E0038]: the trait `UnsizedConstParamTy` cannot be made into an object
+  --> $DIR/const_param_ty_object_safety.rs:9:12
+   |
+LL | fn bar(a: &dyn UnsizedConstParamTy) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` 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>
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | fn bar(a: &impl UnsizedConstParamTy) {}
+   |            ~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.rs b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.rs
index 0d1f023d565..7a4970c2e3c 100644
--- a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.rs
+++ b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.rs
@@ -1,18 +1,30 @@
 // issue: rust-lang/rust/#83993
 
 #![feature(adt_const_params)]
-//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+
 fn bug<'a>()
 where
     for<'b> [(); {
         let x: &'b ();
         //~^ ERROR generic parameters may not be used in const operations
         0
-    }]:
-{}
+    }]:,
+{
+}
 
-fn bad() where for<'b> [();{let _:&'b (); 0}]: Sized { }
-//~^ ERROR generic parameters may not be used in const operations
-fn good() where for<'b> [();{0}]: Sized { }
+fn bad()
+where
+    for<'b> [(); {
+        let _: &'b ();
+        //~^ ERROR generic parameters may not be used in const operations
+        0
+    }]: Sized,
+{
+}
+fn good()
+where
+    for<'b> [(); { 0 }]: Sized,
+{
+}
 
 pub fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr
index a49dfc31916..b7e459511f1 100644
--- a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr
+++ b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr
@@ -8,22 +8,13 @@ LL |         let x: &'b ();
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/index-oob-ice-83993.rs:14:36
+  --> $DIR/index-oob-ice-83993.rs:18:17
    |
-LL | fn bad() where for<'b> [();{let _:&'b (); 0}]: Sized { }
-   |                                    ^^ cannot perform const operation using `'b`
+LL |         let _: &'b ();
+   |                 ^^ cannot perform const operation using `'b`
    |
    = note: lifetime parameters may not be used in const expressions
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/index-oob-ice-83993.rs:3:12
-   |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
index 9f05c53eef0..3a283442a0b 100644
--- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
+++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs
@@ -4,15 +4,18 @@
 use std::marker::ConstParamTy;
 
 #[derive(ConstParamTy)]
-//~^ the trait `ConstParamTy` cannot be implemented for this ty
+//~^ the trait `ConstParamTy_` cannot be implemented for this ty
+//~| the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo([*const u8; 1]);
 
 #[derive(ConstParamTy)]
-//~^ the trait `ConstParamTy` cannot be implemented for this ty
+//~^ the trait `ConstParamTy_` cannot be implemented for this ty
+//~| the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo2([*mut u8; 1]);
 
 #[derive(ConstParamTy)]
-//~^ the trait `ConstParamTy` cannot be implemented for this ty
+//~^ the trait `ConstParamTy_` cannot be implemented for this ty
+//~| the trait `ConstParamTy_` cannot be implemented for this ty
 struct Foo3([fn(); 1]);
 
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
index 9e772e8d55d..c2520f1d103 100644
--- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
+++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr
@@ -1,51 +1,99 @@
-error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
   --> $DIR/nested_bad_const_param_ty.rs:6:10
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-LL |
+...
 LL | struct Foo([*const u8; 1]);
-   |            -------------- this field does not implement `ConstParamTy`
+   |            -------------- this field does not implement `ConstParamTy_`
    |
-note: the `ConstParamTy` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:8:12
+note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_`
+  --> $DIR/nested_bad_const_param_ty.rs:9:12
    |
 LL | struct Foo([*const u8; 1]);
    |            ^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:10:10
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/nested_bad_const_param_ty.rs:11:10
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-LL |
+...
 LL | struct Foo2([*mut u8; 1]);
-   |             ------------ this field does not implement `ConstParamTy`
+   |             ------------ this field does not implement `ConstParamTy_`
    |
-note: the `ConstParamTy` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:12:13
+note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_`
+  --> $DIR/nested_bad_const_param_ty.rs:14:13
    |
 LL | struct Foo2([*mut u8; 1]);
    |             ^^^^^^^^^^^^
    = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
-  --> $DIR/nested_bad_const_param_ty.rs:14:10
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/nested_bad_const_param_ty.rs:16:10
    |
 LL | #[derive(ConstParamTy)]
    |          ^^^^^^^^^^^^
-LL |
+...
 LL | struct Foo3([fn(); 1]);
-   |             --------- this field does not implement `ConstParamTy`
+   |             --------- this field does not implement `ConstParamTy_`
    |
-note: the `ConstParamTy` impl for `[fn(); 1]` requires that `fn(): ConstParamTy`
-  --> $DIR/nested_bad_const_param_ty.rs:16:13
+note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_`
+  --> $DIR/nested_bad_const_param_ty.rs:19:13
    |
 LL | struct Foo3([fn(); 1]);
    |             ^^^^^^^^^
    = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/nested_bad_const_param_ty.rs:6:10
+   |
+LL | #[derive(ConstParamTy)]
+   |          ^^^^^^^^^^^^
+...
+LL | struct Foo([*const u8; 1]);
+   |            -------------- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: UnsizedConstParamTy`
+  --> $DIR/nested_bad_const_param_ty.rs:9:12
+   |
+LL | struct Foo([*const u8; 1]);
+   |            ^^^^^^^^^^^^^^
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/nested_bad_const_param_ty.rs:11:10
+   |
+LL | #[derive(ConstParamTy)]
+   |          ^^^^^^^^^^^^
+...
+LL | struct Foo2([*mut u8; 1]);
+   |             ------------ this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: UnsizedConstParamTy`
+  --> $DIR/nested_bad_const_param_ty.rs:14:13
+   |
+LL | struct Foo2([*mut u8; 1]);
+   |             ^^^^^^^^^^^^
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/nested_bad_const_param_ty.rs:16:10
+   |
+LL | #[derive(ConstParamTy)]
+   |          ^^^^^^^^^^^^
+...
+LL | struct Foo3([fn(); 1]);
+   |             --------- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): UnsizedConstParamTy`
+  --> $DIR/nested_bad_const_param_ty.rs:19:13
+   |
+LL | struct Foo3([fn(); 1]);
+   |             ^^^^^^^^^
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
index c55f3dcec68..f28bebf85db 100644
--- a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
+++ b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs
@@ -3,7 +3,7 @@
 // issues rust-lang/rust#111911
 // test for ICE opaque type with non-universal region substs
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub async fn foo<const X: &'static str>() {}
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs
new file mode 100644
index 00000000000..a1ee1c4cdd5
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.rs
@@ -0,0 +1,11 @@
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::UnsizedConstParamTy;
+
+struct Foo;
+
+impl UnsizedConstParamTy for &'static Foo {}
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr
new file mode 100644
index 00000000000..5ca8e6c7516
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-1.stderr
@@ -0,0 +1,9 @@
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/reference_pointee_is_const_param-1.rs:8:30
+   |
+LL | impl UnsizedConstParamTy for &'static Foo {}
+   |                              ^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs
new file mode 100644
index 00000000000..ac1b522f469
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.rs
@@ -0,0 +1,27 @@
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
+// Regression test for #119299
+
+use std::marker::UnsizedConstParamTy;
+
+#[derive(Eq, PartialEq)]
+struct ConstStrU(*const u8, usize);
+
+impl UnsizedConstParamTy for &'static ConstStrU {}
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+
+impl ConstStrU {
+    const fn from_bytes(bytes: &'static [u8]) -> Self {
+        Self(bytes.as_ptr(), bytes.len())
+    }
+}
+
+const fn chars_s<const S: &'static ConstStrU>() -> [char; 3] {
+    ['a', 'b', 'c']
+}
+
+fn main() {
+    const A: &'static ConstStrU = &ConstStrU::from_bytes(b"abc");
+    chars_s::<A>();
+}
diff --git a/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr
new file mode 100644
index 00000000000..5e5f6cc642d
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/reference_pointee_is_const_param-2.stderr
@@ -0,0 +1,9 @@
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/reference_pointee_is_const_param-2.rs:11:30
+   |
+LL | impl UnsizedConstParamTy for &'static ConstStrU {}
+   |                              ^^^^^^^^^^^^^^^^^^ this field does not implement `ConstParamTy_`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs
index 0d2e65c45ea..33988bc0678 100644
--- a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs
+++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs
@@ -8,9 +8,8 @@ fn uwu_0<const N: &'static mut ()>() {}
 //~| HELP: add `#![feature(adt_const_params)]`
 //~| HELP: add `#![feature(adt_const_params)]`
 //~| HELP: add `#![feature(adt_const_params)]`
-//~| HELP: add `#![feature(adt_const_params)]`
-//~| HELP: add `#![feature(adt_const_params)]`
-//~| HELP: add `#![feature(adt_const_params)]`
+//~| HELP: add `#![feature(unsized_const_params)]`
+//~| HELP: add `#![feature(unsized_const_params)]`
 
 // Needs the feature but can be used, so suggest adding the feature.
 fn owo_0<const N: &'static u32>() {}
diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr
index cd4349623d7..aafc0640dd2 100644
--- a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr
+++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr
@@ -7,7 +7,7 @@ LL | fn uwu_0<const N: &'static mut ()>() {}
    = note: the only supported types are integers, `bool` and `char`
 
 error: `&'static u32` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:16:19
+  --> $DIR/suggest_feature_only_when_possible.rs:15:19
    |
 LL | fn owo_0<const N: &'static u32>() {}
    |                   ^^^^^^^^^^^^
@@ -17,9 +17,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `Meow` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:24:20
+  --> $DIR/suggest_feature_only_when_possible.rs:23:20
    |
 LL | fn meow_0<const N: Meow>() {}
    |                    ^^^^
@@ -31,7 +35,7 @@ LL + #![feature(adt_const_params)]
    |
 
 error: `&'static Meow` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:26:20
+  --> $DIR/suggest_feature_only_when_possible.rs:25:20
    |
 LL | fn meow_1<const N: &'static Meow>() {}
    |                    ^^^^^^^^^^^^^
@@ -41,45 +45,37 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `[Meow; 100]` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:28:20
+  --> $DIR/suggest_feature_only_when_possible.rs:27:20
    |
 LL | fn meow_2<const N: [Meow; 100]>() {}
    |                    ^^^^^^^^^^^
    |
    = 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: `(Meow, u8)` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:30:20
+  --> $DIR/suggest_feature_only_when_possible.rs:29:20
    |
 LL | fn meow_3<const N: (Meow, u8)>() {}
    |                    ^^^^^^^^^^
    |
    = 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: `(Meow, String)` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:35:20
+  --> $DIR/suggest_feature_only_when_possible.rs:34:20
    |
 LL | fn meow_4<const N: (Meow, String)>() {}
    |                    ^^^^^^^^^^^^^^
    |
    = 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: `String` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:39:19
+  --> $DIR/suggest_feature_only_when_possible.rs:38:19
    |
 LL | fn nya_0<const N: String>() {}
    |                   ^^^^^^
@@ -87,7 +83,7 @@ LL | fn nya_0<const N: String>() {}
    = note: the only supported types are integers, `bool` and `char`
 
 error: `Vec<u32>` is forbidden as the type of a const generic parameter
-  --> $DIR/suggest_feature_only_when_possible.rs:41:19
+  --> $DIR/suggest_feature_only_when_possible.rs:40:19
    |
 LL | fn nya_1<const N: Vec<u32>>() {}
    |                   ^^^^^^^^
diff --git a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs
new file mode 100644
index 00000000000..b0934508399
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.rs
@@ -0,0 +1,13 @@
+#![feature(adt_const_params, unsized_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::UnsizedConstParamTy;
+
+trait Trait {}
+
+impl UnsizedConstParamTy for dyn Trait {}
+//~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
+
+fn foo<const N: dyn Trait>() {}
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr
new file mode 100644
index 00000000000..9933ba6e335
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/trait_objects_as_a_const_generic.stderr
@@ -0,0 +1,8 @@
+error: the trait `ConstParamTy` may not be implemented for this type
+  --> $DIR/trait_objects_as_a_const_generic.rs:8:30
+   |
+LL | impl UnsizedConstParamTy for dyn Trait {}
+   |                              ^^^^^^^^^ type is not a structure or enumeration
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs
new file mode 100644
index 00000000000..f6e5bd6e355
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs
@@ -0,0 +1,20 @@
+//@ aux-build:unsized_const_param.rs
+#![feature(adt_const_params)]
+
+extern crate unsized_const_param;
+
+use std::marker::ConstParamTy;
+
+#[derive(ConstParamTy, Eq, PartialEq)]
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+struct A([u8]);
+
+#[derive(ConstParamTy, Eq, PartialEq)]
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+struct B(&'static [u8]);
+
+#[derive(ConstParamTy, Eq, PartialEq)]
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+struct C(unsized_const_param::Foo);
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr
new file mode 100644
index 00000000000..7a4f9b99c63
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr
@@ -0,0 +1,36 @@
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/unsized_field-1.rs:8:10
+   |
+LL | #[derive(ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^
+LL |
+LL | struct A([u8]);
+   |          ---- this field does not implement `ConstParamTy_`
+   |
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/unsized_field-1.rs:12:10
+   |
+LL | #[derive(ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^
+LL |
+LL | struct B(&'static [u8]);
+   |          ------------- this field does not implement `ConstParamTy_`
+   |
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/unsized_field-1.rs:16:10
+   |
+LL | #[derive(ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^
+LL |
+LL | struct C(unsized_const_param::Foo);
+   |          ------------------------ this field does not implement `ConstParamTy_`
+   |
+   = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-2.rs b/tests/ui/const-generics/adt_const_params/unsized_field-2.rs
new file mode 100644
index 00000000000..e4a3a481b4e
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-2.rs
@@ -0,0 +1,14 @@
+//@ aux-build:unsized_const_param.rs
+#![feature(adt_const_params, unsized_const_params)]
+//~^ WARN: the feature `unsized_const_params` is incomplete
+
+extern crate unsized_const_param;
+
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type
+struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+
+#[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)]
+struct B(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr
new file mode 100644
index 00000000000..15acece538f
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr
@@ -0,0 +1,28 @@
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unsized_field-2.rs:2:30
+   |
+LL | #![feature(adt_const_params, unsized_const_params)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+  --> $DIR/unsized_field-2.rs:7:10
+   |
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+   |          ---------------------------------------------------------- this field does not implement `ConstParamTy_`
+   |
+note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `&'static [u8]: ConstParamTy_`
+  --> $DIR/unsized_field-2.rs:9:10
+   |
+LL | struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>);
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
index 1c81b14f8f5..62267224738 100644
--- a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
+++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
@@ -39,6 +39,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:14:15
@@ -51,6 +55,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:22:15
@@ -63,6 +71,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:26:17
@@ -75,6 +87,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:17:21
@@ -87,6 +103,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/const-generics/const-param-elided-lifetime.rs b/tests/ui/const-generics/const-param-elided-lifetime.rs
index ef1eecb59be..e75073de98d 100644
--- a/tests/ui/const-generics/const-param-elided-lifetime.rs
+++ b/tests/ui/const-generics/const-param-elided-lifetime.rs
@@ -3,7 +3,7 @@
 // elided lifetimes within the type of a const generic parameters to be 'static, like elided
 // lifetimes within const/static items.
 //@ revisions: full min
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: &u8>;
@@ -12,8 +12,8 @@ struct A<const N: &u8>;
 trait B {}
 
 impl<const N: &u8> A<N> {
-//~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[min]~^^ ERROR `&u8` is forbidden
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //[min]~^^ ERROR `&u8` is forbidden
     fn foo<const M: &u8>(&self) {}
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
     //[min]~^^ ERROR `&u8` is forbidden
diff --git a/tests/ui/const-generics/const-param-with-additional-obligations.rs b/tests/ui/const-generics/const-param-with-additional-obligations.rs
index f53cf85cdd3..98097e86c7d 100644
--- a/tests/ui/const-generics/const-param-with-additional-obligations.rs
+++ b/tests/ui/const-generics/const-param-with-additional-obligations.rs
@@ -1,14 +1,14 @@
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::ConstParamTy;
+use std::marker::UnsizedConstParamTy;
 
 #[derive(Eq, PartialEq)]
 struct Foo<T>(T);
 
 trait Other {}
 
-impl<T> ConstParamTy for Foo<T> where T: Other + ConstParamTy {}
+impl<T> UnsizedConstParamTy for Foo<T> where T: Other + UnsizedConstParamTy {}
 
 fn foo<const N: Foo<u8>>() {}
 //~^ ERROR `Foo<u8>` must implement `ConstParamTy` to be used as the type of a const generic parameter
diff --git a/tests/ui/const-generics/float-generic.adt_const_params.stderr b/tests/ui/const-generics/float-generic.adt_const_params.stderr
index cae4806368a..1a7c19ba4be 100644
--- a/tests/ui/const-generics/float-generic.adt_const_params.stderr
+++ b/tests/ui/const-generics/float-generic.adt_const_params.stderr
@@ -1,5 +1,5 @@
 error[E0741]: `f32` is forbidden as the type of a const generic parameter
-  --> $DIR/float-generic.rs:5:17
+  --> $DIR/float-generic.rs:7:17
    |
 LL | fn foo<const F: f32>() {}
    |                 ^^^
diff --git a/tests/ui/const-generics/float-generic.full.stderr b/tests/ui/const-generics/float-generic.full.stderr
new file mode 100644
index 00000000000..1a7c19ba4be
--- /dev/null
+++ b/tests/ui/const-generics/float-generic.full.stderr
@@ -0,0 +1,9 @@
+error[E0741]: `f32` is forbidden as the type of a const generic parameter
+  --> $DIR/float-generic.rs:7:17
+   |
+LL | fn foo<const F: f32>() {}
+   |                 ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/const-generics/float-generic.rs b/tests/ui/const-generics/float-generic.rs
index aaf63a93d70..f92e1667701 100644
--- a/tests/ui/const-generics/float-generic.rs
+++ b/tests/ui/const-generics/float-generic.rs
@@ -1,4 +1,6 @@
-//@ revisions: simple adt_const_params
+//@ revisions: simple adt_const_params full
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
+#![cfg_attr(full, allow(incomplete_features))]
 #![cfg_attr(adt_const_params, feature(adt_const_params))]
 #![cfg_attr(adt_const_params, allow(incomplete_features))]
 
diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr
index eccf9059ee3..2999bce32d6 100644
--- a/tests/ui/const-generics/float-generic.simple.stderr
+++ b/tests/ui/const-generics/float-generic.simple.stderr
@@ -1,5 +1,5 @@
 error: `f32` is forbidden as the type of a const generic parameter
-  --> $DIR/float-generic.rs:5:17
+  --> $DIR/float-generic.rs:7:17
    |
 LL | fn foo<const F: f32>() {}
    |                 ^^^
diff --git a/tests/ui/const-generics/fn-const-param-call.adt_const_params.stderr b/tests/ui/const-generics/fn-const-param-call.adt_const_params.stderr
new file mode 100644
index 00000000000..fd9346a533e
--- /dev/null
+++ b/tests/ui/const-generics/fn-const-param-call.adt_const_params.stderr
@@ -0,0 +1,15 @@
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:13:25
+   |
+LL | struct Wrapper<const F: fn() -> u32>;
+   |                         ^^^^^^^^^^^
+
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:15:15
+   |
+LL | impl<const F: fn() -> u32> Wrapper<F> {
+   |               ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/const-generics/fn-const-param-call.full.stderr b/tests/ui/const-generics/fn-const-param-call.full.stderr
index b55c2449858..fd9346a533e 100644
--- a/tests/ui/const-generics/fn-const-param-call.full.stderr
+++ b/tests/ui/const-generics/fn-const-param-call.full.stderr
@@ -1,11 +1,11 @@
 error[E0741]: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:11:25
+  --> $DIR/fn-const-param-call.rs:13:25
    |
 LL | struct Wrapper<const F: fn() -> u32>;
    |                         ^^^^^^^^^^^
 
 error[E0741]: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:13:15
+  --> $DIR/fn-const-param-call.rs:15:15
    |
 LL | impl<const F: fn() -> u32> Wrapper<F> {
    |               ^^^^^^^^^^^
diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr
index 2d316fba1e9..d37766b28c9 100644
--- a/tests/ui/const-generics/fn-const-param-call.min.stderr
+++ b/tests/ui/const-generics/fn-const-param-call.min.stderr
@@ -1,5 +1,5 @@
 error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:11:25
+  --> $DIR/fn-const-param-call.rs:13:25
    |
 LL | struct Wrapper<const F: fn() -> u32>;
    |                         ^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | struct Wrapper<const F: fn() -> u32>;
    = note: the only supported types are integers, `bool` and `char`
 
 error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:13:15
+  --> $DIR/fn-const-param-call.rs:15:15
    |
 LL | impl<const F: fn() -> u32> Wrapper<F> {
    |               ^^^^^^^^^^^
diff --git a/tests/ui/const-generics/fn-const-param-call.rs b/tests/ui/const-generics/fn-const-param-call.rs
index ce780143178..d536c240239 100644
--- a/tests/ui/const-generics/fn-const-param-call.rs
+++ b/tests/ui/const-generics/fn-const-param-call.rs
@@ -1,8 +1,10 @@
 // Check that functions cannot be used as const parameters.
-//@ revisions: full min
+//@ revisions: min adt_const_params full
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 fn function() -> u32 {
     17
@@ -11,7 +13,7 @@ fn function() -> u32 {
 struct Wrapper<const F: fn() -> u32>; //~ ERROR: using function pointers as const generic parameters
 
 impl<const F: fn() -> u32> Wrapper<F> {
-//~^ ERROR: using function pointers as const generic parameters
+    //~^ ERROR: using function pointers as const generic parameters
     fn call() -> u32 {
         F()
     }
diff --git a/tests/ui/const-generics/fn-const-param-infer.adt_const_params.stderr b/tests/ui/const-generics/fn-const-param-infer.adt_const_params.stderr
new file mode 100644
index 00000000000..54f3bff172a
--- /dev/null
+++ b/tests/ui/const-generics/fn-const-param-infer.adt_const_params.stderr
@@ -0,0 +1,30 @@
+error[E0741]: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-infer.rs:8:25
+   |
+LL | struct Checked<const F: fn(usize) -> bool>;
+   |                         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/fn-const-param-infer.rs:33:25
+   |
+LL |     let _ = Checked::<{ generic_arg::<u32> }>;
+   |                         ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
+   |
+   = note: expected fn pointer `fn(usize) -> _`
+                 found fn item `fn(u32) -> _ {generic_arg::<u32>}`
+
+error[E0282]: type annotations needed
+  --> $DIR/fn-const-param-infer.rs:35:23
+   |
+LL |     let _ = Checked::<generic>;
+   |                       ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
+   |
+help: consider specifying the generic argument
+   |
+LL |     let _ = Checked::<generic::<T>>;
+   |                              +++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0308, E0741.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/const-generics/fn-const-param-infer.full.stderr b/tests/ui/const-generics/fn-const-param-infer.full.stderr
index 753558636e1..54f3bff172a 100644
--- a/tests/ui/const-generics/fn-const-param-infer.full.stderr
+++ b/tests/ui/const-generics/fn-const-param-infer.full.stderr
@@ -1,20 +1,20 @@
 error[E0741]: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-infer.rs:6:25
+  --> $DIR/fn-const-param-infer.rs:8:25
    |
 LL | struct Checked<const F: fn(usize) -> bool>;
    |                         ^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/fn-const-param-infer.rs:23:24
+  --> $DIR/fn-const-param-infer.rs:33:25
    |
-LL |     let _ = Checked::<{generic_arg::<u32>}>;
-   |                        ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
+LL |     let _ = Checked::<{ generic_arg::<u32> }>;
+   |                         ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
    |
    = note: expected fn pointer `fn(usize) -> _`
                  found fn item `fn(u32) -> _ {generic_arg::<u32>}`
 
 error[E0282]: type annotations needed
-  --> $DIR/fn-const-param-infer.rs:25:23
+  --> $DIR/fn-const-param-infer.rs:35:23
    |
 LL |     let _ = Checked::<generic>;
    |                       ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr
index 01e224f8d9c..4da503d344a 100644
--- a/tests/ui/const-generics/fn-const-param-infer.min.stderr
+++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr
@@ -1,5 +1,5 @@
 error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-infer.rs:6:25
+  --> $DIR/fn-const-param-infer.rs:8:25
    |
 LL | struct Checked<const F: fn(usize) -> bool>;
    |                         ^^^^^^^^^^^^^^^^^
@@ -7,16 +7,16 @@ LL | struct Checked<const F: fn(usize) -> bool>;
    = note: the only supported types are integers, `bool` and `char`
 
 error[E0308]: mismatched types
-  --> $DIR/fn-const-param-infer.rs:23:24
+  --> $DIR/fn-const-param-infer.rs:33:25
    |
-LL |     let _ = Checked::<{generic_arg::<u32>}>;
-   |                        ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
+LL |     let _ = Checked::<{ generic_arg::<u32> }>;
+   |                         ^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
    |
    = note: expected fn pointer `fn(usize) -> _`
                  found fn item `fn(u32) -> _ {generic_arg::<u32>}`
 
 error[E0282]: type annotations needed
-  --> $DIR/fn-const-param-infer.rs:25:23
+  --> $DIR/fn-const-param-infer.rs:35:23
    |
 LL |     let _ = Checked::<generic>;
    |                       ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
diff --git a/tests/ui/const-generics/fn-const-param-infer.rs b/tests/ui/const-generics/fn-const-param-infer.rs
index ed0bb9f7217..5f1958df26e 100644
--- a/tests/ui/const-generics/fn-const-param-infer.rs
+++ b/tests/ui/const-generics/fn-const-param-infer.rs
@@ -1,17 +1,27 @@
-//@ revisions: full min
+//@ revisions: min adt_const_params full
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 struct Checked<const F: fn(usize) -> bool>;
 //~^ ERROR: using function pointers as const generic parameters
 
-fn not_one(val: usize) -> bool { val != 1 }
-fn not_two(val: usize) -> bool { val != 2 }
+fn not_one(val: usize) -> bool {
+    val != 1
+}
+fn not_two(val: usize) -> bool {
+    val != 2
+}
 
-fn generic_arg<T>(val: T) -> bool { true }
+fn generic_arg<T>(val: T) -> bool {
+    true
+}
 
-fn generic<T>(val: usize) -> bool { val != 1 }
+fn generic<T>(val: usize) -> bool {
+    val != 1
+}
 
 fn main() {
     let _: Option<Checked<not_one>> = None;
@@ -19,11 +29,11 @@ fn main() {
     let _: Checked<not_one> = Checked::<not_two>;
 
     let _ = Checked::<generic_arg>;
-    let _ = Checked::<{generic_arg::<usize>}>;
-    let _ = Checked::<{generic_arg::<u32>}>; //~ ERROR: mismatched types
+    let _ = Checked::<{ generic_arg::<usize> }>;
+    let _ = Checked::<{ generic_arg::<u32> }>; //~ ERROR: mismatched types
 
     let _ = Checked::<generic>; //~ ERROR: type annotations needed
-    let _ = Checked::<{generic::<u16>}>;
-    let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
-    let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
+    let _ = Checked::<{ generic::<u16> }>;
+    let _: Checked<{ generic::<u16> }> = Checked::<{ generic::<u16> }>;
+    let _: Checked<{ generic::<u32> }> = Checked::<{ generic::<u16> }>;
 }
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100360.rs b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs
index b7e677a4a1e..37f015d5e0f 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-100360.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 // (this requires debug assertions)
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 fn foo<const B: &'static bool>(arg: &'static bool) -> bool {
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-89851.rs b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs
index 78189c5225c..f93ba30856d 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-89851.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 // (this requires debug assertions)
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub const BAR: () = ice::<"">();
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
index 5a6565fe2f1..443d0a2fe87 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
-#![feature(adt_const_params, generic_const_exprs)]
-//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 //~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub struct Changes<const CHANGES: &'static [&'static str]>
@@ -16,9 +16,7 @@ where
     [(); CHANGES.len()]:,
 {
     pub const fn new() -> Self {
-        Self {
-            changes: [0; CHANGES.len()],
-        }
+        Self { changes: [0; CHANGES.len()] }
     }
 }
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
index 1cceaece715..b6b297593a2 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
@@ -1,17 +1,17 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-1.rs:3:12
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-97047-ice-1.rs:3:30
    |
-LL | #![feature(adt_const_params, generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-1.rs:3:30
+  --> $DIR/issue-97047-ice-1.rs:3:52
    |
-LL | #![feature(adt_const_params, generic_const_exprs)]
-   |                              ^^^^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+   |                                                    ^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
index 1338f40208c..6a91b522567 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
-#![feature(adt_const_params, generic_const_exprs)]
-//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 //~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub struct Changes<const CHANGES: &'static [&'static str]>
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
index 774e842bcbe..c0c7dcc79dc 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
@@ -1,17 +1,17 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-2.rs:3:12
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-97047-ice-2.rs:3:30
    |
-LL | #![feature(adt_const_params, generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-2.rs:3:30
+  --> $DIR/issue-97047-ice-2.rs:3:52
    |
-LL | #![feature(adt_const_params, generic_const_exprs)]
-   |                              ^^^^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
+   |                                                    ^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
diff --git a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
index 5673f1dd073..ffa9d960e04 100644
--- a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
+++ b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
@@ -7,7 +7,8 @@
 pub fn foo()
 where
     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
-    //~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
 {}
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
index 5924a673da9..814022f26b9 100644
--- a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
@@ -1,8 +1,14 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/no-entry-found-for-key-ice-gce-nlb-113133.rs:9:15
+   |
+LL |     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
+   |               ^
+
 error: defaults for generic parameters are not allowed in `for<...>` binders
   --> $DIR/no-entry-found-for-key-ice-gce-nlb-113133.rs:9:9
    |
 LL |     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
index 5e4acd80e93..2a6d9f53317 100644
--- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
+++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
@@ -1,14 +1,14 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/intrinsics-type_name-as-const-argument.rs:15:44
+  --> $DIR/intrinsics-type_name-as-const-argument.rs:14:45
    |
-LL |     T: Trait<{std::intrinsics::type_name::<T>()}>
-   |                                            ^ cannot perform const operation using `T`
+LL |     T: Trait<{ std::intrinsics::type_name::<T>() }>,
+   |                                             ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22
+  --> $DIR/intrinsics-type_name-as-const-argument.rs:9:22
    |
 LL | trait Trait<const S: &'static str> {}
    |                      ^^^^^^^^^^^^
@@ -18,6 +18,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs
index 02e6d27a27e..79c20fe81e3 100644
--- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs
+++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs
@@ -2,8 +2,7 @@
 //@ revisions: full min
 
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(adt_const_params, generic_const_exprs))]
-
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params, generic_const_exprs))]
 #![feature(core_intrinsics)]
 #![feature(const_type_name)]
 
@@ -12,10 +11,10 @@ trait Trait<const S: &'static str> {}
 
 struct Bug<T>
 where
-    T: Trait<{std::intrinsics::type_name::<T>()}>
+    T: Trait<{ std::intrinsics::type_name::<T>() }>,
     //[min]~^ ERROR generic parameters may not be used in const operations
 {
-    t: T
+    t: T,
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/issue-66451.rs b/tests/ui/const-generics/issue-66451.rs
index c8d5515e987..0b8693e0e67 100644
--- a/tests/ui/const-generics/issue-66451.rs
+++ b/tests/ui/const-generics/issue-66451.rs
@@ -1,30 +1,20 @@
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-use std::marker::ConstParamTy;
+use std::marker::UnsizedConstParamTy;
 
-#[derive(Debug, PartialEq, Eq, ConstParamTy)]
+#[derive(Debug, PartialEq, Eq, UnsizedConstParamTy)]
 struct Foo {
     value: i32,
     nested: &'static Bar<i32>,
 }
 
-#[derive(Debug, PartialEq, Eq, ConstParamTy)]
+#[derive(Debug, PartialEq, Eq, UnsizedConstParamTy)]
 struct Bar<T>(T);
 
 struct Test<const F: Foo>;
 
 fn main() {
-    let x: Test<{
-        Foo {
-            value: 3,
-            nested: &Bar(4),
-        }
-    }> = Test;
-    let y: Test<{
-        Foo {
-            value: 3,
-            nested: &Bar(5),
-        }
-    }> = x; //~ ERROR mismatched types
+    let x: Test<{ Foo { value: 3, nested: &Bar(4) } }> = Test;
+    let y: Test<{ Foo { value: 3, nested: &Bar(5) } }> = x; //~ ERROR mismatched types
 }
diff --git a/tests/ui/const-generics/issue-66451.stderr b/tests/ui/const-generics/issue-66451.stderr
index 404e3839bca..63d193e1bca 100644
--- a/tests/ui/const-generics/issue-66451.stderr
+++ b/tests/ui/const-generics/issue-66451.stderr
@@ -1,16 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-66451.rs:29:10
+  --> $DIR/issue-66451.rs:19:58
    |
-LL |       let y: Test<{
-   |  ____________-
-LL | |         Foo {
-LL | |             value: 3,
-LL | |             nested: &Bar(5),
-LL | |         }
-LL | |     }> = x;
-   | |      -   ^ expected `Foo { value: 3, nested: &Bar::<i32>(5) }`, found `Foo { value: 3, nested: &Bar::<i32>(4) }`
-   | |______|
-   |        expected due to this
+LL |     let y: Test<{ Foo { value: 3, nested: &Bar(5) } }> = x;
+   |            -------------------------------------------   ^ expected `Foo { value: 3, nested: &Bar::<i32>(5) }`, found `Foo { value: 3, nested: &Bar::<i32>(4) }`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Test<Foo { value: 3, nested: &Bar::<i32>(5) }>`
               found struct `Test<Foo { value: 3, nested: &Bar::<i32>(4) }>`
diff --git a/tests/ui/const-generics/issue-70408.rs b/tests/ui/const-generics/issue-70408.rs
index e74bcf945a5..ea7a57d3b2f 100644
--- a/tests/ui/const-generics/issue-70408.rs
+++ b/tests/ui/const-generics/issue-70408.rs
@@ -1,6 +1,6 @@
 //@ build-pass
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {
diff --git a/tests/ui/const-generics/issue-80471.rs b/tests/ui/const-generics/issue-80471.rs
index fa6f1fde435..20d92092b9f 100644
--- a/tests/ui/const-generics/issue-80471.rs
+++ b/tests/ui/const-generics/issue-80471.rs
@@ -1,5 +1,4 @@
 #![feature(adt_const_params)]
-//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 #[derive(PartialEq, Eq)]
 enum Nat {
diff --git a/tests/ui/const-generics/issue-80471.stderr b/tests/ui/const-generics/issue-80471.stderr
index b21ad3aec79..a8514c5cc07 100644
--- a/tests/ui/const-generics/issue-80471.stderr
+++ b/tests/ui/const-generics/issue-80471.stderr
@@ -1,14 +1,5 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-80471.rs:1:12
-   |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0741]: `Nat` must implement `ConstParamTy` to be used as the type of a const generic parameter
-  --> $DIR/issue-80471.rs:10:17
+  --> $DIR/issue-80471.rs:9:17
    |
 LL | fn foo<const N: Nat>() {}
    |                 ^^^
@@ -19,6 +10,6 @@ LL + #[derive(ConstParamTy)]
 LL | enum Nat {
    |
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs
index 4e9d3626aa8..e07fde76a4a 100644
--- a/tests/ui/const-generics/issues/issue-100313.rs
+++ b/tests/ui/const-generics/issues/issue-100313.rs
@@ -1,10 +1,10 @@
 #![allow(incomplete_features)]
 #![feature(const_mut_refs)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 struct T<const B: &'static bool>;
 
-impl <const B: &'static bool> T<B> {
+impl<const B: &'static bool> T<B> {
     const fn set_false(&self) {
         unsafe {
             *(B as *const bool as *mut bool) = false;
@@ -14,7 +14,7 @@ impl <const B: &'static bool> T<B> {
 }
 
 const _: () = {
-    let x = T::<{&true}>;
+    let x = T::<{ &true }>;
     x.set_false();
 };
 
diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs
index ecbae4d9f35..3092893837a 100644
--- a/tests/ui/const-generics/issues/issue-105821.rs
+++ b/tests/ui/const-generics/issues/issue-105821.rs
@@ -4,7 +4,7 @@
 // a failing test, we just started masking the bug.
 
 #![allow(incomplete_features)]
-#![feature(adt_const_params, generic_const_exprs)]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
 #![allow(dead_code)]
 
 const fn catone<const M: usize>(_a: &[u8; M]) -> [u8; M + 1]
diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr
index 580542bb6da..ff0a1bfc0b5 100644
--- a/tests/ui/const-generics/issues/issue-56445-1.min.stderr
+++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr
@@ -17,6 +17,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/issues/issue-56445-1.rs b/tests/ui/const-generics/issues/issue-56445-1.rs
index 35126b3f55a..53aab40b0ad 100644
--- a/tests/ui/const-generics/issues/issue-56445-1.rs
+++ b/tests/ui/const-generics/issues/issue-56445-1.rs
@@ -1,6 +1,6 @@
 // Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995.
 //@ revisions: full min
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 #![crate_type = "lib"]
 
diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
index 5082705927e..8ea96428deb 100644
--- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
+++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr
@@ -4,7 +4,7 @@ error[E0741]: `&'static (dyn A + 'static)` can't be used as a const parameter ty
 LL | fn test<const T: &'static dyn A>() {
    |                  ^^^^^^^^^^^^^^
    |
-   = note: `(dyn A + 'static)` must implement `ConstParamTy`, but it does not
+   = note: `(dyn A + 'static)` must implement `UnsizedConstParamTy`, but it does not
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
index 7f387cbd5a1..101ca456cd9 100644
--- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
+++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs
index c5b83e9d529..9b15a8a7013 100644
--- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs
+++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs
@@ -1,5 +1,5 @@
 //@ revisions: full min
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 trait A {}
diff --git a/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
index 113bf94b5cb..41c5eaa0cd9 100644
--- a/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
+++ b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
@@ -1,8 +1,7 @@
 //@ check-pass
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
-
 trait Trait<const NAME: &'static str> {
     type Assoc;
 }
diff --git a/tests/ui/const-generics/issues/issue-71547.rs b/tests/ui/const-generics/issues/issue-71547.rs
index a2cea433a44..bb9ca63bd32 100644
--- a/tests/ui/const-generics/issues/issue-71547.rs
+++ b/tests/ui/const-generics/issues/issue-71547.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub trait GetType<const N: &'static str> {
diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr
index e9363d42148..cba03b1cb1f 100644
--- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr
+++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs
index 701b3423f31..fcab1f70507 100644
--- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs
+++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs
@@ -3,12 +3,12 @@
 //@ revisions: full min
 //@[full]check-pass
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn a<const X: &'static [u32]>() {}
 //[min]~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter
 
 fn main() {
-    a::<{&[]}>();
+    a::<{ &[] }>();
 }
diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs
index bd9431dbc85..ab68c6b78df 100644
--- a/tests/ui/const-generics/issues/issue-86535-2.rs
+++ b/tests/ui/const-generics/issues/issue-86535-2.rs
@@ -1,10 +1,12 @@
 //@ run-pass
-#![feature(adt_const_params, generic_const_exprs)]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
 #![allow(incomplete_features)]
 
 pub trait Foo {
     const ASSOC_C: usize;
-    fn foo() where [(); Self::ASSOC_C]:;
+    fn foo()
+    where
+        [(); Self::ASSOC_C]:;
 }
 
 #[allow(dead_code)]
@@ -12,7 +14,10 @@ struct Bar<const N: &'static ()>;
 impl<const N: &'static ()> Foo for Bar<N> {
     const ASSOC_C: usize = 3;
 
-    fn foo() where [u8; Self::ASSOC_C]: {
+    fn foo()
+    where
+        [u8; Self::ASSOC_C]:,
+    {
         let _: [u8; Self::ASSOC_C] = loop {};
     }
 }
diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs
index cd9934a4a99..9aaf7ddc9e8 100644
--- a/tests/ui/const-generics/issues/issue-86535.rs
+++ b/tests/ui/const-generics/issues/issue-86535.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-#![feature(adt_const_params, generic_const_exprs)]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
 #![allow(incomplete_features, unused_variables)]
 
 #[allow(dead_code)]
diff --git a/tests/ui/const-generics/issues/issue-90455.fixed b/tests/ui/const-generics/issues/issue-90455.fixed
index 2502d47eb46..423a1fbd765 100644
--- a/tests/ui/const-generics/issues/issue-90455.fixed
+++ b/tests/ui/const-generics/issues/issue-90455.fixed
@@ -1,5 +1,5 @@
 //@ run-rustfix
-#![feature(generic_const_exprs, adt_const_params)]
+#![feature(generic_const_exprs, unsized_const_params, adt_const_params)]
 #![allow(incomplete_features, dead_code)]
 
 struct FieldElement<const N: &'static str> where [(); num_limbs(N)]: {
diff --git a/tests/ui/const-generics/issues/issue-90455.rs b/tests/ui/const-generics/issues/issue-90455.rs
index 794c7d76cb1..be4f27ec689 100644
--- a/tests/ui/const-generics/issues/issue-90455.rs
+++ b/tests/ui/const-generics/issues/issue-90455.rs
@@ -1,5 +1,5 @@
 //@ run-rustfix
-#![feature(generic_const_exprs, adt_const_params)]
+#![feature(generic_const_exprs, unsized_const_params, adt_const_params)]
 #![allow(incomplete_features, dead_code)]
 
 struct FieldElement<const N: &'static str> {
diff --git a/tests/ui/const-generics/issues/issue-99641.stderr b/tests/ui/const-generics/issues/issue-99641.stderr
index 800aec3ef2c..3365012a038 100644
--- a/tests/ui/const-generics/issues/issue-99641.stderr
+++ b/tests/ui/const-generics/issues/issue-99641.stderr
@@ -4,7 +4,7 @@ error[E0741]: `(fn(),)` can't be used as a const parameter type
 LL |     pub struct Color<const WHITE: (fn(),)>;
    |                                   ^^^^^^^
    |
-   = note: `fn()` must implement `ConstParamTy`, but it does not
+   = note: `fn()` must implement `ConstParamTy_`, but it does not
 
 error[E0741]: `(fn(),)` can't be used as a const parameter type
   --> $DIR/issue-99641.rs:8:23
@@ -12,7 +12,7 @@ error[E0741]: `(fn(),)` can't be used as a const parameter type
 LL |     impl<const WHITE: (fn(),)> Color<WHITE> {
    |                       ^^^^^^^
    |
-   = note: `fn()` must implement `ConstParamTy`, but it does not
+   = note: `fn()` must implement `ConstParamTy_`, but it does not
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr
index 8e83ea58194..0211770f9e5 100644
--- a/tests/ui/const-generics/min_const_generics/complex-types.stderr
+++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr
@@ -45,6 +45,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `!` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:17:21
diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.adt_const_params.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.adt_const_params.stderr
new file mode 100644
index 00000000000..18f47f7dc23
--- /dev/null
+++ b/tests/ui/const-generics/raw-ptr-const-param-deref.adt_const_params.stderr
@@ -0,0 +1,15 @@
+error[E0741]: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:11:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+
+error[E0741]: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:13:15
+   |
+LL | impl<const P: *const u32> Const<P> {
+   |               ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr
index 657eee2be24..18f47f7dc23 100644
--- a/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr
+++ b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr
@@ -1,11 +1,11 @@
 error[E0741]: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:9:23
+  --> $DIR/raw-ptr-const-param-deref.rs:11:23
    |
 LL | struct Const<const P: *const u32>;
    |                       ^^^^^^^^^^
 
 error[E0741]: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:11:15
+  --> $DIR/raw-ptr-const-param-deref.rs:13:15
    |
 LL | impl<const P: *const u32> Const<P> {
    |               ^^^^^^^^^^
diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr
index 1eb238255ab..6027dbb01cd 100644
--- a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr
+++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr
@@ -1,5 +1,5 @@
 error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:9:23
+  --> $DIR/raw-ptr-const-param-deref.rs:11:23
    |
 LL | struct Const<const P: *const u32>;
    |                       ^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | struct Const<const P: *const u32>;
    = note: the only supported types are integers, `bool` and `char`
 
 error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:11:15
+  --> $DIR/raw-ptr-const-param-deref.rs:13:15
    |
 LL | impl<const P: *const u32> Const<P> {
    |               ^^^^^^^^^^
diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.rs b/tests/ui/const-generics/raw-ptr-const-param-deref.rs
index b7fcbb3447a..bf077acd4fa 100644
--- a/tests/ui/const-generics/raw-ptr-const-param-deref.rs
+++ b/tests/ui/const-generics/raw-ptr-const-param-deref.rs
@@ -1,21 +1,22 @@
 // Checks that pointers must not be used as the type of const params.
-//@ revisions: full min
+//@ revisions: min adt_const_params full
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 const A: u32 = 3;
 
 struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
 
-impl<const P: *const u32> Const<P> { //~ ERROR: using raw pointers as const generic parameters
+impl<const P: *const u32> Const<P> {
+    //~^ ERROR: using raw pointers as const generic parameters
     fn get() -> u32 {
-        unsafe {
-            *P
-        }
+        unsafe { *P }
     }
 }
 
 fn main() {
-    assert_eq!(Const::<{&A as *const _}>::get(), 3)
+    assert_eq!(Const::<{ &A as *const _ }>::get(), 3)
 }
diff --git a/tests/ui/const-generics/raw-ptr-const-param.adt_const_params.stderr b/tests/ui/const-generics/raw-ptr-const-param.adt_const_params.stderr
new file mode 100644
index 00000000000..f040d3cc36a
--- /dev/null
+++ b/tests/ui/const-generics/raw-ptr-const-param.adt_const_params.stderr
@@ -0,0 +1,21 @@
+error[E0741]: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param.rs:8:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/raw-ptr-const-param.rs:11:40
+   |
+LL |     let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
+   |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Const<{0xf as *const u32}>`
+              found struct `Const<{0xa as *const u32}>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0741.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/raw-ptr-const-param.full.stderr b/tests/ui/const-generics/raw-ptr-const-param.full.stderr
index 7ba9ac15bf3..f040d3cc36a 100644
--- a/tests/ui/const-generics/raw-ptr-const-param.full.stderr
+++ b/tests/ui/const-generics/raw-ptr-const-param.full.stderr
@@ -1,11 +1,11 @@
 error[E0741]: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param.rs:6:23
+  --> $DIR/raw-ptr-const-param.rs:8:23
    |
 LL | struct Const<const P: *const u32>;
    |                       ^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/raw-ptr-const-param.rs:9:40
+  --> $DIR/raw-ptr-const-param.rs:11:40
    |
 LL |     let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
    |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr
index 18bbcc33c4d..c48eea069e0 100644
--- a/tests/ui/const-generics/raw-ptr-const-param.min.stderr
+++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr
@@ -1,5 +1,5 @@
 error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param.rs:6:23
+  --> $DIR/raw-ptr-const-param.rs:8:23
    |
 LL | struct Const<const P: *const u32>;
    |                       ^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | struct Const<const P: *const u32>;
    = note: the only supported types are integers, `bool` and `char`
 
 error[E0308]: mismatched types
-  --> $DIR/raw-ptr-const-param.rs:9:40
+  --> $DIR/raw-ptr-const-param.rs:11:40
    |
 LL |     let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
    |            -------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
diff --git a/tests/ui/const-generics/raw-ptr-const-param.rs b/tests/ui/const-generics/raw-ptr-const-param.rs
index 19d18a2f9d2..49e48d9905f 100644
--- a/tests/ui/const-generics/raw-ptr-const-param.rs
+++ b/tests/ui/const-generics/raw-ptr-const-param.rs
@@ -1,7 +1,9 @@
-//@ revisions: full min
+//@ revisions: min adt_const_params full
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
 
diff --git a/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr b/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr
new file mode 100644
index 00000000000..bcb2bd255da
--- /dev/null
+++ b/tests/ui/const-generics/slice-const-param-mismatch.adt_const_params.stderr
@@ -0,0 +1,49 @@
+error[E0741]: `&'static str` can't be used as a const parameter type
+  --> $DIR/slice-const-param-mismatch.rs:8:29
+   |
+LL | struct ConstString<const T: &'static str>;
+   |                             ^^^^^^^^^^^^
+
+error[E0741]: `&'static [u8]` can't be used as a const parameter type
+  --> $DIR/slice-const-param-mismatch.rs:11:28
+   |
+LL | struct ConstBytes<const T: &'static [u8]>;
+   |                            ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:17:35
+   |
+LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
+   |            --------------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstString<"Hello">`
+              found struct `ConstString<"World">`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:19:33
+   |
+LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
+   |            -------------------   ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstString<"ℇ㇈↦">`
+              found struct `ConstString<"ℇ㇈↥">`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:21:33
+   |
+LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
+   |            ------------------   ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstBytes<b"AAA">`
+              found struct `ConstBytes<b"BBB">`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0741.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/slice-const-param-mismatch.full.stderr b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr
index 80dd1be33c2..883ba988be7 100644
--- a/tests/ui/const-generics/slice-const-param-mismatch.full.stderr
+++ b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:14:35
+  --> $DIR/slice-const-param-mismatch.rs:17:35
    |
 LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
    |            --------------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
@@ -10,7 +10,7 @@ LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
               found struct `ConstString<"World">`
 
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:16:33
+  --> $DIR/slice-const-param-mismatch.rs:19:33
    |
 LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
    |            -------------------   ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
@@ -21,7 +21,7 @@ LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
               found struct `ConstString<"ℇ㇈↥">`
 
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:18:33
+  --> $DIR/slice-const-param-mismatch.rs:21:33
    |
 LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
    |            ------------------   ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr
index 0650dafc685..3b2410c9894 100644
--- a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr
+++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr
@@ -1,5 +1,5 @@
 error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/slice-const-param-mismatch.rs:7:29
+  --> $DIR/slice-const-param-mismatch.rs:8:29
    |
 LL | struct ConstString<const T: &'static str>;
    |                             ^^^^^^^^^^^^
@@ -9,9 +9,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
-  --> $DIR/slice-const-param-mismatch.rs:9:28
+  --> $DIR/slice-const-param-mismatch.rs:11:28
    |
 LL | struct ConstBytes<const T: &'static [u8]>;
    |                            ^^^^^^^^^^^^^
@@ -21,9 +25,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:14:35
+  --> $DIR/slice-const-param-mismatch.rs:17:35
    |
 LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
    |            --------------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
@@ -34,7 +42,7 @@ LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
               found struct `ConstString<"World">`
 
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:16:33
+  --> $DIR/slice-const-param-mismatch.rs:19:33
    |
 LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
    |            -------------------   ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
@@ -45,7 +53,7 @@ LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
               found struct `ConstString<"ℇ㇈↥">`
 
 error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:18:33
+  --> $DIR/slice-const-param-mismatch.rs:21:33
    |
 LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
    |            ------------------   ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
diff --git a/tests/ui/const-generics/slice-const-param-mismatch.rs b/tests/ui/const-generics/slice-const-param-mismatch.rs
index 733eeb69fa9..feee39e602d 100644
--- a/tests/ui/const-generics/slice-const-param-mismatch.rs
+++ b/tests/ui/const-generics/slice-const-param-mismatch.rs
@@ -1,19 +1,22 @@
-//@ revisions: full min
+//@ revisions: min adt_const_params full
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
-
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 struct ConstString<const T: &'static str>;
 //[min]~^ ERROR
+//[adt_const_params]~^^ ERROR
 struct ConstBytes<const T: &'static [u8]>;
 //[min]~^ ERROR
+//[adt_const_params]~^^ ERROR
 
 pub fn main() {
     let _: ConstString<"Hello"> = ConstString::<"Hello">;
     let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
-    let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
+    let _: ConstBytes<b"AAA"> = ConstBytes::<{ &[0x41, 0x41, 0x41] }>;
     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
 }
diff --git a/tests/ui/const-generics/slice-const-param.rs b/tests/ui/const-generics/slice-const-param.rs
index c6c0047c929..1c5088b5283 100644
--- a/tests/ui/const-generics/slice-const-param.rs
+++ b/tests/ui/const-generics/slice-const-param.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 pub fn function_with_str<const STRING: &'static str>() -> &'static str {
@@ -12,9 +12,8 @@ pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
 }
 
 // Also check the codepaths for custom DST
-#[derive(PartialEq, Eq)]
+#[derive(std::marker::UnsizedConstParamTy, PartialEq, Eq)]
 struct MyStr(str);
-impl std::marker::ConstParamTy for MyStr {}
 
 fn function_with_my_str<const S: &'static MyStr>() -> &'static MyStr {
     S
@@ -34,7 +33,7 @@ pub fn main() {
     assert_eq!(function_with_str::<"Rust">(), "Rust");
     assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦");
     assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]);
-    assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA");
+    assert_eq!(function_with_bytes::<{ &[0x41, 0x41, 0x41, 0x41] }>(), b"AAAA");
 
     assert_eq!(function_with_my_str::<{ MyStr::new("hello") }>().as_str(), "hello");
 }
diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr
new file mode 100644
index 00000000000..7a936ced030
--- /dev/null
+++ b/tests/ui/const-generics/transmute-const-param-static-reference.adt_const_params.stderr
@@ -0,0 +1,9 @@
+error[E0741]: `&'static ()` can't be used as a const parameter type
+  --> $DIR/transmute-const-param-static-reference.rs:9:23
+   |
+LL | struct Const<const P: &'static ()>;
+   |                       ^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr
index fdb6ddeb578..cf236487cf0 100644
--- a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr
+++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr
@@ -1,5 +1,5 @@
 error: `&'static ()` is forbidden as the type of a const generic parameter
-  --> $DIR/transmute-const-param-static-reference.rs:7:23
+  --> $DIR/transmute-const-param-static-reference.rs:9:23
    |
 LL | struct Const<const P: &'static ()>;
    |                       ^^^^^^^^^^^
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.rs b/tests/ui/const-generics/transmute-const-param-static-reference.rs
index 49541233ed1..0b47fd31eaf 100644
--- a/tests/ui/const-generics/transmute-const-param-static-reference.rs
+++ b/tests/ui/const-generics/transmute-const-param-static-reference.rs
@@ -1,16 +1,17 @@
-//@ revisions: full min
+//@ revisions: full adt_const_params min
 //@[full] check-pass
 
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(adt_const_params, feature(adt_const_params))]
+#![cfg_attr(adt_const_params, allow(incomplete_features))]
 
 struct Const<const P: &'static ()>;
 //[min]~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter
+//[adt_const_params]~^^ ERROR `&'static ()` can't be used as a const parameter type
 
 fn main() {
-    const A: &'static () = unsafe {
-        std::mem::transmute(10 as *const ())
-    };
+    const A: &'static () = unsafe { std::mem::transmute(10 as *const ()) };
 
-    let _ = Const::<{A}>;
+    let _ = Const::<{ A }>;
 }
diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr
index f42a331a8a4..858900a500d 100644
--- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr
+++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/issue-71348.rs:18:25
@@ -21,6 +25,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs
index f349a88d124..2ffbd015485 100644
--- a/tests/ui/const-generics/type-dependent/issue-71348.rs
+++ b/tests/ui/const-generics/type-dependent/issue-71348.rs
@@ -1,6 +1,6 @@
 //@ [full] run-pass
 //@ revisions: full min
-#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, feature(adt_const_params, unsized_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo {
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index c1748c2e237..d7d24f373eb 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -436,30 +436,20 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:196:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/raw-bytes.rs:196:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC_ID╼ 00 00 00 00                         │ ╾──╼....
-           }
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:198:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/raw-bytes.rs:199:65
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
-           }
+   |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:202:1
+  --> $DIR/raw-bytes.rs:204:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
@@ -470,7 +460,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:203:1
+  --> $DIR/raw-bytes.rs:205:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -481,7 +471,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:204:1
+  --> $DIR/raw-bytes.rs:206:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -492,7 +482,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:208:1
+  --> $DIR/raw-bytes.rs:210:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -503,7 +493,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:211:1
+  --> $DIR/raw-bytes.rs:213:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -516,7 +506,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem:
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:214:1
+  --> $DIR/raw-bytes.rs:216:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -527,7 +517,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:218:1
+  --> $DIR/raw-bytes.rs:220:1
    |
 LL | pub static S7: &[u16] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
@@ -538,7 +528,7 @@ LL | pub static S7: &[u16] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:225:1
+  --> $DIR/raw-bytes.rs:227:1
    |
 LL | pub static R4: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -549,7 +539,7 @@ LL | pub static R4: &[u8] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:230:1
+  --> $DIR/raw-bytes.rs:232:1
    |
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -562,7 +552,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:235:1
+  --> $DIR/raw-bytes.rs:237:1
    |
 LL | pub static R6: &[bool] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index eb97eab9db7..22679acda98 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -436,30 +436,20 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:196:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/raw-bytes.rs:196:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
-           }
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:198:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/raw-bytes.rs:199:65
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
-           }
+   |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:202:1
+  --> $DIR/raw-bytes.rs:204:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
@@ -470,7 +460,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:203:1
+  --> $DIR/raw-bytes.rs:205:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -481,7 +471,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:204:1
+  --> $DIR/raw-bytes.rs:206:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -492,7 +482,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:208:1
+  --> $DIR/raw-bytes.rs:210:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -503,7 +493,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:211:1
+  --> $DIR/raw-bytes.rs:213:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -516,7 +506,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem:
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:214:1
+  --> $DIR/raw-bytes.rs:216:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -527,7 +517,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:218:1
+  --> $DIR/raw-bytes.rs:220:1
    |
 LL | pub static S7: &[u16] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
@@ -538,7 +528,7 @@ LL | pub static S7: &[u16] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:225:1
+  --> $DIR/raw-bytes.rs:227:1
    |
 LL | pub static R4: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -549,7 +539,7 @@ LL | pub static R4: &[u8] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:230:1
+  --> $DIR/raw-bytes.rs:232:1
    |
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -562,7 +552,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:235:1
+  --> $DIR/raw-bytes.rs:237:1
    |
 LL | pub static R6: &[bool] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index 1c7ef6f2b0f..de1a81b0024 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -194,9 +194,11 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool
 //~| expected a boolean
 
 const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| null pointer
 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 
 // Uninhabited types
 const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
index 5c47cbfdf3b..439ccb24e61 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
@@ -1,56 +1,46 @@
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:18:1
-   |
-LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:19:14
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼                         │ ╾──╼╾──╼
-           }
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:23:1
-   |
-LL | const INVALID_VTABLE_SIZE: &dyn Trait =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼                         │ ╾──╼╾──╼
-           }
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:33:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼                         │ ╾──╼╾──╼
+               ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:38:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼                         │ ╾──╼╾──╼
+               ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:44:1
    |
 LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼                         │ ╾──╼╾──╼
+               ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼                         │ ╾──╼╾──╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -61,7 +51,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 4) {
-               ╾ALLOC10<imm>╼ ╾ALLOC11╼                         │ ╾──╼╾──╼
+               ╾ALLOC6<imm>╼ ╾ALLOC7╼                         │ ╾──╼╾──╼
            }
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
index f400073aca2..89bf959703a 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
@@ -1,56 +1,46 @@
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:18:1
-   |
-LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:19:14
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼ │ ╾──────╼╾──────╼
-           }
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:23:1
-   |
-LL | const INVALID_VTABLE_SIZE: &dyn Trait =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
    |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼ │ ╾──────╼╾──────╼
-           }
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:33:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼ │ ╾──────╼╾──────╼
+               ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:38:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──────╼╾──────╼
+               ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-incorrect-vtable.rs:44:1
    |
 LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──────╼╾──────╼
+               ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼ │ ╾──────╼╾──────╼
            }
 
 error[E0080]: it is undefined behavior to use this value
@@ -61,7 +51,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 16, align: 8) {
-               ╾ALLOC10<imm>╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼
+               ╾ALLOC6<imm>╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼
            }
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
index 11c3b2fe560..4325495a380 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
@@ -17,13 +17,13 @@ trait Trait {}
 
 const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-//~^^ ERROR it is undefined behavior to use this value
-//~| expected a vtable pointer
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 
 const INVALID_VTABLE_SIZE: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-//~^^ ERROR it is undefined behavior to use this value
-//~| expected a vtable pointer
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 
 #[repr(transparent)]
 struct W<T>(T);
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs
index d0d93081738..3956146f6ae 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs
@@ -113,27 +113,27 @@ const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
 // bad trait object
 const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
 //~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~| vtable
 // bad trait object
 const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
 //~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~| vtable
 // bad trait object
 const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
 //~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~| vtable
 const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-//~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-//~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-//~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
 //~^ ERROR it is undefined behavior to use this value
-//~| expected a vtable
+//~| vtable
 
 // bad data *inside* the trait object
 const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
@@ -142,21 +142,25 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool
 
 // # raw trait object
 const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| null pointer
 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
+//~| vtable
 const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw
 // Officially blessed way to get the vtable
 const DYN_METADATA: ptr::DynMetadata<dyn Send> = ptr::metadata::<dyn Send>(ptr::null::<i32>());
 
-// Const eval fails for these, so they need to be statics to error.
+
 static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
-//~^ ERROR it is undefined behavior to use this value
     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
+    //~^ ERROR could not evaluate static initializer
+    //~| null pointer
 };
 static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
-//~^ ERROR it is undefined behavior to use this value
     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
+    //~^ ERROR could not evaluate static initializer
+    //~| vtable
 };
 
 fn main() {}
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
index 2fa462a6a64..4fe744265df 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -218,44 +218,29 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
                HEX_DUMP
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:125:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:125:57
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC20 as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:128:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:128:57
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC21 as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:131:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:131:56
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC22 as vtable pointer but it does not point to a vtable
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-wide-ptr.rs:134:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23<imm>, but expected a vtable pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17<imm>, but expected a vtable pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -273,49 +258,29 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
                HEX_DUMP
            }
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:144:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:144:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:146:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-wide-ptr.rs:147:65
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+   |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC23 as vtable pointer but it does not point to a vtable
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:153:1
+error[E0080]: could not evaluate static initializer
+  --> $DIR/ub-wide-ptr.rs:156:5
    |
-LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-wide-ptr.rs:157:1
+error[E0080]: could not evaluate static initializer
+  --> $DIR/ub-wide-ptr.rs:161:5
    |
-LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31<imm>, but expected a vtable pointer
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
+LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC24 as vtable pointer but it does not point to a vtable
 
 error: aborting due to 29 previous errors
 
diff --git a/tests/ui/consts/const_refs_to_static.rs b/tests/ui/consts/const_refs_to_static.rs
index 1baa8535b2c..f41725b786e 100644
--- a/tests/ui/consts/const_refs_to_static.rs
+++ b/tests/ui/consts/const_refs_to_static.rs
@@ -9,7 +9,7 @@ const C1: &i32 = &S;
 const C1_READ: () = {
     assert!(*C1 == 0);
 };
-const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) };
+const C2: *const i32 = std::ptr::addr_of!(S_MUT);
 
 fn main() {
     assert_eq!(*C1, 0);
diff --git a/tests/ui/consts/mut-ptr-to-static.rs b/tests/ui/consts/mut-ptr-to-static.rs
index d8a788bb37d..e921365c7d4 100644
--- a/tests/ui/consts/mut-ptr-to-static.rs
+++ b/tests/ui/consts/mut-ptr-to-static.rs
@@ -16,12 +16,9 @@ static mut STATIC: u32 = 42;
 static INTERIOR_MUTABLE_STATIC: SyncUnsafeCell<u32> = SyncUnsafeCell::new(42);
 
 // A static that mutably points to STATIC.
-static PTR: SyncPtr = SyncPtr {
-    foo: unsafe { ptr::addr_of_mut!(STATIC) },
-};
-static INTERIOR_MUTABLE_PTR: SyncPtr = SyncPtr {
-    foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32,
-};
+static PTR: SyncPtr = SyncPtr { foo: ptr::addr_of_mut!(STATIC) };
+static INTERIOR_MUTABLE_PTR: SyncPtr =
+    SyncPtr { foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32 };
 
 fn main() {
     let ptr = PTR.foo;
diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.rs b/tests/ui/consts/refs_check_const_eq-issue-88384.rs
index fb0405b651c..46cb6275171 100644
--- a/tests/ui/consts/refs_check_const_eq-issue-88384.rs
+++ b/tests/ui/consts/refs_check_const_eq-issue-88384.rs
@@ -1,10 +1,10 @@
 #![feature(fn_traits)]
-#![feature(adt_const_params)]
-//~^ WARNING the feature `adt_const_params` is incomplete
+#![feature(adt_const_params, unsized_const_params)]
+//~^ WARNING the feature `unsized_const_params` is incomplete
 
 #[derive(PartialEq, Eq)]
-struct CompileTimeSettings{
-    hooks: &'static[fn()],
+struct CompileTimeSettings {
+    hooks: &'static [fn()],
 }
 
 struct Foo<const T: CompileTimeSettings>;
@@ -12,14 +12,11 @@ struct Foo<const T: CompileTimeSettings>;
 
 impl<const T: CompileTimeSettings> Foo<T> {
     //~^ ERROR `CompileTimeSettings` must implement `ConstParamTy` to be used as the type of a const generic parameter
-    fn call_hooks(){
-    }
+    fn call_hooks() {}
 }
 
-fn main(){
-    const SETTINGS: CompileTimeSettings = CompileTimeSettings{
-        hooks: &[],
-    };
+fn main() {
+    const SETTINGS: CompileTimeSettings = CompileTimeSettings { hooks: &[] };
 
     Foo::<SETTINGS>::call_hooks();
 }
diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.stderr b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
index c490cd053e7..62c5c527641 100644
--- a/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
+++ b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
@@ -1,8 +1,8 @@
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/refs_check_const_eq-issue-88384.rs:2:12
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/refs_check_const_eq-issue-88384.rs:2:30
    |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
    = note: `#[warn(incomplete_features)]` on by default
@@ -16,7 +16,7 @@ LL | struct Foo<const T: CompileTimeSettings>;
 help: add `#[derive(ConstParamTy)]` to the struct
    |
 LL + #[derive(ConstParamTy)]
-LL | struct CompileTimeSettings{
+LL | struct CompileTimeSettings {
    |
 
 error[E0741]: `CompileTimeSettings` must implement `ConstParamTy` to be used as the type of a const generic parameter
@@ -28,7 +28,7 @@ LL | impl<const T: CompileTimeSettings> Foo<T> {
 help: add `#[derive(ConstParamTy)]` to the struct
    |
 LL + #[derive(ConstParamTy)]
-LL | struct CompileTimeSettings{
+LL | struct CompileTimeSettings {
    |
 
 error: aborting due to 2 previous errors; 1 warning emitted
diff --git a/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs b/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs
index 446fdc75514..33b6b7f52ca 100644
--- a/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs
+++ b/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 struct FooConst<const ARRAY: &'static [&'static str]> {}
 
diff --git a/tests/ui/coroutine/coroutine-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr
index 3f3d51da311..ee3a8f45f44 100644
--- a/tests/ui/coroutine/coroutine-with-nll.stderr
+++ b/tests/ui/coroutine/coroutine-with-nll.stderr
@@ -1,11 +1,19 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/coroutine-with-nll.rs:8:17
    |
+LL |     || {
+   |     -- within this coroutine
+...
 LL |         let b = &mut true;
    |                 ^^^^^^^^^
 LL |
 LL |         yield ();
    |         -------- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     static || {
+   |     ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/issue-48048.stderr b/tests/ui/coroutine/issue-48048.stderr
index 199ecf4ca6a..8231dbef7f6 100644
--- a/tests/ui/coroutine/issue-48048.stderr
+++ b/tests/ui/coroutine/issue-48048.stderr
@@ -1,10 +1,18 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/issue-48048.rs:9:9
    |
+LL |     #[coroutine] || {
+   |                  -- within this coroutine
+...
 LL |         x.0({
    |         ^^^
 LL |             yield;
    |             ----- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     #[coroutine] static || {
+   |                  ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/pattern-borrow.stderr b/tests/ui/coroutine/pattern-borrow.stderr
index 9e7b330d79d..a3954b0b8ad 100644
--- a/tests/ui/coroutine/pattern-borrow.stderr
+++ b/tests/ui/coroutine/pattern-borrow.stderr
@@ -1,10 +1,17 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/pattern-borrow.rs:9:24
    |
+LL |     #[coroutine] move || {
+   |                  ------- within this coroutine
 LL |         if let Test::A(ref _a) = test {
    |                        ^^^^^^
 LL |             yield ();
    |             -------- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     #[coroutine] static move || {
+   |                  ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/self_referential_gen_block.stderr b/tests/ui/coroutine/self_referential_gen_block.stderr
index e23d653d0d4..2f53e7c84a1 100644
--- a/tests/ui/coroutine/self_referential_gen_block.stderr
+++ b/tests/ui/coroutine/self_referential_gen_block.stderr
@@ -1,6 +1,9 @@
 error[E0626]: borrow may still be in use when `gen` block yields
   --> $DIR/self_referential_gen_block.rs:9:21
    |
+LL |         let mut x = gen {
+   |                     --- within this `gen` block
+LL |             let y = 42;
 LL |             let z = &y;
    |                     ^^
 LL |             yield 43;
diff --git a/tests/ui/coroutine/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr
index 1d2c54f9bdb..1cc3c83deb3 100644
--- a/tests/ui/coroutine/yield-in-args.stderr
+++ b/tests/ui/coroutine/yield-in-args.stderr
@@ -1,8 +1,16 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-in-args.rs:9:13
    |
+LL |     || {
+   |     -- within this coroutine
+LL |         let b = true;
 LL |         foo(&b, yield);
    |             ^^  ----- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     static || {
+   |     ++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/yield-while-iterating.stderr b/tests/ui/coroutine/yield-while-iterating.stderr
index f81c914c4bd..a92237e44c1 100644
--- a/tests/ui/coroutine/yield-while-iterating.stderr
+++ b/tests/ui/coroutine/yield-while-iterating.stderr
@@ -1,10 +1,17 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-iterating.rs:13:18
    |
+LL |     let _b =#[coroutine]  move || {
+   |                           ------- within this coroutine
 LL |         for p in &x {
    |                  ^^
 LL |             yield();
    |             ------- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     let _b =#[coroutine]  static move || {
+   |                           ++++++
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/yield-while-iterating.rs:58:20
diff --git a/tests/ui/coroutine/yield-while-local-borrowed.stderr b/tests/ui/coroutine/yield-while-local-borrowed.stderr
index 8fe981de929..b42ca3ba461 100644
--- a/tests/ui/coroutine/yield-while-local-borrowed.stderr
+++ b/tests/ui/coroutine/yield-while-local-borrowed.stderr
@@ -1,20 +1,35 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-local-borrowed.rs:13:17
    |
+LL |     let mut b = #[coroutine] move || {
+   |                              ------- within this coroutine
 LL |         let a = &mut 3;
    |                 ^^^^^^
 LL |
 LL |         yield ();
    |         -------- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     let mut b = #[coroutine] static move || {
+   |                              ++++++
 
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/yield-while-local-borrowed.rs:40:21
    |
+LL |     let mut b = #[coroutine] move || {
+   |                              ------- within this coroutine
+...
 LL |             let b = &a;
    |                     ^^
 LL |
 LL |             yield ();
    |             -------- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     let mut b = #[coroutine] static move || {
+   |                              ++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/empty/empty-struct-braces-expr.stderr b/tests/ui/empty/empty-struct-braces-expr.stderr
index 4604ebeaa8b..28c701443de 100644
--- a/tests/ui/empty/empty-struct-braces-expr.stderr
+++ b/tests/ui/empty/empty-struct-braces-expr.stderr
@@ -71,12 +71,22 @@ error[E0533]: expected value, found struct variant `E::Empty3`
    |
 LL |     let e3 = E::Empty3;
    |              ^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let e3 = E::Empty3 {};
+   |                        ++
 
 error[E0533]: expected value, found struct variant `E::Empty3`
   --> $DIR/empty-struct-braces-expr.rs:19:14
    |
 LL |     let e3 = E::Empty3();
    |              ^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let e3 = E::Empty3 {};
+   |                        ~~
 
 error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
   --> $DIR/empty-struct-braces-expr.rs:23:15
@@ -104,25 +114,34 @@ error[E0599]: no variant or associated item named `Empty3` found for enum `empty
   --> $DIR/empty-struct-braces-expr.rs:25:19
    |
 LL |     let xe3 = XE::Empty3;
-   |                   ^^^^^^
-   |                   |
-   |                   variant or associated item not found in `XE`
-   |                   help: there is a variant with a similar name: `XEmpty3`
+   |                   ^^^^^^ variant or associated item not found in `XE`
+   |
+help: there is a variant with a similar name
+   |
+LL |     let xe3 = XE::XEmpty3;
+   |                   ~~~~~~~
 
 error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:26:19
    |
 LL |     let xe3 = XE::Empty3();
-   |                   ^^^^^^
-   |                   |
-   |                   variant or associated item not found in `XE`
-   |                   help: there is a variant with a similar name: `XEmpty3`
+   |                   ^^^^^^ variant or associated item not found in `XE`
+   |
+help: there is a variant with a similar name
+   |
+LL |     let xe3 = XE::XEmpty3 {};
+   |                   ~~~~~~~~~~
 
 error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
   --> $DIR/empty-struct-braces-expr.rs:28:9
    |
 LL |     XE::Empty1 {};
-   |         ^^^^^^ help: there is a variant with a similar name: `XEmpty3`
+   |         ^^^^^^
+   |
+help: there is a variant with a similar name
+   |
+LL |     XE::XEmpty3 {};
+   |         ~~~~~~~~~~
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/enum/error-variant-with-turbofishes.stderr b/tests/ui/enum/error-variant-with-turbofishes.stderr
index 66bed1c0d85..ffc2862bfe0 100644
--- a/tests/ui/enum/error-variant-with-turbofishes.stderr
+++ b/tests/ui/enum/error-variant-with-turbofishes.stderr
@@ -3,6 +3,11 @@ error[E0533]: expected value, found struct variant `Struct<0>::Variant`
    |
 LL |     let x = Struct::<0>::Variant;
    |             ^^^^^^^^^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let x = Struct::<0>::Variant { x: /* value */ };
+   |                                  ++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0746.stderr b/tests/ui/error-codes/E0746.stderr
index 9fe90ab7bec..cfc747cb1e2 100644
--- a/tests/ui/error-codes/E0746.stderr
+++ b/tests/ui/error-codes/E0746.stderr
@@ -4,11 +4,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn foo() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn foo() -> impl Trait { Struct }
    |             ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL | fn foo() -> Box<dyn Trait> { Box::new(Struct) }
    |             ++++         +   +++++++++      +
@@ -19,10 +19,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bar() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn bar() -> impl Trait {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn bar() -> Box<dyn Trait> {
diff --git a/tests/ui/error-codes/E0771.rs b/tests/ui/error-codes/E0771.rs
index c0a2e98a7df..a932c5ef981 100644
--- a/tests/ui/error-codes/E0771.rs
+++ b/tests/ui/error-codes/E0771.rs
@@ -1,5 +1,5 @@
-#![feature(adt_const_params)]
-//~^ WARN the feature `adt_const_params` is incomplete
+#![feature(adt_const_params, unsized_const_params)]
+//~^ WARN the feature `unsized_const_params` is incomplete
 
 fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0770
 
diff --git a/tests/ui/error-codes/E0771.stderr b/tests/ui/error-codes/E0771.stderr
index e1384effe37..5e829e6f6d2 100644
--- a/tests/ui/error-codes/E0771.stderr
+++ b/tests/ui/error-codes/E0771.stderr
@@ -6,11 +6,11 @@ LL | fn function_with_str<'a, const STRING: &'a str>() {}
    |
    = note: lifetime parameters may not be used in the type of const parameters
 
-warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/E0771.rs:1:12
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/E0771.rs:1:30
    |
-LL | #![feature(adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params, unsized_const_params)]
+   |                              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
    = note: `#[warn(incomplete_features)]` on by default
diff --git a/tests/ui/errors/wrong-target-spec.rs b/tests/ui/errors/wrong-target-spec.rs
new file mode 100644
index 00000000000..bc9038c1fab
--- /dev/null
+++ b/tests/ui/errors/wrong-target-spec.rs
@@ -0,0 +1,8 @@
+// The attentive may note the underscores in the target triple, making it invalid. This test
+// checks that such invalid target specs are rejected by the compiler.
+// See https://github.com/rust-lang/rust/issues/33329
+
+//@ needs-llvm-components: x86
+//@ compile-flags: --target x86_64_unknown-linux-musl
+
+fn main() {}
diff --git a/tests/ui/errors/wrong-target-spec.stderr b/tests/ui/errors/wrong-target-spec.stderr
new file mode 100644
index 00000000000..8b06f404078
--- /dev/null
+++ b/tests/ui/errors/wrong-target-spec.stderr
@@ -0,0 +1,2 @@
+error: Error loading target specification: Could not find specification for target "x86_64_unknown-linux-musl". Run `rustc --print target-list` for a list of built-in targets
+
diff --git a/tests/ui/expr/issue-22933-2.stderr b/tests/ui/expr/issue-22933-2.stderr
index 8cda8598f3c..dadc3121362 100644
--- a/tests/ui/expr/issue-22933-2.stderr
+++ b/tests/ui/expr/issue-22933-2.stderr
@@ -5,10 +5,12 @@ LL | enum Delicious {
    | -------------- variant or associated item `PIE` not found for this enum
 ...
 LL |     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-   |                                                       ^^^
-   |                                                       |
-   |                                                       variant or associated item not found in `Delicious`
-   |                                                       help: there is a variant with a similar name: `Pie`
+   |                                                       ^^^ variant or associated item not found in `Delicious`
+   |
+help: there is a variant with a similar name
+   |
+LL |     ApplePie = Delicious::Apple as isize | Delicious::Pie as isize,
+   |                                                       ~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
index fcb9b8a6fc5..649e936888b 100644
--- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
+++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-unsized-const-params.rs b/tests/ui/feature-gates/feature-gate-unsized-const-params.rs
new file mode 100644
index 00000000000..d088d382377
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsized-const-params.rs
@@ -0,0 +1,6 @@
+struct Foo<const N: [u8]>;
+//~^ ERROR: `[u8]` is forbidden as the type of a const generic parameter
+//~| HELP: add `#![feature(adt_const_params)]` to the crate
+//~| HELP: add `#![feature(unsized_const_params)]` to the crate
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr b/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr
new file mode 100644
index 00000000000..0a87f34f4f5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr
@@ -0,0 +1,18 @@
+error: `[u8]` is forbidden as the type of a const generic parameter
+  --> $DIR/feature-gate-unsized-const-params.rs:1:21
+   |
+LL | struct Foo<const N: [u8]>;
+   |                     ^^^^
+   |
+   = 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)]
+   |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
index 4205c5c5ef7..d1decc0c3f1 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr
@@ -13,8 +13,8 @@ LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
-             Fooer<T>
              Fooy
+             Fooer<T>
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/gat-in-trait-path.rs:32:5
@@ -31,8 +31,8 @@ LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
-             Fooer<T>
              Fooy
+             Fooer<T>
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/gat-in-trait-path.rs:32:5
@@ -49,8 +49,8 @@ LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
-             Fooer<T>
              Fooy
+             Fooer<T>
    = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A = &'a ()> + 'static)>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr
index 7f58f825702..bcc6382cf7c 100644
--- a/tests/ui/generic-associated-types/issue-79422.base.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.base.stderr
@@ -29,8 +29,8 @@ LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
-             Source
              std::collections::BTreeMap<K, V>
+             Source
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:44:13
@@ -47,8 +47,8 @@ LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
-             Source
              std::collections::BTreeMap<K, V>
+             Source
    = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/generic-const-items/elided-lifetimes.stderr b/tests/ui/generic-const-items/elided-lifetimes.stderr
index 1d4a997ff60..85807a1b631 100644
--- a/tests/ui/generic-const-items/elided-lifetimes.stderr
+++ b/tests/ui/generic-const-items/elided-lifetimes.stderr
@@ -32,6 +32,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
index a6dcad3face..00034fb9f44 100644
--- a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
+++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 trait Bar<const FOO: &'static str> {}
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index f25269ca032..9c546659564 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -48,10 +48,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bap() -> Trait { Struct }
    |             ^^^^^ doesn't have a size known at compile-time
    |
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL | fn bap() -> impl Trait { Struct }
+   |             ++++
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn bap() -> Box<Trait> { Box::new(Struct) }
-   |             ++++     +   +++++++++      +
+LL | fn bap() -> Box<dyn Trait> { Box::new(Struct) }
+   |             +++++++      +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
@@ -59,11 +63,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn ban() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn ban() -> impl Trait { Struct }
    |             ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
    |             ++++         +   +++++++++      +
@@ -74,11 +78,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn bak() -> impl Trait { unimplemented!() }
    |             ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
    |             ++++         +   +++++++++                +
@@ -89,10 +93,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bal() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn bal() -> impl Trait {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn bal() -> Box<dyn Trait> {
@@ -108,10 +109,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bax() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn bax() -> impl Trait {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn bax() -> Box<dyn Trait> {
@@ -263,10 +261,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bat() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn bat() -> impl Trait {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn bat() -> Box<dyn Trait> {
@@ -282,10 +277,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bay() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn bay() -> impl Trait {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn bay() -> Box<dyn Trait> {
diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
index fc9c30abf13..09a689e6396 100644
--- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
+++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
@@ -54,10 +54,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn car() -> dyn NotObjectSafe {
    |             ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn car() -> impl NotObjectSafe {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn car() -> Box<dyn NotObjectSafe> {
diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
index 9205d74504f..54849c112f5 100644
--- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -171,11 +171,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn hat() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn hat() -> impl std::fmt::Display {
    |             ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn hat() -> Box<dyn std::fmt::Display> {
 LL |     match 13 {
@@ -192,11 +192,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn pug() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn pug() -> impl std::fmt::Display {
    |             ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn pug() -> Box<dyn std::fmt::Display> {
 LL |     match 13 {
@@ -211,10 +211,7 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn man() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
-   |
-LL | fn man() -> impl std::fmt::Display {
-   |             ~~~~
+   = help: if there were a single returned type, you could use `impl Trait` instead
 help: box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn man() -> Box<dyn std::fmt::Display> {
diff --git a/tests/ui/impl-trait/static-lifetime-return-position-impl-trait.rs b/tests/ui/impl-trait/static-lifetime-return-position-impl-trait.rs
index b6395258c89..9205f1e1632 100644
--- a/tests/ui/impl-trait/static-lifetime-return-position-impl-trait.rs
+++ b/tests/ui/impl-trait/static-lifetime-return-position-impl-trait.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
 #![allow(incomplete_features)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 
 pub struct Element;
 
diff --git a/tests/ui/inference/ice-cannot-relate-region-109178.rs b/tests/ui/inference/ice-cannot-relate-region-109178.rs
index 3282f95a992..2e3953646ff 100644
--- a/tests/ui/inference/ice-cannot-relate-region-109178.rs
+++ b/tests/ui/inference/ice-cannot-relate-region-109178.rs
@@ -2,7 +2,7 @@
 
 #![allow(incomplete_features)]
 #![crate_type = "lib"]
-#![feature(adt_const_params, generic_const_exprs)]
+#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
 
 struct Changes<const CHANGES: &[&'static str]>
 //~^ ERROR `&` without an explicit lifetime name cannot be used here
diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr
index 702207c30f7..705f7d0df12 100644
--- a/tests/ui/issues/issue-18107.stderr
+++ b/tests/ui/issues/issue-18107.stderr
@@ -4,11 +4,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL |     dyn AbstractRenderer
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL |     impl AbstractRenderer
    |     ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~     Box<dyn AbstractRenderer>
 LL |
diff --git a/tests/ui/issues/issue-23217.stderr b/tests/ui/issues/issue-23217.stderr
index 05ee0474c78..d14da75ab72 100644
--- a/tests/ui/issues/issue-23217.stderr
+++ b/tests/ui/issues/issue-23217.stderr
@@ -4,10 +4,12 @@ error[E0599]: no variant or associated item named `A` found for enum `SomeEnum`
 LL | pub enum SomeEnum {
    | ----------------- variant or associated item `A` not found for this enum
 LL |     B = SomeEnum::A,
-   |                   ^
-   |                   |
-   |                   variant or associated item not found in `SomeEnum`
-   |                   help: there is a variant with a similar name: `B`
+   |                   ^ variant or associated item not found in `SomeEnum`
+   |
+help: there is a variant with a similar name
+   |
+LL |     B = SomeEnum::B,
+   |                   ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr
index 26057cbc2d1..7ca57d6b998 100644
--- a/tests/ui/issues/issue-28971.stderr
+++ b/tests/ui/issues/issue-28971.stderr
@@ -5,10 +5,12 @@ LL | enum Foo {
    | -------- variant or associated item `Baz` not found for this enum
 ...
 LL |             Foo::Baz(..) => (),
-   |                  ^^^
-   |                  |
-   |                  variant or associated item not found in `Foo`
-   |                  help: there is a variant with a similar name: `Bar`
+   |                  ^^^ variant or associated item not found in `Foo`
+   |
+help: there is a variant with a similar name
+   |
+LL |             Foo::Bar(..) => (),
+   |                  ~~~
 
 error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
   --> $DIR/issue-28971.rs:15:5
diff --git a/tests/ui/issues/issue-34209.stderr b/tests/ui/issues/issue-34209.stderr
index 41bc60d03dd..4c61d250f52 100644
--- a/tests/ui/issues/issue-34209.stderr
+++ b/tests/ui/issues/issue-34209.stderr
@@ -5,7 +5,12 @@ LL | enum S {
    | ------ variant `B` not found here
 ...
 LL |         S::B {} => {},
-   |            ^ help: there is a variant with a similar name: `A`
+   |            ^
+   |
+help: there is a variant with a similar name
+   |
+LL |         S::A {} => {},
+   |            ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-4736.stderr b/tests/ui/issues/issue-4736.stderr
index 146dd1d57ce..c1ae2c47b43 100644
--- a/tests/ui/issues/issue-4736.stderr
+++ b/tests/ui/issues/issue-4736.stderr
@@ -9,8 +9,8 @@ LL |     let z = NonCopyable{ p: () };
    |
 help: `NonCopyable` is a tuple struct, use the appropriate syntax
    |
-LL |     let z = NonCopyable(/* fields */);
-   |             ~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let z = NonCopyable(/* () */);
+   |             ~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-80607.stderr b/tests/ui/issues/issue-80607.stderr
index 20494f319dd..d096910297b 100644
--- a/tests/ui/issues/issue-80607.stderr
+++ b/tests/ui/issues/issue-80607.stderr
@@ -9,8 +9,8 @@ LL |     Enum::V1 { x }
    |
 help: `Enum::V1` is a tuple variant, use the appropriate syntax
    |
-LL |     Enum::V1(/* fields */)
-   |     ~~~~~~~~~~~~~~~~~~~~~~
+LL |     Enum::V1(/* i32 */)
+   |             ~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
index 48e7da96612..192b5eebdaa 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
@@ -4,27 +4,27 @@ error[E0275]: overflow evaluating the requirement `Loop == _`
 LL | impl Loop {}
    |      ^^^^
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/inherent-impls-overflow.rs:14:12
+error: type parameter `T` is only used recursively
+  --> $DIR/inherent-impls-overflow.rs:14:24
    |
 LL | type Poly0<T> = Poly1<(T,)>;
-   |            ^           - `T` is named here, but is likely unused in the containing type
+   |            -           ^
    |            |
-   |            unused type parameter
+   |            type parameter must be used non-recursively in the definition
    |
    = help: consider removing `T` or referring to it in the body of the type alias
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+   = note: all type parameters must be used in a non-recursive way in order to constrain their variance
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/inherent-impls-overflow.rs:17:12
+error: type parameter `T` is only used recursively
+  --> $DIR/inherent-impls-overflow.rs:17:24
    |
 LL | type Poly1<T> = Poly0<(T,)>;
-   |            ^           - `T` is named here, but is likely unused in the containing type
+   |            -           ^
    |            |
-   |            unused type parameter
+   |            type parameter must be used non-recursively in the definition
    |
    = help: consider removing `T` or referring to it in the body of the type alias
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+   = note: all type parameters must be used in a non-recursive way in order to constrain their variance
 
 error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
   --> $DIR/inherent-impls-overflow.rs:21:6
@@ -36,5 +36,4 @@ LL | impl Poly0<()> {}
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0275, E0392.
-For more information about an error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
index 98f0d811a47..1397695a3fe 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
@@ -13,10 +13,10 @@ impl Loop {}
 
 type Poly0<T> = Poly1<(T,)>;
 //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
-//[next]~^^ ERROR type parameter `T` is never used
+//[next]~^^ ERROR type parameter `T` is only used recursively
 type Poly1<T> = Poly0<(T,)>;
 //[current]~^ ERROR  overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
-//[next]~^^ ERROR type parameter `T` is never used
+//[next]~^^ ERROR type parameter `T` is only used recursively
 
 impl Poly0<()> {}
 //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 70f06b4be60..e446345aedc 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -63,6 +63,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/lto/debuginfo-lto-alloc.rs b/tests/ui/lto/debuginfo-lto-alloc.rs
index 459103c354c..89043275329 100644
--- a/tests/ui/lto/debuginfo-lto-alloc.rs
+++ b/tests/ui/lto/debuginfo-lto-alloc.rs
@@ -9,7 +9,8 @@
 // that compilation is successful.
 
 //@ check-pass
-//@ compile-flags: --test -C debuginfo=2 -C lto=fat -C incremental=inc-fat
+//@ compile-flags: --test -C debuginfo=2 -C lto=fat
+//@ incremental
 
 extern crate alloc;
 
diff --git a/tests/ui/macros/builtin-std-paths-fail.stderr b/tests/ui/macros/builtin-std-paths-fail.stderr
index 331943843c0..49034c3987b 100644
--- a/tests/ui/macros/builtin-std-paths-fail.stderr
+++ b/tests/ui/macros/builtin-std-paths-fail.stderr
@@ -104,6 +104,8 @@ LL | #[std::test]
    |
 note: found an item that was configured out
   --> $SRC_DIR/std/src/lib.rs:LL:COL
+note: the item is gated here
+  --> $SRC_DIR/std/src/lib.rs:LL:COL
 
 error: aborting due to 16 previous errors
 
diff --git a/tests/ui/macros/macro-metavar-expr-concat/repetitions.rs b/tests/ui/macros/macro-metavar-expr-concat/repetitions.rs
new file mode 100644
index 00000000000..781443207ac
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/repetitions.rs
@@ -0,0 +1,18 @@
+//@ run-pass
+
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! one_rep {
+    ( $($a:ident)* ) => {
+        $(
+            const ${concat($a, Z)}: i32 = 3;
+        )*
+    };
+}
+
+fn main() {
+    one_rep!(A B C);
+    assert_eq!(AZ, 3);
+    assert_eq!(BZ, 3);
+    assert_eq!(CZ, 3);
+}
diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr
index 87c0655a422..a8809f3fcff 100644
--- a/tests/ui/macros/macro-outer-attributes.stderr
+++ b/tests/ui/macros/macro-outer-attributes.stderr
@@ -9,6 +9,17 @@ note: found an item that was configured out
    |
 LL |       pub fn bar() { });
    |              ^^^
+note: the item is gated here
+  --> $DIR/macro-outer-attributes.rs:5:45
+   |
+LL |                        $i:item) => (mod $nm { #[$a] $i }); }
+   |                                               ^^^^^
+LL |
+LL | / test!(a,
+LL | |       #[cfg(FALSE)],
+LL | |       pub fn bar() { });
+   | |_______________________- in this macro invocation
+   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider importing this function
    |
 LL + use b::bar;
diff --git a/tests/ui/mir/ice-mir-const-qualif-125837.rs b/tests/ui/mir/ice-mir-const-qualif-125837.rs
new file mode 100644
index 00000000000..a0f57caaba4
--- /dev/null
+++ b/tests/ui/mir/ice-mir-const-qualif-125837.rs
@@ -0,0 +1,17 @@
+// Test for ICE: mir_const_qualif: index out of bounds: the len is 0 but the index is 0
+// https://github.com/rust-lang/rust/issues/125837
+
+use std::fmt::Debug;
+
+trait Foo<Item> {}
+
+impl<Item, D: Debug + Clone> Foo for D {
+//~^ ERROR missing generics for trait `Foo`
+    fn foo<'a>(&'a self) -> impl Debug {
+    //~^ ERROR method `foo` is not a member of trait `Foo`
+        const { return }
+//~^ ERROR return statement outside of function body
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/mir/ice-mir-const-qualif-125837.stderr b/tests/ui/mir/ice-mir-const-qualif-125837.stderr
new file mode 100644
index 00000000000..003b327210b
--- /dev/null
+++ b/tests/ui/mir/ice-mir-const-qualif-125837.stderr
@@ -0,0 +1,41 @@
+error[E0407]: method `foo` is not a member of trait `Foo`
+  --> $DIR/ice-mir-const-qualif-125837.rs:10:5
+   |
+LL | /     fn foo<'a>(&'a self) -> impl Debug {
+LL | |
+LL | |         const { return }
+LL | |
+LL | |     }
+   | |_____^ not a member of trait `Foo`
+
+error[E0107]: missing generics for trait `Foo`
+  --> $DIR/ice-mir-const-qualif-125837.rs:8:30
+   |
+LL | impl<Item, D: Debug + Clone> Foo for D {
+   |                              ^^^ expected 1 generic argument
+   |
+note: trait defined here, with 1 generic parameter: `Item`
+  --> $DIR/ice-mir-const-qualif-125837.rs:6:7
+   |
+LL | trait Foo<Item> {}
+   |       ^^^ ----
+help: add missing generic argument
+   |
+LL | impl<Item, D: Debug + Clone> Foo<Item> for D {
+   |                                 ++++++
+
+error[E0572]: return statement outside of function body
+  --> $DIR/ice-mir-const-qualif-125837.rs:12:17
+   |
+LL | /     fn foo<'a>(&'a self) -> impl Debug {
+LL | |
+LL | |         const { return }
+   | |               --^^^^^^-- the return is part of this body...
+LL | |
+LL | |     }
+   | |_____- ...not the enclosing function body
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0107, E0407, E0572.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/nll/issue-55850.stderr b/tests/ui/nll/issue-55850.stderr
index 3d43817f4d8..5a9c7799197 100644
--- a/tests/ui/nll/issue-55850.stderr
+++ b/tests/ui/nll/issue-55850.stderr
@@ -10,8 +10,16 @@ LL |         yield &s[..]
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/issue-55850.rs:28:16
    |
+LL |     GenIter(#[coroutine] move || {
+   |                          ------- within this coroutine
+LL |         let mut s = String::new();
 LL |         yield &s[..]
    |         -------^---- possible yield occurs here
+   |
+help: add `static` to mark this coroutine as unmovable
+   |
+LL |     GenIter(#[coroutine] static move || {
+   |                          ++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/numeric/numeric-fields.stderr b/tests/ui/numeric/numeric-fields.stderr
index 668405ed638..8ab1718ff5e 100644
--- a/tests/ui/numeric/numeric-fields.stderr
+++ b/tests/ui/numeric/numeric-fields.stderr
@@ -9,8 +9,8 @@ LL |     let s = S{0b1: 10, 0: 11};
    |
 help: `S` is a tuple struct, use the appropriate syntax
    |
-LL |     let s = S(/* fields */);
-   |             ~~~~~~~~~~~~~~~
+LL |     let s = S(/* u8 */, /* u16 */);
+   |             ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:7:17
diff --git a/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.rs b/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.rs
new file mode 100644
index 00000000000..722303dd034
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.rs
@@ -0,0 +1,5 @@
+fn foo<T>() where T: Default -> impl Default + 'static {}
+//~^ ERROR return type should be specified after the function parameters
+//~| HELP place the return type after the function parameters
+
+fn main() {}
diff --git a/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.stderr
new file mode 100644
index 00000000000..2ce3b78bb8b
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-complex-type-issue-126311.stderr
@@ -0,0 +1,14 @@
+error: return type should be specified after the function parameters
+  --> $DIR/misplaced-return-type-complex-type-issue-126311.rs:1:30
+   |
+LL | fn foo<T>() where T: Default -> impl Default + 'static {}
+   |                              ^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
+   |
+help: place the return type after the function parameters
+   |
+LL - fn foo<T>() where T: Default -> impl Default + 'static {}
+LL + fn foo<T>() -> impl Default + 'static where T: Default  {}
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/misplaced-return-type-issue-126311.rs b/tests/ui/parser/issues/misplaced-return-type-issue-126311.rs
new file mode 100644
index 00000000000..ad164f77bee
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-issue-126311.rs
@@ -0,0 +1,5 @@
+fn foo<T>() where T: Default -> u8 {}
+//~^ ERROR return type should be specified after the function parameters
+//~| HELP place the return type after the function parameters
+
+fn main() {}
diff --git a/tests/ui/parser/issues/misplaced-return-type-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-issue-126311.stderr
new file mode 100644
index 00000000000..e473b902ce3
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-issue-126311.stderr
@@ -0,0 +1,14 @@
+error: return type should be specified after the function parameters
+  --> $DIR/misplaced-return-type-issue-126311.rs:1:30
+   |
+LL | fn foo<T>() where T: Default -> u8 {}
+   |                              ^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
+   |
+help: place the return type after the function parameters
+   |
+LL - fn foo<T>() where T: Default -> u8 {}
+LL + fn foo<T>() -> u8 where T: Default  {}
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.rs b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.rs
new file mode 100644
index 00000000000..782d7d5ee49
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.rs
@@ -0,0 +1,11 @@
+fn foo<T, K>()
+//~^ HELP place the return type after the function parameters
+where
+    T: Default,
+    K: Clone, -> Result<u8, String>
+//~^ ERROR return type should be specified after the function parameters
+{
+    Ok(0)
+}
+
+fn main() {}
diff --git a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr
new file mode 100644
index 00000000000..196a46d7ea5
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr
@@ -0,0 +1,17 @@
+error: return type should be specified after the function parameters
+  --> $DIR/misplaced-return-type-where-in-next-line-issue-126311.rs:5:15
+   |
+LL |     K: Clone, -> Result<u8, String>
+   |               ^^ expected one of `{`, lifetime, or type
+   |
+help: place the return type after the function parameters
+   |
+LL ~ fn foo<T, K>() -> Result<u8, String>
+LL |
+LL | where
+LL |     T: Default,
+LL ~     K: Clone, 
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.rs b/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.rs
new file mode 100644
index 00000000000..2c09edbc792
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.rs
@@ -0,0 +1,6 @@
+fn foo<T>() where T: Default -> {
+//~^ ERROR expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.stderr
new file mode 100644
index 00000000000..0eb3bb7d812
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-without-type-issue-126311.stderr
@@ -0,0 +1,8 @@
+error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->`
+  --> $DIR/misplaced-return-type-without-type-issue-126311.rs:1:30
+   |
+LL | fn foo<T>() where T: Default -> {
+   |                              ^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.rs b/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.rs
new file mode 100644
index 00000000000..672233674a0
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.rs
@@ -0,0 +1,4 @@
+fn bar<T>() -> u8 -> u64 {}
+//~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `->`
+
+fn main() {}
diff --git a/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.stderr
new file mode 100644
index 00000000000..730904d3671
--- /dev/null
+++ b/tests/ui/parser/issues/misplaced-return-type-without-where-issue-126311.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `->`
+  --> $DIR/misplaced-return-type-without-where-issue-126311.rs:1:19
+   |
+LL | fn bar<T>() -> u8 -> u64 {}
+   |                   ^^ expected one of 7 possible tokens
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/struct-literal-variant-in-if.stderr b/tests/ui/parser/struct-literal-variant-in-if.stderr
index 9f0c0074d67..15f059f145b 100644
--- a/tests/ui/parser/struct-literal-variant-in-if.stderr
+++ b/tests/ui/parser/struct-literal-variant-in-if.stderr
@@ -47,6 +47,11 @@ error[E0533]: expected value, found struct variant `E::V`
    |
 LL |     if x == E::V { field } {}
    |             ^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     if x == (E::V { field }) {}
+   |             +              +
 
 error[E0308]: mismatched types
   --> $DIR/struct-literal-variant-in-if.rs:10:20
diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
index 6e50dfe6a26..9b57c895eea 100644
--- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
@@ -204,6 +204,7 @@ note: `Option<Void>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<Void>`
+   = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~             None => {},
@@ -349,6 +350,7 @@ LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
    |
    = note: the matched value is of type `&[!]`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         [] => {},
@@ -484,6 +486,7 @@ note: `Option<!>` defined here
    |
    = note: not covered
    = note: the matched value is of type `&Option<!>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         &None => {},
@@ -502,6 +505,7 @@ note: `Option<!>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<!>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         None => {},
@@ -520,6 +524,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Ok(_) => {},
@@ -538,6 +543,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Ok(_a) => {},
@@ -589,6 +595,7 @@ LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&_` not covered
    |
    = note: the matched value is of type `&!`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
    = note: references are always considered inhabited
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -609,6 +616,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Err(_) => {},
@@ -627,6 +635,7 @@ note: `Option<Result<!, !>>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<Result<!, !>>`
+   = note: `Result<!, !>` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         None => {},
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
index a1239466c9c..f24ce154d14 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
@@ -5,6 +5,7 @@ LL |     match nevers {
    |           ^^^^^^ pattern `&[_, ..]` not covered
    |
    = note: the matched value is of type `&[!]`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         &[] => (),
diff --git a/tests/ui/resolve/issue-18252.stderr b/tests/ui/resolve/issue-18252.stderr
index 511b8da716f..6cb9c1f1dd2 100644
--- a/tests/ui/resolve/issue-18252.stderr
+++ b/tests/ui/resolve/issue-18252.stderr
@@ -3,6 +3,11 @@ error[E0533]: expected value, found struct variant `Foo::Variant`
    |
 LL |     let f = Foo::Variant(42);
    |             ^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let f = Foo::Variant { x: /* value */ };
+   |                          ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/resolve/issue-19452.stderr b/tests/ui/resolve/issue-19452.stderr
index eff89241fd2..aa7b752ca50 100644
--- a/tests/ui/resolve/issue-19452.stderr
+++ b/tests/ui/resolve/issue-19452.stderr
@@ -3,12 +3,22 @@ error[E0533]: expected value, found struct variant `Homura::Madoka`
    |
 LL |     let homura = Homura::Madoka;
    |                  ^^^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let homura = Homura::Madoka { age: /* value */ };
+   |                                 ++++++++++++++++++++
 
 error[E0533]: expected value, found struct variant `issue_19452_aux::Homura::Madoka`
   --> $DIR/issue-19452.rs:13:18
    |
 LL |     let homura = issue_19452_aux::Homura::Madoka;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let homura = issue_19452_aux::Homura::Madoka { age: /* value */ };
+   |                                                  ++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index ee3aecddcc3..12a6580048e 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -295,6 +295,11 @@ error[E0533]: expected value, found struct variant `Z::Struct`
    |
 LL |         let _: Z = Z::Struct;
    |                    ^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |         let _: Z = Z::Struct { s: /* value */ };
+   |                              ++++++++++++++++++
 
 error[E0618]: expected function, found enum variant `Z::Unit`
   --> $DIR/privacy-enum-ctor.rs:31:17
@@ -336,6 +341,11 @@ error[E0533]: expected value, found struct variant `m::E::Struct`
    |
 LL |     let _: E = m::E::Struct;
    |                ^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let _: E = m::E::Struct { s: /* value */ };
+   |                             ++++++++++++++++++
 
 error[E0618]: expected function, found enum variant `m::E::Unit`
   --> $DIR/privacy-enum-ctor.rs:47:16
@@ -377,6 +387,11 @@ error[E0533]: expected value, found struct variant `E::Struct`
    |
 LL |     let _: E = E::Struct;
    |                ^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let _: E = E::Struct { s: /* value */ };
+   |                          ++++++++++++++++++
 
 error[E0618]: expected function, found enum variant `E::Unit`
   --> $DIR/privacy-enum-ctor.rs:55:16
@@ -400,6 +415,11 @@ error[E0533]: expected value, found struct variant `m::n::Z::Struct`
    |
 LL |     let _: Z = m::n::Z::Struct;
    |                ^^^^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let _: Z = m::n::Z::Struct { s: /* value */ };
+   |                                ++++++++++++++++++
 
 error: aborting due to 23 previous errors
 
diff --git a/tests/ui/rust-2024/safe-outside-extern.gated.stderr b/tests/ui/rust-2024/safe-outside-extern.gated.stderr
index 18a3361f35b..e0b218281f3 100644
--- a/tests/ui/rust-2024/safe-outside-extern.gated.stderr
+++ b/tests/ui/rust-2024/safe-outside-extern.gated.stderr
@@ -28,5 +28,11 @@ error: function pointers cannot be declared with `safe` safety qualifier
 LL | type FnPtr = safe fn(i32, i32) -> i32;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+  --> $DIR/safe-outside-extern.rs:28:1
+   |
+LL | unsafe static LOL: u8 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs
index 9ec0c5c70e1..6773df5ef03 100644
--- a/tests/ui/rust-2024/safe-outside-extern.rs
+++ b/tests/ui/rust-2024/safe-outside-extern.rs
@@ -25,4 +25,7 @@ type FnPtr = safe fn(i32, i32) -> i32;
 //~^ ERROR: function pointers cannot be declared with `safe` safety qualifier
 //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
+unsafe static LOL: u8 = 0;
+//~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+
 fn main() {}
diff --git a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr
index 9ea6d451e8c..98a4c0eab92 100644
--- a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr
+++ b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr
@@ -28,6 +28,12 @@ error: function pointers cannot be declared with `safe` safety qualifier
 LL | type FnPtr = safe fn(i32, i32) -> i32;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+  --> $DIR/safe-outside-extern.rs:28:1
+   |
+LL | unsafe static LOL: u8 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental
   --> $DIR/safe-outside-extern.rs:4:1
    |
@@ -78,6 +84,6 @@ LL | type FnPtr = safe fn(i32, i32) -> i32;
    = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 10 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.fixed b/tests/ui/rust-2024/unsafe-env-suggestion.fixed
index 1f3d2dc0a31..eba35180ef6 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.fixed
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.fixed
@@ -1,6 +1,6 @@
 //@ run-rustfix
 
-#![deny(deprecated_safe)]
+#![deny(deprecated_safe_2024)]
 
 use std::env;
 
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.rs b/tests/ui/rust-2024/unsafe-env-suggestion.rs
index 3bd169973e3..c039d7f2583 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.rs
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.rs
@@ -1,6 +1,6 @@
 //@ run-rustfix
 
-#![deny(deprecated_safe)]
+#![deny(deprecated_safe_2024)]
 
 use std::env;
 
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.stderr b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
index 7c12f4aa5ed..3aa10a3bed6 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
@@ -9,8 +9,8 @@ LL |     env::set_var("FOO", "BAR");
 note: the lint level is defined here
   --> $DIR/unsafe-env-suggestion.rs:3:9
    |
-LL | #![deny(deprecated_safe)]
-   |         ^^^^^^^^^^^^^^^
+LL | #![deny(deprecated_safe_2024)]
+   |         ^^^^^^^^^^^^^^^^^^^^
 help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code
    |
 LL +     // TODO: Audit that the environment access only happens in single-threaded code.
diff --git a/tests/ui/sanitizer/cfi-supertraits.rs b/tests/ui/sanitizer/cfi-supertraits.rs
index ed3d722ebb7..4bb6177577f 100644
--- a/tests/ui/sanitizer/cfi-supertraits.rs
+++ b/tests/ui/sanitizer/cfi-supertraits.rs
@@ -16,6 +16,9 @@
 trait Parent1 {
     type P1;
     fn p1(&self) -> Self::P1;
+    fn d(&self) -> i32 {
+        42
+    }
 }
 
 trait Parent2 {
@@ -60,14 +63,17 @@ fn main() {
     x.c();
     x.p1();
     x.p2();
+    x.d();
     // Parents can be created and access their methods.
     let y = &Foo as &dyn Parent1<P1=u16>;
     y.p1();
+    y.d();
     let z = &Foo as &dyn Parent2<P2=u32>;
     z.p2();
     // Trait upcasting works
     let x1 = x as &dyn Parent1<P1=u16>;
     x1.p1();
+    x1.d();
     let x2 = x as &dyn Parent2<P2=u32>;
     x2.p2();
 }
diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs
index abceb08ecc5..aec75a67306 100644
--- a/tests/ui/simd/intrinsic/generic-elements.rs
+++ b/tests/ui/simd/intrinsic/generic-elements.rs
@@ -1,6 +1,6 @@
 //@ build-fail
 
-#![feature(repr_simd, intrinsics, rustc_attrs, adt_const_params)]
+#![feature(repr_simd, intrinsics, rustc_attrs, adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 #[repr(simd)]
@@ -14,8 +14,7 @@ struct i32x4(i32, i32, i32, i32);
 #[repr(simd)]
 #[derive(Copy, Clone)]
 #[allow(non_camel_case_types)]
-struct i32x8(i32, i32, i32, i32,
-             i32, i32, i32, i32);
+struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32);
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
@@ -28,8 +27,7 @@ struct f32x4(f32, f32, f32, f32);
 #[repr(simd)]
 #[derive(Copy, Clone)]
 #[allow(non_camel_case_types)]
-struct f32x8(f32, f32, f32, f32,
-             f32, f32, f32, f32);
+struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
 
 extern "rust-intrinsic" {
     fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
@@ -61,11 +59,11 @@ fn main() {
         //~^ ERROR expected SIMD input type, found non-SIMD `i32`
 
         simd_shuffle::<_, _, f32x2>(x, x, IDX2);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
         simd_shuffle::<_, _, f32x4>(x, x, IDX4);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
         simd_shuffle::<_, _, f32x8>(x, x, IDX8);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
 
         simd_shuffle::<_, _, i32x8>(x, x, IDX2);
         //~^ ERROR expected return type of length 2, found `i32x8` with length 8
@@ -85,11 +83,11 @@ fn main() {
         //~^ ERROR expected SIMD input type, found non-SIMD `i32`
 
         simd_shuffle_generic::<_, f32x2, I2>(x, x);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
         simd_shuffle_generic::<_, f32x4, I4>(x, x);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
         simd_shuffle_generic::<_, f32x8, I8>(x, x);
-//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+        //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
 
         simd_shuffle_generic::<_, i32x8, I2>(x, x);
         //~^ ERROR expected return type of length 2, found `i32x8` with length 8
diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr
index 26e01344939..0788a7c17f9 100644
--- a/tests/ui/simd/intrinsic/generic-elements.stderr
+++ b/tests/ui/simd/intrinsic/generic-elements.stderr
@@ -1,125 +1,125 @@
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:46:9
+  --> $DIR/generic-elements.rs:44:9
    |
 LL |         simd_insert(0, 0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
-  --> $DIR/generic-elements.rs:48:9
+  --> $DIR/generic-elements.rs:46:9
    |
 LL |         simd_insert(x, 0, 1.0);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
-  --> $DIR/generic-elements.rs:50:9
+  --> $DIR/generic-elements.rs:48:9
    |
 LL |         simd_extract::<_, f32>(x, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:54:9
+  --> $DIR/generic-elements.rs:52:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:57:9
+  --> $DIR/generic-elements.rs:55:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:60:9
+  --> $DIR/generic-elements.rs:58:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
-  --> $DIR/generic-elements.rs:63:9
+  --> $DIR/generic-elements.rs:61:9
    |
 LL |         simd_shuffle::<_, _, f32x2>(x, x, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
-  --> $DIR/generic-elements.rs:65:9
+  --> $DIR/generic-elements.rs:63:9
    |
 LL |         simd_shuffle::<_, _, f32x4>(x, x, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
-  --> $DIR/generic-elements.rs:67:9
+  --> $DIR/generic-elements.rs:65:9
    |
 LL |         simd_shuffle::<_, _, f32x8>(x, x, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:70:9
+  --> $DIR/generic-elements.rs:68:9
    |
 LL |         simd_shuffle::<_, _, i32x8>(x, x, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:72:9
+  --> $DIR/generic-elements.rs:70:9
    |
 LL |         simd_shuffle::<_, _, i32x8>(x, x, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2
-  --> $DIR/generic-elements.rs:74:9
+  --> $DIR/generic-elements.rs:72:9
    |
 LL |         simd_shuffle::<_, _, i32x2>(x, x, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:78:9
+  --> $DIR/generic-elements.rs:76:9
    |
 LL |         simd_shuffle_generic::<i32, i32, I2>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:81:9
+  --> $DIR/generic-elements.rs:79:9
    |
 LL |         simd_shuffle_generic::<i32, i32, I4>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:84:9
+  --> $DIR/generic-elements.rs:82:9
    |
 LL |         simd_shuffle_generic::<i32, i32, I8>(0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
-  --> $DIR/generic-elements.rs:87:9
+  --> $DIR/generic-elements.rs:85:9
    |
 LL |         simd_shuffle_generic::<_, f32x2, I2>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
-  --> $DIR/generic-elements.rs:89:9
+  --> $DIR/generic-elements.rs:87:9
    |
 LL |         simd_shuffle_generic::<_, f32x4, I4>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
-  --> $DIR/generic-elements.rs:91:9
+  --> $DIR/generic-elements.rs:89:9
    |
 LL |         simd_shuffle_generic::<_, f32x8, I8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:94:9
+  --> $DIR/generic-elements.rs:92:9
    |
 LL |         simd_shuffle_generic::<_, i32x8, I2>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:96:9
+  --> $DIR/generic-elements.rs:94:9
    |
 LL |         simd_shuffle_generic::<_, i32x8, I4>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2
-  --> $DIR/generic-elements.rs:98:9
+  --> $DIR/generic-elements.rs:96:9
    |
 LL |         simd_shuffle_generic::<_, i32x2, I8>(x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs
index 379616884a1..30c345cb904 100644
--- a/tests/ui/simd/monomorphize-shuffle-index.rs
+++ b/tests/ui/simd/monomorphize-shuffle-index.rs
@@ -1,7 +1,7 @@
 //@[old]run-pass
 //@[generic_with_fn]run-pass
 //@ revisions: old generic generic_with_fn
-#![feature(repr_simd, intrinsics, adt_const_params, generic_const_exprs)]
+#![feature(repr_simd, intrinsics, adt_const_params, unsized_const_params, generic_const_exprs)]
 #![allow(incomplete_features)]
 
 extern "rust-intrinsic" {
diff --git a/tests/ui/static/raw-ref-deref-with-unsafe.rs b/tests/ui/static/raw-ref-deref-with-unsafe.rs
new file mode 100644
index 00000000000..4b8f72de5b7
--- /dev/null
+++ b/tests/ui/static/raw-ref-deref-with-unsafe.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+#![feature(const_mut_refs)]
+use std::ptr;
+
+// This code should remain unsafe because of the two unsafe operations here,
+// even if in a hypothetical future we deem all &raw (const|mut) *ptr exprs safe.
+
+static mut BYTE: u8 = 0;
+static mut BYTE_PTR: *mut u8 = ptr::addr_of_mut!(BYTE);
+// An unsafe static's ident is a place expression in its own right, so despite the above being safe
+// (it's fine to create raw refs to places!) the following derefs the ptr before creating its ref
+static mut DEREF_BYTE_PTR: *mut u8 = unsafe { ptr::addr_of_mut!(*BYTE_PTR) };
+
+fn main() {
+    let _ = unsafe { DEREF_BYTE_PTR };
+}
diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.rs b/tests/ui/static/raw-ref-deref-without-unsafe.rs
new file mode 100644
index 00000000000..f9bce4368c1
--- /dev/null
+++ b/tests/ui/static/raw-ref-deref-without-unsafe.rs
@@ -0,0 +1,18 @@
+#![feature(const_mut_refs)]
+
+use std::ptr;
+
+// This code should remain unsafe because of the two unsafe operations here,
+// even if in a hypothetical future we deem all &raw (const|mut) *ptr exprs safe.
+
+static mut BYTE: u8 = 0;
+static mut BYTE_PTR: *mut u8 = ptr::addr_of_mut!(BYTE);
+// An unsafe static's ident is a place expression in its own right, so despite the above being safe
+// (it's fine to create raw refs to places!) the following derefs the ptr before creating its ref!
+static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR);
+//~^ ERROR: use of mutable static
+//~| ERROR: dereference of raw pointer
+
+fn main() {
+    let _ = unsafe { DEREF_BYTE_PTR };
+}
diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.stderr b/tests/ui/static/raw-ref-deref-without-unsafe.stderr
new file mode 100644
index 00000000000..ac4df8b410c
--- /dev/null
+++ b/tests/ui/static/raw-ref-deref-without-unsafe.stderr
@@ -0,0 +1,19 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/raw-ref-deref-without-unsafe.rs:12:56
+   |
+LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR);
+   |                                                        ^^^^^^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/raw-ref-deref-without-unsafe.rs:12:57
+   |
+LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR);
+   |                                                         ^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/static/raw-ref-extern-static.rs b/tests/ui/static/raw-ref-extern-static.rs
new file mode 100644
index 00000000000..95a53a8640d
--- /dev/null
+++ b/tests/ui/static/raw-ref-extern-static.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+#![feature(raw_ref_op)]
+use std::ptr;
+
+// see https://github.com/rust-lang/rust/issues/125833
+// notionally, taking the address of an extern static is a safe operation,
+// as we only point at it instead of generating a true reference to it
+
+// it may potentially induce linker errors, but the safety of that is not about taking addresses!
+// any safety obligation of the extern static's correctness in declaration is on the extern itself,
+// see RFC 3484 for more on that: https://rust-lang.github.io/rfcs/3484-unsafe-extern-blocks.html
+
+extern "C" {
+    static THERE: u8;
+    static mut SOMEWHERE: u8;
+}
+
+fn main() {
+    let ptr2there = ptr::addr_of!(THERE);
+    let ptr2somewhere = ptr::addr_of!(SOMEWHERE);
+    let ptr2somewhere = ptr::addr_of_mut!(SOMEWHERE);
+
+    // testing both addr_of and the expression it directly expands to
+    let raw2there = &raw const THERE;
+    let raw2somewhere = &raw const SOMEWHERE;
+    let raw2somewhere = &raw mut SOMEWHERE;
+}
diff --git a/tests/ui/static/raw-ref-static-mut.rs b/tests/ui/static/raw-ref-static-mut.rs
new file mode 100644
index 00000000000..6855cc7b050
--- /dev/null
+++ b/tests/ui/static/raw-ref-static-mut.rs
@@ -0,0 +1,17 @@
+//@ check-pass
+#![feature(raw_ref_op)]
+use std::ptr;
+
+// see https://github.com/rust-lang/rust/issues/125833
+// notionally, taking the address of a static mut is a safe operation,
+// as we only point at it instead of generating a true reference to it
+static mut NOWHERE: usize = 0;
+
+fn main() {
+    let p2nowhere = ptr::addr_of!(NOWHERE);
+    let p2nowhere = ptr::addr_of_mut!(NOWHERE);
+
+    // testing both addr_of and the expression it directly expands to
+    let raw2nowhere  = &raw const NOWHERE;
+    let raw2nowhere  = &raw mut NOWHERE;
+}
diff --git a/tests/ui/statics/const_generics.rs b/tests/ui/statics/const_generics.rs
index 70d9b933a76..7f64f6995a4 100644
--- a/tests/ui/statics/const_generics.rs
+++ b/tests/ui/statics/const_generics.rs
@@ -11,7 +11,7 @@
 //@[opt] compile-flags: -O
 
 #![feature(const_refs_to_static)]
-#![feature(adt_const_params)]
+#![feature(adt_const_params, unsized_const_params)]
 #![allow(incomplete_features)]
 
 static FOO: usize = 42;
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 40bb87c8a40..1af86860ce1 100644
--- a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -129,6 +129,11 @@ error[E0533]: expected value, found struct variant `E::B`
    |
 LL |     let _: E = E::B;
    |                ^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     let _: E = E::B { a: /* value */ };
+   |                     ++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/fn-or-tuple-struct-without-args.rs:37:20
diff --git a/tests/ui/suggestions/incorrect-variant-literal.rs b/tests/ui/suggestions/incorrect-variant-literal.rs
new file mode 100644
index 00000000000..aac2cc54904
--- /dev/null
+++ b/tests/ui/suggestions/incorrect-variant-literal.rs
@@ -0,0 +1,55 @@
+//@ only-linux
+//@ compile-flags: --error-format=human --color=always
+
+enum Enum {
+    Unit,
+    Tuple(i32),
+    Struct { x: i32 },
+}
+
+fn main() {
+    Enum::Unit;
+    Enum::Tuple;
+    Enum::Struct;
+    Enum::Unit();
+    Enum::Tuple();
+    Enum::Struct();
+    Enum::Unit {};
+    Enum::Tuple {};
+    Enum::Struct {};
+    Enum::Unit(0);
+    Enum::Tuple(0);
+    Enum::Struct(0);
+    Enum::Unit { x: 0 };
+    Enum::Tuple { x: 0 };
+    Enum::Struct { x: 0 }; // ok
+    Enum::Unit(0, 0);
+    Enum::Tuple(0, 0);
+    Enum::Struct(0, 0);
+    Enum::Unit { x: 0, y: 0 };
+
+    Enum::Tuple { x: 0, y: 0 };
+
+    Enum::Struct { x: 0, y: 0 };
+    Enum::unit;
+    Enum::tuple;
+    Enum::r#struct;
+    Enum::unit();
+    Enum::tuple();
+    Enum::r#struct();
+    Enum::unit {};
+    Enum::tuple {};
+    Enum::r#struct {};
+    Enum::unit(0);
+    Enum::tuple(0);
+    Enum::r#struct(0);
+    Enum::unit { x: 0 };
+    Enum::tuple { x: 0 };
+    Enum::r#struct { x: 0 };
+    Enum::unit(0, 0);
+    Enum::tuple(0, 0);
+    Enum::r#struct(0, 0);
+    Enum::unit { x: 0, y: 0 };
+    Enum::tuple { x: 0, y: 0 };
+    Enum::r#struct { x: 0, y: 0 };
+}
diff --git a/tests/ui/suggestions/incorrect-variant-literal.svg b/tests/ui/suggestions/incorrect-variant-literal.svg
new file mode 100644
index 00000000000..980a7b29a00
--- /dev/null
+++ b/tests/ui/suggestions/incorrect-variant-literal.svg
@@ -0,0 +1,1028 @@
+<svg width="886px" height="9038px" xmlns="http://www.w3.org/2000/svg">
+  <style>
+    .fg { fill: #AAAAAA }
+    .bg { background: #000000 }
+    .fg-ansi256-009 { fill: #FF5555 }
+    .fg-ansi256-010 { fill: #55FF55 }
+    .fg-ansi256-012 { fill: #5555FF }
+    .fg-ansi256-014 { fill: #55FFFF }
+    .container {
+      padding: 0 10px;
+      line-height: 18px;
+    }
+    .bold { font-weight: bold; }
+    tspan {
+      font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+      white-space: pre;
+      line-height: 18px;
+    }
+  </style>
+
+  <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
+
+  <text xml:space="preserve" class="container fg">
+    <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[E0533]</tspan><tspan class="bold">: expected value, found struct variant `Enum::Struct`</tspan>
+</tspan>
+    <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:13:5</tspan>
+</tspan>
+    <tspan x="10px" y="64px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct;</tspan>
+</tspan>
+    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">not a value</tspan>
+</tspan>
+    <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="136px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: you might have meant to create a new value of the struct</tspan>
+</tspan>
+    <tspan x="10px" y="154px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Struct</tspan><tspan class="fg-ansi256-010"> { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="190px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-010">++++++++++++++++++</tspan>
+</tspan>
+    <tspan x="10px" y="208px">
+</tspan>
+    <tspan x="10px" y="226px"><tspan class="fg-ansi256-009 bold">error[E0618]</tspan><tspan class="bold">: expected function, found enum variant `Enum::Unit`</tspan>
+</tspan>
+    <tspan x="10px" y="244px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:14:5</tspan>
+</tspan>
+    <tspan x="10px" y="262px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="280px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Unit,</tspan>
+</tspan>
+    <tspan x="10px" y="298px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">enum variant `Enum::Unit` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="334px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit();</tspan>
+</tspan>
+    <tspan x="10px" y="352px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan class="fg-ansi256-012 bold">--</tspan>
+</tspan>
+    <tspan x="10px" y="370px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="388px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">call expression requires function</tspan>
+</tspan>
+    <tspan x="10px" y="406px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="424px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: `Enum::Unit` is a unit enum variant, and does not take parentheses to be constructed</tspan>
+</tspan>
+    <tspan x="10px" y="442px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan>    Enum::Unit</tspan><tspan class="fg-ansi256-009">()</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan>    Enum::Unit;</tspan>
+</tspan>
+    <tspan x="10px" y="496px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="514px">
+</tspan>
+    <tspan x="10px" y="532px"><tspan class="fg-ansi256-009 bold">error[E0061]</tspan><tspan class="bold">: this enum variant takes 1 argument but 0 arguments were supplied</tspan>
+</tspan>
+    <tspan x="10px" y="550px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:15:5</tspan>
+</tspan>
+    <tspan x="10px" y="568px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple();</tspan>
+</tspan>
+    <tspan x="10px" y="604px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^</tspan><tspan class="fg-ansi256-012 bold">--</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">argument #1 of type `i32` is missing</tspan>
+</tspan>
+    <tspan x="10px" y="622px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="640px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: tuple variant defined here</tspan>
+</tspan>
+    <tspan x="10px" y="658px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:6:5</tspan>
+</tspan>
+    <tspan x="10px" y="676px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="694px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Tuple(i32),</tspan>
+</tspan>
+    <tspan x="10px" y="712px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="730px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: provide the argument</tspan>
+</tspan>
+    <tspan x="10px" y="748px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="766px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Tuple</tspan><tspan class="fg-ansi256-010">(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="784px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="802px">
+</tspan>
+    <tspan x="10px" y="820px"><tspan class="fg-ansi256-009 bold">error[E0533]</tspan><tspan class="bold">: expected value, found struct variant `Enum::Struct`</tspan>
+</tspan>
+    <tspan x="10px" y="838px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:16:5</tspan>
+</tspan>
+    <tspan x="10px" y="856px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="874px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct();</tspan>
+</tspan>
+    <tspan x="10px" y="892px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">not a value</tspan>
+</tspan>
+    <tspan x="10px" y="910px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="928px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: you might have meant to create a new value of the struct</tspan>
+</tspan>
+    <tspan x="10px" y="946px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="964px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Struct</tspan><tspan class="fg-ansi256-010"> { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="982px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="1000px">
+</tspan>
+    <tspan x="10px" y="1018px"><tspan class="fg-ansi256-009 bold">error[E0063]</tspan><tspan class="bold">: missing field `0` in initializer of `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="1036px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:18:5</tspan>
+</tspan>
+    <tspan x="10px" y="1054px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1072px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple {};</tspan>
+</tspan>
+    <tspan x="10px" y="1090px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">missing `0`</tspan>
+</tspan>
+    <tspan x="10px" y="1108px">
+</tspan>
+    <tspan x="10px" y="1126px"><tspan class="fg-ansi256-009 bold">error[E0063]</tspan><tspan class="bold">: missing field `x` in initializer of `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="1144px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:19:5</tspan>
+</tspan>
+    <tspan x="10px" y="1162px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1180px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct {};</tspan>
+</tspan>
+    <tspan x="10px" y="1198px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">missing `x`</tspan>
+</tspan>
+    <tspan x="10px" y="1216px">
+</tspan>
+    <tspan x="10px" y="1234px"><tspan class="fg-ansi256-009 bold">error[E0618]</tspan><tspan class="bold">: expected function, found `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="1252px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:20:5</tspan>
+</tspan>
+    <tspan x="10px" y="1270px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1288px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Unit,</tspan>
+</tspan>
+    <tspan x="10px" y="1306px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`Enum::Unit` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="1324px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="1342px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit(0);</tspan>
+</tspan>
+    <tspan x="10px" y="1360px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan class="fg-ansi256-012 bold">---</tspan>
+</tspan>
+    <tspan x="10px" y="1378px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1396px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">call expression requires function</tspan>
+</tspan>
+    <tspan x="10px" y="1414px">
+</tspan>
+    <tspan x="10px" y="1432px"><tspan class="fg-ansi256-009 bold">error[E0533]</tspan><tspan class="bold">: expected value, found struct variant `Enum::Struct`</tspan>
+</tspan>
+    <tspan x="10px" y="1450px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:22:5</tspan>
+</tspan>
+    <tspan x="10px" y="1468px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1486px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct(0);</tspan>
+</tspan>
+    <tspan x="10px" y="1504px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">not a value</tspan>
+</tspan>
+    <tspan x="10px" y="1522px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1540px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: you might have meant to create a new value of the struct</tspan>
+</tspan>
+    <tspan x="10px" y="1558px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1576px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Struct</tspan><tspan class="fg-ansi256-010"> { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="1594px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="1612px">
+</tspan>
+    <tspan x="10px" y="1630px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Unit` has no field named `x`</tspan>
+</tspan>
+    <tspan x="10px" y="1648px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:23:18</tspan>
+</tspan>
+    <tspan x="10px" y="1666px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1684px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit { x: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="1702px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`Enum::Unit` does not have this field</tspan>
+</tspan>
+    <tspan x="10px" y="1720px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1738px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: all struct fields are already assigned</tspan>
+</tspan>
+    <tspan x="10px" y="1756px">
+</tspan>
+    <tspan x="10px" y="1774px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Tuple` has no field named `x`</tspan>
+</tspan>
+    <tspan x="10px" y="1792px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:24:19</tspan>
+</tspan>
+    <tspan x="10px" y="1810px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1828px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Tuple(i32),</tspan>
+</tspan>
+    <tspan x="10px" y="1846px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`Enum::Tuple` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="1864px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="1882px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple { x: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="1900px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                   </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">field does not exist</tspan>
+</tspan>
+    <tspan x="10px" y="1918px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1936px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: `Enum::Tuple` is a tuple variant, use the appropriate syntax</tspan>
+</tspan>
+    <tspan x="10px" y="1954px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="1972px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Tuple</tspan><tspan class="fg-ansi256-010">(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="1990px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="2008px">
+</tspan>
+    <tspan x="10px" y="2026px"><tspan class="fg-ansi256-009 bold">error[E0618]</tspan><tspan class="bold">: expected function, found `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="2044px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:26:5</tspan>
+</tspan>
+    <tspan x="10px" y="2062px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2080px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Unit,</tspan>
+</tspan>
+    <tspan x="10px" y="2098px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`Enum::Unit` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="2116px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="2134px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="2152px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^</tspan><tspan class="fg-ansi256-012 bold">------</tspan>
+</tspan>
+    <tspan x="10px" y="2170px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2188px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">call expression requires function</tspan>
+</tspan>
+    <tspan x="10px" y="2206px">
+</tspan>
+    <tspan x="10px" y="2224px"><tspan class="fg-ansi256-009 bold">error[E0061]</tspan><tspan class="bold">: this enum variant takes 1 argument but 2 arguments were supplied</tspan>
+</tspan>
+    <tspan x="10px" y="2242px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:27:5</tspan>
+</tspan>
+    <tspan x="10px" y="2260px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2278px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="2296px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^</tspan><tspan>    </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">unexpected argument #2 of type `{integer}`</tspan>
+</tspan>
+    <tspan x="10px" y="2314px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2332px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: tuple variant defined here</tspan>
+</tspan>
+    <tspan x="10px" y="2350px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:6:5</tspan>
+</tspan>
+    <tspan x="10px" y="2368px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2386px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Tuple(i32),</tspan>
+</tspan>
+    <tspan x="10px" y="2404px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-010 bold">^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="2422px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: remove the extra argument</tspan>
+</tspan>
+    <tspan x="10px" y="2440px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2458px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan>    Enum::Tuple(0</tspan><tspan class="fg-ansi256-009">, 0</tspan><tspan>);</tspan>
+</tspan>
+    <tspan x="10px" y="2476px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan>    Enum::Tuple(0);</tspan>
+</tspan>
+    <tspan x="10px" y="2494px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2512px">
+</tspan>
+    <tspan x="10px" y="2530px"><tspan class="fg-ansi256-009 bold">error[E0533]</tspan><tspan class="bold">: expected value, found struct variant `Enum::Struct`</tspan>
+</tspan>
+    <tspan x="10px" y="2548px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:28:5</tspan>
+</tspan>
+    <tspan x="10px" y="2566px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2584px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="2602px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">not a value</tspan>
+</tspan>
+    <tspan x="10px" y="2620px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2638px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: you might have meant to create a new value of the struct</tspan>
+</tspan>
+    <tspan x="10px" y="2656px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2674px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Struct</tspan><tspan class="fg-ansi256-010"> { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="2692px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="2710px">
+</tspan>
+    <tspan x="10px" y="2728px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Unit` has no field named `x`</tspan>
+</tspan>
+    <tspan x="10px" y="2746px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:29:18</tspan>
+</tspan>
+    <tspan x="10px" y="2764px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2782px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="2800px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                  </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`Enum::Unit` does not have this field</tspan>
+</tspan>
+    <tspan x="10px" y="2818px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2836px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: all struct fields are already assigned</tspan>
+</tspan>
+    <tspan x="10px" y="2854px">
+</tspan>
+    <tspan x="10px" y="2872px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Unit` has no field named `y`</tspan>
+</tspan>
+    <tspan x="10px" y="2890px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:29:24</tspan>
+</tspan>
+    <tspan x="10px" y="2908px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2926px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Unit { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="2944px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                        </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`Enum::Unit` does not have this field</tspan>
+</tspan>
+    <tspan x="10px" y="2962px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="2980px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: all struct fields are already assigned</tspan>
+</tspan>
+    <tspan x="10px" y="2998px">
+</tspan>
+    <tspan x="10px" y="3016px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Tuple` has no field named `x`</tspan>
+</tspan>
+    <tspan x="10px" y="3034px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:31:19</tspan>
+</tspan>
+    <tspan x="10px" y="3052px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3070px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Tuple(i32),</tspan>
+</tspan>
+    <tspan x="10px" y="3088px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`Enum::Tuple` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="3106px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="3124px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="3142px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                   </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">field does not exist</tspan>
+</tspan>
+    <tspan x="10px" y="3160px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3178px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: `Enum::Tuple` is a tuple variant, use the appropriate syntax</tspan>
+</tspan>
+    <tspan x="10px" y="3196px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3214px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Tuple</tspan><tspan class="fg-ansi256-010">(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="3232px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="3250px">
+</tspan>
+    <tspan x="10px" y="3268px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Tuple` has no field named `y`</tspan>
+</tspan>
+    <tspan x="10px" y="3286px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:31:25</tspan>
+</tspan>
+    <tspan x="10px" y="3304px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3322px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Tuple(i32),</tspan>
+</tspan>
+    <tspan x="10px" y="3340px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     </tspan><tspan class="fg-ansi256-012 bold">-----</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`Enum::Tuple` defined here</tspan>
+</tspan>
+    <tspan x="10px" y="3358px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="3376px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Tuple { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="3394px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                         </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">field does not exist</tspan>
+</tspan>
+    <tspan x="10px" y="3412px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3430px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: `Enum::Tuple` is a tuple variant, use the appropriate syntax</tspan>
+</tspan>
+    <tspan x="10px" y="3448px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3466px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::Tuple</tspan><tspan class="fg-ansi256-010">(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="3484px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="3502px">
+</tspan>
+    <tspan x="10px" y="3520px"><tspan class="fg-ansi256-009 bold">error[E0559]</tspan><tspan class="bold">: variant `Enum::Struct` has no field named `y`</tspan>
+</tspan>
+    <tspan x="10px" y="3538px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:33:26</tspan>
+</tspan>
+    <tspan x="10px" y="3556px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3574px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::Struct { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="3592px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>                          </tspan><tspan class="fg-ansi256-009 bold">^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`Enum::Struct` does not have this field</tspan>
+</tspan>
+    <tspan x="10px" y="3610px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3628px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: all struct fields are already assigned</tspan>
+</tspan>
+    <tspan x="10px" y="3646px">
+</tspan>
+    <tspan x="10px" y="3664px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `unit` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="3682px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:34:11</tspan>
+</tspan>
+    <tspan x="10px" y="3700px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3718px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="3736px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `unit` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="3754px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="3772px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit;</tspan>
+</tspan>
+    <tspan x="10px" y="3790px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="3808px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3826px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name (notice the capitalization difference)</tspan>
+</tspan>
+    <tspan x="10px" y="3844px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3862px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="3880px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="3898px">
+</tspan>
+    <tspan x="10px" y="3916px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `tuple` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="3934px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:35:11</tspan>
+</tspan>
+    <tspan x="10px" y="3952px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="3970px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="3988px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `tuple` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="4006px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="4024px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple;</tspan>
+</tspan>
+    <tspan x="10px" y="4042px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="4060px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4078px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="4096px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4114px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="4132px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="4150px">
+</tspan>
+    <tspan x="10px" y="4168px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `r#struct` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="4186px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:36:11</tspan>
+</tspan>
+    <tspan x="10px" y="4204px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4222px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="4240px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `r#struct` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="4258px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="4276px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct;</tspan>
+</tspan>
+    <tspan x="10px" y="4294px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="4312px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4330px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="4348px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4366px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="4384px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="4402px">
+</tspan>
+    <tspan x="10px" y="4420px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `unit` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="4438px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:37:11</tspan>
+</tspan>
+    <tspan x="10px" y="4456px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4474px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="4492px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `unit` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="4510px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="4528px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit();</tspan>
+</tspan>
+    <tspan x="10px" y="4546px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="4564px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4582px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="4600px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4618px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="4636px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="4654px">
+</tspan>
+    <tspan x="10px" y="4672px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `tuple` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="4690px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:38:11</tspan>
+</tspan>
+    <tspan x="10px" y="4708px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4726px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="4744px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `tuple` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="4762px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="4780px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple();</tspan>
+</tspan>
+    <tspan x="10px" y="4798px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="4816px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4834px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="4852px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4870px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="4888px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="4906px">
+</tspan>
+    <tspan x="10px" y="4924px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `r#struct` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="4942px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:39:11</tspan>
+</tspan>
+    <tspan x="10px" y="4960px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="4978px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="4996px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `r#struct` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="5014px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="5032px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct();</tspan>
+</tspan>
+    <tspan x="10px" y="5050px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="5068px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5086px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="5104px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5122px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="5140px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="5158px">
+</tspan>
+    <tspan x="10px" y="5176px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `unit` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="5194px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:40:11</tspan>
+</tspan>
+    <tspan x="10px" y="5212px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5230px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="5248px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `unit` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="5266px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="5284px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit {};</tspan>
+</tspan>
+    <tspan x="10px" y="5302px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="5320px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5338px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="5356px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5374px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="5392px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="5410px">
+</tspan>
+    <tspan x="10px" y="5428px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `tuple` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="5446px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:41:11</tspan>
+</tspan>
+    <tspan x="10px" y="5464px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5482px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="5500px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `tuple` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="5518px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="5536px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple {};</tspan>
+</tspan>
+    <tspan x="10px" y="5554px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="5572px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5590px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="5608px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5626px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="5644px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="5662px">
+</tspan>
+    <tspan x="10px" y="5680px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `r#struct` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="5698px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:42:11</tspan>
+</tspan>
+    <tspan x="10px" y="5716px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5734px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="5752px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `r#struct` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="5770px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="5788px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct {};</tspan>
+</tspan>
+    <tspan x="10px" y="5806px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="5824px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5842px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="5860px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5878px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="5896px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="5914px">
+</tspan>
+    <tspan x="10px" y="5932px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `unit` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="5950px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:43:11</tspan>
+</tspan>
+    <tspan x="10px" y="5968px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="5986px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="6004px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `unit` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="6022px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="6040px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit(0);</tspan>
+</tspan>
+    <tspan x="10px" y="6058px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="6076px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6094px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="6112px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6130px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="6148px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="6166px">
+</tspan>
+    <tspan x="10px" y="6184px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `tuple` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="6202px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:44:11</tspan>
+</tspan>
+    <tspan x="10px" y="6220px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6238px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="6256px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `tuple` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="6274px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="6292px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple(0);</tspan>
+</tspan>
+    <tspan x="10px" y="6310px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="6328px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6346px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="6364px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6382px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple</tspan><tspan>(0);</tspan>
+</tspan>
+    <tspan x="10px" y="6400px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="6418px">
+</tspan>
+    <tspan x="10px" y="6436px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `r#struct` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="6454px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:45:11</tspan>
+</tspan>
+    <tspan x="10px" y="6472px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6490px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="6508px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `r#struct` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="6526px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="6544px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct(0);</tspan>
+</tspan>
+    <tspan x="10px" y="6562px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="6580px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6598px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="6616px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6634px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="6652px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="6670px">
+</tspan>
+    <tspan x="10px" y="6688px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `unit` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="6706px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:46:11</tspan>
+</tspan>
+    <tspan x="10px" y="6724px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6742px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="6760px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `unit` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="6778px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="6796px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit { x: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="6814px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="6832px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6850px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="6868px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6886px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="6904px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="6922px">
+</tspan>
+    <tspan x="10px" y="6940px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `tuple` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="6958px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:47:11</tspan>
+</tspan>
+    <tspan x="10px" y="6976px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="6994px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="7012px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `tuple` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="7030px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="7048px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple { x: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="7066px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="7084px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7102px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="7120px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7138px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="7156px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="7174px">
+</tspan>
+    <tspan x="10px" y="7192px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `r#struct` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="7210px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:48:11</tspan>
+</tspan>
+    <tspan x="10px" y="7228px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7246px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="7264px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `r#struct` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="7282px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="7300px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct { x: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="7318px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="7336px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7354px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="7372px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7390px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="7408px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="7426px">
+</tspan>
+    <tspan x="10px" y="7444px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `unit` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="7462px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:49:11</tspan>
+</tspan>
+    <tspan x="10px" y="7480px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7498px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="7516px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `unit` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="7534px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="7552px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="7570px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="7588px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7606px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="7624px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7642px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="7660px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="7678px">
+</tspan>
+    <tspan x="10px" y="7696px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `tuple` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="7714px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:50:11</tspan>
+</tspan>
+    <tspan x="10px" y="7732px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7750px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="7768px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `tuple` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="7786px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="7804px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="7822px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="7840px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7858px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="7876px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="7894px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple</tspan><tspan>(</tspan><tspan class="fg-ansi256-010">/* i32 */</tspan><tspan>);</tspan>
+</tspan>
+    <tspan x="10px" y="7912px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~</tspan><tspan> </tspan><tspan class="fg-ansi256-010">~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="7930px">
+</tspan>
+    <tspan x="10px" y="7948px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant or associated item named `r#struct` found for enum `Enum` in the current scope</tspan>
+</tspan>
+    <tspan x="10px" y="7966px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:51:11</tspan>
+</tspan>
+    <tspan x="10px" y="7984px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8002px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="8020px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant or associated item `r#struct` not found for this enum</tspan>
+</tspan>
+    <tspan x="10px" y="8038px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="8056px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct(0, 0);</tspan>
+</tspan>
+    <tspan x="10px" y="8074px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">variant or associated item not found in `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="8092px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8110px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="8128px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8146px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="8164px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="8182px">
+</tspan>
+    <tspan x="10px" y="8200px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `unit` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="8218px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:52:11</tspan>
+</tspan>
+    <tspan x="10px" y="8236px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8254px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="8272px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `unit` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="8290px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="8308px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::unit { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="8326px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="8344px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8362px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="8380px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8398px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Unit</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="8416px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="8434px">
+</tspan>
+    <tspan x="10px" y="8452px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `tuple` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="8470px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:53:11</tspan>
+</tspan>
+    <tspan x="10px" y="8488px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8506px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="8524px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `tuple` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="8542px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="8560px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::tuple { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="8578px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="8596px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8614px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="8632px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8650px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Tuple(/* i32 */)</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="8668px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="8686px">
+</tspan>
+    <tspan x="10px" y="8704px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: no variant named `r#struct` found for enum `Enum`</tspan>
+</tspan>
+    <tspan x="10px" y="8722px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/incorrect-variant-literal.rs:54:11</tspan>
+</tspan>
+    <tspan x="10px" y="8740px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8758px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> enum Enum {</tspan>
+</tspan>
+    <tspan x="10px" y="8776px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">---------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">variant `r#struct` not found here</tspan>
+</tspan>
+    <tspan x="10px" y="8794px"><tspan class="fg-ansi256-012 bold">...</tspan>
+</tspan>
+    <tspan x="10px" y="8812px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     Enum::r#struct { x: 0, y: 0 };</tspan>
+</tspan>
+    <tspan x="10px" y="8830px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^^</tspan>
+</tspan>
+    <tspan x="10px" y="8848px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8866px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: there is a variant with a similar name</tspan>
+</tspan>
+    <tspan x="10px" y="8884px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="8902px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">| </tspan><tspan>    Enum::</tspan><tspan class="fg-ansi256-010">Struct { x: /* value */ }</tspan><tspan>;</tspan>
+</tspan>
+    <tspan x="10px" y="8920px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           </tspan><tspan class="fg-ansi256-010">~~~~~~~~~~~~~~~~~~~~~~~~~</tspan>
+</tspan>
+    <tspan x="10px" y="8938px">
+</tspan>
+    <tspan x="10px" y="8956px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 39 previous errors</tspan>
+</tspan>
+    <tspan x="10px" y="8974px">
+</tspan>
+    <tspan x="10px" y="8992px"><tspan class="bold">Some errors have detailed explanations: E0061, E0063, E0533, E0559, E0599, E0618.</tspan>
+</tspan>
+    <tspan x="10px" y="9010px"><tspan class="bold">For more information about an error, try `rustc --explain E0061`.</tspan>
+</tspan>
+    <tspan x="10px" y="9028px">
+</tspan>
+  </text>
+
+</svg>
diff --git a/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr
index 948f09fc3fa..4523333850c 100644
--- a/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr
+++ b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr
@@ -9,8 +9,8 @@ LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
    |
 help: `S` is a tuple struct, use the appropriate syntax
    |
-LL |     let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
-   |               ~~~~~~~~~~~~~~~
+LL |     let _x = (S(/* f32 */, /* f32 */), S { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0560]: struct `S` has no field named `y`
   --> $DIR/nested-non-tuple-tuple-struct.rs:8:27
@@ -23,8 +23,8 @@ LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
    |
 help: `S` is a tuple struct, use the appropriate syntax
    |
-LL |     let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
-   |               ~~~~~~~~~~~~~~~
+LL |     let _x = (S(/* f32 */, /* f32 */), S { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0560]: struct `S` has no field named `x`
   --> $DIR/nested-non-tuple-tuple-struct.rs:8:41
@@ -37,8 +37,8 @@ LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
    |
 help: `S` is a tuple struct, use the appropriate syntax
    |
-LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
-   |                                     ~~~~~~~~~~~~~~~
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* f32 */, /* f32 */));
+   |                                     ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0560]: struct `S` has no field named `y`
   --> $DIR/nested-non-tuple-tuple-struct.rs:8:49
@@ -51,8 +51,8 @@ LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
    |
 help: `S` is a tuple struct, use the appropriate syntax
    |
-LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
-   |                                     ~~~~~~~~~~~~~~~
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* f32 */, /* f32 */));
+   |                                     ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0559]: variant `E::V` has no field named `x`
   --> $DIR/nested-non-tuple-tuple-struct.rs:13:22
@@ -65,8 +65,8 @@ LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
    |
 help: `E::V` is a tuple variant, use the appropriate syntax
    |
-LL |     let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
-   |               ~~~~~~~~~~~~~~~~~~
+LL |     let _y = (E::V(/* f32 */, /* f32 */), E::V { x: 3.0, y: 4.0 });
+   |                   ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0559]: variant `E::V` has no field named `y`
   --> $DIR/nested-non-tuple-tuple-struct.rs:13:30
@@ -79,8 +79,8 @@ LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
    |
 help: `E::V` is a tuple variant, use the appropriate syntax
    |
-LL |     let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
-   |               ~~~~~~~~~~~~~~~~~~
+LL |     let _y = (E::V(/* f32 */, /* f32 */), E::V { x: 3.0, y: 4.0 });
+   |                   ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0559]: variant `E::V` has no field named `x`
   --> $DIR/nested-non-tuple-tuple-struct.rs:13:47
@@ -93,8 +93,8 @@ LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
    |
 help: `E::V` is a tuple variant, use the appropriate syntax
    |
-LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
-   |                                        ~~~~~~~~~~~~~~~~~~
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* f32 */, /* f32 */));
+   |                                            ~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0559]: variant `E::V` has no field named `y`
   --> $DIR/nested-non-tuple-tuple-struct.rs:13:55
@@ -107,8 +107,8 @@ LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
    |
 help: `E::V` is a tuple variant, use the appropriate syntax
    |
-LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
-   |                                        ~~~~~~~~~~~~~~~~~~
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* f32 */, /* f32 */));
+   |                                            ~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/suggestions/suggest-variants.stderr b/tests/ui/suggestions/suggest-variants.stderr
index a422bc65635..d93bf2d8cd7 100644
--- a/tests/ui/suggestions/suggest-variants.stderr
+++ b/tests/ui/suggestions/suggest-variants.stderr
@@ -5,7 +5,12 @@ LL | enum Shape {
    | ---------- variant `Squareee` not found here
 ...
 LL |     println!("My shape is {:?}", Shape::Squareee { size: 5});
-   |                                         ^^^^^^^^ help: there is a variant with a similar name: `Square`
+   |                                         ^^^^^^^^
+   |
+help: there is a variant with a similar name
+   |
+LL |     println!("My shape is {:?}", Shape::Square { size: 5});
+   |                                         ~~~~~~
 
 error[E0599]: no variant named `Circl` found for enum `Shape`
   --> $DIR/suggest-variants.rs:13:41
@@ -14,7 +19,12 @@ LL | enum Shape {
    | ---------- variant `Circl` not found here
 ...
 LL |     println!("My shape is {:?}", Shape::Circl { size: 5});
-   |                                         ^^^^^ help: there is a variant with a similar name: `Circle`
+   |                                         ^^^^^
+   |
+help: there is a variant with a similar name
+   |
+LL |     println!("My shape is {:?}", Shape::Circle { size: 5});
+   |                                         ~~~~~~
 
 error[E0599]: no variant named `Rombus` found for enum `Shape`
   --> $DIR/suggest-variants.rs:14:41
@@ -32,10 +42,12 @@ LL | enum Shape {
    | ---------- variant or associated item `Squareee` not found for this enum
 ...
 LL |     Shape::Squareee;
-   |            ^^^^^^^^
-   |            |
-   |            variant or associated item not found in `Shape`
-   |            help: there is a variant with a similar name: `Square`
+   |            ^^^^^^^^ variant or associated item not found in `Shape`
+   |
+help: there is a variant with a similar name
+   |
+LL |     Shape::Square { size: /* value */ };
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:16:12
@@ -44,10 +56,12 @@ LL | enum Shape {
    | ---------- variant or associated item `Circl` not found for this enum
 ...
 LL |     Shape::Circl;
-   |            ^^^^^
-   |            |
-   |            variant or associated item not found in `Shape`
-   |            help: there is a variant with a similar name: `Circle`
+   |            ^^^^^ variant or associated item not found in `Shape`
+   |
+help: there is a variant with a similar name
+   |
+LL |     Shape::Circle { radius: /* value */ };
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope
   --> $DIR/suggest-variants.rs:17:12
diff --git a/tests/ui/symbol-names/const-generics-str-demangling.rs b/tests/ui/symbol-names/const-generics-str-demangling.rs
index 871f3694e00..87b1fdf8a47 100644
--- a/tests/ui/symbol-names/const-generics-str-demangling.rs
+++ b/tests/ui/symbol-names/const-generics-str-demangling.rs
@@ -1,7 +1,7 @@
 //@ build-fail
 //@ compile-flags: -C symbol-mangling-version=v0 --crate-name=c
 //@ normalize-stderr-test: "c\[.*?\]" -> "c[HASH]"
-#![feature(adt_const_params, rustc_attrs)]
+#![feature(adt_const_params, unsized_const_params, rustc_attrs)]
 #![allow(incomplete_features)]
 
 pub struct Str<const S: &'static str>;
diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.rs b/tests/ui/symbol-names/const-generics-structural-demangling.rs
index 6c79ed7314c..9f5f31177b3 100644
--- a/tests/ui/symbol-names/const-generics-structural-demangling.rs
+++ b/tests/ui/symbol-names/const-generics-structural-demangling.rs
@@ -3,10 +3,10 @@
 
 //@ normalize-stderr-test: "c\[[0-9a-f]+\]" -> "c[HASH]"
 
-#![feature(adt_const_params, decl_macro, rustc_attrs)]
+#![feature(adt_const_params, unsized_const_params, decl_macro, rustc_attrs)]
 #![allow(incomplete_features)]
 
-use std::marker::ConstParamTy;
+use std::marker::UnsizedConstParamTy;
 
 pub struct RefByte<const RB: &'static u8>;
 
@@ -14,7 +14,7 @@ pub struct RefByte<const RB: &'static u8>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::RefByte<{&123}>>)
-impl RefByte<{&123}> {}
+impl RefByte<{ &123 }> {}
 
 // FIXME(eddyb) this was supposed to be `RefMutZst` with `&mut []`,
 // but that is currently not allowed in const generics.
@@ -24,7 +24,7 @@ pub struct RefZst<const RMZ: &'static [u8; 0]>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::RefZst<{&[]}>>)
-impl RefZst<{&[]}> {}
+impl RefZst<{ &[] }> {}
 
 pub struct Array3Bytes<const A3B: [u8; 3]>;
 
@@ -32,7 +32,7 @@ pub struct Array3Bytes<const A3B: [u8; 3]>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::Array3Bytes<{[1, 2, 3]}>>)
-impl Array3Bytes<{[1, 2, 3]}> {}
+impl Array3Bytes<{ [1, 2, 3] }> {}
 
 pub struct TupleByteBool<const TBB: (u8, bool)>;
 
@@ -40,9 +40,9 @@ pub struct TupleByteBool<const TBB: (u8, bool)>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::TupleByteBool<{(1, false)}>>)
-impl TupleByteBool<{(1, false)}> {}
+impl TupleByteBool<{ (1, false) }> {}
 
-#[derive(PartialEq, Eq, ConstParamTy)]
+#[derive(PartialEq, Eq, UnsizedConstParamTy)]
 pub enum MyOption<T> {
     Some(T),
     None,
@@ -56,7 +56,7 @@ pub struct OptionUsize<const OU: MyOption<usize>>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::OptionUsize<{c::MyOption::<usize>::None}>>)
-impl OptionUsize<{MyOption::None}> {}
+impl OptionUsize<{ MyOption::None }> {}
 
 // HACK(eddyb) the full mangling is only in `.stderr` because we can normalize
 // the `core` disambiguator hash away there, but not here.
@@ -64,9 +64,9 @@ impl OptionUsize<{MyOption::None}> {}
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::OptionUsize<{c::MyOption::<usize>::Some(0)}>>)
-impl OptionUsize<{MyOption::Some(0)}> {}
+impl OptionUsize<{ MyOption::Some(0) }> {}
 
-#[derive(PartialEq, Eq, ConstParamTy)]
+#[derive(PartialEq, Eq, UnsizedConstParamTy)]
 pub struct Foo {
     s: &'static str,
     ch: char,
@@ -78,12 +78,12 @@ pub struct Foo_<const F: Foo>;
 //~^ ERROR symbol-name
 //~| ERROR demangling
 //~| ERROR demangling-alt(<c::Foo_<{c::Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}>>)
-impl Foo_<{Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}> {}
+impl Foo_<{ Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] } }> {}
 
 // NOTE(eddyb) this tests specifically the use of disambiguators in field names,
 // using macros 2.0 hygiene to create a `struct` with conflicting field names.
 macro duplicate_field_name_test($x:ident) {
-    #[derive(PartialEq, Eq, ConstParamTy)]
+    #[derive(PartialEq, Eq, UnsizedConstParamTy)]
     pub struct Bar {
         $x: u8,
         x: u16,
@@ -94,7 +94,7 @@ macro duplicate_field_name_test($x:ident) {
     //~^ ERROR symbol-name
     //~| ERROR demangling
     //~| ERROR demangling-alt(<c::Bar_<{c::Bar { x: 123, x: 4096 }}>>)
-    impl Bar_<{Bar { $x: 123, x: 4096 }}> {}
+    impl Bar_<{ Bar { $x: 123, x: 4096 } }> {}
 }
 duplicate_field_name_test!(x);
 
diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs
index af47e84672f..94d79d56c59 100644
--- a/tests/ui/target-feature/gate.rs
+++ b/tests/ui/target-feature/gate.rs
@@ -21,6 +21,7 @@
 // gate-test-loongarch_target_feature
 // gate-test-lahfsahf_target_feature
 // gate-test-prfchw_target_feature
+// gate-test-s390x_target_feature
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr
index 31198f73c20..a69020e6864 100644
--- a/tests/ui/target-feature/gate.stderr
+++ b/tests/ui/target-feature/gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:25:18
+  --> $DIR/gate.rs:26:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
index fc64381b961..b61a21eab41 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
@@ -18,7 +18,8 @@ trait TraitC {}
 fn foo<T>()
 where
     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
-    //~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
     //~| ERROR `impl Trait` is not allowed in bounds
 {
 }
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
index a4a79413a9b..e891df3f0c0 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/bad-suggestion-on-missing-assoc.rs:20:15
+   |
+LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
+   |               ^
+
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bad-suggestion-on-missing-assoc.rs:1:12
    |
@@ -29,6 +35,6 @@ LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl Trai
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
index c6bf0dc1f72..13f9f196970 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
@@ -4,10 +4,11 @@
 pub fn bar()
 where
     for<const N: usize = {
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
     (||1usize)()
 }> V: IntoIterator
-//~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
-//~^^ ERROR cannot find type `V` in this scope
+//~^ ERROR cannot find type `V` in this scope
 {
 }
 
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
index edc55a3c8e6..d9e77dec794 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `V` in this scope
-  --> $DIR/binder-defaults-112547.rs:8:4
+  --> $DIR/binder-defaults-112547.rs:10:4
    |
 LL | }> V: IntoIterator
    |    ^ not found in this scope
@@ -9,6 +9,12 @@ help: you might be missing a type parameter
 LL | pub fn bar<V>()
    |           +++
 
+error: late-bound const parameters cannot be used currently
+  --> $DIR/binder-defaults-112547.rs:6:15
+   |
+LL |     for<const N: usize = {
+   |               ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/binder-defaults-112547.rs:1:12
    |
@@ -23,10 +29,12 @@ error: defaults for generic parameters are not allowed in `for<...>` binders
    |
 LL |       for<const N: usize = {
    |  _________^
+LL | |
+LL | |
 LL | |     (||1usize)()
 LL | | }> V: IntoIterator
    | |_^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
index f33da416ad8..bdfe41ca11b 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
@@ -5,8 +5,9 @@
 fn fun()
 where
     for<T = (), const N: usize = 1> ():,
-//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
-//~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
 {}
 
 fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
index 7fe82f1f097..947dd3a73bf 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/binder-defaults-119489.rs:7:23
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |                       ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/binder-defaults-119489.rs:1:12
    |
@@ -27,5 +33,5 @@ error: defaults for generic parameters are not allowed in `for<...>` binders
 LL |     for<T = (), const N: usize = 1> ():,
    |                 ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
new file mode 100644
index 00000000000..2d44388f875
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn b()
+where
+    for<const C: usize> [(); C]: Copy,
+    //~^ ERROR late-bound const parameters cannot be used currently
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
new file mode 100644
index 00000000000..136d533a03c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
@@ -0,0 +1,17 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/late-const-param-wf.rs:6:15
+   |
+LL |     for<const C: usize> [(); C]: Copy,
+   |               ^
+
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/late-const-param-wf.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index c30b6334fed..642a93d64e2 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -23,9 +23,7 @@ LL |     Some(3)?;
    |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Result<T, F>` implements `FromResidual<Result<Infallible, E>>`
-             `Result<T, F>` implements `FromResidual<Yeet<E>>`
+   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:17:31
@@ -36,9 +34,7 @@ LL |     Ok(ControlFlow::Break(123)?)
    |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Result<T, F>` implements `FromResidual<Result<Infallible, E>>`
-             `Result<T, F>` implements `FromResidual<Yeet<E>>`
+   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:22:22
@@ -49,9 +45,7 @@ LL |     Some(Err("hello")?)
    |                      ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Option<T>` implements `FromResidual<Yeet<()>>`
-             `Option<T>` implements `FromResidual`
+   = help: the trait `FromResidual` is implemented for `Option<T>`
 
 error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:27:33
@@ -62,9 +56,7 @@ LL |     Some(ControlFlow::Break(123)?)
    |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
    |
    = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Option<T>` implements `FromResidual<Yeet<()>>`
-             `Option<T>` implements `FromResidual`
+   = help: the trait `FromResidual` is implemented for `Option<T>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:32:39
diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr
index 2d97226275d..8055b2a0b04 100644
--- a/tests/ui/try-trait/option-to-result.stderr
+++ b/tests/ui/try-trait/option-to-result.stderr
@@ -8,9 +8,7 @@ LL |     a?;
    |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Result<T, F>` implements `FromResidual<Result<Infallible, E>>`
-             `Result<T, F>` implements `FromResidual<Yeet<E>>`
+   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/option-to-result.rs:11:6
@@ -22,9 +20,7 @@ LL |     a?;
    |      ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
    |
    = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Option<T>` implements `FromResidual<Yeet<()>>`
-             `Option<T>` implements `FromResidual`
+   = help: the trait `FromResidual` is implemented for `Option<T>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr
index 84a51a078af..15d0b28ddc1 100644
--- a/tests/ui/try-trait/try-on-option.stderr
+++ b/tests/ui/try-trait/try-on-option.stderr
@@ -8,9 +8,7 @@ LL |     x?;
    |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
-   = help: the following other types implement trait `FromResidual<R>`:
-             `Result<T, F>` implements `FromResidual<Result<Infallible, E>>`
-             `Result<T, F>` implements `FromResidual<Yeet<E>>`
+   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option.rs:11:6
diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
index c9ac99ede6f..c21c59397c7 100644
--- a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
+++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
@@ -3,6 +3,11 @@ error[E0533]: expected value, found struct variant `Alias::Braced`
    |
 LL |     Alias::Braced;
    |     ^^^^^^^^^^^^^ not a value
+   |
+help: you might have meant to create a new value of the struct
+   |
+LL |     Alias::Braced {};
+   |                   ++
 
 error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced`
   --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:9
diff --git a/tests/ui/typeck/ice-unexpected-region-123863.stderr b/tests/ui/typeck/ice-unexpected-region-123863.stderr
index 08f1ede95b4..0479f134a38 100644
--- a/tests/ui/typeck/ice-unexpected-region-123863.stderr
+++ b/tests/ui/typeck/ice-unexpected-region-123863.stderr
@@ -9,6 +9,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/ice-unexpected-region-123863.rs:3:27
@@ -21,6 +25,10 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
    |
 LL + #![feature(adt_const_params)]
    |
+help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait
+   |
+LL + #![feature(unsized_const_params)]
+   |
 
 error[E0223]: ambiguous associated type
   --> $DIR/ice-unexpected-region-123863.rs:5:5
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
index f2828b384b2..1f1845569ef 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -4,11 +4,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
    |                                                        ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> impl Fn() + 'a {
    |                                                        ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL ~ fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
 LL |
diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr
index d1d652d1860..e13cabbb81d 100644
--- a/tests/ui/unsized/issue-91801.stderr
+++ b/tests/ui/unsized/issue-91801.stderr
@@ -4,10 +4,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
    |                                                                             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
-LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<Validator<'a>> {
-   |                                                                             ++++             +
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Validator<'a> {
+   |                                                                             ++++
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<dyn Validator<'a>> {
+   |                                                                             +++++++              +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr
index 632af02b4b6..3b89066499d 100644
--- a/tests/ui/unsized/issue-91803.stderr
+++ b/tests/ui/unsized/issue-91803.stderr
@@ -4,11 +4,11 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> {
    |                                           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+help: consider returning an `impl Trait` instead of a `dyn Trait`
    |
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> {
    |                                           ~~~~
-help: box the return type, and wrap all of the returned values in `Box::new`
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
    |
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> Box<dyn Foo<'a>> {
    |                                           ++++           +
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index e30cb8ff921..8d5b377988c 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -26,8 +26,8 @@ LL | trait Trait: Sized {}
    |       |
    |       this trait cannot be made into an object...
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
-             R
              S
+             R
    = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -48,8 +48,8 @@ LL | trait Trait: Sized {}
    |       |
    |       this trait cannot be made into an object...
    = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
-             R
              S
+             R
    = note: required for the cast from `&R` to `&dyn Trait`
 
 error: aborting due to 3 previous errors
diff --git a/triagebot.toml b/triagebot.toml
index 5335cf4e4bf..5c5aa475385 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -905,7 +905,7 @@ cc = ["@kobzol"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "jhpratt", "oli-obk"]
+users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "michaelwoerister"]
 
 [assign.adhoc_groups]
 compiler-team = [