about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc/Cargo.toml2
-rw-r--r--compiler/rustc/src/main.rs2
-rw-r--r--compiler/rustc_abi/Cargo.toml8
-rw-r--r--compiler/rustc_ast/src/token.rs3
-rw-r--r--compiler/rustc_ast_ir/Cargo.toml8
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs23
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs135
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs12
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs29
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs228
-rw-r--r--compiler/rustc_ast_passes/messages.ftl3
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs8
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs81
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs25
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs1
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/cmdline_attrs.rs16
-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_gcc/.rustfmt.toml2
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs2
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/config.rs14
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs14
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/utils.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs18
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs10
-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/mir/constant.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs16
-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_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0120.md24
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0158.md17
-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_expand/src/mbe/macro_check.rs8
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs18
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs106
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs66
-rw-r--r--compiler/rustc_hir/src/intravisit.rs26
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl28
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/errs.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs134
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs87
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs110
-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/bounds.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs156
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs27
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs82
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs6
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs48
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs21
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs60
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs125
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs6
-rw-r--r--compiler/rustc_index/Cargo.toml6
-rw-r--r--compiler/rustc_index/src/vec.rs6
-rw-r--r--compiler/rustc_infer/messages.ftl5
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/mod.rs10
-rw-r--r--compiler/rustc_infer/src/error_reporting/infer/region.rs104
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs22
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs17
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs16
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs13
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs2
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs12
-rw-r--r--compiler/rustc_infer/src/infer/relate/type_relating.rs19
-rw-r--r--compiler/rustc_interface/Cargo.toml9
-rw-r--r--compiler/rustc_lint/messages.ftl8
-rw-r--r--compiler/rustc_lint/src/builtin.rs57
-rw-r--r--compiler/rustc_lint/src/internal.rs46
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs12
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs8
-rw-r--r--compiler/rustc_macros/src/lift.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs5
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs4
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs8
-rw-r--r--compiler/rustc_middle/src/query/erase.rs7
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/thir.rs11
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs179
-rw-r--r--compiler/rustc_middle/src/ty/context.rs8
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs14
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs4
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs4
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs2
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/messages.ftl2
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs26
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs30
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/matches/match_pair.rs46
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs441
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs52
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs29
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs23
-rw-r--r--compiler/rustc_mir_build/src/errors.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs224
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs144
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.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_next_trait_solver/Cargo.toml6
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs25
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs34
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs240
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs25
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs151
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs224
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs31
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs2
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs9
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs70
-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/hir_stats.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs18
-rw-r--r--compiler/rustc_query_system/Cargo.toml2
-rw-r--r--compiler/rustc_resolve/messages.ftl2
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs15
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs32
-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.rs78
-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.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs48
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/_match.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs173
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs16
-rw-r--r--compiler/rustc_transmute/Cargo.toml14
-rw-r--r--compiler/rustc_type_ir/Cargo.toml8
-rw-r--r--compiler/rustc_type_ir/src/binder.rs36
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs12
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs10
-rw-r--r--compiler/rustc_type_ir/src/effects.rs22
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs8
-rw-r--r--compiler/rustc_type_ir/src/fast_reject.rs6
-rw-r--r--compiler/rustc_type_ir/src/fold.rs22
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/lift.rs2
-rw-r--r--compiler/rustc_type_ir/src/opaque_ty.rs10
-rw-r--r--compiler/rustc_type_ir/src/outlives.rs14
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs38
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs2
-rw-r--r--compiler/rustc_type_ir/src/relate.rs116
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs8
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs16
-rw-r--r--compiler/rustc_type_ir/src/ty_kind/closure.rs34
-rw-r--r--compiler/rustc_type_ir_macros/src/lib.rs4
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs10
-rw-r--r--config.example.toml1
-rw-r--r--library/core/src/fmt/builders.rs2
-rw-r--r--library/core/src/intrinsics.rs221
-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.rs24
-rw-r--r--library/core/src/ptr/metadata.rs16
-rw-r--r--library/core/tests/future.rs2
-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/macros.rs22
-rw-r--r--library/std/src/os/fd/owned.rs13
-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/sync/reentrant_lock.rs138
-rw-r--r--library/std/src/sys/os_str/mod.rs2
-rw-r--r--library/std/src/sys/os_str/wtf8.rs5
-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/stack_overflow.rs294
-rw-r--r--library/std/src/sys/pal/windows/alloc.rs2
-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.rs34
-rw-r--r--library/std/src/sys/pal/windows/futex.rs11
-rw-r--r--library/std/src/sys/pal/windows/handle.rs53
-rw-r--r--library/std/src/sys/pal/windows/io.rs29
-rw-r--r--library/std/src/sys/pal/windows/net.rs112
-rw-r--r--library/std/src/sys/pal/windows/os.rs17
-rw-r--r--library/std/src/sys/pal/windows/pipe.rs20
-rw-r--r--library/std/src/sys/pal/windows/stack_overflow.rs19
-rw-r--r--library/std/src/sys/pal/windows/thread.rs31
-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/once/futex.rs2
-rw-r--r--library/std/src/sys/sync/once/mod.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.rs106
-rw-r--r--library/test/src/test_result.rs15
-rw-r--r--rustfmt.toml5
-rw-r--r--src/bootstrap/defaults/config.tools.toml4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs35
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs68
-rw-r--r--src/bootstrap/src/core/builder.rs34
-rw-r--r--src/bootstrap/src/core/config/config.rs36
-rw-r--r--src/bootstrap/src/core/download.rs2
-rw-r--r--src/bootstrap/src/lib.rs14
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs10
-rw-r--r--src/bootstrap/src/utils/helpers.rs24
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile2
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh12
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh4
-rwxr-xr-xsrc/ci/docker/run.sh11
-rwxr-xr-xsrc/ci/run.sh2
-rw-r--r--src/doc/rustc/src/codegen-options/index.md15
-rw-r--r--src/doc/style-guide/src/README.md34
-rw-r--r--src/doc/style-guide/src/items.md10
-rwxr-xr-xsrc/etc/htmldocck.py1
-rw-r--r--src/librustdoc/clean/mod.rs69
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs21
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css62
-rw-r--r--src/librustdoc/html/static/js/main.js8
-rw-r--r--src/tools/build-manifest/src/main.rs1
-rw-r--r--src/tools/build_helper/src/git.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs28
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs32
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs16
-rw-r--r--src/tools/clippy/tests/ui/author/repeat.stdout3
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.stderr8
-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.rs270
-rw-r--r--src/tools/jsondocck/src/main.rs67
-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/run-make-support/src/artifact_names.rs57
-rw-r--r--src/tools/run-make-support/src/assertion_helpers.rs73
-rw-r--r--src/tools/run-make-support/src/command.rs4
-rw-r--r--src/tools/run-make-support/src/diff/mod.rs14
-rw-r--r--src/tools/run-make-support/src/env.rs19
-rw-r--r--src/tools/run-make-support/src/external_deps/c_build.rs27
-rw-r--r--src/tools/run-make-support/src/external_deps/cc.rs (renamed from src/tools/run-make-support/src/cc.rs)11
-rw-r--r--src/tools/run-make-support/src/external_deps/clang.rs (renamed from src/tools/run-make-support/src/clang.rs)2
-rw-r--r--src/tools/run-make-support/src/external_deps/cygpath.rs35
-rw-r--r--src/tools/run-make-support/src/external_deps/htmldocck.rs14
-rw-r--r--src/tools/run-make-support/src/external_deps/llvm.rs (renamed from src/tools/run-make-support/src/llvm.rs)13
-rw-r--r--src/tools/run-make-support/src/external_deps/mod.rs14
-rw-r--r--src/tools/run-make-support/src/external_deps/python.rs11
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs (renamed from src/tools/run-make-support/src/rustc.rs)8
-rw-r--r--src/tools/run-make-support/src/external_deps/rustdoc.rs (renamed from src/tools/run-make-support/src/rustdoc.rs)5
-rw-r--r--src/tools/run-make-support/src/fs.rs (renamed from src/tools/run-make-support/src/fs_wrapper.rs)99
-rw-r--r--src/tools/run-make-support/src/lib.rs677
-rw-r--r--src/tools/run-make-support/src/macros.rs113
-rw-r--r--src/tools/run-make-support/src/path_helpers.rs80
-rw-r--r--src/tools/run-make-support/src/run.rs5
-rw-r--r--src/tools/run-make-support/src/scoped_run.rs69
-rw-r--r--src/tools/run-make-support/src/string.rs50
-rw-r--r--src/tools/run-make-support/src/targets.rs49
-rw-r--r--src/tools/run-make-support/src/util.rs39
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/panic_context.rs1
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt29
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/version2
-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/codegen/option-as-slice.rs35
-rw-r--r--tests/crashes/122903-1.rs4
-rw-r--r--tests/crashes/122903-2.rs9
-rw-r--r--tests/crashes/127009.rs11
-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/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff4
-rw-r--r--tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff4
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs4
-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/atomic-lock-free/Makefile48
-rw-r--r--tests/run-make/atomic-lock-free/rmake.rs52
-rw-r--r--tests/run-make/c-link-to-rust-dylib/rmake.rs8
-rw-r--r--tests/run-make/c-link-to-rust-staticlib/rmake.rs2
-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/cdylib/rmake.rs4
-rw-r--r--tests/run-make/comment-section/rmake.rs5
-rw-r--r--tests/run-make/compiler-builtins/rmake.rs2
-rw-r--r--tests/run-make/compiler-lookup-paths/rmake.rs14
-rw-r--r--tests/run-make/const-prop-lint/rmake.rs4
-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/crate-name-priority/rmake.rs10
-rw-r--r--tests/run-make/doctests-keep-binaries/rmake.rs2
-rw-r--r--tests/run-make/doctests-runtool/rmake.rs2
-rw-r--r--tests/run-make/dump-mono-stats/rmake.rs4
-rw-r--r--tests/run-make/dylib-chain/rmake.rs8
-rw-r--r--tests/run-make/emit-named-files/rmake.rs4
-rw-r--r--tests/run-make/emit-path-unhashed/rmake.rs10
-rw-r--r--tests/run-make/extern-flag-pathless/rmake.rs18
-rw-r--r--tests/run-make/extern-fn-explicit-align/Makefile6
-rw-r--r--tests/run-make/extern-fn-explicit-align/rmake.rs17
-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-mangle/Makefile6
-rw-r--r--tests/run-make/extern-fn-mangle/rmake.rs16
-rw-r--r--tests/run-make/extern-fn-slice-no-ice/rmake.rs17
-rw-r--r--tests/run-make/extern-fn-slice-no-ice/test.c (renamed from tests/run-make/issue-25581/test.c)0
-rw-r--r--tests/run-make/extern-fn-slice-no-ice/test.rs (renamed from tests/run-make/issue-25581/test.rs)0
-rw-r--r--tests/run-make/extern-fn-struct-passing-abi/Makefile6
-rw-r--r--tests/run-make/extern-fn-struct-passing-abi/rmake.rs16
-rw-r--r--tests/run-make/extern-fn-with-extern-types/Makefile6
-rw-r--r--tests/run-make/extern-fn-with-extern-types/rmake.rs16
-rw-r--r--tests/run-make/extern-fn-with-packed-struct/Makefile6
-rw-r--r--tests/run-make/extern-fn-with-packed-struct/rmake.rs17
-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/extra-filename-with-temp-outputs/rmake.rs8
-rw-r--r--tests/run-make/ice-dep-cannot-find-dep/rmake.rs2
-rw-r--r--tests/run-make/ice-static-mir/bar.rs (renamed from tests/run-make/issue-85401-static-mir/bar.rs)0
-rw-r--r--tests/run-make/ice-static-mir/baz.rs (renamed from tests/run-make/issue-85401-static-mir/baz.rs)0
-rw-r--r--tests/run-make/ice-static-mir/foo.rs (renamed from tests/run-make/issue-85401-static-mir/foo.rs)0
-rw-r--r--tests/run-make/ice-static-mir/rmake.rs42
-rw-r--r--tests/run-make/inaccessible-temp-dir/rmake.rs4
-rw-r--r--tests/run-make/incr-prev-body-beyond-eof/rmake.rs10
-rw-r--r--tests/run-make/incr-test-moved-file/rmake.rs12
-rw-r--r--tests/run-make/incremental-debugger-visualizer/rmake.rs22
-rw-r--r--tests/run-make/incremental-session-fail/rmake.rs4
-rw-r--r--tests/run-make/inline-always-many-cgu/rmake.rs8
-rw-r--r--tests/run-make/intrinsic-unreachable/rmake.rs6
-rw-r--r--tests/run-make/invalid-library/rmake.rs4
-rw-r--r--tests/run-make/invalid-so/rmake.rs4
-rw-r--r--tests/run-make/invalid-staticlib/rmake.rs4
-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/issue-107495-archive-permissions/rmake.rs4
-rw-r--r--tests/run-make/issue-22131/Makefile8
-rw-r--r--tests/run-make/issue-25581/Makefile6
-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-85401-static-mir/Makefile16
-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/longjmp-across-rust/Makefile6
-rw-r--r--tests/run-make/longjmp-across-rust/rmake.rs18
-rw-r--r--tests/run-make/ls-metadata/rmake.rs4
-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-readonly-lib/rmake.rs2
-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/many-crates-but-no-match/rmake.rs8
-rw-r--r--tests/run-make/missing-crate-dependency/Makefile9
-rw-r--r--tests/run-make/missing-crate-dependency/rmake.rs17
-rw-r--r--tests/run-make/mixing-libs/rmake.rs4
-rw-r--r--tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs14
-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/non-unicode-env/rmake.rs4
-rw-r--r--tests/run-make/non-unicode-in-incremental-dir/rmake.rs6
-rw-r--r--tests/run-make/obey-crate-type-flag/rmake.rs4
-rw-r--r--tests/run-make/output-filename-conflicts-with-directory/rmake.rs4
-rw-r--r--tests/run-make/output-filename-overwrites-input/rmake.rs6
-rw-r--r--tests/run-make/output-type-permutations/rmake.rs13
-rw-r--r--tests/run-make/parallel-rustc-no-overwrite/rmake.rs4
-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-branch-weights/rmake.rs9
-rw-r--r--tests/run-make/pgo-use/rmake.rs6
-rw-r--r--tests/run-make/prefer-dylib/rmake.rs4
-rw-r--r--tests/run-make/prefer-rlib/rmake.rs6
-rw-r--r--tests/run-make/pretty-print-with-dep-file/rmake.rs4
-rw-r--r--tests/run-make/print-cfg/rmake.rs4
-rw-r--r--tests/run-make/print-to-output/rmake.rs4
-rw-r--r--tests/run-make/remap-path-prefix/rmake.rs16
-rw-r--r--tests/run-make/repr128-dwarf/rmake.rs4
-rw-r--r--tests/run-make/reset-codegen-1/rmake.rs2
-rw-r--r--tests/run-make/resolve-rename/rmake.rs4
-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-chain/rmake.rs8
-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/rustdoc-scrape-examples-remap/scrape.rs4
-rw-r--r--tests/run-make/rustdoc-test-args/rmake.rs4
-rw-r--r--tests/run-make/rustdoc-themes/rmake.rs11
-rw-r--r--tests/run-make/rustdoc-verify-output-files/rmake.rs10
-rw-r--r--tests/run-make/sepcomp-cci-copies/rmake.rs2
-rw-r--r--tests/run-make/sepcomp-inlining/rmake.rs2
-rw-r--r--tests/run-make/sepcomp-separate/rmake.rs2
-rw-r--r--tests/run-make/silly-file-names/rmake.rs10
-rw-r--r--tests/run-make/split-debuginfo/Makefile2
-rw-r--r--tests/run-make/static-extern-type/Makefile6
-rw-r--r--tests/run-make/static-extern-type/rmake.rs16
-rw-r--r--tests/run-make/symlinked-extern/rmake.rs6
-rw-r--r--tests/run-make/symlinked-libraries/rmake.rs6
-rw-r--r--tests/run-make/symlinked-rlib/rmake.rs4
-rw-r--r--tests/run-make/target-specs/rmake.rs8
-rw-r--r--tests/run-make/track-path-dep-info/rmake.rs4
-rw-r--r--tests/run-make/track-pgo-dep-info/rmake.rs4
-rw-r--r--tests/run-make/unstable-flag-required/Makefile4
-rw-r--r--tests/run-make/unstable-flag-required/rmake.rs12
-rw-r--r--tests/run-make/volatile-intrinsics/rmake.rs4
-rw-r--r--tests/run-make/wasm-custom-section/rmake.rs4
-rw-r--r--tests/run-make/wasm-custom-sections-opt/rmake.rs4
-rw-r--r--tests/run-make/wasm-export-all-symbols/rmake.rs4
-rw-r--r--tests/run-make/wasm-import-module/rmake.rs4
-rw-r--r--tests/run-make/wasm-panic-small/rmake.rs4
-rw-r--r--tests/run-make/wasm-spurious-import/rmake.rs4
-rw-r--r--tests/run-make/wasm-stringify-ints-small/rmake.rs4
-rw-r--r--tests/run-make/wasm-symbols-different-module/rmake.rs4
-rw-r--r--tests/run-make/wasm-symbols-not-exported/rmake.rs4
-rw-r--r--tests/run-make/wasm-symbols-not-imported/rmake.rs4
-rw-r--r--tests/run-make/weird-output-filenames/rmake.rs6
-rw-r--r--tests/run-make/windows-ws2_32/rmake.rs4
-rw-r--r--tests/rustdoc-gui/huge-logo.goml8
-rw-r--r--tests/rustdoc-gui/sidebar.goml19
-rw-r--r--tests/rustdoc-gui/src/lib2/lib.rs1
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs6
-rw-r--r--tests/rustdoc-gui/trait-with-bounds.goml35
-rw-r--r--tests/rustdoc-gui/type-declation-overflow.goml26
-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/ice-unresolved-import-100241.stderr11
-rw-r--r--tests/rustdoc-ui/invalid_associated_const.stderr10
-rw-r--r--tests/rustdoc-ui/issue-102467.stderr10
-rw-r--r--tests/rustdoc/auxiliary/precise-capturing.rs7
-rw-r--r--tests/rustdoc/impl-trait-precise-capturing.rs13
-rw-r--r--tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs38
-rw-r--r--tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr68
-rw-r--r--tests/ui-fulldeps/stable-mir/check_instance.rs2
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.stderr4
-rw-r--r--tests/ui/anon-params/anon-params-denied-2018.stderr8
-rw-r--r--tests/ui/argument-suggestions/basic.stderr4
-rw-r--r--tests/ui/argument-suggestions/display-is-suggestable.stderr2
-rw-r--r--tests/ui/argument-suggestions/extern-fn-arg-names.stderr2
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr56
-rw-r--r--tests/ui/argument-suggestions/issue-100478.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-101097.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-109425.stderr20
-rw-r--r--tests/ui/argument-suggestions/issue-109831.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-112507.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-96638.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-97484.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-98894.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-98897.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-99482.stderr2
-rw-r--r--tests/ui/argument-suggestions/missing_arguments.stderr20
-rw-r--r--tests/ui/argument-suggestions/mixed_cases.stderr16
-rw-r--r--tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr12
-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/associated-consts/associated-const-type-parameter-arms.stderr15
-rw-r--r--tests/ui/associated-consts/associated-const-type-parameter-pattern.rs (renamed from tests/ui/associated-consts/associated-const-type-parameter-arms.rs)10
-rw-r--r--tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr27
-rw-r--r--tests/ui/associated-consts/issue-102335-const.stderr10
-rw-r--r--tests/ui/associated-inherent-types/issue-109768.stderr2
-rw-r--r--tests/ui/associated-type-bounds/issue-102335-ty.stderr20
-rw-r--r--tests/ui/associated-type-bounds/no-gat-position.stderr5
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr4
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/display.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/display.stderr78
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.stderr40
-rw-r--r--tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr5
-rw-r--r--tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs23
-rw-r--r--tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr33
-rw-r--r--tests/ui/async-await/in-trait/unconstrained-impl-region.stderr4
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.stderr8
-rw-r--r--tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr5
-rw-r--r--tests/ui/blind/blind-item-block-item-shadow.stderr2
-rw-r--r--tests/ui/blind/blind-item-item-shadow.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-access-permissions.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr2
-rw-r--r--tests/ui/borrowck/issue-20801.stderr2
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr6
-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/borrowck/moved-value-suggest-reborrow-issue-127285.fixed17
-rw-r--r--tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs17
-rw-r--r--tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr18
-rw-r--r--tests/ui/borrowck/mut-borrow-in-loop-2.stderr15
-rw-r--r--tests/ui/c-variadic/variadic-ffi-1.stderr2
-rw-r--r--tests/ui/cast/ice-cast-type-with-error-124848.stderr2
-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/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/generic_const_type_mismatch.rs4
-rw-r--r--tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr20
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.rs2
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.stderr13
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type_mismatch.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr12
-rw-r--r--tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-88119.stderr34
-rw-r--r--tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs2
-rw-r--r--tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr11
-rw-r--r--tests/ui/const-generics/transmute-fail.rs5
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr54
-rw-r--r--tests/ui/const-generics/type_mismatch.rs4
-rw-r--r--tests/ui/const-generics/type_mismatch.stderr20
-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_in_pattern/custom-eq-branch-pass.rs11
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs2
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr5
-rw-r--r--tests/ui/consts/const_let_assign2.stderr2
-rw-r--r--tests/ui/consts/invalid-inline-const-in-match-arm.rs1
-rw-r--r--tests/ui/consts/invalid-inline-const-in-match-arm.stderr8
-rw-r--r--tests/ui/consts/issue-36163.stderr6
-rw-r--r--tests/ui/consts/issue-73976-polymorphic.stderr5
-rw-r--r--tests/ui/consts/issue-79137-toogeneric.stderr3
-rw-r--r--tests/ui/coroutine/issue-102645.stderr2
-rw-r--r--tests/ui/drop/issue-23338-ensure-param-drop-order.stderr2
-rw-r--r--tests/ui/drop/issue-23611-enum-swap-in-drop.stderr2
-rw-r--r--tests/ui/duplicate/duplicate-check-macro-exports.stderr2
-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/E0057.stderr4
-rw-r--r--tests/ui/error-codes/E0060.stderr2
-rw-r--r--tests/ui/error-codes/E0061.stderr4
-rw-r--r--tests/ui/error-codes/E0229.stderr15
-rw-r--r--tests/ui/error-codes/E0252.stderr2
-rw-r--r--tests/ui/error-codes/E0254.stderr2
-rw-r--r--tests/ui/error-codes/E0255.stderr2
-rw-r--r--tests/ui/error-codes/E0746.stderr9
-rw-r--r--tests/ui/expr/issue-22933-2.stderr10
-rw-r--r--tests/ui/extern/issue-18819.stderr2
-rw-r--r--tests/ui/fn/issue-3044.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-102335-gat.stderr10
-rw-r--r--tests/ui/generic-associated-types/issue-91139.migrate.stderr1
-rw-r--r--tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr30
-rw-r--r--tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr4
-rw-r--r--tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr8
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr8
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-58451.stderr2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr38
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr4
-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/precise-capturing/hidden-type-suggestion.rs12
-rw-r--r--tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr44
-rw-r--r--tests/ui/imports/double-import.stderr2
-rw-r--r--tests/ui/imports/issue-19498.stderr6
-rw-r--r--tests/ui/imports/issue-24081.stderr10
-rw-r--r--tests/ui/imports/issue-25396.stderr8
-rw-r--r--tests/ui/imports/issue-32354-suggest-import-rename.stderr2
-rw-r--r--tests/ui/imports/issue-45829/import-self.stderr2
-rw-r--r--tests/ui/imports/issue-45829/issue-45829.stderr2
-rw-r--r--tests/ui/imports/issue-45829/rename-use-vs-extern.stderr2
-rw-r--r--tests/ui/imports/issue-45829/rename-use-with-tabs.stderr2
-rw-r--r--tests/ui/imports/issue-45829/rename-with-path.stderr2
-rw-r--r--tests/ui/imports/issue-45829/rename.stderr2
-rw-r--r--tests/ui/imports/issue-52891.stderr2
-rw-r--r--tests/ui/imports/issue-8640.stderr2
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.stderr5
-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-4935.stderr2
-rw-r--r--tests/ui/issues/issue-54410.stderr2
-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/issue-26638.stderr2
-rw-r--r--tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr5
-rw-r--r--tests/ui/lifetimes/issue-95023.rs1
-rw-r--r--tests/ui/lifetimes/issue-95023.stderr10
-rw-r--r--tests/ui/macros/builtin-std-paths-fail.stderr2
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs61
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/repetitions.rs18
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs54
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr153
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs11
-rw-r--r--tests/ui/macros/macro-outer-attributes.stderr11
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr4
-rw-r--r--tests/ui/mismatched_types/overloaded-calls-bad.stderr4
-rw-r--r--tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr2
-rw-r--r--tests/ui/not-enough-arguments.stderr2
-rw-r--r--tests/ui/numeric/numeric-fields.stderr4
-rw-r--r--tests/ui/parser/issues/issue-101477-enum.stderr5
-rw-r--r--tests/ui/parser/issues/issue-101477-let.stderr5
-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/recover/unicode-double-equals-recovery.rs3
-rw-r--r--tests/ui/parser/recover/unicode-double-equals-recovery.stderr24
-rw-r--r--tests/ui/parser/struct-literal-variant-in-if.stderr5
-rw-r--r--tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs26
-rw-r--r--tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr15
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.stderr17
-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/resolve/resolve-conflict-import-vs-extern-crate.stderr2
-rw-r--r--tests/ui/resolve/resolve-conflict-item-vs-import.stderr2
-rw-r--r--tests/ui/resolve/resolve-conflict-type-vs-import.stderr2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr5
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs4
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr34
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr17
-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/sanitizer/cfi-supertraits.rs6
-rw-r--r--tests/ui/self/elision/ignore-non-reference-lifetimes.rs22
-rw-r--r--tests/ui/self/elision/multiple-ref-self-async.rs6
-rw-r--r--tests/ui/self/elision/multiple-ref-self-async.stderr63
-rw-r--r--tests/ui/self/elision/multiple-ref-self.rs7
-rw-r--r--tests/ui/self/elision/multiple-ref-self.stderr63
-rw-r--r--tests/ui/self/elision/no-shadow-pin-self.rs17
-rw-r--r--tests/ui/self/elision/no-shadow-pin-self.stderr32
-rw-r--r--tests/ui/self/elision/ref-assoc-async.rs6
-rw-r--r--tests/ui/self/elision/ref-assoc-async.stderr77
-rw-r--r--tests/ui/self/elision/ref-assoc.rs7
-rw-r--r--tests/ui/self/elision/ref-assoc.stderr77
-rw-r--r--tests/ui/self/elision/ref-self-multi.rs29
-rw-r--r--tests/ui/self/elision/ref-self-multi.stderr27
-rw-r--r--tests/ui/self/elision/ref-self.fixed7
-rw-r--r--tests/ui/self/elision/ref-self.rs7
-rw-r--r--tests/ui/self/elision/ref-self.stderr31
-rw-r--r--tests/ui/span/issue-34264.stderr4
-rw-r--r--tests/ui/span/missing-unit-argument.stderr10
-rw-r--r--tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs1
-rw-r--r--tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr14
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs1
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr14
-rw-r--r--tests/ui/static/reference-to-mut-static-safe.e2021.stderr2
-rw-r--r--tests/ui/static/reference-to-mut-static-safe.e2024.stderr2
-rw-r--r--tests/ui/static/reference-to-mut-static-unsafe-fn.stderr12
-rw-r--r--tests/ui/static/reference-to-mut-static.e2021.stderr12
-rw-r--r--tests/ui/static/reference-to-mut-static.e2024.stderr12
-rw-r--r--tests/ui/static/safe-extern-statics-mut.stderr4
-rw-r--r--tests/ui/statics/issue-15261.stderr2
-rw-r--r--tests/ui/statics/static-mut-xc.stderr4
-rw-r--r--tests/ui/statics/static-recursive.stderr2
-rw-r--r--tests/ui/stats/hir-stats.stderr12
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr6
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple.stderr2
-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/issue-109396.stderr8
-rw-r--r--tests/ui/suggestions/issue-109854.stderr4
-rw-r--r--tests/ui/suggestions/issue-85347.stderr10
-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/test-attrs/test-panic-abort-nocapture.rs1
-rw-r--r--tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr4
-rw-r--r--tests/ui/test-attrs/test-panic-abort.rs1
-rw-r--r--tests/ui/test-attrs/test-panic-abort.run.stdout2
-rw-r--r--tests/ui/traits/issue-105231.rs4
-rw-r--r--tests/ui/traits/issue-105231.stderr22
-rw-r--r--tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr19
-rw-r--r--tests/ui/transmutability/issue-101739-1.rs1
-rw-r--r--tests/ui/transmutability/issue-101739-1.stderr11
-rw-r--r--tests/ui/transmutability/issue-101739-2.rs2
-rw-r--r--tests/ui/transmutability/issue-101739-2.stderr11
-rw-r--r--tests/ui/tuple/wrong_argument_ice-3.stderr2
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr2
-rw-r--r--tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr5
-rw-r--r--tests/ui/type/type-ascription-instead-of-initializer.stderr2
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.rs2
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.stderr2
-rw-r--r--tests/ui/typeck/cyclic_type_ice.stderr2
-rw-r--r--tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs2
-rw-r--r--tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr6
-rw-r--r--tests/ui/typeck/remove-extra-argument.stderr2
-rw-r--r--tests/ui/typeck/struct-enum-wrong-args.stderr16
-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/variance/variance-unused-type-param.rs10
-rw-r--r--tests/ui/variance/variance-unused-type-param.stderr41
-rw-r--r--tests/ui/variants/variant-namespacing.stderr12
-rw-r--r--triagebot.toml5
938 files changed, 13623 insertions, 6685 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2d3bc59dddb..1c1607e4c1a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4411,6 +4411,7 @@ dependencies = [
 name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
+ "either",
  "itertools",
  "rustc_apfloat",
  "rustc_arena",
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index 3cb56a7d312..5008069542f 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -27,7 +27,7 @@ features = ['unprefixed_malloc_on_supported_platforms']
 
 [features]
 # tidy-alphabetical-start
-jemalloc = ['jemalloc-sys']
+jemalloc = ['dep:jemalloc-sys']
 llvm = ['rustc_driver_impl/llvm']
 max_level_info = ['rustc_driver_impl/max_level_info']
 rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 7ba58406ef1..29766fc9d87 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -34,7 +34,7 @@
 
 fn main() {
     // See the comment at the top of this file for an explanation of this.
-    #[cfg(feature = "jemalloc-sys")]
+    #[cfg(feature = "jemalloc")]
     {
         use std::os::raw::{c_int, c_void};
 
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 5031e7a6705..7448f066d0a 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -21,10 +21,10 @@ default = ["nightly", "randomize"]
 # rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
 # without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
-    "rustc_data_structures",
+    "dep:rustc_data_structures",
+    "dep:rustc_macros",
+    "dep:rustc_serialize",
     "rustc_index/nightly",
-    "rustc_macros",
-    "rustc_serialize",
 ]
-randomize = ["rand", "rand_xoshiro", "nightly"]
+randomize = ["dep:rand", "dep:rand_xoshiro", "nightly"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index efe19566152..9478da236c3 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -699,8 +699,7 @@ impl Token {
         false
     }
 
-    /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
-    /// That is, is this a pre-parsed expression dropped into the token stream
+    /// Is this a pre-parsed expression dropped into the token stream
     /// (which happens while parsing the result of macro expansion)?
     pub fn is_whole_expr(&self) -> bool {
         if let Interpolated(nt) = &self.kind
diff --git a/compiler/rustc_ast_ir/Cargo.toml b/compiler/rustc_ast_ir/Cargo.toml
index a78c91e0615..1905574073f 100644
--- a/compiler/rustc_ast_ir/Cargo.toml
+++ b/compiler/rustc_ast_ir/Cargo.toml
@@ -14,8 +14,8 @@ rustc_span = { path = "../rustc_span", optional = true }
 [features]
 default = ["nightly"]
 nightly = [
-    "rustc_serialize",
-    "rustc_data_structures",
-    "rustc_macros",
-    "rustc_span",
+    "dep:rustc_serialize",
+    "dep:rustc_data_structures",
+    "dep:rustc_macros",
+    "dep:rustc_span",
 ]
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 666e7763e62..de0874af934 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             .emit();
                         }
                         hir::InlineAsmOperand::Const {
-                            anon_const: self.lower_anon_const(anon_const),
+                            anon_const: self.lower_anon_const_to_anon_const(anon_const),
                         }
                     }
                     InlineAsmOperand::Sym { sym } => {
@@ -222,18 +222,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             };
 
                             // Wrap the expression in an AnonConst.
-                            let parent_def_id = self.current_hir_id_owner;
+                            let parent_def_id = self.current_def_id_parent;
                             let node_id = self.next_node_id();
-                            self.create_def(
-                                parent_def_id.def_id,
-                                node_id,
-                                kw::Empty,
-                                DefKind::AnonConst,
-                                *op_sp,
-                            );
+                            // HACK(min_generic_const_args): see lower_anon_const
+                            if !expr.is_potential_trivial_const_arg() {
+                                self.create_def(
+                                    parent_def_id,
+                                    node_id,
+                                    kw::Empty,
+                                    DefKind::AnonConst,
+                                    *op_sp,
+                                );
+                            }
                             let anon_const = AnonConst { id: node_id, value: P(expr) };
                             hir::InlineAsmOperand::SymFn {
-                                anon_const: self.lower_anon_const(&anon_const),
+                                anon_const: self.lower_anon_const_to_anon_const(&anon_const),
                             }
                         }
                     }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 218fa974022..d870f9fe0ae 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -75,10 +75,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
                 ExprKind::ConstBlock(c) => {
-                    let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
-                        def_id: this.local_def_id(c.id),
-                        hir_id: this.lower_node_id(c.id),
-                        body: this.lower_const_body(c.value.span, Some(&c.value)),
+                    let c = self.with_new_scopes(c.value.span, |this| {
+                        let def_id = this.local_def_id(c.id);
+                        hir::ConstBlock {
+                            def_id,
+                            hir_id: this.lower_node_id(c.id),
+                            body: this.with_def_id_parent(def_id, |this| {
+                                this.lower_const_body(c.value.span, Some(&c.value))
+                            }),
+                        }
                     });
                     hir::ExprKind::ConstBlock(c)
                 }
@@ -377,17 +382,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let mut generic_args = ThinVec::new();
         for (idx, arg) in args.into_iter().enumerate() {
             if legacy_args_idx.contains(&idx) {
-                let parent_def_id = self.current_hir_id_owner;
+                let parent_def_id = self.current_def_id_parent;
                 let node_id = self.next_node_id();
 
-                // Add a definition for the in-band const def.
-                self.create_def(
-                    parent_def_id.def_id,
-                    node_id,
-                    kw::Empty,
-                    DefKind::AnonConst,
-                    f.span,
-                );
+                // HACK(min_generic_const_args): see lower_anon_const
+                if !arg.is_potential_trivial_const_arg() {
+                    // Add a definition for the in-band const def.
+                    self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
+                }
 
                 let anon_const = AnonConst { id: node_id, value: arg };
                 generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@@ -622,6 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         coroutine_source: hir::CoroutineSource,
         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
     ) -> hir::ExprKind<'hir> {
+        let closure_def_id = self.local_def_id(closure_node_id);
         let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
 
         // The `async` desugaring takes a resume argument and maintains a `task_context`,
@@ -672,22 +675,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
             lifetime_elision_allowed: false,
         });
 
-        let body = self.lower_body(move |this| {
-            this.coroutine_kind = Some(coroutine_kind);
+        let body = self.with_def_id_parent(closure_def_id, move |this| {
+            this.lower_body(move |this| {
+                this.coroutine_kind = Some(coroutine_kind);
 
-            let old_ctx = this.task_context;
-            if task_context.is_some() {
-                this.task_context = task_context;
-            }
-            let res = body(this);
-            this.task_context = old_ctx;
+                let old_ctx = this.task_context;
+                if task_context.is_some() {
+                    this.task_context = task_context;
+                }
+                let res = body(this);
+                this.task_context = old_ctx;
 
-            (params, res)
+                (params, res)
+            })
         });
 
         // `static |<_task_context?>| -> <return_ty> { <body> }`:
         hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
-            def_id: self.local_def_id(closure_node_id),
+            def_id: closure_def_id,
             binder: hir::ClosureBinder::Default,
             capture_clause,
             bound_generic_params: &[],
@@ -966,27 +971,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
         fn_decl_span: Span,
         fn_arg_span: Span,
     ) -> hir::ExprKind<'hir> {
+        let closure_def_id = self.local_def_id(closure_id);
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
         let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
-            let mut coroutine_kind = if this
-                .attrs
-                .get(&closure_hir_id.local_id)
-                .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
-            {
-                Some(hir::CoroutineKind::Coroutine(Movability::Movable))
-            } else {
-                None
-            };
-            let body_id = this.lower_fn_body(decl, |this| {
-                this.coroutine_kind = coroutine_kind;
-                let e = this.lower_expr_mut(body);
-                coroutine_kind = this.coroutine_kind;
-                e
-            });
-            let coroutine_option =
-                this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
-            (body_id, coroutine_option)
+            this.with_def_id_parent(closure_def_id, move |this| {
+                let mut coroutine_kind = if this
+                    .attrs
+                    .get(&closure_hir_id.local_id)
+                    .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
+                {
+                    Some(hir::CoroutineKind::Coroutine(Movability::Movable))
+                } else {
+                    None
+                };
+                let body_id = this.lower_fn_body(decl, |this| {
+                    this.coroutine_kind = coroutine_kind;
+                    let e = this.lower_expr_mut(body);
+                    coroutine_kind = this.coroutine_kind;
+                    e
+                });
+                let coroutine_option =
+                    this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
+                (body_id, coroutine_option)
+            })
         });
 
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
@@ -994,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
 
         let c = self.arena.alloc(hir::Closure {
-            def_id: self.local_def_id(closure_id),
+            def_id: closure_def_id,
             binder: binder_clause,
             capture_clause,
             bound_generic_params,
@@ -1066,6 +1074,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         fn_decl_span: Span,
         fn_arg_span: Span,
     ) -> hir::ExprKind<'hir> {
+        let closure_def_id = self.local_def_id(closure_id);
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
         assert_matches!(
@@ -1075,27 +1084,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
         );
 
         let body = self.with_new_scopes(fn_decl_span, |this| {
-            let inner_decl =
-                FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
-
-            // Transform `async |x: u8| -> X { ... }` into
-            // `|x: u8| || -> X { ... }`.
-            let body_id = this.lower_body(|this| {
-                let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
-                    &inner_decl,
-                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
-                    fn_decl_span,
-                    body.span,
-                    coroutine_kind,
-                    hir::CoroutineSource::Closure,
-                );
+            this.with_def_id_parent(closure_def_id, |this| {
+                let inner_decl =
+                    FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
+
+                // Transform `async |x: u8| -> X { ... }` into
+                // `|x: u8| || -> X { ... }`.
+                let body_id = this.lower_body(|this| {
+                    let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
+                        &inner_decl,
+                        |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
+                        fn_decl_span,
+                        body.span,
+                        coroutine_kind,
+                        hir::CoroutineSource::Closure,
+                    );
 
-                let hir_id = this.lower_node_id(coroutine_kind.closure_id());
-                this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
+                    let hir_id = this.lower_node_id(coroutine_kind.closure_id());
+                    this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
 
-                (parameters, expr)
-            });
-            body_id
+                    (parameters, expr)
+                });
+                body_id
+            })
         });
 
         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
@@ -1106,7 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
 
         let c = self.arena.alloc(hir::Closure {
-            def_id: self.local_def_id(closure_id),
+            def_id: closure_def_id,
             binder: binder_clause,
             capture_clause,
             bound_generic_params,
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 44f37b5533a..23729124e21 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -181,7 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         intravisit::walk_generic_param(self, param);
     }
 
-    fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
+    fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) {
         self.with_parent(param, |this| {
             intravisit::walk_const_param_default(this, ct);
         })
@@ -229,6 +229,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
+        // FIXME: use real span?
         self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
 
         self.with_parent(constant.hir_id, |this| {
@@ -244,6 +245,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
+    fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
+        // FIXME: use real span?
+        self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
+
+        self.with_parent(const_arg.hir_id, |this| {
+            intravisit::walk_const_arg(this, const_arg);
+        });
+    }
+
     fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
         self.insert(expr.span, expr.hir_id, Node::Expr(expr));
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 0ad23b53566..f990b4ba69b 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -61,7 +61,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
 
         for (def_id, info) in lctx.children {
             let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
-            debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
+            debug_assert!(
+                matches!(owner, hir::MaybeOwner::Phantom),
+                "duplicate copy of {def_id:?} in lctx.children"
+            );
             *owner = info;
         }
     }
@@ -713,7 +716,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             hir_id,
             def_id: self.local_def_id(v.id),
             data: self.lower_variant_data(hir_id, &v.data),
-            disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
+            disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
             ident: self.lower_ident(v.ident),
             span: self.lower_span(v.span),
         }
@@ -1601,7 +1604,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         if let Some((span, hir_id, def_id)) = host_param_parts {
             let const_node_id = self.next_node_id();
-            let anon_const =
+            let anon_const_did =
                 self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
 
             let const_id = self.next_id();
@@ -1609,7 +1612,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let bool_id = self.next_id();
 
             self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
-            self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
+            self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
 
             let const_body = self.lower_body(|this| {
                 (
@@ -1624,6 +1627,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 )
             });
 
+            let default_ac = self.arena.alloc(hir::AnonConst {
+                def_id: anon_const_did,
+                hir_id: const_id,
+                body: const_body,
+                span,
+            });
+            let default_ct = self.arena.alloc(hir::ConstArg {
+                hir_id: self.next_id(),
+                kind: hir::ConstArgKind::Anon(default_ac),
+                is_desugared_from_effects: false,
+            });
             let param = hir::GenericParam {
                 def_id,
                 hir_id,
@@ -1648,12 +1662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         )),
                     )),
                     // FIXME(effects) we might not need a default.
-                    default: Some(self.arena.alloc(hir::AnonConst {
-                        def_id: anon_const,
-                        hir_id: const_id,
-                        body: const_body,
-                        span,
-                    })),
+                    default: Some(default_ct),
                     is_host_effect: true,
                     synthetic: true,
                 },
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 24748d2d009..0f5f4d8023b 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> {
     is_in_dyn_type: bool,
 
     current_hir_id_owner: hir::OwnerId,
+    /// Why do we need this in addition to [`Self::current_hir_id_owner`]?
+    ///
+    /// Currently (as of June 2024), anonymous constants are not HIR owners; however,
+    /// they do get their own DefIds. Some of these DefIds have to be created during
+    /// AST lowering, rather than def collection, because we can't tell until after
+    /// name resolution whether an anonymous constant will end up instead being a
+    /// [`hir::ConstArgKind::Path`]. However, to compute which generics are
+    /// available to an anonymous constant nested inside another, we need to make
+    /// sure that the parent is recorded as the parent anon const, not the enclosing
+    /// item. So we need to track parent defs differently from HIR owners, since they
+    /// will be finer-grained in the case of anon consts.
+    current_def_id_parent: LocalDefId,
     item_local_id_counter: hir::ItemLocalId,
     trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
 
@@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             attrs: SortedMap::default(),
             children: Vec::default(),
             current_hir_id_owner: hir::CRATE_OWNER_ID,
+            current_def_id_parent: CRATE_DEF_ID,
             item_local_id_counter: hir::ItemLocalId::ZERO,
             node_id_to_local_id: Default::default(),
             trait_map: Default::default(),
@@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
         debug_assert_eq!(_old, None);
 
-        let item = f(self);
+        let item = self.with_def_id_parent(def_id, f);
         debug_assert_eq!(def_id, item.def_id().def_id);
         // `f` should have consumed all the elements in these vectors when constructing `item`.
         debug_assert!(self.impl_trait_defs.is_empty());
@@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.children.push((def_id, hir::MaybeOwner::Owner(info)));
     }
 
+    fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T {
+        let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent);
+        let result = f(self);
+        self.current_def_id_parent = current_def_id_parent;
+        result
+    }
+
     /// Installs the remapping `remap` in scope while `f` is being executed.
     /// This causes references to the `LocalDefId` keys to be changed to
     /// refer to the values instead.
@@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             LifetimeRes::Fresh { param, kind, .. } => {
                 // Late resolution delegates to us the creation of the `LocalDefId`.
                 let _def_id = self.create_def(
-                    self.current_hir_id_owner.def_id,
+                    self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
                     param,
                     kw::UnderscoreLifetime,
                     DefKind::LifetimeParam,
@@ -1044,7 +1064,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             AssocItemConstraintKind::Equality { term } => {
                 let term = match term {
                     Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
-                    Term::Const(c) => self.lower_anon_const(c).into(),
+                    Term::Const(c) => self.lower_anon_const_to_const_arg(c).into(),
                 };
                 hir::AssocItemConstraintKind::Equality { term }
             }
@@ -1150,42 +1170,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                     ty,
                                 );
 
-                                // Construct an AnonConst where the expr is the "ty"'s path.
-
-                                let parent_def_id = self.current_hir_id_owner;
-                                let node_id = self.next_node_id();
-                                let span = self.lower_span(ty.span);
-
-                                // Add a definition for the in-band const def.
-                                let def_id = self.create_def(
-                                    parent_def_id.def_id,
-                                    node_id,
-                                    kw::Empty,
-                                    DefKind::AnonConst,
-                                    span,
-                                );
-
-                                let path_expr = Expr {
-                                    id: ty.id,
-                                    kind: ExprKind::Path(None, path.clone()),
-                                    span,
-                                    attrs: AttrVec::new(),
-                                    tokens: None,
-                                };
-
-                                let ct = self.with_new_scopes(span, |this| {
-                                    self.arena.alloc(hir::AnonConst {
-                                        def_id,
-                                        hir_id: this.lower_node_id(node_id),
-                                        body: this
-                                            .lower_const_body(path_expr.span, Some(&path_expr)),
-                                        span,
-                                    })
-                                });
-                                return GenericArg::Const(ConstArg {
-                                    value: ct,
-                                    is_desugared_from_effects: false,
-                                });
+                                let ct =
+                                    self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);
+                                return GenericArg::Const(ct);
                             }
                         }
                     }
@@ -1193,10 +1180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
                 GenericArg::Type(self.lower_ty(ty, itctx))
             }
-            ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
-                value: self.lower_anon_const(ct),
-                is_desugared_from_effects: false,
-            }),
+            ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)),
         }
     }
 
@@ -1355,7 +1339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             TyKind::Array(ty, length) => {
                 hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
             }
-            TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
+            TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
             TyKind::TraitObject(bounds, kind) => {
                 let mut lifetime_bound = None;
                 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
@@ -1429,7 +1413,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         );
 
                         self.create_def(
-                            self.current_hir_id_owner.def_id,
+                            self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
                             *def_node_id,
                             ident.name,
                             DefKind::TyParam,
@@ -1637,7 +1621,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
     ) -> hir::TyKind<'hir> {
         let opaque_ty_def_id = self.create_def(
-            self.current_hir_id_owner.def_id,
+            self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
             opaque_ty_node_id,
             kw::Empty,
             DefKind::OpaqueTy,
@@ -2222,7 +2206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             false
                         }
                     })
-                    .map(|def| self.lower_anon_const(def));
+                    .map(|def| self.lower_anon_const_to_const_arg(def));
 
                 (
                     hir::ParamName::Plain(self.lower_ident(param.ident)),
@@ -2360,19 +2344,153 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         "using `_` for array lengths is unstable",
                     )
                     .stash(c.value.span, StashKey::UnderscoreForArrayLengths);
-                    hir::ArrayLen::Body(self.lower_anon_const(c))
+                    hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
                 }
             }
-            _ => hir::ArrayLen::Body(self.lower_anon_const(c)),
+            _ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)),
+        }
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    fn lower_const_path_to_const_arg(
+        &mut self,
+        path: &Path,
+        res: Res<NodeId>,
+        ty_id: NodeId,
+        span: Span,
+    ) -> &'hir hir::ConstArg<'hir> {
+        let ct_kind = match res {
+            Res::Def(DefKind::ConstParam, _) => {
+                let qpath = self.lower_qpath(
+                    ty_id,
+                    &None,
+                    path,
+                    ParamMode::Optional,
+                    ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                    None,
+                );
+                hir::ConstArgKind::Path(qpath)
+            }
+            _ => {
+                // Construct an AnonConst where the expr is the "ty"'s path.
+
+                let parent_def_id = self.current_def_id_parent;
+                let node_id = self.next_node_id();
+                let span = self.lower_span(span);
+
+                // Add a definition for the in-band const def.
+                let def_id =
+                    self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
+                let hir_id = self.lower_node_id(node_id);
+
+                let path_expr = Expr {
+                    id: ty_id,
+                    kind: ExprKind::Path(None, path.clone()),
+                    span,
+                    attrs: AttrVec::new(),
+                    tokens: None,
+                };
+
+                let ct = self.with_new_scopes(span, |this| {
+                    self.arena.alloc(hir::AnonConst {
+                        def_id,
+                        hir_id,
+                        body: this.with_def_id_parent(def_id, |this| {
+                            this.lower_const_body(path_expr.span, Some(&path_expr))
+                        }),
+                        span,
+                    })
+                });
+                hir::ConstArgKind::Anon(ct)
+            }
+        };
+
+        self.arena.alloc(hir::ConstArg {
+            hir_id: self.next_id(),
+            kind: ct_kind,
+            is_desugared_from_effects: false,
+        })
+    }
+
+    /// See [`hir::ConstArg`] for when to use this function vs
+    /// [`Self::lower_anon_const_to_anon_const`].
+    fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
+        self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
+        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
+        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
+        let expr = if let ExprKind::Block(block, _) = &anon.value.kind
+            && let [stmt] = block.stmts.as_slice()
+            && let StmtKind::Expr(expr) = &stmt.kind
+            && let ExprKind::Path(..) = &expr.kind
+        {
+            expr
+        } else {
+            &anon.value
+        };
+        let maybe_res =
+            self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
+        debug!("res={:?}", maybe_res);
+        // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
+        if let Some(res) = maybe_res
+            && let Res::Def(DefKind::ConstParam, _) = res
+            && let ExprKind::Path(qself, path) = &expr.kind
+        {
+            let qpath = self.lower_qpath(
+                expr.id,
+                qself,
+                path,
+                ParamMode::Optional,
+                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                None,
+            );
+
+            return ConstArg {
+                hir_id: self.next_id(),
+                kind: hir::ConstArgKind::Path(qpath),
+                is_desugared_from_effects: false,
+            };
+        }
+
+        let lowered_anon = self.lower_anon_const_to_anon_const(anon);
+        ConstArg {
+            hir_id: self.next_id(),
+            kind: hir::ConstArgKind::Anon(lowered_anon),
+            is_desugared_from_effects: false,
         }
     }
 
-    fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
-        self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst {
-            def_id: this.local_def_id(c.id),
-            hir_id: this.lower_node_id(c.id),
-            body: this.lower_const_body(c.value.span, Some(&c.value)),
-            span: this.lower_span(c.value.span),
+    /// See [`hir::ConstArg`] for when to use this function vs
+    /// [`Self::lower_anon_const_to_const_arg`].
+    fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
+        if c.value.is_potential_trivial_const_arg() {
+            // HACK(min_generic_const_args): see DefCollector::visit_anon_const
+            // Over there, we guess if this is a bare param and only create a def if
+            // we think it's not. However we may can guess wrong (see there for example)
+            // in which case we have to create the def here.
+            self.create_def(
+                self.current_def_id_parent,
+                c.id,
+                kw::Empty,
+                DefKind::AnonConst,
+                c.value.span,
+            );
+        }
+
+        self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
+            let def_id = this.local_def_id(c.id);
+            let hir_id = this.lower_node_id(c.id);
+            hir::AnonConst {
+                def_id,
+                hir_id,
+                body: this.with_def_id_parent(def_id, |this| {
+                    this.lower_const_body(c.value.span, Some(&c.value))
+                }),
+                span: this.lower_span(c.value.span),
+            }
         }))
     }
 
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 02bdff96aa6..8f7dd774207 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -269,6 +269,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..783bca6b695 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -225,6 +225,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_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c7f6840e401..a4fd00efe05 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -205,9 +205,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                     is_loop_move = true;
                 }
 
+                let mut has_suggest_reborrow = false;
                 if !seen_spans.contains(&move_span) {
                     if !closure {
-                        self.suggest_ref_or_clone(mpi, &mut err, &mut in_pattern, move_spans);
+                        self.suggest_ref_or_clone(
+                            mpi,
+                            &mut err,
+                            &mut in_pattern,
+                            move_spans,
+                            moved_place.as_ref(),
+                            &mut has_suggest_reborrow,
+                        );
                     }
 
                     let msg_opt = CapturedMessageOpt {
@@ -215,6 +223,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                         is_loop_message,
                         is_move_msg,
                         is_loop_move,
+                        has_suggest_reborrow,
                         maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
                             .is_empty(),
                     };
@@ -259,17 +268,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
             if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
                 if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
                     // We have a `&mut` ref, we need to reborrow on each iteration (#62112).
-                    err.span_suggestion_verbose(
-                        span.shrink_to_lo(),
-                        format!(
-                            "consider creating a fresh reborrow of {} here",
-                            self.describe_place(moved_place)
-                                .map(|n| format!("`{n}`"))
-                                .unwrap_or_else(|| "the mutable reference".to_string()),
-                        ),
-                        "&mut *",
-                        Applicability::MachineApplicable,
-                    );
+                    self.suggest_reborrow(&mut err, span, moved_place);
                 }
             }
 
@@ -346,6 +345,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
         err: &mut Diag<'infcx>,
         in_pattern: &mut bool,
         move_spans: UseSpans<'tcx>,
+        moved_place: PlaceRef<'tcx>,
+        has_suggest_reborrow: &mut bool,
     ) {
         let move_span = match move_spans {
             UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
@@ -435,20 +436,49 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
                 let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
                     && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
-                    && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
                 {
-                    (def_id.as_local(), args, 1)
+                    (typeck.type_dependent_def_id(parent_expr.hir_id), args, 1)
                 } else if let hir::Node::Expr(parent_expr) = parent
                     && let hir::ExprKind::Call(call, args) = parent_expr.kind
                     && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
                 {
-                    (def_id.as_local(), args, 0)
+                    (Some(*def_id), args, 0)
                 } else {
                     (None, &[][..], 0)
                 };
+
+                // If the moved value is a mut reference, it is used in a
+                // generic function and it's type is a generic param, it can be
+                // reborrowed to avoid moving.
+                // for example:
+                // struct Y(u32);
+                // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
+                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 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;
+                    if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
+                        *has_suggest_reborrow = true;
+                        self.suggest_reborrow(err, expr.span, moved_place);
+                        return;
+                    }
+                }
+
                 let mut can_suggest_clone = true;
                 if let Some(def_id) = def_id
-                    && let node = self.infcx.tcx.hir_node_by_def_id(def_id)
+                    && let Some(local_def_id) = def_id.as_local()
+                    && let node = self.infcx.tcx.hir_node_by_def_id(local_def_id)
                     && let Some(fn_sig) = node.fn_sig()
                     && let Some(ident) = node.ident()
                     && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
@@ -622,6 +652,25 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
         }
     }
 
+    pub fn suggest_reborrow(
+        &self,
+        err: &mut Diag<'infcx>,
+        span: Span,
+        moved_place: PlaceRef<'tcx>,
+    ) {
+        err.span_suggestion_verbose(
+            span.shrink_to_lo(),
+            format!(
+                "consider creating a fresh reborrow of {} here",
+                self.describe_place(moved_place)
+                    .map(|n| format!("`{n}`"))
+                    .unwrap_or_else(|| "the mutable reference".to_string()),
+            ),
+            "&mut *",
+            Applicability::MachineApplicable,
+        );
+    }
+
     fn report_use_of_uninitialized(
         &self,
         mpi: MovePathIndex,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index b7fbb71a0cf..f97459d16ba 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -768,10 +768,11 @@ struct CapturedMessageOpt {
     is_loop_message: bool,
     is_move_msg: bool,
     is_loop_move: bool,
+    has_suggest_reborrow: bool,
     maybe_reinitialized_locations_is_empty: bool,
 }
 
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
         &self,
@@ -997,7 +998,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
     #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn explain_captures(
         &mut self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'infcx>,
         span: Span,
         move_span: Span,
         move_spans: UseSpans<'tcx>,
@@ -1009,6 +1010,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
             is_loop_message,
             is_move_msg,
             is_loop_move,
+            has_suggest_reborrow,
             maybe_reinitialized_locations_is_empty,
         } = msg_opt;
         if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
@@ -1182,18 +1184,15 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
                         if let ty::Ref(_, _, hir::Mutability::Mut) =
                             moved_place.ty(self.body, self.infcx.tcx).ty.kind()
                         {
-                            // If we are in a loop this will be suggested later.
-                            if !is_loop_move {
-                                err.span_suggestion_verbose(
+                            // Suggest `reborrow` in other place for following situations:
+                            // 1. If we are in a loop this will be suggested later.
+                            // 2. If the moved value is a mut reference, it is used in a
+                            // generic function and the corresponding arg's type is generic param.
+                            if !is_loop_move && !has_suggest_reborrow {
+                                self.suggest_reborrow(
+                                    err,
                                     move_span.shrink_to_lo(),
-                                    format!(
-                                        "consider creating a fresh reborrow of {} here",
-                                        self.describe_place(moved_place.as_ref())
-                                            .map(|n| format!("`{n}`"))
-                                            .unwrap_or_else(|| "the mutable reference".to_string()),
-                                    ),
-                                    "&mut *",
-                                    Applicability::MachineApplicable,
+                                    moved_place.as_ref(),
                                 );
                             }
                         }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 4b6c1b29f28..fcf23aa4785 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -554,6 +554,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
             is_loop_message: false,
             is_move_msg: false,
             is_loop_move: false,
+            has_suggest_reborrow: false,
             maybe_reinitialized_locations_is_empty: true,
         };
         if let Some(use_spans) = use_spans {
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 02b9c2d48b1..8da4d80badf 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -309,14 +309,10 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
 }
 
 impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.type_checker.infcx.tcx
     }
 
-    fn tag(&self) -> &'static str {
-        "nll::subtype"
-    }
-
     #[instrument(skip(self, info), level = "trace", ret)]
     fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
         &mut self,
@@ -370,7 +366,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
                     // shouldn't ever fail. Instead, it unconditionally emits an
                     // alias-relate goal.
                     assert!(!self.type_checker.infcx.next_trait_solver());
-                    self.tcx().dcx().span_delayed_bug(
+                    self.cx().dcx().span_delayed_bug(
                         self.span(),
                         "failure to relate an opaque to itself should result in an error later on",
                     );
@@ -540,7 +536,7 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating
         &mut self,
         obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
     ) {
-        let tcx = self.tcx();
+        let tcx = self.cx();
         let param_env = self.param_env();
         self.register_goals(
             obligations.into_iter().map(|to_pred| Goal::new(tcx, param_env, to_pred)),
@@ -559,7 +555,7 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating
                     .into_iter()
                     .map(|goal| {
                         Obligation::new(
-                            self.tcx(),
+                            self.cx(),
                             ObligationCause::dummy_with_span(self.span()),
                             goal.param_env,
                             goal.predicate,
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_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_gcc/.rustfmt.toml b/compiler/rustc_codegen_gcc/.rustfmt.toml
index 2a35f0230c6..725aec25a07 100644
--- a/compiler/rustc_codegen_gcc/.rustfmt.toml
+++ b/compiler/rustc_codegen_gcc/.rustfmt.toml
@@ -1 +1,3 @@
+version = "Two"
 use_small_heuristics = "Max"
+merge_derives = false
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
index aee46afaeb0..cbf590c0c32 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
@@ -34,7 +34,7 @@ impl Args {
                 "--out-path" => match args.next() {
                     Some(path) if !path.is_empty() => out_path = Some(path),
                     _ => {
-                        return Err("Expected an argument after `--out-path`, found nothing".into())
+                        return Err("Expected an argument after `--out-path`, found nothing".into());
                     }
                 },
                 "--help" => {
diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs
index 965aedd8be8..bbb711c8428 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/config.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs
@@ -54,7 +54,7 @@ impl ConfigFile {
                     config.gcc_path = Some(value.as_str().to_string())
                 }
                 ("gcc-path", _) => {
-                    return failed_config_parsing(config_file, "Expected a string for `gcc-path`")
+                    return failed_config_parsing(config_file, "Expected a string for `gcc-path`");
                 }
                 ("download-gccjit", TomlValue::Boolean(value)) => {
                     config.download_gccjit = Some(*value)
@@ -63,7 +63,7 @@ impl ConfigFile {
                     return failed_config_parsing(
                         config_file,
                         "Expected a boolean for `download-gccjit`",
-                    )
+                    );
                 }
                 _ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)),
             }
@@ -73,7 +73,7 @@ impl ConfigFile {
                 return failed_config_parsing(
                     config_file,
                     "At least one of `gcc-path` or `download-gccjit` value must be set",
-                )
+                );
             }
             (Some(_), Some(true)) => {
                 println!(
@@ -144,7 +144,7 @@ impl ConfigInfo {
                 _ => {
                     return Err(
                         "Expected a value after `--target-triple`, found nothing".to_string()
-                    )
+                    );
                 }
             },
             "--out-dir" => match args.next() {
@@ -158,7 +158,7 @@ impl ConfigInfo {
                     self.config_file = Some(arg.to_string());
                 }
                 _ => {
-                    return Err("Expected a value after `--config-file`, found nothing".to_string())
+                    return Err("Expected a value after `--config-file`, found nothing".to_string());
                 }
             },
             "--release-sysroot" => self.sysroot_release_channel = true,
@@ -169,7 +169,7 @@ impl ConfigInfo {
                     self.cg_gcc_path = Some(arg.into());
                 }
                 _ => {
-                    return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string())
+                    return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string());
                 }
             },
             "--use-backend" => match args.next() {
@@ -277,7 +277,7 @@ impl ConfigInfo {
         self.gcc_path = match gcc_path {
             Some(path) => path,
             None => {
-                return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),))
+                return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),));
             }
         };
         Ok(())
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 8d088a3aac3..06f28d13fb3 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -109,7 +109,7 @@ impl TestArg {
                         test_arg.flags.extend_from_slice(&["--features".into(), feature]);
                     }
                     _ => {
-                        return Err("Expected an argument after `--features`, found nothing".into())
+                        return Err("Expected an argument after `--features`, found nothing".into());
                     }
                 },
                 "--use-system-gcc" => {
@@ -458,11 +458,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
     .map_err(|error| format!("Failed to retrieve cargo path: {:?}", error))
     .and_then(|cargo| {
         let cargo = cargo.trim().to_owned();
-        if cargo.is_empty() {
-            Err(format!("`cargo` path is empty"))
-        } else {
-            Ok(cargo)
-        }
+        if cargo.is_empty() { Err(format!("`cargo` path is empty")) } else { Ok(cargo) }
     })?;
     let rustc = String::from_utf8(
         run_command_with_env(&[&"rustup", &toolchain, &"which", &"rustc"], rust_dir, Some(env))?
@@ -471,11 +467,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
     .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error))
     .and_then(|rustc| {
         let rustc = rustc.trim().to_owned();
-        if rustc.is_empty() {
-            Err(format!("`rustc` path is empty"))
-        } else {
-            Ok(rustc)
-        }
+        if rustc.is_empty() { Err(format!("`rustc` path is empty")) } else { Ok(rustc) }
     })?;
     let llvm_filecheck = match run_command_with_env(
         &[
diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
index 3bba8df6c65..e338d1b4992 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/utils.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
@@ -175,11 +175,7 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> {
 pub fn get_os_name() -> Result<String, String> {
     let output = run_command(&[&"uname"], None)?;
     let name = std::str::from_utf8(&output.stdout).unwrap_or("").trim().to_string();
-    if !name.is_empty() {
-        Ok(name)
-    } else {
-        Err("Failed to retrieve the OS name".to_string())
-    }
+    if !name.is_empty() { Ok(name) } else { Err("Failed to retrieve the OS name".to_string()) }
 }
 
 #[derive(Default, PartialEq)]
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 166dd080cf2..0a99e7213be 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -26,11 +26,7 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         } else {
             false
         };
-        if on_stack {
-            param.to_lvalue().get_address(None)
-        } else {
-            param.to_rvalue()
-        }
+        if on_stack { param.to_lvalue().get_address(None) } else { param.to_rvalue() }
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index aa485846cd4..1da691252ab 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -858,11 +858,7 @@ fn modifier_to_gcc(
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
         | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
-            if modifier == Some('v') {
-                None
-            } else {
-                modifier
-            }
+            if modifier == Some('v') { None } else { modifier }
         }
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
             unreachable!("clobber-only")
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 307348f595d..b9e4bd79fe1 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1043,11 +1043,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
                 let llty = place.layout.scalar_pair_element_gcc_type(self, i);
                 let load = self.load(llty, llptr, align);
                 scalar_load_metadata(self, load, scalar);
-                if scalar.is_bool() {
-                    self.trunc(load, self.type_i1())
-                } else {
-                    load
-                }
+                if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
             };
 
             OperandValue::Pair(
@@ -1795,18 +1791,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
         let int_max = |signed: bool, int_width: u64| -> u128 {
             let shift_amount = 128 - int_width;
-            if signed {
-                i128::MAX as u128 >> shift_amount
-            } else {
-                u128::MAX >> shift_amount
-            }
+            if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
         };
         let int_min = |signed: bool, int_width: u64| -> i128 {
-            if signed {
-                i128::MIN >> (128 - int_width)
-            } else {
-                0
-            }
+            if signed { i128::MIN >> (128 - int_width) } else { 0 }
         };
 
         let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 19333689aaa..70f0dc37e39 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -58,11 +58,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
 
 impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
-        if type_is_pointer(typ) {
-            self.context.new_null(typ)
-        } else {
-            self.const_int(typ, 0)
-        }
+        if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
     }
 
     fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
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_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/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 822f5c2c44a..35e9a3b7dc2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -37,13 +37,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn eval_unevaluated_mir_constant_to_valtree(
         &self,
         constant: &mir::ConstOperand<'tcx>,
-    ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
+    ) -> Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled> {
         let uv = match self.monomorphize(constant.const_) {
             mir::Const::Unevaluated(uv, _) => uv.shrink(),
             mir::Const::Ty(_, c) => match c.kind() {
                 // A constant that came from a const generic but was then used as an argument to old-style
                 // simd_shuffle (passing as argument instead of as a generic param).
-                rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)),
+                rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Ok(valtree)),
                 other => span_bug!(constant.span, "{other:#?}"),
             },
             // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
@@ -70,6 +70,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let val = self
             .eval_unevaluated_mir_constant_to_valtree(constant)
             .ok()
+            .map(|x| x.ok())
             .flatten()
             .map(|val| {
                 let field_ty = ty.builtin_index().unwrap();
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_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 4ae4816e33a..3a6dc81eff1 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -27,15 +27,15 @@ pub(crate) use valtrees::{eval_to_valtree, valtree_to_const_value};
 // We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
 const VALTREE_MAX_NODES: usize = 100000;
 
-pub(crate) enum ValTreeCreationError {
+pub(crate) enum ValTreeCreationError<'tcx> {
     NodesOverflow,
     /// Values of this type, or this particular value, are not supported as valtrees.
-    NonSupportedType,
+    NonSupportedType(Ty<'tcx>),
 }
-pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
+pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError<'tcx>>;
 
-impl From<InterpErrorInfo<'_>> for ValTreeCreationError {
-    fn from(err: InterpErrorInfo<'_>) -> Self {
+impl<'tcx> From<InterpErrorInfo<'tcx>> for ValTreeCreationError<'tcx> {
+    fn from(err: InterpErrorInfo<'tcx>) -> Self {
         ty::tls::with(|tcx| {
             bug!(
                 "Unexpected Undefined Behavior error during valtree construction: {}",
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 2e8ad445cf5..3bc01510730 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -120,13 +120,13 @@ fn const_to_valtree_inner<'tcx>(
             // We could allow wide raw pointers where both sides are integers in the future,
             // but for now we reject them.
             if matches!(val.layout.abi, Abi::ScalarPair(..)) {
-                return Err(ValTreeCreationError::NonSupportedType);
+                return Err(ValTreeCreationError::NonSupportedType(ty));
             }
             let val = val.to_scalar();
             // We are in the CTFE machine, so ptr-to-int casts will fail.
             // This can only be `Ok` if `val` already is an integer.
             let Ok(val) = val.try_to_scalar_int() else {
-                return Err(ValTreeCreationError::NonSupportedType);
+                return Err(ValTreeCreationError::NonSupportedType(ty));
             };
             // It's just a ScalarInt!
             Ok(ty::ValTree::Leaf(val))
@@ -134,7 +134,7 @@ fn const_to_valtree_inner<'tcx>(
 
         // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
         // agree with runtime equality tests.
-        ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType),
+        ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
 
         ty::Ref(_, _, _)  => {
             let derefd_place = ecx.deref_pointer(place)?;
@@ -148,7 +148,7 @@ fn const_to_valtree_inner<'tcx>(
         // resolving their backing type, even if we can do that at const eval time. We may
         // hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future,
         // but it is unclear if this is useful.
-        ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
+        ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
 
         ty::Tuple(elem_tys) => {
             branches(ecx, place, elem_tys.len(), None, num_nodes)
@@ -156,7 +156,7 @@ fn const_to_valtree_inner<'tcx>(
 
         ty::Adt(def, _) => {
             if def.is_union() {
-                return Err(ValTreeCreationError::NonSupportedType);
+                return Err(ValTreeCreationError::NonSupportedType(ty));
             } else if def.variants().is_empty() {
                 bug!("uninhabited types should have errored and never gotten converted to valtree")
             }
@@ -180,7 +180,7 @@ fn const_to_valtree_inner<'tcx>(
         | ty::Closure(..)
         | ty::CoroutineClosure(..)
         | ty::Coroutine(..)
-        | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType),
+        | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
     }
 }
 
@@ -251,7 +251,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
     let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
 
     match valtree_result {
-        Ok(valtree) => Ok(Some(valtree)),
+        Ok(valtree) => Ok(Ok(valtree)),
         Err(err) => {
             let did = cid.instance.def_id();
             let global_const_id = cid.display(tcx);
@@ -262,7 +262,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
                         tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
                     Err(handled.into())
                 }
-                ValTreeCreationError::NonSupportedType => Ok(None),
+                ValTreeCreationError::NonSupportedType(ty) => Ok(Err(ty)),
             }
         }
     }
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_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index e5e733439ea..3794a6e043c 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -56,5 +56,5 @@ portable-atomic = "1.5.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon"]
+rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "dep:rustc-rayon"]
 # tidy-alphabetical-end
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/E0158.md b/compiler/rustc_error_codes/src/error_codes/E0158.md
index 03b93d925c1..c31f1e13bee 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0158.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0158.md
@@ -1,5 +1,4 @@
-An associated `const`, `const` parameter or `static` has been referenced
-in a pattern.
+A generic parameter or `static` has been referenced in a pattern.
 
 Erroneous code example:
 
@@ -15,25 +14,25 @@ trait Bar {
 
 fn test<A: Bar>(arg: Foo) {
     match arg {
-        A::X => println!("A::X"), // error: E0158: associated consts cannot be
-                                  //        referenced in patterns
+        A::X => println!("A::X"), // error: E0158: constant pattern depends
+                                  //        on a generic parameter
         Foo::Two => println!("Two")
     }
 }
 ```
 
-Associated `const`s cannot be referenced in patterns because it is impossible
+Generic parameters cannot be referenced in patterns because it is impossible
 for the compiler to prove exhaustiveness (that some pattern will always match).
 Take the above example, because Rust does type checking in the *generic*
 method, not the *monomorphized* specific instance. So because `Bar` could have
-theoretically infinite implementations, there's no way to always be sure that
+theoretically arbitrary implementations, there's no way to always be sure that
 `A::X` is `Foo::One`. So this code must be rejected. Even if code can be
 proven exhaustive by a programmer, the compiler cannot currently prove this.
 
-The same holds true of `const` parameters and `static`s.
+The same holds true of `static`s.
 
-If you want to match against an associated `const`, `const` parameter or
-`static` consider using a guard instead:
+If you want to match against a `const` that depends on a generic parameter or a
+`static`, consider using a guard instead:
 
 ```
 trait Trait {
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_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 dbbd948fd70..c4ba98f581e 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -111,14 +111,24 @@ 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,
         }
     }
 }
 
+/// Indicates what is placed in a `concat` parameter. For example, literals
+/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
 #[derive(Debug, Decodable, Encodable, PartialEq)]
 pub(crate) enum MetaVarExprConcatElem {
     /// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 9b4dc13c703..62337756cd8 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -6,9 +6,10 @@ use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
 use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
 use crate::mbe::{self, KleeneOp, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::IdentIsRaw;
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{IdentIsRaw, Lit, LitKind};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::ExprKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, Diag, DiagCtxtHandle, PResult};
 use rustc_parse::lexer::nfc_normalize;
@@ -17,7 +18,7 @@ use rustc_session::parse::ParseSess;
 use rustc_session::parse::SymbolGallery;
 use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
-use rustc_span::{with_metavar_spans, Span, SyntaxContext};
+use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
 use smallvec::{smallvec, SmallVec};
 use std::mem;
 
@@ -556,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,
     }
@@ -691,12 +688,28 @@ fn transcribe_metavar_expr<'a>(
         MetaVarExpr::Concat(ref elements) => {
             let mut concatenated = String::new();
             for element in elements.into_iter() {
-                let string = match element {
-                    MetaVarExprConcatElem::Ident(elem) => elem.to_string(),
-                    MetaVarExprConcatElem::Literal(elem) => elem.as_str().into(),
-                    MetaVarExprConcatElem::Var(elem) => extract_ident(dcx, *elem, interp)?,
+                let symbol = match element {
+                    MetaVarExprConcatElem::Ident(elem) => elem.name,
+                    MetaVarExprConcatElem::Literal(elem) => *elem,
+                    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(&string);
+                concatenated.push_str(symbol.as_str());
             }
             let symbol = nfc_normalize(&concatenated);
             let concatenated_span = visited_span();
@@ -750,32 +763,49 @@ fn transcribe_metavar_expr<'a>(
     Ok(())
 }
 
-/// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree.
-fn extract_ident<'a>(
+/// Extracts an metavariable symbol that can be an identifier, a token tree or a literal.
+fn extract_symbol_from_pnr<'a>(
     dcx: DiagCtxtHandle<'a>,
-    ident: Ident,
-    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
-) -> PResult<'a, String> {
-    if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
-        if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
+    pnr: &ParseNtResult,
+    span_err: Span,
+) -> PResult<'a, Symbol> {
+    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.to_string());
+            return Ok(nt_ident.name);
         }
-        if let ParseNtResult::Tt(TokenTree::Token(
-            Token { kind: TokenKind::Ident(token_ident, is_raw), .. },
+        ParseNtResult::Tt(TokenTree::Token(
+            Token { kind: TokenKind::Ident(symbol, is_raw), .. },
             _,
-        )) = pnr
-        {
+        )) => {
             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(token_ident.to_string());
+            return Ok(*symbol);
+        }
+        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_span_err(
-        ident.span,
-        "`${concat(..)}` currently only accepts identifiers or meta-variables as 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/hir.rs b/compiler/rustc_hir/src/hir.rs
index 3bd7b300758..bf773f2d487 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -228,13 +228,53 @@ impl<'hir> PathSegment<'hir> {
     }
 }
 
+/// A constant that enters the type system, used for arguments to const generics (e.g. array lengths).
+///
+/// These are distinct from [`AnonConst`] as anon consts in the type system are not allowed
+/// to use any generic parameters, therefore we must represent `N` differently. Additionally
+/// future designs for supporting generic parameters in const arguments will likely not use
+/// an anon const based design.
+///
+/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args
+/// that are [just paths](ConstArgKind::Path) (currently just bare const params)
+/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`).
 #[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct ConstArg<'hir> {
-    pub value: &'hir AnonConst,
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub kind: ConstArgKind<'hir>,
     /// Indicates whether this comes from a `~const` desugaring.
     pub is_desugared_from_effects: bool,
 }
 
+impl<'hir> ConstArg<'hir> {
+    pub fn anon_const_hir_id(&self) -> Option<HirId> {
+        match self.kind {
+            ConstArgKind::Anon(ac) => Some(ac.hir_id),
+            _ => None,
+        }
+    }
+
+    pub fn span(&self) -> Span {
+        match self.kind {
+            ConstArgKind::Path(path) => path.span(),
+            ConstArgKind::Anon(anon) => anon.span,
+        }
+    }
+}
+
+/// See [`ConstArg`].
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
+pub enum ConstArgKind<'hir> {
+    /// **Note:** Currently this is only used for bare const params
+    /// (`N` where `fn foo<const N: usize>(...)`),
+    /// not paths to any const (`N` where `const N: usize = ...`).
+    ///
+    /// However, in the future, we'll be using it for all of those.
+    Path(QPath<'hir>),
+    Anon(&'hir AnonConst),
+}
+
 #[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct InferArg {
     pub hir_id: HirId,
@@ -251,7 +291,7 @@ impl InferArg {
 pub enum GenericArg<'hir> {
     Lifetime(&'hir Lifetime),
     Type(&'hir Ty<'hir>),
-    Const(ConstArg<'hir>),
+    Const(&'hir ConstArg<'hir>),
     Infer(InferArg),
 }
 
@@ -260,7 +300,7 @@ impl GenericArg<'_> {
         match self {
             GenericArg::Lifetime(l) => l.ident.span,
             GenericArg::Type(t) => t.span,
-            GenericArg::Const(c) => c.value.span,
+            GenericArg::Const(c) => c.span(),
             GenericArg::Infer(i) => i.span,
         }
     }
@@ -269,7 +309,7 @@ impl GenericArg<'_> {
         match self {
             GenericArg::Lifetime(l) => l.hir_id,
             GenericArg::Type(t) => t.hir_id,
-            GenericArg::Const(c) => c.value.hir_id,
+            GenericArg::Const(c) => c.hir_id,
             GenericArg::Infer(i) => i.hir_id,
         }
     }
@@ -524,7 +564,7 @@ pub enum GenericParamKind<'hir> {
     Const {
         ty: &'hir Ty<'hir>,
         /// Optional default value for the const generic param
-        default: Option<&'hir AnonConst>,
+        default: Option<&'hir ConstArg<'hir>>,
         is_host_effect: bool,
         synthetic: bool,
     },
@@ -1598,13 +1638,13 @@ pub type Lit = Spanned<LitKind>;
 #[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum ArrayLen<'hir> {
     Infer(InferArg),
-    Body(&'hir AnonConst),
+    Body(&'hir ConstArg<'hir>),
 }
 
 impl ArrayLen<'_> {
     pub fn hir_id(&self) -> HirId {
         match self {
-            ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => {
+            ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => {
                 *hir_id
             }
         }
@@ -2434,7 +2474,7 @@ impl<'hir> AssocItemConstraint<'hir> {
     }
 
     /// Obtain the const on the RHS of an assoc const equality constraint if applicable.
-    pub fn ct(self) -> Option<&'hir AnonConst> {
+    pub fn ct(self) -> Option<&'hir ConstArg<'hir>> {
         match self.kind {
             AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
             _ => None,
@@ -2445,7 +2485,7 @@ impl<'hir> AssocItemConstraint<'hir> {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum Term<'hir> {
     Ty(&'hir Ty<'hir>),
-    Const(&'hir AnonConst),
+    Const(&'hir ConstArg<'hir>),
 }
 
 impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
@@ -2454,8 +2494,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
     }
 }
 
-impl<'hir> From<&'hir AnonConst> for Term<'hir> {
-    fn from(c: &'hir AnonConst) -> Self {
+impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> {
+    fn from(c: &'hir ConstArg<'hir>) -> Self {
         Term::Const(c)
     }
 }
@@ -3689,6 +3729,7 @@ pub enum Node<'hir> {
     Field(&'hir FieldDef<'hir>),
     AnonConst(&'hir AnonConst),
     ConstBlock(&'hir ConstBlock),
+    ConstArg(&'hir ConstArg<'hir>),
     Expr(&'hir Expr<'hir>),
     ExprField(&'hir ExprField<'hir>),
     Stmt(&'hir Stmt<'hir>),
@@ -3750,6 +3791,7 @@ impl<'hir> Node<'hir> {
             Node::Param(..)
             | Node::AnonConst(..)
             | Node::ConstBlock(..)
+            | Node::ConstArg(..)
             | Node::Expr(..)
             | Node::Stmt(..)
             | Node::Block(..)
@@ -3966,7 +4008,7 @@ mod size_asserts {
     static_assert_size!(FnDecl<'_>, 40);
     static_assert_size!(ForeignItem<'_>, 72);
     static_assert_size!(ForeignItemKind<'_>, 40);
-    static_assert_size!(GenericArg<'_>, 24);
+    static_assert_size!(GenericArg<'_>, 16);
     static_assert_size!(GenericBound<'_>, 48);
     static_assert_size!(Generics<'_>, 56);
     static_assert_size!(Impl<'_>, 80);
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 9bb3245ae05..c202ee41e31 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -347,6 +347,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
         walk_inline_const(self, c)
     }
+    fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
+        walk_const_arg(self, c)
+    }
     fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
         walk_expr(self, ex)
     }
@@ -364,7 +367,7 @@ pub trait Visitor<'v>: Sized {
     fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
         walk_generic_param(self, p)
     }
-    fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result {
+    fn visit_const_param_default(&mut self, _param: HirId, ct: &'v ConstArg<'v>) -> Self::Result {
         walk_const_param_default(self, ct)
     }
     fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
@@ -708,7 +711,7 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>
     match len {
         // FIXME: Use `visit_infer` here.
         ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
-        ArrayLen::Body(c) => visitor.visit_anon_const(c),
+        ArrayLen::Body(c) => visitor.visit_const_arg(c),
     }
 }
 
@@ -725,6 +728,17 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>(
     visitor.visit_nested_body(constant.body)
 }
 
+pub fn walk_const_arg<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    const_arg: &'v ConstArg<'v>,
+) -> V::Result {
+    try_visit!(visitor.visit_id(const_arg.hir_id));
+    match &const_arg.kind {
+        ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
+        ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
+    }
+}
+
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
     try_visit!(visitor.visit_id(expression.hir_id));
     match expression.kind {
@@ -928,9 +942,9 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
 
 pub fn walk_const_param_default<'v, V: Visitor<'v>>(
     visitor: &mut V,
-    ct: &'v AnonConst,
+    ct: &'v ConstArg<'v>,
 ) -> V::Result {
-    visitor.visit_anon_const(ct)
+    visitor.visit_const_arg(ct)
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
@@ -1216,7 +1230,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(
     match generic_arg {
         GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
         GenericArg::Type(ty) => visitor.visit_ty(ty),
-        GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value),
+        GenericArg::Const(ct) => visitor.visit_const_arg(ct),
         GenericArg::Infer(inf) => visitor.visit_infer(inf),
     }
 }
@@ -1278,7 +1292,7 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
     match constraint.kind {
         AssocItemConstraintKind::Equality { ref term } => match term {
             Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
-            Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
+            Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)),
         },
         AssocItemConstraintKind::Bound { bounds } => {
             walk_list!(visitor, visit_param_bound, bounds)
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 91dd9f92fa8..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
@@ -386,6 +403,10 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no
 hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
     .label = `Self` is not a generic argument, but an alias to the type of the {$what}
 
+hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively
+    .label = {$param_def_kind} must be used non-recursively in the definition
+    .note = all type parameters must be used in a non-recursive way in order to constrain their variance
+
 hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
     .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
 
@@ -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}
 
@@ -553,6 +579,8 @@ hir_analysis_unused_generic_parameter =
     {$param_def_kind} `{$param_name}` is never used
     .label = unused {$param_def_kind}
     .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead
+    .usage_spans = `{$param_name}` is named here, but is likely unused in the containing type
+
 hir_analysis_unused_generic_parameter_adt_help =
     consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`
 hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index bf8ef18c04f..dbc265ad3ff 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1572,6 +1572,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
                 param_name,
                 param_def_kind: tcx.def_descr(param.def_id),
                 help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
+                usage_spans: vec![],
                 const_param_help,
             });
             diag.code(E0091);
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
index 17cb20df754..19a0476e630 100644
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -1,5 +1,4 @@
 use rustc_hir as hir;
-use rustc_hir_pretty::qpath_to_string;
 use rustc_lint_defs::builtin::STATIC_MUT_REFS;
 use rustc_middle::ty::{Mutability, TyCtxt};
 use rustc_span::Span;
@@ -12,9 +11,17 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
     let hir_id = expr.hir_id;
     if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
         && matches!(borrow_kind, hir::BorrowKind::Ref)
-        && let Some(var) = path_if_static_mut(tcx, expr)
+        && path_if_static_mut(expr)
     {
-        handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
+        handle_static_mut_ref(
+            tcx,
+            span,
+            span.with_hi(expr.span.lo()),
+            span.shrink_to_hi(),
+            span.edition().at_least_rust_2024(),
+            m,
+            hir_id,
+        );
     }
 }
 
@@ -24,12 +31,13 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
         && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
         && let hir::ByRef::Yes(rmutbl) = ba.0
         && let Some(init) = loc.init
-        && let Some(var) = path_if_static_mut(tcx, init)
+        && path_if_static_mut(init)
     {
         handle_static_mut_ref(
             tcx,
             init.span,
-            var,
+            init.span.shrink_to_lo(),
+            init.span.shrink_to_hi(),
             loc.span.edition().at_least_rust_2024(),
             rmutbl,
             stmt.hir_id,
@@ -37,38 +45,39 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
     }
 }
 
-fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
+fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool {
     if let hir::ExprKind::Path(qpath) = expr.kind
         && let hir::QPath::Resolved(_, path) = qpath
         && let hir::def::Res::Def(def_kind, _) = path.res
         && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
             def_kind
     {
-        return Some(qpath_to_string(&tcx, &qpath));
+        return true;
     }
-    None
+    false
 }
 
 fn handle_static_mut_ref(
     tcx: TyCtxt<'_>,
     span: Span,
-    var: String,
+    lo: Span,
+    hi: Span,
     e2024: bool,
     mutable: Mutability,
     hir_id: hir::HirId,
 ) {
     if e2024 {
         let (sugg, shared) = if mutable == Mutability::Mut {
-            (errors::StaticMutRefSugg::Mut { span, var }, "mutable")
+            (errors::MutRefSugg::Mut { lo, hi }, "mutable")
         } else {
-            (errors::StaticMutRefSugg::Shared { span, var }, "shared")
+            (errors::MutRefSugg::Shared { lo, hi }, "shared")
         };
         tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared });
     } else {
         let (sugg, shared) = if mutable == Mutability::Mut {
-            (errors::RefOfMutStaticSugg::Mut { span, var }, "mutable")
+            (errors::MutRefSugg::Mut { lo, hi }, "mutable")
         } else {
-            (errors::RefOfMutStaticSugg::Shared { span, var }, "shared")
+            (errors::MutRefSugg::Shared { lo, hi }, "shared")
         };
         tcx.emit_node_span_lint(
             STATIC_MUT_REFS,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9fef31acef8..24aeb024461 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -166,21 +166,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 c1621b6ae4a..974a2d92947 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -4,12 +4,12 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
 use crate::errors;
 use crate::fluent_generated as fluent;
 
-use hir::intravisit::Visitor;
+use hir::intravisit::{self, Visitor};
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
@@ -1822,7 +1822,7 @@ fn receiver_is_implemented<'tcx>(
 
 fn check_variances_for_type_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item: &hir::Item<'tcx>,
+    item: &'tcx hir::Item<'tcx>,
     hir_generics: &hir::Generics<'tcx>,
 ) {
     let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
@@ -1909,21 +1909,21 @@ fn check_variances_for_type_defn<'tcx>(
             hir::ParamName::Error => {}
             _ => {
                 let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
-                report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind);
+                report_bivariance(tcx, hir_param, has_explicit_bounds, item);
             }
         }
     }
 }
 
-fn report_bivariance(
-    tcx: TyCtxt<'_>,
-    param: &rustc_hir::GenericParam<'_>,
+fn report_bivariance<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param: &'tcx hir::GenericParam<'tcx>,
     has_explicit_bounds: bool,
-    item_kind: ItemKind<'_>,
+    item: &'tcx hir::Item<'tcx>,
 ) -> ErrorGuaranteed {
     let param_name = param.name.ident();
 
-    let help = match item_kind {
+    let help = match item.kind {
         ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
             if let Some(def_id) = tcx.lang_items().phantom_data() {
                 errors::UnusedGenericParameterHelp::Adt {
@@ -1938,6 +1938,41 @@ fn report_bivariance(
         item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
     };
 
+    let mut usage_spans = vec![];
+    intravisit::walk_item(
+        &mut CollectUsageSpans { spans: &mut usage_spans, param_def_id: param.def_id.to_def_id() },
+        item,
+    );
+
+    if !usage_spans.is_empty() {
+        // 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 =
+            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 {
+            return tcx.dcx().emit_err(errors::RecursiveGenericParameter {
+                spans: usage_spans,
+                param_span: param.span,
+                param_name,
+                param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
+                help,
+                note: (),
+            });
+        }
+    }
+
     let const_param_help =
         matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
             .then_some(());
@@ -1946,6 +1981,7 @@ fn report_bivariance(
         span: param.span,
         param_name,
         param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
+        usage_spans,
         help,
         const_param_help,
     });
@@ -1953,6 +1989,86 @@ fn report_bivariance(
     diag.emit()
 }
 
+/// 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>,
+    item_def_id: DefId,
+    seen: FxHashSet<DefId>,
+}
+
+impl<'tcx> IsProbablyCyclical<'tcx> {
+    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(()),
+        }
+    }
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
+    type Result = ControlFlow<(), ()>;
+
+    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(def_id) {
+                self.visit_def(def_id)?;
+            }
+        }
+        ty.super_visit_with(self)
+    }
+}
+
+/// Collect usages of the `param_def_id` and `Res::SelfTyAlias` in the HIR.
+///
+/// This is used to report places where the user has used parameters in a
+/// non-variance-constraining way for better bivariance errors.
+struct CollectUsageSpans<'a> {
+    spans: &'a mut Vec<Span>,
+    param_def_id: DefId,
+}
+
+impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> {
+    type Result = ();
+
+    fn visit_generics(&mut self, _g: &'tcx rustc_hir::Generics<'tcx>) -> Self::Result {
+        // Skip the generics. We only care about fields, not where clause/param bounds.
+    }
+
+    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
+        if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind {
+            if let Res::Def(DefKind::TyParam, def_id) = qpath.res
+                && def_id == self.param_def_id
+            {
+                self.spans.push(t.span);
+                return;
+            } else if let Res::SelfTyAlias { .. } = qpath.res {
+                self.spans.push(t.span);
+                return;
+            }
+        }
+        intravisit::walk_ty(self, t);
+    }
+}
+
 impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
     /// aren't true.
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index e0aad299163..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
     };
 }
@@ -304,7 +305,9 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
                     self.tcx.ensure().type_of(param.def_id);
                     if let Some(default) = default {
                         // need to store default and type of default
-                        self.tcx.ensure().type_of(default.def_id);
+                        if let hir::ConstArgKind::Anon(ac) = default.kind {
+                            self.tcx.ensure().type_of(ac.def_id);
+                        }
                         self.tcx.ensure().const_param_default(param.def_id);
                     }
                 }
@@ -1880,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/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 22d465c8e62..690423421b9 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -13,7 +13,7 @@ use rustc_session::lint;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
 
-#[instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx), ret)]
 pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     use rustc_hir::*;
 
@@ -102,6 +102,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 None
             } else if tcx.features().generic_const_exprs {
                 let parent_node = tcx.parent_hir_node(hir_id);
+                debug!(?parent_node);
                 if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
                     && constant.hir_id == hir_id
                 {
@@ -164,13 +165,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 }
             } else {
                 let parent_node = tcx.parent_hir_node(hir_id);
+                let parent_node = match parent_node {
+                    Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
+                    _ => parent_node,
+                };
                 match parent_node {
                     // HACK(eddyb) this provides the correct generics for repeat
                     // expressions' count (i.e. `N` in `[x; N]`), and explicit
                     // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
                     // as they shouldn't be able to cause query cycle errors.
-                    Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
-                        if constant.hir_id() == hir_id =>
+                    Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. })
+                        if ct.anon_const_hir_id() == Some(hir_id) =>
                     {
                         Some(parent_did)
                     }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index b89d034fc2e..9e430c83e20 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -388,7 +388,7 @@ fn const_evaluatable_predicates_of(
             }
         }
 
-        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
             // Do not look into const param defaults,
             // these get checked when they are actually instantiated.
             //
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 cad7870a0a1..7930f54038d 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -954,7 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             GenericParamKind::Const { ty, default, .. } => {
                 self.visit_ty(ty);
                 if let Some(default) = default {
-                    self.visit_body(self.tcx.hir().body(default.body));
+                    self.visit_const_arg(default);
                 }
             }
         }
@@ -1594,7 +1594,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     i += 1;
                 }
                 GenericArg::Const(ct) => {
-                    self.visit_anon_const(&ct.value);
+                    self.visit_const_arg(ct);
                     i += 1;
                 }
                 GenericArg::Infer(inf) => {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 974dd415f46..9affd654366 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -35,16 +35,32 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     let parent_node_id = tcx.parent_hir_id(hir_id);
     let parent_node = tcx.hir_node(parent_node_id);
 
-    let (generics, arg_idx) = match parent_node {
-        // Easy case: arrays repeat expressions.
-        Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
-        | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
-            if constant.hir_id() == hir_id =>
+    match parent_node {
+        // Anon consts "inside" the type system.
+        Node::ConstArg(&ConstArg {
+            hir_id: arg_hir_id,
+            kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
+            ..
+        }) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
+
+        // Anon consts outside the type system.
+        Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+        | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
+            if asm.operands.iter().any(|(op, _op_sp)| match op {
+                hir::InlineAsmOperand::Const { anon_const }
+                | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
+                _ => false,
+            }) =>
         {
-            return tcx.types.usize;
+            tcx.typeck(def_id).node_type(hir_id)
+        }
+        Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
+            tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
         }
+        // Sort of affects the type system, but only for the purpose of diagnostics
+        // so no need for ConstArg.
         Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
-            let ty = tcx.typeck(def_id).node_type(e.hir_id);
+            let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
             let ty = tcx.fold_regions(ty, |r, _| {
                 if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
             });
@@ -56,24 +72,35 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
             return ty;
         }
-        Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
-        | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
-            if asm.operands.iter().any(|(op, _op_sp)| match op {
-                hir::InlineAsmOperand::Const { anon_const }
-                | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
-                _ => false,
-            }) =>
+
+        _ => Ty::new_error_with_message(
+            tcx,
+            span,
+            format!("unexpected anon const parent in type_of(): {parent_node:?}"),
+        ),
+    }
+}
+
+fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
+    use hir::*;
+    use rustc_middle::ty::Ty;
+
+    let parent_node_id = tcx.parent_hir_id(arg_hir_id);
+    let parent_node = tcx.hir_node(parent_node_id);
+
+    let (generics, arg_idx) = match parent_node {
+        // Easy case: arrays repeat expressions.
+        Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
+        | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+            if constant.hir_id() == arg_hir_id =>
         {
-            return tcx.typeck(def_id).node_type(hir_id);
-        }
-        Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
-            return tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx);
+            return tcx.types.usize;
         }
         Node::GenericParam(&GenericParam {
             def_id: param_def_id,
             kind: GenericParamKind::Const { default: Some(ct), .. },
             ..
-        }) if ct.hir_id == hir_id => {
+        }) if ct.hir_id == arg_hir_id => {
             return tcx
                 .type_of(param_def_id)
                 .no_bound_vars()
@@ -104,7 +131,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
             let item_def_id = tcx
                 .hir()
-                .parent_owner_iter(hir_id)
+                .parent_owner_iter(arg_hir_id)
                 .find(|(_, node)| matches!(node, OwnerNode::Item(_)))
                 .unwrap()
                 .0
@@ -124,7 +151,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                         args.args
                             .iter()
                             .filter(|arg| arg.is_ty_or_const())
-                            .position(|arg| arg.hir_id() == hir_id)
+                            .position(|arg| arg.hir_id() == arg_hir_id)
                     })
                     .unwrap_or_else(|| {
                         bug!("no arg matching AnonConst in segment");
@@ -145,7 +172,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
             ..
         }) => {
-            let body_owner = tcx.hir().enclosing_body_owner(hir_id);
+            let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
             let tables = tcx.typeck(body_owner);
             // This may fail in case the method/path does not actually exist.
             // As there is no relevant param for `def_id`, we simply return
@@ -163,10 +190,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                     args.args
                         .iter()
                         .filter(|arg| arg.is_ty_or_const())
-                        .position(|arg| arg.hir_id() == hir_id)
+                        .position(|arg| arg.hir_id() == arg_hir_id)
                 })
                 .unwrap_or_else(|| {
-                    bug!("no arg matching AnonConst in segment");
+                    bug!("no arg matching ConstArg in segment");
                 });
 
             (tcx.generics_of(type_dependent_def), idx)
@@ -185,18 +212,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                         | ExprKind::Struct(&QPath::Resolved(_, path), ..),
                     ..
                 }) => {
-                    let body_owner = tcx.hir().enclosing_body_owner(hir_id);
+                    let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
                     let _tables = tcx.typeck(body_owner);
                     &*path
                 }
                 Node::Pat(pat) => {
-                    if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
+                    if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
                         path
                     } else {
                         return Ty::new_error_with_message(
                             tcx,
                             span,
-                            format!("unable to find const parent for {hir_id} in pat {pat:?}"),
+                            format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
                         );
                     }
                 }
@@ -217,14 +244,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 args.args
                     .iter()
                     .filter(|arg| arg.is_ty_or_const())
-                    .position(|arg| arg.hir_id() == hir_id)
+                    .position(|arg| arg.hir_id() == arg_hir_id)
                     .map(|index| (index, seg))
                     .or_else(|| {
                         args.constraints
                             .iter()
                             .copied()
                             .filter_map(AssocItemConstraint::ct)
-                            .position(|ct| ct.hir_id == hir_id)
+                            .position(|ct| ct.hir_id == arg_hir_id)
                             .map(|idx| (idx, seg))
                     })
             }) else {
@@ -249,7 +276,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             return Ty::new_error_with_message(
                 tcx,
                 span,
-                format!("unexpected const parent in type_of(): {parent_node:?}"),
+                format!("unexpected const arg parent in type_of(): {parent_node:?}"),
             );
         }
     };
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7f8aefd564d..c83788928a9 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1508,33 +1508,33 @@ pub struct StaticMutRef<'a> {
     #[label]
     pub span: Span,
     #[subdiagnostic]
-    pub sugg: StaticMutRefSugg,
+    pub sugg: MutRefSugg,
     pub shared: &'a str,
 }
 
 #[derive(Subdiagnostic)]
-pub enum StaticMutRefSugg {
-    #[suggestion(
+pub enum MutRefSugg {
+    #[multipart_suggestion(
         hir_analysis_suggestion,
         style = "verbose",
-        code = "addr_of!({var})",
         applicability = "maybe-incorrect"
     )]
     Shared {
-        #[primary_span]
-        span: Span,
-        var: String,
+        #[suggestion_part(code = "addr_of!(")]
+        lo: Span,
+        #[suggestion_part(code = ")")]
+        hi: Span,
     },
-    #[suggestion(
+    #[multipart_suggestion(
         hir_analysis_suggestion_mut,
         style = "verbose",
-        code = "addr_of_mut!({var})",
         applicability = "maybe-incorrect"
     )]
     Mut {
-        #[primary_span]
-        span: Span,
-        var: String,
+        #[suggestion_part(code = "addr_of_mut!(")]
+        lo: Span,
+        #[suggestion_part(code = ")")]
+        hi: Span,
     },
 }
 
@@ -1547,36 +1547,10 @@ pub struct RefOfMutStatic<'a> {
     #[label]
     pub span: Span,
     #[subdiagnostic]
-    pub sugg: RefOfMutStaticSugg,
+    pub sugg: MutRefSugg,
     pub shared: &'a str,
 }
 
-#[derive(Subdiagnostic)]
-pub enum RefOfMutStaticSugg {
-    #[suggestion(
-        hir_analysis_suggestion,
-        style = "verbose",
-        code = "addr_of!({var})",
-        applicability = "maybe-incorrect"
-    )]
-    Shared {
-        #[primary_span]
-        span: Span,
-        var: String,
-    },
-    #[suggestion(
-        hir_analysis_suggestion_mut,
-        style = "verbose",
-        code = "addr_of_mut!({var})",
-        applicability = "maybe-incorrect"
-    )]
-    Mut {
-        #[primary_span]
-        span: Span,
-        var: String,
-    },
-}
-
 #[derive(Diagnostic)]
 #[diag(hir_analysis_not_supported_delegation)]
 pub struct NotSupportedDelegation<'a> {
@@ -1605,12 +1579,29 @@ pub(crate) struct UnusedGenericParameter {
     pub span: Span,
     pub param_name: Ident,
     pub param_def_kind: &'static str,
+    #[label(hir_analysis_usage_spans)]
+    pub usage_spans: Vec<Span>,
     #[subdiagnostic]
     pub help: UnusedGenericParameterHelp,
     #[help(hir_analysis_const_param_help)]
     pub const_param_help: Option<()>,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_recursive_generic_parameter)]
+pub(crate) struct RecursiveGenericParameter {
+    #[primary_span]
+    pub spans: Vec<Span>,
+    #[label]
+    pub param_span: Span,
+    pub param_name: Ident,
+    pub param_def_kind: &'static str,
+    #[subdiagnostic]
+    pub help: UnusedGenericParameterHelp,
+    #[note]
+    pub note: (),
+}
+
 #[derive(Subdiagnostic)]
 pub(crate) enum UnusedGenericParameterHelp {
     #[help(hir_analysis_unused_generic_parameter_adt_help)]
@@ -1622,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 {
@@ -1690,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/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index a1feef9e15b..6f9c481650b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -413,12 +413,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             });
 
             // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
-            if let Some(anon_const) = constraint.ct() {
-                let ty = alias_term
-                    .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
-                let ty =
-                    check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
-                tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
+            if let Some(const_arg) = constraint.ct() {
+                if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
+                    let ty = alias_term
+                        .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
+                    let ty = check_assoc_const_binding_type(
+                        self,
+                        constraint.ident,
+                        ty,
+                        constraint.hir_id,
+                    );
+                    tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
+                }
             }
 
             alias_term
@@ -435,7 +441,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::AssocItemConstraintKind::Equality { term } => {
                 let term = match term {
                     hir::Term::Ty(ty) => self.lower_ty(ty).into(),
-                    hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
+                    hir::Term::Const(ct) => {
+                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
+                    }
                 };
 
                 // Find any late-bound regions declared in `ty` that are not
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/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5e595488ea7..8ff6ced8b39 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -340,7 +340,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         {
             let span = match term {
                 hir::Term::Ty(ty) => ty.span,
-                hir::Term::Const(ct) => tcx.def_span(ct.def_id),
+                hir::Term::Const(ct) => ct.span(),
             };
             (span, Some(ident.span), assoc_item.kind, assoc_kind)
         } else {
@@ -1257,14 +1257,12 @@ pub fn prohibit_assoc_item_constraint(
             };
 
             // Now emit the suggestion
-            if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
-                e.span_suggestion_verbose(
-                    removal_span,
-                    format!("consider removing this associated item {}", constraint.kind.descr()),
-                    suggestion,
-                    Applicability::MaybeIncorrect,
-                );
-            }
+            e.span_suggestion_verbose(
+                removal_span,
+                format!("consider removing this associated item {}", constraint.kind.descr()),
+                "",
+                Applicability::MaybeIncorrect,
+            );
         };
 
         // Suggest replacing the associated item binding with a generic argument.
@@ -1296,8 +1294,7 @@ pub fn prohibit_assoc_item_constraint(
                     hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
                     GenericParamDefKind::Const { .. },
                 ) => {
-                    let span = tcx.hir().span(c.hir_id);
-                    suggest_direct_use(&mut err, span);
+                    suggest_direct_use(&mut err, c.span());
                 }
                 (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
                     // Suggest `impl<T: Bound> Trait<T> for Foo` when finding
@@ -1340,11 +1337,13 @@ pub fn prohibit_assoc_item_constraint(
                                 format!("<{lifetimes}{type_with_constraints}>"),
                             )
                         };
-                        let suggestions =
-                            vec![param_decl, (constraint.span, format!("{}", matching_param.name))];
+                        let suggestions = vec![
+                            param_decl,
+                            (constraint.span.with_lo(constraint.ident.span.hi()), String::new()),
+                        ];
 
                         err.multipart_suggestion_verbose(
-                            format!("declare the type parameter right after the `impl` keyword"),
+                            "declare the type parameter right after the `impl` keyword",
                             suggestions,
                             Applicability::MaybeIncorrect,
                         );
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index b1c77db9f37..abe2cff321f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -113,8 +113,12 @@ fn generic_arg_mismatch_err(
             }
         }
         (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
-            let body = tcx.hir().body(cnst.value.body);
-            if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
+            // FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
+            // this should match against that instead of ::Anon
+            if let hir::ConstArgKind::Anon(anon) = cnst.kind
+                && let body = tcx.hir().body(anon.body)
+                && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
+                    body.value.kind
             {
                 if let Res::Def(DefKind::Fn { .. }, id) = path.res {
                     err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a665306f2c6..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;
@@ -471,11 +472,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         handle_ty_args(has_default, &inf.to_ty())
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
-                        let did = ct.value.def_id;
-                        tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
-                        ty::Const::from_anon_const(tcx, did).into()
+                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
+                            .into()
                     }
-                    (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
+                    (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
                         self.lowerer.ct_infer(Some(param), inf.span).into()
                     }
                     (kind, arg) => span_bug!(
@@ -912,7 +912,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 let term: ty::Term<'_> = match term {
                                     hir::Term::Ty(ty) => self.lower_ty(ty).into(),
                                     hir::Term::Const(ct) => {
-                                        ty::Const::from_anon_const(tcx, ct.def_id).into()
+                                        ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
+                                            .into()
                                     }
                                 };
                                 // FIXME(#97583): This isn't syntactically well-formed!
@@ -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(
@@ -2140,7 +2195,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let length = match length {
                     hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
                     hir::ArrayLen::Body(constant) => {
-                        ty::Const::from_anon_const(tcx, constant.def_id)
+                        ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
                     }
                 };
 
@@ -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/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_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 5105d60ae18..db5eba0d9eb 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -12,8 +12,9 @@ use rustc_ast_pretty::pp::{self, Breaks};
 use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_hir as hir;
 use rustc_hir::{
-    BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
-    LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier,
+    BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
+    HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
+    TraitBoundModifier,
 };
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -87,6 +88,7 @@ impl<'a> State<'a> {
             Node::Variant(a) => self.print_variant(a),
             Node::AnonConst(a) => self.print_anon_const(a),
             Node::ConstBlock(a) => self.print_inline_const(a),
+            Node::ConstArg(a) => self.print_const_arg(a),
             Node::Expr(a) => self.print_expr(a),
             Node::ExprField(a) => self.print_expr_field(a),
             Node::Stmt(a) => self.print_stmt(a),
@@ -983,7 +985,7 @@ impl<'a> State<'a> {
     fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) {
         match len {
             hir::ArrayLen::Infer(..) => self.word("_"),
-            hir::ArrayLen::Body(ct) => self.print_anon_const(ct),
+            hir::ArrayLen::Body(ct) => self.print_const_arg(ct),
         }
     }
 
@@ -991,6 +993,13 @@ impl<'a> State<'a> {
         self.ann.nested(self, Nested::Body(constant.body))
     }
 
+    fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
+        match &const_arg.kind {
+            ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
+            ConstArgKind::Anon(anon) => self.print_anon_const(anon),
+        }
+    }
+
     fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
         self.popen();
         self.commasep_exprs(Inconsistent, args);
@@ -1679,7 +1688,7 @@ impl<'a> State<'a> {
                             GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
                             GenericArg::Lifetime(_) => {}
                             GenericArg::Type(ty) => s.print_type(ty),
-                            GenericArg::Const(ct) => s.print_anon_const(&ct.value),
+                            GenericArg::Const(ct) => s.print_const_arg(ct),
                             GenericArg::Infer(_inf) => s.word("_"),
                         }
                     });
@@ -1720,7 +1729,7 @@ impl<'a> State<'a> {
                 self.word_space("=");
                 match term {
                     Term::Ty(ty) => self.print_type(ty),
-                    Term::Const(ref c) => self.print_anon_const(c),
+                    Term::Const(ref c) => self.print_const_arg(c),
                 }
             }
             hir::AssocItemConstraintKind::Bound { bounds } => {
@@ -2155,7 +2164,7 @@ impl<'a> State<'a> {
                 if let Some(default) = default {
                     self.space();
                     self.word_space("=");
-                    self.print_anon_const(default);
+                    self.print_const_arg(default);
                 }
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 035a3429ed7..d708269f1f5 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -519,7 +519,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)
             }
             _ => {
@@ -1439,9 +1447,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         };
         if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
-            && let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length
+            && let hir::ArrayLen::Body(ct) = length
         {
-            let span = self.tcx.hir().span(hir_id);
+            let span = ct.span();
             self.dcx().try_steal_modify_and_emit_err(
                 span,
                 StashKey::UnderscoreForArrayLengths,
@@ -2210,8 +2218,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 +2230,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,
                     );
                 }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6da3f1dd114..cc2c1a302f5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -457,22 +457,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
         match length {
             hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
-            hir::ArrayLen::Body(anon_const) => {
-                let span = self.tcx.def_span(anon_const.def_id);
-                let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
+            hir::ArrayLen::Body(const_arg) => {
+                let span = const_arg.span();
+                let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
                 self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
                 self.normalize(span, c)
             }
         }
     }
 
-    pub fn lower_const_arg(&self, hir_ct: &hir::AnonConst, param_def_id: DefId) -> ty::Const<'tcx> {
-        let did = hir_ct.def_id;
-        self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
-        let ct = ty::Const::from_anon_const(self.tcx, did);
+    pub fn lower_const_arg(
+        &self,
+        const_arg: &'tcx hir::ConstArg<'tcx>,
+        param_def_id: DefId,
+    ) -> ty::Const<'tcx> {
+        let ct =
+            ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
         self.register_wf_obligation(
             ct.into(),
-            self.tcx.hir().span(hir_ct.hir_id),
+            self.tcx.hir().span(const_arg.hir_id),
             ObligationCauseCode::WellFormed(None),
         );
         ct
@@ -1298,7 +1301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.fcx.lower_ty(ty).raw.into()
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
-                        self.fcx.lower_const_arg(&ct.value, param.def_id).into()
+                        self.fcx.lower_const_arg(ct, param.def_id).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
                         self.fcx.ty_infer(Some(param), inf.span).into()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index b6b1bf34653..2b4025ca808 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1105,7 +1105,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     } else {
                         "".to_string()
                     };
-                    labels.push((provided_span, format!("unexpected argument{provided_ty_name}")));
+                    let idx = if provided_arg_tys.len() == 1 {
+                        "".to_string()
+                    } else {
+                        format!(" #{}", arg_idx.as_usize() + 1)
+                    };
+                    labels.push((
+                        provided_span,
+                        format!("unexpected argument{idx}{provided_ty_name}"),
+                    ));
                     let mut span = provided_span;
                     if span.can_be_used_for_suggestions()
                         && error_span.can_be_used_for_suggestions()
@@ -1186,7 +1194,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             } else {
                                 "".to_string()
                             };
-                            labels.push((span, format!("an argument{rendered} is missing")));
+                            labels.push((
+                                span,
+                                format!(
+                                    "argument #{}{rendered} is missing",
+                                    expected_idx.as_usize() + 1
+                                ),
+                            ));
+
                             suggestion_text = match suggestion_text {
                                 SuggestionText::None => SuggestionText::Provide(false),
                                 SuggestionText::Provide(_) => SuggestionText::Provide(true),
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/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index e574fde14fb..e70431a68ff 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -400,7 +400,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                         self.cfcx.lower_ty(ty).raw.into()
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
-                        self.cfcx.lower_const_arg(&ct.value, param.def_id).into()
+                        self.cfcx.lower_const_arg(ct, param.def_id).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
                         self.cfcx.ty_infer(Some(param), inf.span).into()
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 425289ce3c5..9bb30780a6e 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1265,9 +1265,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 +1596,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,
                 );
             }
         }
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_index/Cargo.toml b/compiler/rustc_index/Cargo.toml
index 3a4c813b5d4..92ea3f278dc 100644
--- a/compiler/rustc_index/Cargo.toml
+++ b/compiler/rustc_index/Cargo.toml
@@ -15,5 +15,9 @@ smallvec = "1.8.1"
 [features]
 # tidy-alphabetical-start
 default = ["nightly"]
-nightly = ["rustc_serialize", "rustc_macros", "rustc_index_macros/nightly"]
+nightly = [
+    "dep:rustc_serialize",
+    "dep:rustc_macros",
+    "rustc_index_macros/nightly",
+]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index b866c8b8433..346ce945bf9 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -1,4 +1,4 @@
-#[cfg(feature = "rustc_serialize")]
+#[cfg(feature = "nightly")]
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use std::borrow::{Borrow, BorrowMut};
@@ -322,14 +322,14 @@ impl<I: Idx, T, const N: usize> From<[T; N]> for IndexVec<I, T> {
     }
 }
 
-#[cfg(feature = "rustc_serialize")]
+#[cfg(feature = "nightly")]
 impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
     fn encode(&self, s: &mut S) {
         Encodable::encode(&self.raw, s);
     }
 }
 
-#[cfg(feature = "rustc_serialize")]
+#[cfg(feature = "nightly")]
 impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
     fn decode(d: &mut D) -> Self {
         IndexVec::from_raw(Vec::<T>::decode(d))
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 7a5e7159920..c279195a7e9 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -225,6 +225,8 @@ infer_outlives_content = lifetime of reference outlives lifetime of borrowed con
 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)
@@ -387,6 +389,9 @@ infer_type_annotations_needed = {$source_kind ->
     .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/infer/mod.rs b/compiler/rustc_infer/src/error_reporting/infer/mod.rs
index ddd5818203c..9998fbca056 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_infer/src/error_reporting/infer/mod.rs
@@ -1762,9 +1762,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         };
         if let Some(tykind) = tykind
             && let hir::TyKind::Array(_, length) = tykind
-            && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
+            && let hir::ArrayLen::Body(ct) = length
         {
-            let span = self.tcx.hir().span(*hir_id);
+            let span = ct.span();
             Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
         } else {
             None
@@ -1930,14 +1930,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.0.tcx
     }
 
-    fn tag(&self) -> &'static str {
-        "SameTypeModuloInfer"
-    }
-
     fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
         &mut self,
         _variance: ty::Variance,
diff --git a/compiler/rustc_infer/src/error_reporting/infer/region.rs b/compiler/rustc_infer/src/error_reporting/infer/region.rs
index 093d2d3d743..5d41bb5d271 100644
--- a/compiler/rustc_infer/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_infer/src/error_reporting/infer/region.rs
@@ -1269,9 +1269,13 @@ fn suggest_precise_capturing<'tcx>(
     captured_lifetime: ty::Region<'tcx>,
     diag: &mut Diag<'_>,
 ) {
-    let hir::OpaqueTy { bounds, .. } =
+    let hir::OpaqueTy { bounds, origin, .. } =
         tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
 
+    let hir::OpaqueTyOrigin::FnReturn(fn_def_id) = *origin else {
+        return;
+    };
+
     let new_lifetime = Symbol::intern(&captured_lifetime.to_string());
 
     if let Some((args, span)) = bounds.iter().find_map(|bound| match bound {
@@ -1306,6 +1310,7 @@ fn suggest_precise_capturing<'tcx>(
 
         let variances = tcx.variances_of(opaque_def_id);
         let mut generics = tcx.generics_of(opaque_def_id);
+        let mut synthetics = vec![];
         loop {
             for param in &generics.own_params {
                 if variances[param.index as usize] == ty::Bivariant {
@@ -1317,9 +1322,7 @@ fn suggest_precise_capturing<'tcx>(
                         captured_lifetimes.insert(param.name);
                     }
                     ty::GenericParamDefKind::Type { synthetic: true, .. } => {
-                        // FIXME: We can't provide a good suggestion for
-                        // `use<...>` if we have an APIT. Bail for now.
-                        return;
+                        synthetics.push((tcx.def_span(param.def_id), param.name));
                     }
                     ty::GenericParamDefKind::Type { .. }
                     | ty::GenericParamDefKind::Const { .. } => {
@@ -1340,17 +1343,86 @@ fn suggest_precise_capturing<'tcx>(
             return;
         }
 
-        let concatenated_bounds = captured_lifetimes
-            .into_iter()
-            .chain(captured_non_lifetimes)
-            .map(|sym| sym.to_string())
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        diag.subdiagnostic(errors::AddPreciseCapturing::New {
-            span: tcx.def_span(opaque_def_id).shrink_to_hi(),
-            new_lifetime,
-            concatenated_bounds,
-        });
+        if synthetics.is_empty() {
+            let concatenated_bounds = captured_lifetimes
+                .into_iter()
+                .chain(captured_non_lifetimes)
+                .map(|sym| sym.to_string())
+                .collect::<Vec<_>>()
+                .join(", ");
+
+            diag.subdiagnostic(errors::AddPreciseCapturing::New {
+                span: tcx.def_span(opaque_def_id).shrink_to_hi(),
+                new_lifetime,
+                concatenated_bounds,
+            });
+        } else {
+            let mut next_fresh_param = || {
+                ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
+                    .into_iter()
+                    .map(Symbol::intern)
+                    .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
+                    .find(|s| captured_non_lifetimes.insert(*s))
+                    .unwrap()
+            };
+
+            let mut new_params = String::new();
+            let mut suggs = vec![];
+            let mut apit_spans = vec![];
+
+            for (i, (span, name)) in synthetics.into_iter().enumerate() {
+                apit_spans.push(span);
+
+                let fresh_param = next_fresh_param();
+
+                // Suggest renaming.
+                suggs.push((span, fresh_param.to_string()));
+
+                // Super jank. Turn `impl Trait` into `T: Trait`.
+                //
+                // This currently involves stripping the `impl` from the name of
+                // the parameter, since APITs are always named after how they are
+                // rendered in the AST. This sucks! But to recreate the bound list
+                // from the APIT itself would be miserable, so we're stuck with
+                // this for now!
+                if i > 0 {
+                    new_params += ", ";
+                }
+                let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
+                new_params += fresh_param.as_str();
+                new_params += ": ";
+                new_params += name_as_bounds;
+            }
+
+            let Some(generics) = tcx.hir().get_generics(fn_def_id) else {
+                // This shouldn't happen, but don't ICE.
+                return;
+            };
+
+            // Add generics or concatenate to the end of the list.
+            suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
+                (params_span, format!(", {new_params}"))
+            } else {
+                (generics.span, format!("<{new_params}>"))
+            });
+
+            let concatenated_bounds = captured_lifetimes
+                .into_iter()
+                .chain(captured_non_lifetimes)
+                .map(|sym| sym.to_string())
+                .collect::<Vec<_>>()
+                .join(", ");
+
+            suggs.push((
+                tcx.def_span(opaque_def_id).shrink_to_hi(),
+                format!(" + use<{concatenated_bounds}>"),
+            ));
+
+            diag.subdiagnostic(errors::AddPreciseCapturingAndParams {
+                suggs,
+                new_lifetime,
+                apit_spans,
+            });
+        }
     }
 }
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index f849a1a7322..2ce712e0bff 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1609,3 +1609,25 @@ pub enum AddPreciseCapturing {
         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 cfef1f13015..c9073d8c23e 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1427,17 +1427,17 @@ impl<'tcx> InferCtxt<'tcx> {
         span: Span,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
         match self.const_eval_resolve(param_env, unevaluated, span) {
-            Ok(Some(val)) => Ok(ty::Const::new_value(
+            Ok(Ok(val)) => Ok(ty::Const::new_value(
                 self.tcx,
                 val,
                 self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
             )),
-            Ok(None) => {
+            Ok(Err(bad_ty)) => {
                 let tcx = self.tcx;
                 let def_id = unevaluated.def;
                 span_bug!(
                     tcx.def_span(def_id),
-                    "unable to construct a constant value for the unevaluated constant {:?}",
+                    "unable to construct a valtree for the unevaluated constant {:?}: type {bad_ty} is not valtree-compatible",
                     unevaluated
                 );
             }
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 978b92fd898..c63eeaf812c 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -110,7 +110,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
 
     /// Binds the pattern variable `br` to `value`; returns an `Err` if the pattern
     /// is already bound to a different value.
-    #[instrument(level = "debug", skip(self))]
+    #[instrument(level = "trace", skip(self))]
     fn bind(
         &mut self,
         br: ty::BoundRegion,
@@ -133,11 +133,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx> {
-    fn tag(&self) -> &'static str {
-        "MatchAgainstHigherRankedOutlives"
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
@@ -154,13 +150,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
         if variance != ty::Bivariant { self.relate(a, b) } else { Ok(a) }
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn regions(
         &mut self,
         pattern: ty::Region<'tcx>,
         value: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("self.pattern_depth = {:?}", self.pattern_depth);
         if let ty::RegionKind::ReBound(depth, br) = pattern.kind()
             && depth == self.pattern_depth
         {
@@ -172,7 +167,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
         }
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn tys(&mut self, pattern: Ty<'tcx>, value: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         // FIXME(non_lifetime_binders): What to do here?
         if matches!(pattern.kind(), ty::Error(_) | ty::Bound(..)) {
@@ -185,13 +180,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
         }
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn consts(
         &mut self,
         pattern: ty::Const<'tcx>,
         value: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        debug!("{}.consts({:?}, {:?})", self.tag(), pattern, value);
         if pattern == value {
             Ok(pattern)
         } else {
@@ -199,6 +193,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
         }
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn binders<T>(
         &mut self,
         pattern: ty::Binder<'tcx, T>,
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index c93b89756f9..1dc03de4c8b 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -79,6 +79,7 @@ impl<'tcx> InferCtxt<'tcx> {
     where
         R: PredicateEmittingRelation<InferCtxt<'tcx>>,
     {
+        debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
         debug_assert!(!a.has_escaping_bound_vars());
         debug_assert!(!b.has_escaping_bound_vars());
 
@@ -174,9 +175,10 @@ impl<'tcx> InferCtxt<'tcx> {
     where
         R: PredicateEmittingRelation<InferCtxt<'tcx>>,
     {
-        debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
+        debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
         debug_assert!(!a.has_escaping_bound_vars());
         debug_assert!(!b.has_escaping_bound_vars());
+
         if a == b {
             return Ok(a);
         }
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index fe3b8d60fb9..30cfbcae6b2 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -372,7 +372,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
 
         let is_nested_alias = mem::replace(&mut self.in_alias, true);
         let result = match self.relate(alias, alias) {
-            Ok(alias) => Ok(alias.to_ty(self.tcx())),
+            Ok(alias) => Ok(alias.to_ty(self.cx())),
             Err(e) => {
                 if is_nested_alias {
                     return Err(e);
@@ -397,14 +397,10 @@ impl<'tcx> Generalizer<'_, 'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
-    fn tag(&self) -> &'static str {
-        "Generalizer"
-    }
-
     fn relate_item_args(
         &mut self,
         item_def_id: DefId,
@@ -417,7 +413,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
             // (e.g., #41849).
             relate::relate_args_invariantly(self, a_arg, b_arg)
         } else {
-            let tcx = self.tcx();
+            let tcx = self.cx();
             let opt_variances = tcx.variances_of(item_def_id);
             relate::relate_args_with_variances(
                 self,
@@ -525,7 +521,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                             }
 
                             debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
-                            Ok(Ty::new_var(self.tcx(), new_var_id))
+                            Ok(Ty::new_var(self.cx(), new_var_id))
                         }
                     }
                 }
@@ -654,7 +650,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                             {
                                 variable_table.union(vid, new_var_id);
                             }
-                            Ok(ty::Const::new_var(self.tcx(), new_var_id))
+                            Ok(ty::Const::new_var(self.cx(), new_var_id))
                         }
                     }
                 }
@@ -672,7 +668,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
                     args,
                     args,
                 )?;
-                Ok(ty::Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst { def, args }))
+                Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
             }
             ty::ConstKind::Placeholder(placeholder) => {
                 if self.for_universe.can_name(placeholder.universe) {
diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
index 5bb8a113e17..4f2cf2c43e7 100644
--- a/compiler/rustc_infer/src/infer/relate/glb.rs
+++ b/compiler/rustc_infer/src/infer/relate/glb.rs
@@ -23,11 +23,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
-    fn tag(&self) -> &'static str {
-        "Glb"
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
 
@@ -47,27 +43,28 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         lattice::super_lattice_tys(self, a, b)
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
-
         let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
         // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
         Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
-            self.tcx(),
+            self.cx(),
             origin,
             a,
             b,
         ))
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn consts(
         &mut self,
         a: ty::Const<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 46e7466141a..d1d87071562 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -56,8 +56,6 @@ pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
 where
     L: LatticeDir<'a, 'tcx>,
 {
-    debug!("{}", this.tag());
-
     if a == b {
         return Ok(a);
     }
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index 94c1464817f..2eb20f311cf 100644
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -23,11 +23,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
-    fn tag(&self) -> &'static str {
-        "Lub"
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.fields.tcx()
     }
 
@@ -51,23 +47,23 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
         lattice::super_lattice_tys(self, a, b)
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
-
         let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
         // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
         Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
-            self.tcx(),
+            self.cx(),
             origin,
             a,
             b,
         ))
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn consts(
         &mut self,
         a: ty::Const<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index e206f530519..3fe35354286 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -28,11 +28,7 @@ impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
-    fn tag(&self) -> &'static str {
-        "TypeRelating"
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.fields.infcx.tcx
     }
 
@@ -48,7 +44,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
             // (e.g., #41849).
             relate_args_invariantly(self, a_arg, b_arg)
         } else {
-            let tcx = self.tcx();
+            let tcx = self.cx();
             let opt_variances = tcx.variances_of(item_def_id);
             relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, false)
         }
@@ -71,7 +67,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         r
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         if a == b {
             return Ok(a);
@@ -88,7 +84,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
                         // can't make progress on `A <: B` if both A and B are
                         // type variables, so record an obligation.
                         self.fields.goals.push(Goal::new(
-                            self.tcx(),
+                            self.cx(),
                             self.fields.param_env,
                             ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                 a_is_expected: true,
@@ -101,7 +97,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
                         // can't make progress on `B <: A` if both A and B are
                         // type variables, so record an obligation.
                         self.fields.goals.push(Goal::new(
-                            self.tcx(),
+                            self.cx(),
                             self.fields.param_env,
                             ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                 a_is_expected: false,
@@ -134,7 +130,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
 
             (&ty::Error(e), _) | (_, &ty::Error(e)) => {
                 infcx.set_tainted_by_errors(e);
-                return Ok(Ty::new_error(self.tcx(), e));
+                return Ok(Ty::new_error(self.cx(), e));
             }
 
             (
@@ -166,12 +162,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         Ok(a)
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
         let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
 
         match self.ambient_variance {
@@ -209,6 +205,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         Ok(a)
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn consts(
         &mut self,
         a: ty::Const<'tcx>,
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 4b3b0728f38..b5abf145d6b 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -53,6 +53,11 @@ tracing = "0.1"
 
 [features]
 # tidy-alphabetical-start
-llvm = ['rustc_codegen_llvm']
-rustc_use_parallel_compiler = ['rustc-rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
+llvm = ['dep:rustc_codegen_llvm']
+rustc_use_parallel_compiler = [
+    'dep:rustc-rayon',
+    'dep:rustc-rayon-core',
+    'rustc_query_impl/rustc_use_parallel_compiler',
+    'rustc_errors/rustc_use_parallel_compiler'
+]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index de04d882f51..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
@@ -556,6 +557,9 @@ lint_non_fmt_panic_unused =
     }
     .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally
 
+lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inherent`
+    .suggestion = try using a glob import instead
+
 lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`
 
 lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
diff --git a/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/internal.rs b/compiler/rustc_lint/src/internal.rs
index 772cc2ff8b9..e15eb90f827 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -3,7 +3,8 @@
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
-    QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
+    NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
+    TykindKind, UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
@@ -264,6 +265,49 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
 }
 
 declare_tool_lint! {
+    /// The `non_glob_import_of_type_ir_inherent_item` lint detects
+    /// non-glob imports of module `rustc_type_ir::inherent`.
+    pub rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
+    Allow,
+    "non-glob import of `rustc_type_ir::inherent`",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT]);
+
+impl<'tcx> LateLintPass<'tcx> for TypeIr {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
+
+        let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
+        let (lo, hi, snippet) = match path.segments {
+            [.., penultimate, segment]
+                if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>
+            {
+                (segment.ident.span, item.ident.span, "*")
+            }
+            [.., segment]
+                if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent)
+                    && let rustc_hir::UseKind::Single = kind =>
+            {
+                let (lo, snippet) =
+                    match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() {
+                        Ok("self") => (path.span, "*"),
+                        _ => (segment.ident.span.shrink_to_hi(), "::*"),
+                    };
+                (lo, if segment.ident == item.ident { lo } else { item.ident.span }, snippet)
+            }
+            _ => return,
+        };
+        cx.emit_span_lint(
+            NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
+            path.span,
+            NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet },
+        );
+    }
+}
+
+declare_tool_lint! {
     /// The `lint_pass_impl_without_macro` detects manual implementations of a lint
     /// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
     pub rustc::LINT_PASS_IMPL_WITHOUT_MACRO,
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4e83ef0c629..290f91045c4 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -572,6 +572,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
     store.register_lints(&TyTyKind::get_lints());
     store.register_late_mod_pass(|_| Box::new(TyTyKind));
+    store.register_lints(&TypeIr::get_lints());
+    store.register_late_mod_pass(|_| Box::new(TypeIr));
     store.register_lints(&Diagnostics::get_lints());
     store.register_late_mod_pass(|_| Box::new(Diagnostics));
     store.register_lints(&BadOptAccess::get_lints());
@@ -595,6 +597,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(PASS_BY_VALUE),
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(USAGE_OF_QUALIFIED_TY),
+            LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
             LintId::of(EXISTING_DOC_KEYWORD),
             LintId::of(BAD_OPT_ACCESS),
             LintId::of(SPAN_USE_EQ_CTXT),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 308bb73f4ce..6c5f366727f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -927,6 +927,14 @@ pub struct TyQualified {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_non_glob_import_type_ir_inherent)]
+pub struct NonGlobImportTypeIrInherent {
+    #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
+    pub suggestion: Option<Span>,
+    pub snippet: &'static str,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_lintpass_by_hand)]
 #[help]
 pub struct LintPassByHand;
@@ -2066,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/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index c1f5cd45dc8..fa23f120468 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
                     .tcx
                     .sess
                     .source_map()
-                    .span_to_snippet(c.value.span)
+                    .span_to_snippet(c.span())
                     .unwrap_or_else(|_| "_".into()),
                 GenericArg::Infer(_) => String::from("_"),
             })
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index aa7844f4012..04764b71b10 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1203,16 +1203,16 @@ declare_lint! {
     /// This was historically allowed, but is not the intended behavior
     /// according to the visibility rules. This is a [future-incompatible]
     /// lint to transition this to a hard error in the future. See [issue
-    /// #34537] for more details.
+    /// #127909] for more details.
     ///
-    /// [issue #34537]: https://github.com/rust-lang/rust/issues/34537
+    /// [issue #127909]: https://github.com/rust-lang/rust/issues/127909
     /// [future-incompatible]: ../index.md#future-incompatible-lints
     pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     Deny,
     "detect public re-exports of private extern crates",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #127909 <https://github.com/rust-lang/rust/issues/127909>",
     };
 }
 
diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs
index d41ceb29816..627f4088d5f 100644
--- a/compiler/rustc_macros/src/lift.rs
+++ b/compiler/rustc_macros/src/lift.rs
@@ -45,7 +45,7 @@ pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStre
         quote! {
             type Lifted = #lifted;
 
-            fn lift_to_tcx(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
+            fn lift_to_interner(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
                 Some(match self { #body })
             }
         },
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..8596a0645e4 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1496,6 +1496,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)
@@ -1635,6 +1636,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 +1644,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;
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/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 3dc592980fd..290ebde8712 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -40,5 +40,5 @@ tracing = "0.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["rustc-rayon-core"]
+rustc_use_parallel_compiler = ["dep:rustc-rayon-core"]
 # tidy-alphabetical-end
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 2f3a6ee601b..ad59bfa9047 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -912,6 +912,7 @@ impl<'hir> Map<'hir> {
             Node::Field(field) => field.span,
             Node::AnonConst(constant) => constant.span,
             Node::ConstBlock(constant) => self.body(constant.body).value.span,
+            Node::ConstArg(const_arg) => const_arg.span(),
             Node::Expr(expr) => expr.span,
             Node::ExprField(field) => field.span,
             Node::Stmt(stmt) => stmt.span,
@@ -962,7 +963,8 @@ impl<'hir> Map<'hir> {
     /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
     /// called with the HirId for the `{ ... }` anon const
     pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
-        match self.tcx.parent_hir_node(anon_const) {
+        let const_arg = self.tcx.parent_hir_id(anon_const);
+        match self.tcx.parent_hir_node(const_arg) {
             Node::GenericParam(GenericParam {
                 def_id: param_id,
                 kind: GenericParamKind::Const { .. },
@@ -1182,6 +1184,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         }
         Node::AnonConst(_) => node_str("const"),
         Node::ConstBlock(_) => node_str("const"),
+        Node::ConstArg(_) => node_str("const"),
         Node::Expr(_) => node_str("expr"),
         Node::ExprField(_) => node_str("expr field"),
         Node::Stmt(_) => node_str("stmt"),
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/macros.rs b/compiler/rustc_middle/src/macros.rs
index fcea1ea81a7..d385be007d3 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -59,7 +59,7 @@ macro_rules! TrivialLiftImpls {
         $(
             impl<'tcx> $crate::ty::Lift<$crate::ty::TyCtxt<'tcx>> for $ty {
                 type Lifted = Self;
-                fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
+                fn lift_to_interner(self, _: $crate::ty::TyCtxt<'tcx>) -> Option<Self> {
                     Some(self)
                 }
             }
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/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 6a8498abaf9..9df19565ab3 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -90,9 +90,11 @@ TrivialTypeTraversalImpls! { ErrorHandled }
 pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
 pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
 pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
-/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
-/// This is needed in `thir::pattern::lower_inline_const`.
-pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
+/// `Ok(Err(ty))` indicates the constant was fine, but the valtree couldn't be constructed
+/// because the value containts something of type `ty` that is not valtree-compatible.
+/// The caller can then show an appropriate error; the query does not have the
+/// necssary context to give good user-facing errors for this case.
+pub type EvalToValTreeResult<'tcx> = Result<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>;
 
 #[cfg(target_pointer_width = "64")]
 rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8);
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 301c9911b44..d9fa5b02f7f 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -157,9 +157,10 @@ impl EraseType for Result<mir::ConstValue<'_>, mir::interpret::ErrorHandled> {
     type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()];
 }
 
-impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> {
-    type Result =
-        [u8; size_of::<Result<Option<ty::ValTree<'static>>, mir::interpret::ErrorHandled>>()];
+impl EraseType for Result<Result<ty::ValTree<'_>, Ty<'_>>, mir::interpret::ErrorHandled> {
+    type Result = [u8; size_of::<
+        Result<Result<ty::ValTree<'static>, Ty<'static>>, mir::interpret::ErrorHandled>,
+    >()];
 }
 
 impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
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/thir.rs b/compiler/rustc_middle/src/thir.rs
index c97af68c29e..b80d00719ee 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -783,16 +783,13 @@ pub enum PatKind<'tcx> {
     },
 
     /// One of the following:
-    /// * `&str` (represented as a valtree), which will be handled as a string pattern and thus
-    ///   exhaustiveness checking will detect if you use the same string twice in different
-    ///   patterns.
+    /// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern
+    ///   and thus exhaustiveness checking will detect if you use the same string/slice twice in
+    ///   different patterns.
     /// * integer, bool, char or float (represented as a valtree), which will be handled by
     ///   exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
     ///   much simpler.
-    /// * Opaque constants (represented as `mir::ConstValue`), that must not be matched
-    ///   structurally. So anything that does not derive `PartialEq` and `Eq`.
-    ///
-    /// These are always compared with the matched place using (the semantics of) `PartialEq`.
+    /// * `String`, if `string_deref_patterns` is enabled.
     Constant {
         value: mir::Const<'tcx>,
     },
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 32d01d07c17..5cf1247f0c8 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,11 +1,12 @@
 use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
 use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+use either::Either;
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
-use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, HirId};
 use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, instrument};
@@ -182,16 +183,55 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
     }
 }
 
+/// In some cases, [`hir::ConstArg`]s that are being used in the type system
+/// through const generics need to have their type "fed" to them
+/// using the query system.
+///
+/// Use this enum with [`Const::from_const_arg`] to instruct it with the
+/// desired behavior.
+#[derive(Debug, Clone, Copy)]
+pub enum FeedConstTy {
+    /// Feed the type.
+    ///
+    /// The `DefId` belongs to the const param that we are supplying
+    /// this (anon) const arg to.
+    Param(DefId),
+    /// Don't feed the type.
+    No,
+}
+
 impl<'tcx> Const<'tcx> {
+    /// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
+    #[instrument(skip(tcx), level = "debug")]
+    pub fn from_const_arg(
+        tcx: TyCtxt<'tcx>,
+        const_arg: &'tcx hir::ConstArg<'tcx>,
+        feed: FeedConstTy,
+    ) -> Self {
+        if let FeedConstTy::Param(param_def_id) = feed
+            && let hir::ConstArgKind::Anon(anon) = &const_arg.kind
+        {
+            tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
+        }
+
+        match const_arg.kind {
+            hir::ConstArgKind::Path(qpath) => {
+                // FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
+                Self::from_param(tcx, qpath, const_arg.hir_id)
+            }
+            hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
+        }
+    }
+
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
     /// becomes `Unevaluated`.
     #[instrument(skip(tcx), level = "debug")]
     pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
         let body_id = match tcx.hir_node_by_def_id(def) {
             hir::Node::AnonConst(ac) => ac.body,
-            _ => span_bug!(
+            node => span_bug!(
                 tcx.def_span(def.to_def_id()),
-                "from_anon_const can only process anonymous constants"
+                "from_anon_const can only process anonymous constants, not {node:?}"
             ),
         };
 
@@ -200,7 +240,7 @@ impl<'tcx> Const<'tcx> {
 
         let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
 
-        match Self::try_from_lit_or_param(tcx, ty, expr) {
+        match Self::try_from_lit(tcx, ty, expr) {
             Some(v) => v,
             None => ty::Const::new_unevaluated(
                 tcx,
@@ -212,12 +252,36 @@ impl<'tcx> Const<'tcx> {
         }
     }
 
+    /// Lower a const param to a [`Const`].
+    ///
+    /// IMPORTANT: `qpath` must be a const param, otherwise this will panic
+    fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
+        let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
+            qpath
+        else {
+            span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
+        };
+
+        match tcx.named_bound_var(hir_id) {
+            Some(rbv::ResolvedArg::EarlyBound(_)) => {
+                // Find the name and index of the const parameter by indexing the generics of
+                // the parent item and construct a `ParamConst`.
+                let item_def_id = tcx.parent(def_id);
+                let generics = tcx.generics_of(item_def_id);
+                let index = generics.param_def_id_to_index[&def_id];
+                let name = tcx.item_name(def_id);
+                ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
+            }
+            Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+                ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
+            }
+            Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
+            arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
+        }
+    }
+
     #[instrument(skip(tcx), level = "debug")]
-    fn try_from_lit_or_param(
-        tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
-        expr: &'tcx hir::Expr<'tcx>,
-    ) -> Option<Self> {
+    fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
         // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
         // currently have to be wrapped in curly brackets, so it's necessary to special-case.
         let expr = match &expr.kind {
@@ -250,34 +314,15 @@ impl<'tcx> Const<'tcx> {
             }
         }
 
-        // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
-        // does not provide the parents generics to anonymous constants. We still allow generic const
-        // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
-        // ever try to instantiate the generic parameters in their bodies.
-        match expr.kind {
-            hir::ExprKind::Path(hir::QPath::Resolved(
-                _,
-                &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
-            )) => {
-                match tcx.named_bound_var(expr.hir_id) {
-                    Some(rbv::ResolvedArg::EarlyBound(_)) => {
-                        // Find the name and index of the const parameter by indexing the generics of
-                        // the parent item and construct a `ParamConst`.
-                        let item_def_id = tcx.parent(def_id);
-                        let generics = tcx.generics_of(item_def_id);
-                        let index = generics.param_def_id_to_index[&def_id];
-                        let name = tcx.item_name(def_id);
-                        Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
-                    }
-                    Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
-                        Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
-                    }
-                    Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
-                    arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
-                }
-            }
-            _ => None,
+        if let hir::ExprKind::Path(hir::QPath::Resolved(
+            _,
+            &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
+        )) = expr.kind
+        {
+            span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
         }
+
+        None
     }
 
     #[inline]
@@ -312,14 +357,16 @@ impl<'tcx> Const<'tcx> {
         Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
     }
 
-    /// Returns the evaluated constant
+    /// Returns the evaluated constant as a valtree;
+    /// if that fails due to a valtree-incompatible type, indicate which type that is
+    /// by returning `Err(Left(bad_type))`.
     #[inline]
-    pub fn eval(
+    pub fn eval_valtree(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
         span: Span,
-    ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
+    ) -> Result<(Ty<'tcx>, ValTree<'tcx>), Either<Ty<'tcx>, ErrorHandled>> {
         assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
         match self.kind() {
             ConstKind::Unevaluated(unevaluated) => {
@@ -328,27 +375,47 @@ impl<'tcx> Const<'tcx> {
                 let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
                 // try to resolve e.g. associated constants to their definition on an impl, and then
                 // evaluate the const.
-                let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?
-                else {
-                    // This can happen when we run on ill-typed code.
-                    let e = tcx.dcx().span_delayed_bug(
-                        span,
-                        "`ty::Const::eval` called on a non-valtree-compatible type",
-                    );
-                    return Err(e.into());
-                };
-                Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
+                match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span) {
+                    Ok(Ok(c)) => {
+                        Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
+                    }
+                    Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
+                    Err(err) => Err(Either::Right(err.into())),
+                }
             }
             ConstKind::Value(ty, val) => Ok((ty, val)),
-            ConstKind::Error(g) => Err(g.into()),
+            ConstKind::Error(g) => Err(Either::Right(g.into())),
             ConstKind::Param(_)
             | ConstKind::Infer(_)
             | ConstKind::Bound(_, _)
             | ConstKind::Placeholder(_)
-            | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span)),
+            | ConstKind::Expr(_) => Err(Either::Right(ErrorHandled::TooGeneric(span))),
         }
     }
 
+    /// Returns the evaluated constant
+    #[inline]
+    pub fn eval(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        span: Span,
+    ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
+        self.eval_valtree(tcx, param_env, span).map_err(|err| {
+            match err {
+                Either::Right(err) => err,
+                Either::Left(_bad_ty) => {
+                    // This can happen when we run on ill-typed code.
+                    let e = tcx.dcx().span_delayed_bug(
+                        span,
+                        "`ty::Const::eval` called on a non-valtree-compatible type",
+                    );
+                    e.into()
+                }
+            }
+        })
+    }
+
     /// Normalizes the constant to a value or an error if possible.
     #[inline]
     pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
@@ -460,15 +527,15 @@ pub fn const_param_default<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
-    let default_def_id = match tcx.hir_node_by_def_id(def_id) {
+    let default_ct = match tcx.hir_node_by_def_id(def_id) {
         hir::Node::GenericParam(hir::GenericParam {
-            kind: hir::GenericParamKind::Const { default: Some(ac), .. },
+            kind: hir::GenericParamKind::Const { default: Some(ct), .. },
             ..
-        }) => ac.def_id,
+        }) => ct,
         _ => span_bug!(
             tcx.def_span(def_id),
             "`const_param_default` expected a generic parameter with a constant"
         ),
     };
-    ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
+    ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 25070e6b042..fd41668ae44 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1484,7 +1484,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
-        value.lift_to_tcx(self)
+        value.lift_to_interner(self)
     }
 
     /// Creates a type context. To use the context call `fn enter` which
@@ -2087,7 +2087,7 @@ macro_rules! nop_lift {
     ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for $ty {
             type Lifted = $lifted;
-            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 // Assert that the set has the right type.
                 // Given an argument that has an interned type, the return type has the type of
                 // the corresponding interner set. This won't actually return anything, we're
@@ -2122,7 +2122,7 @@ macro_rules! nop_list_lift {
     ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<$ty> {
             type Lifted = &'tcx List<$lifted>;
-            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 // Assert that the set has the right type.
                 if false {
                     let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set;
@@ -2160,7 +2160,7 @@ macro_rules! nop_slice_lift {
     ($ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a [$ty] {
             type Lifted = &'tcx [$lifted];
-            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 if self.is_empty() {
                     return Some(&[]);
                 }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 4bf22337991..f479b18c7c4 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -271,6 +271,19 @@ pub fn suggest_constraining_type_params<'a>(
             }
         }
 
+        // in the scenario like impl has stricter requirements than trait,
+        // we should not suggest restrict bound on the impl, here we double check
+        // the whether the param already has the constraint by checking `def_id`
+        let bound_trait_defs: Vec<DefId> = generics
+            .bounds_for_param(param.def_id)
+            .flat_map(|bound| {
+                bound.bounds.iter().flat_map(|b| b.trait_ref().and_then(|t| t.trait_def_id()))
+            })
+            .collect();
+
+        constraints
+            .retain(|(_, def_id)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def)));
+
         if constraints.is_empty() {
             continue;
         }
@@ -332,6 +345,7 @@ pub fn suggest_constraining_type_params<'a>(
         //          --
         //          |
         //          replace with: `T: Bar +`
+
         if let Some((span, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
             suggest_restrict(span, true, open_paren_sp);
             continue;
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 5ac3168196a..10919623de7 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -308,7 +308,7 @@ impl<'tcx> GenericArg<'tcx> {
 impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for GenericArg<'a> {
     type Lifted = GenericArg<'tcx>;
 
-    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         match self.unpack() {
             GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()),
             GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 9a4562e9cfc..bd073cd891f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -86,7 +86,7 @@ pub use self::closure::{
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::consts::{
-    Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
+    Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index df080b2887b..0e241663e18 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1214,11 +1214,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             && let ty::Alias(_, alias_ty) =
                 self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
             && alias_ty.def_id == def_id
+            && let generics = self.tcx().generics_of(fn_def_id)
+            // FIXME(return_type_notation): We only support lifetime params for now.
+            && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
         {
-            let num_args = self.tcx().generics_of(fn_def_id).count();
+            let num_args = generics.count();
             write!(self, " {{ ")?;
             self.print_def_path(fn_def_id, &args[..num_args])?;
-            write!(self, "() }}")?;
+            write!(self, "(..) }}")?;
         }
 
         Ok(())
@@ -2624,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/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index ebf0d7ed737..61c03922ac0 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -69,7 +69,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
                 if inc_a != inc_b {
                     todo!()
                 }
-                Ok(relation.tcx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a }))
+                Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a }))
             }
         }
     }
@@ -81,7 +81,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
         a: Self,
         b: Self,
     ) -> RelateResult<'tcx, Self> {
-        let tcx = relation.tcx();
+        let tcx = relation.cx();
 
         // FIXME: this is wasteful, but want to do a perf run to see how slow it is.
         // We need to perform this deduplication as we sometimes generate duplicate projections
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 00ea87690c1..7cdc0e32953 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -283,7 +283,7 @@ TrivialTypeTraversalAndLiftImpls! {
 
 impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
     type Lifted = Option<T::Lifted>;
-    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         Some(match self {
             Some(x) => Some(tcx.lift(x)?),
             None => None,
@@ -293,7 +293,7 @@ impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
 
 impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Term<'a> {
     type Lifted = ty::Term<'tcx>;
-    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         match self.unpack() {
             TermKind::Ty(ty) => tcx.lift(ty).map(Into::into),
             TermKind::Const(c) => tcx.lift(c).map(Into::into),
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 24e3e623ff2..a6dec66449e 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -607,7 +607,9 @@ impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
     type Output = V;
 
     fn index(&self, key: HirId) -> &V {
-        self.get(key).expect("LocalTableInContext: key not found")
+        self.get(key).unwrap_or_else(|| {
+            bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
+        })
     }
 }
 
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/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 5d828d0093f..529e9cc2711 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+either = "1.5.0"
 itertools = "0.12"
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 0c277811fda..281f3ef6ef3 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -4,8 +4,6 @@ mir_build_already_borrowed = cannot borrow value as mutable because it is also b
 
 mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
 
-mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
-
 mir_build_bindings_with_variant_name =
     pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
     .suggestion = to match on the variant, qualify the path
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 5ccbd7c59cf..c608e5c63d8 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -71,11 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 StmtKind::Expr { scope, expr } => {
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
                     let si = (*scope, source_info);
-                    unpack!(
-                        block = this.in_scope(si, LintLevel::Inherited, |this| {
+                    block = this
+                        .in_scope(si, LintLevel::Inherited, |this| {
                             this.stmt_expr(block, *expr, Some(*scope))
                         })
-                    );
+                        .into_block();
                 }
                 StmtKind::Let {
                     remainder_scope,
@@ -166,14 +166,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let dummy_place = this.temp(this.tcx.types.never, else_block_span);
                     let failure_entry = this.cfg.start_new_block();
                     let failure_block;
-                    unpack!(
-                        failure_block = this.ast_block(
+                    failure_block = this
+                        .ast_block(
                             dummy_place,
                             failure_entry,
                             *else_block,
                             this.source_info(else_block_span),
                         )
-                    );
+                        .into_block();
                     this.cfg.terminate(
                         failure_block,
                         this.source_info(else_block_span),
@@ -267,8 +267,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         let initializer_span = this.thir[init].span;
                         let scope = (*init_scope, source_info);
 
-                        unpack!(
-                            block = this.in_scope(scope, *lint_level, |this| {
+                        block = this
+                            .in_scope(scope, *lint_level, |this| {
                                 this.declare_bindings(
                                     visibility_scope,
                                     remainder_span,
@@ -279,10 +279,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 this.expr_into_pattern(block, &pattern, init)
                                 // irrefutable pattern
                             })
-                        )
+                            .into_block();
                     } else {
                         let scope = (*init_scope, source_info);
-                        unpack!(this.in_scope(scope, *lint_level, |this| {
+                        let _: BlockAnd<()> = this.in_scope(scope, *lint_level, |this| {
                             this.declare_bindings(
                                 visibility_scope,
                                 remainder_span,
@@ -291,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 None,
                             );
                             block.unit()
-                        }));
+                        });
 
                         debug!("ast_block_stmts: pattern={:?}", pattern);
                         this.visit_primary_bindings(
@@ -333,7 +333,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             this.block_context
                 .push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
 
-            unpack!(block = this.expr_into_dest(destination, block, expr_id));
+            block = this.expr_into_dest(destination, block, expr_id).into_block();
             let popped = this.block_context.pop();
 
             assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
@@ -355,7 +355,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Finally, we pop all the let scopes before exiting out from the scope of block
         // itself.
         for scope in let_scope_stack.into_iter().rev() {
-            unpack!(block = this.pop_scope((*scope, source_info), block));
+            block = this.pop_scope((*scope, source_info), block).into_block();
         }
         // Restore the original source scope.
         this.source_scope = outer_source_scope;
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index c5ee6db5999..40cfe563acc 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -185,13 +185,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.push_assign(block, source_info, Place::from(result), box_);
 
                 // initialize the box contents:
-                unpack!(
-                    block = this.expr_into_dest(
-                        this.tcx.mk_place_deref(Place::from(result)),
-                        block,
-                        value,
-                    )
-                );
+                block = this
+                    .expr_into_dest(this.tcx.mk_place_deref(Place::from(result)), block, value)
+                    .into_block();
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
             }
             ExprKind::Cast { source } => {
@@ -486,7 +482,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::Aggregate(result, operands))
             }
             ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
-                block = unpack!(this.stmt_expr(block, expr_id, None));
+                block = this.stmt_expr(block, expr_id, None).into_block();
                 block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
                     span: expr_span,
                     user_ty: None,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 607c7c3259c..82673582e79 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -112,7 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        unpack!(block = this.expr_into_dest(temp_place, block, expr_id));
+        block = this.expr_into_dest(temp_place, block, expr_id).into_block();
 
         if let Some(temp_lifetime) = temp_lifetime {
             this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 942c69b5c0a..9cd958a21da 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -82,13 +82,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         // Lower the condition, and have it branch into `then` and `else` blocks.
                         let (then_block, else_block) =
                             this.in_if_then_scope(condition_scope, then_span, |this| {
-                                let then_blk = unpack!(this.then_else_break(
-                                    block,
-                                    cond,
-                                    Some(condition_scope), // Temp scope
-                                    source_info,
-                                    DeclareLetBindings::Yes, // Declare `let` bindings normally
-                                ));
+                                let then_blk = this
+                                    .then_else_break(
+                                        block,
+                                        cond,
+                                        Some(condition_scope), // Temp scope
+                                        source_info,
+                                        DeclareLetBindings::Yes, // Declare `let` bindings normally
+                                    )
+                                    .into_block();
 
                                 // Lower the `then` arm into its block.
                                 this.expr_into_dest(destination, then_blk, then)
@@ -105,7 +107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // If there is an `else` arm, lower it into `else_blk`.
                 if let Some(else_expr) = else_opt {
-                    unpack!(else_blk = this.expr_into_dest(destination, else_blk, else_expr));
+                    else_blk = this.expr_into_dest(destination, else_blk, else_expr).into_block();
                 } else {
                     // There is no `else` arm, so we know both arms have type `()`.
                     // Generate the implicit `else {}` by assigning unit.
@@ -187,7 +189,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         const_: Const::from_bool(this.tcx, constant),
                     },
                 );
-                let mut rhs_block = unpack!(this.expr_into_dest(destination, continuation, rhs));
+                let mut rhs_block =
+                    this.expr_into_dest(destination, continuation, rhs).into_block();
                 // Instrument the lowered RHS's value for condition coverage.
                 // (Does nothing if condition coverage is not enabled.)
                 this.visit_coverage_standalone_condition(rhs, destination, &mut rhs_block);
@@ -230,7 +233,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // introduce a unit temporary as the destination for the loop body.
                     let tmp = this.get_unit_temp();
                     // Execute the body, branching back to the test.
-                    let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, body));
+                    let body_block_end = this.expr_into_dest(tmp, body_block, body).into_block();
                     this.cfg.goto(body_block_end, source_info, loop_block);
 
                     // Loops are only exited by `break` expressions.
@@ -462,7 +465,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             targets.push(target);
 
                             let tmp = this.get_unit_temp();
-                            let target = unpack!(this.ast_block(tmp, target, block, source_info));
+                            let target =
+                                this.ast_block(tmp, target, block, source_info).into_block();
                             this.cfg.terminate(
                                 target,
                                 source_info,
@@ -502,7 +506,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             // These cases don't actually need a destination
             ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
-                unpack!(block = this.stmt_expr(block, expr_id, None));
+                block = this.stmt_expr(block, expr_id, None).into_block();
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
                 block.unit()
             }
@@ -511,7 +515,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::Break { .. }
             | ExprKind::Return { .. }
             | ExprKind::Become { .. } => {
-                unpack!(block = this.stmt_expr(block, expr_id, None));
+                block = this.stmt_expr(block, expr_id, None).into_block();
                 // No assign, as these have type `!`.
                 block.unit()
             }
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 88b76c46c90..8e13edb4c89 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -44,7 +44,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 if lhs_expr.ty.needs_drop(this.tcx, this.param_env) {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
-                    unpack!(block = this.build_drop_and_replace(block, lhs_expr.span, lhs, rhs));
+                    block =
+                        this.build_drop_and_replace(block, lhs_expr.span, lhs, rhs).into_block();
                 } else {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
index 2f540478674..95fec154918 100644
--- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
@@ -3,37 +3,37 @@ use rustc_middle::thir::{self, *};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
-use crate::build::matches::{FlatPat, MatchPair, TestCase};
+use crate::build::matches::{FlatPat, MatchPairTree, TestCase};
 use crate::build::Builder;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    /// Builds and returns [`MatchPair`] trees, one for each pattern in
+    /// Builds and returns [`MatchPairTree`] subtrees, one for each pattern in
     /// `subpatterns`, representing the fields of a [`PatKind::Variant`] or
     /// [`PatKind::Leaf`].
     ///
-    /// Used internally by [`MatchPair::new`].
+    /// Used internally by [`MatchPairTree::for_pattern`].
     fn field_match_pairs<'pat>(
         &mut self,
         place: PlaceBuilder<'tcx>,
         subpatterns: &'pat [FieldPat<'tcx>],
-    ) -> Vec<MatchPair<'pat, 'tcx>> {
+    ) -> Vec<MatchPairTree<'pat, 'tcx>> {
         subpatterns
             .iter()
             .map(|fieldpat| {
                 let place =
                     place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
-                MatchPair::new(place, &fieldpat.pattern, self)
+                MatchPairTree::for_pattern(place, &fieldpat.pattern, self)
             })
             .collect()
     }
 
-    /// Builds [`MatchPair`] trees for the prefix/middle/suffix parts of an
+    /// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an
     /// array pattern or slice pattern, and adds those trees to `match_pairs`.
     ///
-    /// Used internally by [`MatchPair::new`].
+    /// Used internally by [`MatchPairTree::for_pattern`].
     fn prefix_slice_suffix<'pat>(
         &mut self,
-        match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
+        match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
         place: &PlaceBuilder<'tcx>,
         prefix: &'pat [Box<Pat<'tcx>>],
         opt_slice: &'pat Option<Box<Pat<'tcx>>>,
@@ -52,7 +52,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
             let elem =
                 ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
-            MatchPair::new(place.clone_project(elem), subpattern, self)
+            MatchPairTree::for_pattern(place.clone_project(elem), subpattern, self)
         }));
 
         if let Some(subslice_pat) = opt_slice {
@@ -62,7 +62,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 to: if exact_size { min_length - suffix_len } else { suffix_len },
                 from_end: !exact_size,
             });
-            match_pairs.push(MatchPair::new(subslice, subslice_pat, self));
+            match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self));
         }
 
         match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
@@ -73,19 +73,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 from_end: !exact_size,
             };
             let place = place.clone_project(elem);
-            MatchPair::new(place, subpattern, self)
+            MatchPairTree::for_pattern(place, subpattern, self)
         }));
     }
 }
 
-impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    /// Recursively builds a `MatchPair` tree for the given pattern and its
+impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
+    /// Recursively builds a match pair tree for the given pattern and its
     /// subpatterns.
-    pub(in crate::build) fn new(
+    pub(in crate::build) fn for_pattern(
         mut place_builder: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
-    ) -> MatchPair<'pat, 'tcx> {
+    ) -> MatchPairTree<'pat, 'tcx> {
         // Force the place type to the pattern's type.
         // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
         if let Some(resolved) = place_builder.resolve_upvar(cx) {
@@ -138,7 +138,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                     variance,
                 });
 
-                subpairs.push(MatchPair::new(place_builder, subpattern, cx));
+                subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx));
                 TestCase::Irrefutable { ascription, binding: None }
             }
 
@@ -152,7 +152,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
 
                 if let Some(subpattern) = subpattern.as_ref() {
                     // this is the `x @ P` case; have to keep matching against `P` now
-                    subpairs.push(MatchPair::new(place_builder, subpattern, cx));
+                    subpairs.push(MatchPairTree::for_pattern(place_builder, subpattern, cx));
                 }
                 TestCase::Irrefutable { ascription: None, binding }
             }
@@ -182,7 +182,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                     super::Ascription { annotation, source, variance: ty::Contravariant }
                 });
 
-                subpairs.push(MatchPair::new(place_builder, pattern, cx));
+                subpairs.push(MatchPairTree::for_pattern(place_builder, pattern, cx));
                 TestCase::Irrefutable { ascription, binding: None }
             }
 
@@ -231,7 +231,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
             }
 
             PatKind::Deref { ref subpattern } => {
-                subpairs.push(MatchPair::new(place_builder.deref(), subpattern, cx));
+                subpairs.push(MatchPairTree::for_pattern(place_builder.deref(), subpattern, cx));
                 default_irrefutable()
             }
 
@@ -242,13 +242,17 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
                     Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, subpattern.ty, mutability),
                     pattern.span,
                 );
-                subpairs.push(MatchPair::new(PlaceBuilder::from(temp).deref(), subpattern, cx));
+                subpairs.push(MatchPairTree::for_pattern(
+                    PlaceBuilder::from(temp).deref(),
+                    subpattern,
+                    cx,
+                ));
                 TestCase::Deref { temp, mutability }
             }
 
             PatKind::Never => TestCase::Never,
         };
 
-        MatchPair { place, test_case, subpairs, pattern }
+        MatchPairTree { place, test_case, subpairs, pattern }
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index fc4e9ebec0a..95bc8b3d0cb 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -122,8 +122,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match expr.kind {
             ExprKind::LogicalOp { op: op @ LogicalOp::And, lhs, rhs } => {
                 this.visit_coverage_branch_operation(op, expr_span);
-                let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args));
-                let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args));
+                let lhs_then_block = this.then_else_break_inner(block, lhs, args).into_block();
+                let rhs_then_block =
+                    this.then_else_break_inner(lhs_then_block, rhs, args).into_block();
                 rhs_then_block.unit()
             }
             ExprKind::LogicalOp { op: op @ LogicalOp::Or, lhs, rhs } => {
@@ -140,14 +141,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             },
                         )
                     });
-                let rhs_success_block = unpack!(this.then_else_break_inner(
-                    failure_block,
-                    rhs,
-                    ThenElseArgs {
-                        declare_let_bindings: DeclareLetBindings::LetNotPermitted,
-                        ..args
-                    },
-                ));
+                let rhs_success_block = this
+                    .then_else_break_inner(
+                        failure_block,
+                        rhs,
+                        ThenElseArgs {
+                            declare_let_bindings: DeclareLetBindings::LetNotPermitted,
+                            ..args
+                        },
+                    )
+                    .into_block();
 
                 // Make the LHS and RHS success arms converge to a common block.
                 // (We can't just make LHS goto RHS, because `rhs_success_block`
@@ -452,7 +455,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         outer_source_info: SourceInfo,
         fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
     ) -> BlockAnd<()> {
-        let arm_end_blocks: Vec<_> = arm_candidates
+        let arm_end_blocks: Vec<BasicBlock> = arm_candidates
             .into_iter()
             .map(|(arm, candidate)| {
                 debug!("lowering arm {:?}\ncandidate = {:?}", arm, candidate);
@@ -503,6 +506,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     this.expr_into_dest(destination, arm_block, arm.body)
                 })
+                .into_block()
             })
             .collect();
 
@@ -513,10 +517,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             outer_source_info.span.with_lo(outer_source_info.span.hi() - BytePos::from_usize(1)),
         );
         for arm_block in arm_end_blocks {
-            let block = &self.cfg.basic_blocks[arm_block.0];
+            let block = &self.cfg.basic_blocks[arm_block];
             let last_location = block.statements.last().map(|s| s.source_info);
 
-            self.cfg.goto(unpack!(arm_block), last_location.unwrap_or(end_brace), end_block);
+            self.cfg.goto(arm_block, last_location.unwrap_or(end_brace), end_block);
         }
 
         self.source_scope = outer_source_info.scope;
@@ -622,7 +626,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     OutsideGuard,
                     ScheduleDrops::Yes,
                 );
-                unpack!(block = self.expr_into_dest(place, block, initializer_id));
+                block = self.expr_into_dest(place, block, initializer_id).into_block();
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let source_info = self.source_info(irrefutable_pat.span);
@@ -661,7 +665,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     OutsideGuard,
                     ScheduleDrops::Yes,
                 );
-                unpack!(block = self.expr_into_dest(place, block, initializer_id));
+                block = self.expr_into_dest(place, block, initializer_id).into_block();
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let pattern_source_info = self.source_info(irrefutable_pat.span);
@@ -1028,15 +1032,15 @@ impl<'tcx> PatternExtraData<'tcx> {
 #[derive(Debug, Clone)]
 struct FlatPat<'pat, 'tcx> {
     /// To match the pattern, all of these must be satisfied...
-    // Invariant: all the `MatchPair`s are recursively simplified.
+    // Invariant: all the match pairs are recursively simplified.
     // Invariant: or-patterns must be sorted to the end.
-    match_pairs: Vec<MatchPair<'pat, 'tcx>>,
+    match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
 
     extra_data: PatternExtraData<'tcx>,
 }
 
 impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
-    /// Creates a `FlatPat` containing a simplified [`MatchPair`] list/forest
+    /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
     /// for the given pattern.
     fn new(
         place: PlaceBuilder<'tcx>,
@@ -1044,7 +1048,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
         cx: &mut Builder<'_, 'tcx>,
     ) -> Self {
         // First, recursively build a tree of match pairs for the given pattern.
-        let mut match_pairs = vec![MatchPair::new(place, pattern, cx)];
+        let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
         let mut extra_data = PatternExtraData {
             span: pattern.span,
             bindings: Vec::new(),
@@ -1061,9 +1065,9 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
 #[derive(Debug)]
 struct Candidate<'pat, 'tcx> {
     /// For the candidate to match, all of these must be satisfied...
-    // Invariant: all the `MatchPair`s are recursively simplified.
+    // Invariant: all the match pairs are recursively simplified.
     // Invariant: or-patterns must be sorted at the end.
-    match_pairs: Vec<MatchPair<'pat, 'tcx>>,
+    match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
 
     /// ...and if this is non-empty, one of these subcandidates also has to match...
     // Invariant: at the end of the algorithm, this must never contain a `is_never` candidate
@@ -1122,7 +1126,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
 
     /// Returns whether the first match pair of this candidate is an or-pattern.
     fn starts_with_or_pattern(&self) -> bool {
-        matches!(&*self.match_pairs, [MatchPair { test_case: TestCase::Or { .. }, .. }, ..])
+        matches!(&*self.match_pairs, [MatchPairTree { test_case: TestCase::Or { .. }, .. }, ..])
     }
 
     /// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1202,7 +1206,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
 /// Each node also has a list of subpairs (possibly empty) that must also match,
 /// and a reference to the THIR pattern it represents.
 #[derive(Debug, Clone)]
-pub(crate) struct MatchPair<'pat, 'tcx> {
+pub(crate) struct MatchPairTree<'pat, 'tcx> {
     /// This place...
     ///
     /// ---
@@ -1594,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.
@@ -1609,23 +1616,32 @@ 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>,
-        match_pair: MatchPair<'pat, 'tcx>,
+        match_pair: MatchPairTree<'pat, 'tcx>,
     ) {
         let TestCase::Or { pats } = match_pair.test_case else { bug!() };
         debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
@@ -1638,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
@@ -1691,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.
@@ -1809,8 +1851,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// [`Range`]: TestKind::Range
     fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
         // Extract the match-pair from the highest priority candidate
-        let match_pair = &candidates.first().unwrap().match_pairs[0];
-        let test = self.test(match_pair);
+        let match_pair = &candidates[0].match_pairs[0];
+        let test = self.pick_test_for_match_pair(match_pair);
         // Unwrap is ok after simplification.
         let match_place = match_pair.place.unwrap();
         debug!(?test, ?match_pair);
@@ -2158,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(),
@@ -2383,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,
@@ -2414,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,
@@ -2429,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/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 543301c71a0..20310f60821 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -12,7 +12,7 @@
 //! sort of test: for example, testing which variant an enum is, or
 //! testing a value against a constant.
 
-use crate::build::matches::{MatchPair, PatternExtraData, TestCase};
+use crate::build::matches::{MatchPairTree, PatternExtraData, TestCase};
 use crate::build::Builder;
 use tracing::{debug, instrument};
 
@@ -24,7 +24,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub(super) fn simplify_match_pairs<'pat>(
         &mut self,
-        match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
+        match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
         extra_data: &mut PatternExtraData<'tcx>,
     ) {
         // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index d29874a5ad4..8a02ea1a06d 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -5,7 +5,7 @@
 // identify what tests are needed, perform the tests, and then filter
 // the candidates based on the result.
 
-use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind};
+use crate::build::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind};
 use crate::build::Builder;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::{LangItem, RangeEnd};
@@ -26,7 +26,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a not-fully-simplified pattern.
-    pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
+    pub(super) fn pick_test_for_match_pair<'pat>(
+        &mut self,
+        match_pair: &MatchPairTree<'pat, 'tcx>,
+    ) -> Test<'tcx> {
         let kind = match match_pair.test_case {
             TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
 
@@ -144,7 +147,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     && tcx.is_lang_item(def.did(), LangItem::String)
                 {
                     if !tcx.features().string_deref_patterns {
-                        bug!(
+                        span_bug!(
+                            test.span,
                             "matching on `String` went through without enabling string_deref_patterns"
                         );
                     }
@@ -432,40 +436,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        match *ty.kind() {
-            ty::Ref(_, deref_ty, _) => ty = deref_ty,
-            _ => {
-                // non_scalar_compare called on non-reference type
-                let temp = self.temp(ty, source_info.span);
-                self.cfg.push_assign(block, source_info, temp, Rvalue::Use(expect));
-                let ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, ty);
-                let ref_temp = self.temp(ref_ty, source_info.span);
-
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    ref_temp,
-                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, temp),
-                );
-                expect = Operand::Move(ref_temp);
-
-                let ref_temp = self.temp(ref_ty, source_info.span);
-                self.cfg.push_assign(
-                    block,
-                    source_info,
-                    ref_temp,
-                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, val),
-                );
-                val = ref_temp;
+        // Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping
+        // reference: we can only compare two `&T`, and then compare_ty will be `T`.
+        // Make sure that we do *not* call any user-defined code here.
+        // The only types that can end up here are string and byte literals,
+        // which have their comparison defined in `core`.
+        // (Interestingly this means that exhaustiveness analysis relies, for soundness,
+        // on the `PartialEq` impls for `str` and `[u8]` to b correct!)
+        let compare_ty = match *ty.kind() {
+            ty::Ref(_, deref_ty, _)
+                if deref_ty == self.tcx.types.str_ || deref_ty != self.tcx.types.u8 =>
+            {
+                deref_ty
             }
-        }
+            _ => span_bug!(source_info.span, "invalid type for non-scalar compare: {}", ty),
+        };
 
         let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
         let method = trait_method(
             self.tcx,
             eq_def_id,
             sym::eq,
-            self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [ty, ty]),
+            self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [compare_ty, compare_ty]),
         );
 
         let bool_ty = self.tcx.types.bool;
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index e67fc843285..8fe8069b345 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,7 +1,7 @@
 use std::marker::PhantomData;
 
 use crate::build::expr::as_place::PlaceBase;
-use crate::build::matches::{Binding, Candidate, FlatPat, MatchPair, TestCase};
+use crate::build::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestCase};
 use crate::build::Builder;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_middle::mir::*;
@@ -152,7 +152,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
         }
     }
 
-    fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) {
+    fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
         if let TestCase::Or { pats, .. } = &match_pair.test_case {
             for flat_pat in pats.iter() {
                 self.visit_flat_pat(flat_pat)
@@ -260,7 +260,7 @@ where
         }
     }
 
-    fn visit_match_pair(&mut self, match_pair: &MatchPair<'_, 'tcx>) {
+    fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
         if let TestCase::Or { pats, .. } = &match_pair.test_case {
             // All the or-alternatives should bind the same locals, so we only visit the first one.
             self.visit_flat_pat(&pats[0])
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 0f9746cb719..2793a7d8736 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -403,6 +403,15 @@ enum NeedsTemporary {
 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
 struct BlockAnd<T>(BasicBlock, T);
 
+impl BlockAnd<()> {
+    /// Unpacks `BlockAnd<()>` into a [`BasicBlock`].
+    #[must_use]
+    fn into_block(self) -> BasicBlock {
+        let Self(block, ()) = self;
+        block
+    }
+}
+
 trait BlockAndExtension {
     fn and<T>(self, v: T) -> BlockAnd<T>;
     fn unit(self) -> BlockAnd<()>;
@@ -426,11 +435,6 @@ macro_rules! unpack {
         $x = b;
         v
     }};
-
-    ($c:expr) => {{
-        let BlockAnd(b, ()) = $c;
-        b
-    }};
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -516,21 +520,22 @@ fn construct_fn<'tcx>(
         region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::Arguments };
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
-    unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
+    let _: BlockAnd<()> = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
         let arg_scope_s = (arg_scope, source_info);
         // Attribute epilogue to function's closing brace
         let fn_end = span_with_body.shrink_to_hi();
-        let return_block =
-            unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
+        let return_block = builder
+            .in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
                 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
                     builder.args_and_body(START_BLOCK, arguments, arg_scope, expr)
                 }))
-            }));
+            })
+            .into_block();
         let source_info = builder.source_info(fn_end);
         builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
         builder.build_drop_trees();
         return_block.unit()
-    }));
+    });
 
     let mut body = builder.finish();
 
@@ -579,7 +584,7 @@ fn construct_const<'a, 'tcx>(
         Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);
 
     let mut block = START_BLOCK;
-    unpack!(block = builder.expr_into_dest(Place::return_place(), block, expr));
+    block = builder.expr_into_dest(Place::return_place(), block, expr).into_block();
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -961,7 +966,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         Some((Some(&place), span)),
                     );
                     let place_builder = PlaceBuilder::from(local);
-                    unpack!(block = self.place_into_pattern(block, pat, place_builder, false));
+                    block = self.place_into_pattern(block, pat, place_builder, false).into_block();
                 }
             }
             self.source_scope = original_source_scope;
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 948301e2ece..b630c74a202 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -510,12 +510,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let target = self.cfg.start_new_block();
                 let source_info = self.source_info(span);
                 self.cfg.terminate(
-                    unpack!(normal_block),
+                    normal_block.into_block(),
                     source_info,
                     TerminatorKind::Goto { target },
                 );
                 self.cfg.terminate(
-                    unpack!(exit_block),
+                    exit_block.into_block(),
                     source_info,
                     TerminatorKind::Goto { target },
                 );
@@ -552,14 +552,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let scope = IfThenScope { region_scope, else_drops: DropTree::new() };
         let previous_scope = mem::replace(&mut self.scopes.if_then_scope, Some(scope));
 
-        let then_block = unpack!(f(self));
+        let then_block = f(self).into_block();
 
         let if_then_scope = mem::replace(&mut self.scopes.if_then_scope, previous_scope).unwrap();
         assert!(if_then_scope.region_scope == region_scope);
 
-        let else_block = self
-            .build_exit_tree(if_then_scope.else_drops, region_scope, span, None)
-            .map_or_else(|| self.cfg.start_new_block(), |else_block_and| unpack!(else_block_and));
+        let else_block =
+            self.build_exit_tree(if_then_scope.else_drops, region_scope, span, None).map_or_else(
+                || self.cfg.start_new_block(),
+                |else_block_and| else_block_and.into_block(),
+            );
 
         (then_block, else_block)
     }
@@ -585,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.push_scope(region_scope);
         let mut block;
         let rv = unpack!(block = f(self));
-        unpack!(block = self.pop_scope(region_scope, block));
+        block = self.pop_scope(region_scope, block).into_block();
         self.source_scope = source_scope;
         debug!(?block);
         block.and(rv)
@@ -657,7 +659,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             (Some(destination), Some(value)) => {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
-                unpack!(block = self.expr_into_dest(destination, block, value));
+                block = self.expr_into_dest(destination, block, value).into_block();
                 self.block_context.pop();
             }
             (Some(destination), None) => {
@@ -838,7 +840,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let unwind_to = if needs_cleanup { self.diverge_cleanup() } else { DropIdx::MAX };
 
         let scope = self.scopes.scopes.last().expect("leave_top_scope called with no scopes");
-        unpack!(build_scope_drops(
+        build_scope_drops(
             &mut self.cfg,
             &mut self.scopes.unwind_drops,
             scope,
@@ -846,7 +848,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             unwind_to,
             is_coroutine && needs_cleanup,
             self.arg_count,
-        ))
+        )
+        .into_block()
     }
 
     /// Possibly creates a new source scope if `current_root` and `parent_root`
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 7c73d8a6d47..f6f443b64a6 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -567,13 +567,6 @@ pub(crate) struct StaticInPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_assoc_const_in_pattern, code = E0158)]
-pub(crate) struct AssocConstInPattern {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(mir_build_const_param_in_pattern, code = E0158)]
 pub(crate) struct ConstParamInPattern {
     #[primary_span]
@@ -597,7 +590,7 @@ pub(crate) struct UnreachablePattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_const_pattern_depends_on_generic_parameter)]
+#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
 pub(crate) struct ConstPatternDependsOnGenericParameter {
     #[primary_span]
     pub(crate) span: Span,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 5745dc0969c..0d54f332585 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -1,42 +1,45 @@
+use either::Either;
 use rustc_apfloat::Float;
 use rustc_hir as hir;
 use rustc_index::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::mir;
-use rustc_middle::span_bug;
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
-use rustc_span::{ErrorGuaranteed, Span};
+use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCause};
+use rustc_trait_selection::traits::ObligationCause;
 use tracing::{debug, instrument, trace};
 
-use std::cell::Cell;
-
 use super::PatCtxt;
 use crate::errors::{
-    InvalidPattern, NaNPattern, PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern,
-    UnsizedPattern,
+    ConstPatternDependsOnGenericParameter, CouldNotEvalConstPattern, InvalidPattern, NaNPattern,
+    PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
 };
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
-    /// Converts an evaluated constant to a pattern (if possible).
+    /// Converts a constant to a pattern (if possible).
     /// This means aggregate values (like structs and enums) are converted
     /// to a pattern that matches the value (as if you'd compared via structural equality).
     ///
-    /// `cv` must be a valtree or a `mir::ConstValue`.
+    /// Only type system constants are supported, as we are using valtrees
+    /// as an intermediate step. Unfortunately those don't carry a type
+    /// so we have to carry one ourselves.
     #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn const_to_pat(
         &self,
-        cv: mir::Const<'tcx>,
+        c: ty::Const<'tcx>,
+        ty: Ty<'tcx>,
         id: hir::HirId,
         span: Span,
     ) -> Box<Pat<'tcx>> {
         let infcx = self.tcx.infer_ctxt().build();
         let mut convert = ConstToPat::new(self, id, span, infcx);
-        convert.to_pat(cv)
+        convert.to_pat(c, ty)
     }
 }
 
@@ -45,23 +48,12 @@ struct ConstToPat<'tcx> {
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
 
-    // This tracks if we emitted some hard error for a given const value, so that
-    // we will not subsequently issue an irrelevant lint for the same const
-    // value.
-    saw_const_match_error: Cell<Option<ErrorGuaranteed>>,
-
     // inference context used for checking `T: Structural` bounds.
     infcx: InferCtxt<'tcx>,
 
     treat_byte_string_as_slice: bool,
 }
 
-/// This error type signals that we encountered a non-struct-eq situation.
-/// We will fall back to calling `PartialEq::eq` on such patterns,
-/// and exhaustiveness checking will consider them as matching nothing.
-#[derive(Debug)]
-struct FallbackToOpaqueConst;
-
 impl<'tcx> ConstToPat<'tcx> {
     fn new(
         pat_ctxt: &PatCtxt<'_, 'tcx>,
@@ -75,7 +67,6 @@ impl<'tcx> ConstToPat<'tcx> {
             span,
             infcx,
             param_env: pat_ctxt.param_env,
-            saw_const_match_error: Cell::new(None),
             treat_byte_string_as_slice: pat_ctxt
                 .typeck_results
                 .treat_byte_string_as_slice
@@ -91,116 +82,55 @@ impl<'tcx> ConstToPat<'tcx> {
         ty.is_structural_eq_shallow(self.infcx.tcx)
     }
 
-    fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box<Pat<'tcx>> {
+    fn to_pat(&mut self, c: ty::Const<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
         trace!(self.treat_byte_string_as_slice);
-        // This method is just a wrapper handling a validity check; the heavy lifting is
-        // performed by the recursive `recur` method, which is not meant to be
-        // invoked except by this method.
-        //
-        // once indirect_structural_match is a full fledged error, this
-        // level of indirection can be eliminated
+        let pat_from_kind = |kind| Box::new(Pat { span: self.span, ty, kind });
 
-        let have_valtree =
-            matches!(cv, mir::Const::Ty(_, c) if matches!(c.kind(), ty::ConstKind::Value(_, _)));
-        let inlined_const_as_pat = match cv {
-            mir::Const::Ty(_, c) => match c.kind() {
-                ty::ConstKind::Param(_)
-                | ty::ConstKind::Infer(_)
-                | ty::ConstKind::Bound(_, _)
-                | ty::ConstKind::Placeholder(_)
-                | ty::ConstKind::Unevaluated(_)
-                | ty::ConstKind::Error(_)
-                | ty::ConstKind::Expr(_) => {
-                    span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
-                }
-                ty::ConstKind::Value(ty, valtree) => {
-                    self.recur(valtree, ty).unwrap_or_else(|_: FallbackToOpaqueConst| {
-                        Box::new(Pat {
-                            span: self.span,
-                            ty: cv.ty(),
-                            kind: PatKind::Constant { value: cv },
-                        })
-                    })
-                }
-            },
-            mir::Const::Unevaluated(_, _) => {
-                span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}")
+        // Get a valtree. If that fails, this const is definitely not valid for use as a pattern.
+        let valtree = match c.eval_valtree(self.tcx(), self.param_env, self.span) {
+            Ok((_, valtree)) => valtree,
+            Err(Either::Right(e)) => {
+                let err = match e {
+                    ErrorHandled::Reported(..) => {
+                        // Let's tell the use where this failing const occurs.
+                        self.tcx().dcx().emit_err(CouldNotEvalConstPattern { span: self.span })
+                    }
+                    ErrorHandled::TooGeneric(_) => self
+                        .tcx()
+                        .dcx()
+                        .emit_err(ConstPatternDependsOnGenericParameter { span: self.span }),
+                };
+                return pat_from_kind(PatKind::Error(err));
+            }
+            Err(Either::Left(bad_ty)) => {
+                // The pattern cannot be turned into a valtree.
+                let e = match bad_ty.kind() {
+                    ty::Adt(def, ..) => {
+                        assert!(def.is_union());
+                        self.tcx().dcx().emit_err(UnionPattern { span: self.span })
+                    }
+                    ty::FnPtr(..) | ty::RawPtr(..) => {
+                        self.tcx().dcx().emit_err(PointerPattern { span: self.span })
+                    }
+                    _ => self
+                        .tcx()
+                        .dcx()
+                        .emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }),
+                };
+                return pat_from_kind(PatKind::Error(e));
             }
-            mir::Const::Val(_, _) => Box::new(Pat {
-                span: self.span,
-                ty: cv.ty(),
-                kind: PatKind::Constant { value: cv },
-            }),
         };
 
-        if self.saw_const_match_error.get().is_none() {
-            // If we were able to successfully convert the const to some pat (possibly with some
-            // lints, but no errors), double-check that all types in the const implement
-            // `PartialEq`. Even if we have a valtree, we may have found something
-            // in there with non-structural-equality, meaning we match using `PartialEq`
-            // and we hence have to check if that impl exists.
-            // This is all messy but not worth cleaning up: at some point we'll emit
-            // a hard error when we don't have a valtree or when we find something in
-            // the valtree that is not structural; then this can all be made a lot simpler.
-
-            let structural = traits::search_for_structural_match_violation(self.tcx(), cv.ty());
-            debug!(
-                "search_for_structural_match_violation cv.ty: {:?} returned: {:?}",
-                cv.ty(),
-                structural
-            );
-
-            if let Some(non_sm_ty) = structural {
-                if !self.type_has_partial_eq_impl(cv.ty()) {
-                    // This is reachable and important even if we have a valtree: there might be
-                    // non-structural things in a valtree, in which case we fall back to `PartialEq`
-                    // comparison, in which case we better make sure the trait is implemented for
-                    // each inner type (and not just for the surrounding type).
-                    let e = if let ty::Adt(def, ..) = non_sm_ty.kind() {
-                        if def.is_union() {
-                            let err = UnionPattern { span: self.span };
-                            self.tcx().dcx().emit_err(err)
-                        } else {
-                            // fatal avoids ICE from resolution of nonexistent method (rare case).
-                            self.tcx()
-                                .dcx()
-                                .emit_fatal(TypeNotStructural { span: self.span, non_sm_ty })
-                        }
-                    } else {
-                        let err = InvalidPattern { span: self.span, non_sm_ty };
-                        self.tcx().dcx().emit_err(err)
-                    };
-                    // All branches above emitted an error. Don't print any more lints.
-                    // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                    let kind = PatKind::Error(e);
-                    return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
-                } else if !have_valtree {
-                    // Not being structural prevented us from constructing a valtree,
-                    // so this is definitely a case we want to reject.
-                    let err = TypeNotStructural { span: self.span, non_sm_ty };
-                    let e = self.tcx().dcx().emit_err(err);
-                    let kind = PatKind::Error(e);
-                    return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
-                } else {
-                    // This could be a violation in an inactive enum variant.
-                    // Since we have a valtree, we trust that we have traversed the full valtree and
-                    // complained about structural match violations there, so we don't
-                    // have to check anything any more.
-                }
-            } else if !have_valtree {
-                // The only way valtree construction can fail without the structural match
-                // checker finding a violation is if there is a pointer somewhere.
-                let e = self.tcx().dcx().emit_err(PointerPattern { span: self.span });
-                let kind = PatKind::Error(e);
-                return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
-            }
+        // Convert the valtree to a const.
+        let inlined_const_as_pat = self.valtree_to_pat(valtree, ty);
 
+        if !inlined_const_as_pat.references_error() {
             // Always check for `PartialEq` if we had no other errors yet.
-            if !self.type_has_partial_eq_impl(cv.ty()) {
-                let err = TypeNotPartialEq { span: self.span, non_peq_ty: cv.ty() };
+            if !self.type_has_partial_eq_impl(ty) {
+                let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
                 let e = self.tcx().dcx().emit_err(err);
                 let kind = PatKind::Error(e);
-                return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
+                return Box::new(Pat { span: self.span, ty: ty, kind });
             }
         }
 
@@ -243,40 +173,31 @@ impl<'tcx> ConstToPat<'tcx> {
     fn field_pats(
         &self,
         vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
-    ) -> Result<Vec<FieldPat<'tcx>>, FallbackToOpaqueConst> {
+    ) -> Vec<FieldPat<'tcx>> {
         vals.enumerate()
             .map(|(idx, (val, ty))| {
                 let field = FieldIdx::new(idx);
                 // Patterns can only use monomorphic types.
                 let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
-                Ok(FieldPat { field, pattern: self.recur(val, ty)? })
+                FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
             })
             .collect()
     }
 
     // Recursive helper for `to_pat`; invoke that (instead of calling this directly).
     #[instrument(skip(self), level = "debug")]
-    fn recur(
-        &self,
-        cv: ValTree<'tcx>,
-        ty: Ty<'tcx>,
-    ) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> {
+    fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
         let span = self.span;
         let tcx = self.tcx();
         let param_env = self.param_env;
 
         let kind = match ty.kind() {
-            ty::FnDef(..) => {
-                let e = tcx.dcx().emit_err(InvalidPattern { span, non_sm_ty: ty });
-                self.saw_const_match_error.set(Some(e));
-                // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Error(e)
-            }
             ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
+                // Extremely important check for all ADTs! Make sure they opted-in to be used in
+                // patterns.
                 debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
                 let err = TypeNotStructural { span, non_sm_ty: ty };
                 let e = tcx.dcx().emit_err(err);
-                self.saw_const_match_error.set(Some(e));
                 // We errored. Signal that in the pattern, so that follow up errors can be silenced.
                 PatKind::Error(e)
             }
@@ -294,13 +215,9 @@ impl<'tcx> ConstToPat<'tcx> {
                                 .iter()
                                 .map(|field| field.ty(self.tcx(), args)),
                         ),
-                    )?,
+                    ),
                 }
             }
-            ty::Tuple(fields) => PatKind::Leaf {
-                subpatterns: self
-                    .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?,
-            },
             ty::Adt(def, args) => {
                 assert!(!def.is_union()); // Valtree construction would never succeed for unions.
                 PatKind::Leaf {
@@ -311,15 +228,18 @@ impl<'tcx> ConstToPat<'tcx> {
                                 .iter()
                                 .map(|field| field.ty(self.tcx(), args)),
                         ),
-                    )?,
+                    ),
                 }
             }
+            ty::Tuple(fields) => PatKind::Leaf {
+                subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter())),
+            },
             ty::Slice(elem_ty) => PatKind::Slice {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.recur(*val, *elem_ty))
-                    .collect::<Result<_, _>>()?,
+                    .map(|val| self.valtree_to_pat(*val, *elem_ty))
+                    .collect(),
                 slice: None,
                 suffix: Box::new([]),
             },
@@ -327,8 +247,8 @@ impl<'tcx> ConstToPat<'tcx> {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.recur(*val, *elem_ty))
-                    .collect::<Result<_, _>>()?,
+                    .map(|val| self.valtree_to_pat(*val, *elem_ty))
+                    .collect(),
                 slice: None,
                 suffix: Box::new([]),
             },
@@ -361,7 +281,7 @@ impl<'tcx> ConstToPat<'tcx> {
                             _ => *pointee_ty,
                         };
                         // References have the same valtree representation as their pointee.
-                        let subpattern = self.recur(cv, pointee_ty)?;
+                        let subpattern = self.valtree_to_pat(cv, pointee_ty);
                         PatKind::Deref { subpattern }
                     }
                 }
@@ -378,8 +298,7 @@ impl<'tcx> ConstToPat<'tcx> {
                     // NaNs are not ever equal to anything so they make no sense as patterns.
                     // Also see <https://github.com/rust-lang/rfcs/pull/3535>.
                     let e = tcx.dcx().emit_err(NaNPattern { span });
-                    self.saw_const_match_error.set(Some(e));
-                    return Err(FallbackToOpaqueConst);
+                    PatKind::Error(e)
                 } else {
                     PatKind::Constant {
                         value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
@@ -399,12 +318,11 @@ impl<'tcx> ConstToPat<'tcx> {
             _ => {
                 let err = InvalidPattern { span, non_sm_ty: ty };
                 let e = tcx.dcx().emit_err(err);
-                self.saw_const_match_error.set(Some(e));
                 // We errored. Signal that in the pattern, so that follow up errors can be silenced.
                 PatKind::Error(e)
             }
         };
 
-        Ok(Box::new(Pat { span, ty, kind }))
+        Box::new(Pat { span, ty, kind })
     }
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index fd778ef78a3..622651800f4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -14,8 +14,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd};
 use rustc_index::Idx;
 use rustc_lint as lint;
-use rustc_middle::mir::interpret::{ErrorHandled, GlobalId, LitToConstError, LitToConstInput};
-use rustc_middle::mir::{self, Const};
+use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::thir::{
     Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
 };
@@ -549,89 +548,36 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             _ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])),
         };
 
-        // Use `Reveal::All` here because patterns are always monomorphic even if their function
-        // isn't.
-        let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
-        // N.B. There is no guarantee that args collected in typeck results are fully normalized,
-        // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE
-        // if given unnormalized types.
-        let args = self
-            .tcx
-            .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_args(id));
-        let instance = match ty::Instance::try_resolve(self.tcx, param_env_reveal_all, def_id, args)
-        {
-            Ok(Some(i)) => i,
-            Ok(None) => {
-                // It should be assoc consts if there's no error but we cannot resolve it.
-                debug_assert!(is_associated_const);
-
-                let e = self.tcx.dcx().emit_err(AssocConstInPattern { span });
-                return pat_from_kind(PatKind::Error(e));
-            }
-
-            Err(_) => {
-                let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span });
-                return pat_from_kind(PatKind::Error(e));
-            }
-        };
+        let args = self.typeck_results.node_args(id);
+        let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
+        let pattern = self.const_to_pat(c, ty, id, span);
 
-        let cid = GlobalId { instance, promoted: None };
-        // Prefer valtrees over opaque constants.
-        let const_value = self
-            .tcx
-            .const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
-            .map(|val| match val {
-                Some(valtree) => mir::Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
-                None => mir::Const::Val(
-                    self.tcx
-                        .const_eval_global_id(param_env_reveal_all, cid, span)
-                        .expect("const_eval_global_id_for_typeck should have already failed"),
-                    ty,
-                ),
-            });
-
-        match const_value {
-            Ok(const_) => {
-                let pattern = self.const_to_pat(const_, id, span);
-
-                if !is_associated_const {
-                    return pattern;
-                }
+        if !is_associated_const {
+            return pattern;
+        }
 
-                let user_provided_types = self.typeck_results().user_provided_types();
-                if let Some(&user_ty) = user_provided_types.get(id) {
-                    let annotation = CanonicalUserTypeAnnotation {
-                        user_ty: Box::new(user_ty),
-                        span,
-                        inferred_ty: self.typeck_results().node_type(id),
-                    };
-                    Box::new(Pat {
-                        span,
-                        kind: PatKind::AscribeUserType {
-                            subpattern: pattern,
-                            ascription: Ascription {
-                                annotation,
-                                // Note that use `Contravariant` here. See the
-                                // `variance` field documentation for details.
-                                variance: ty::Contravariant,
-                            },
-                        },
-                        ty: const_.ty(),
-                    })
-                } else {
-                    pattern
-                }
-            }
-            Err(ErrorHandled::TooGeneric(_)) => {
-                // While `Reported | Linted` cases will have diagnostics emitted already
-                // it is not true for TooGeneric case, so we need to give user more information.
-                let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span });
-                pat_from_kind(PatKind::Error(e))
-            }
-            Err(_) => {
-                let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span });
-                pat_from_kind(PatKind::Error(e))
-            }
+        let user_provided_types = self.typeck_results().user_provided_types();
+        if let Some(&user_ty) = user_provided_types.get(id) {
+            let annotation = CanonicalUserTypeAnnotation {
+                user_ty: Box::new(user_ty),
+                span,
+                inferred_ty: self.typeck_results().node_type(id),
+            };
+            Box::new(Pat {
+                span,
+                kind: PatKind::AscribeUserType {
+                    subpattern: pattern,
+                    ascription: Ascription {
+                        annotation,
+                        // Note that use `Contravariant` here. See the
+                        // `variance` field documentation for details.
+                        variance: ty::Contravariant,
+                    },
+                },
+                ty,
+            })
+        } else {
+            pattern
         }
     }
 
@@ -662,7 +608,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         };
         if let Some(lit_input) = lit_input {
             match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return self.const_to_pat(Const::Ty(ty, c), id, span).kind,
+                Ok(c) => return self.const_to_pat(c, ty, id, span).kind,
                 // If an error occurred, ignore that it's a literal
                 // and leave reporting the error up to const eval of
                 // the unevaluated constant below.
@@ -675,33 +621,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id));
         let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args;
 
-        let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), args, promoted: None };
         debug_assert!(!args.has_free_regions());
 
         let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
-        // First try using a valtree in order to destructure the constant into a pattern.
-        // FIXME: replace "try to do a thing, then fall back to another thing"
-        // but something more principled, like a trait query checking whether this can be turned into a valtree.
-        if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
-        {
-            let subpattern = self.const_to_pat(
-                Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
-                id,
-                span,
-            );
-            PatKind::InlineConstant { subpattern, def: def_id }
-        } else {
-            // If that fails, convert it to an opaque constant pattern.
-            match tcx.const_eval_resolve(self.param_env, uneval, span) {
-                Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind,
-                Err(ErrorHandled::TooGeneric(_)) => {
-                    // If we land here it means the const can't be evaluated because it's `TooGeneric`.
-                    let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span });
-                    PatKind::Error(e)
-                }
-                Err(ErrorHandled::Reported(err, ..)) => PatKind::Error(err.into()),
-            }
-        }
+        let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
+        PatKind::InlineConstant { subpattern, def: def_id }
     }
 
     /// Converts literals, paths and negation of literals to patterns.
@@ -729,9 +653,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let ct_ty = self.typeck_results.expr_ty(expr);
         let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
         match self.tcx.at(expr.span).lit_to_const(lit_input) {
-            Ok(constant) => {
-                self.const_to_pat(Const::Ty(ct_ty, constant), expr.hir_id, lit.span).kind
-            }
+            Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,
             Err(LitToConstError::Reported(e)) => PatKind::Error(e),
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
diff --git a/compiler/rustc_mir_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/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_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 07cd4ae68d9..79d2107b2a0 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -20,10 +20,10 @@ tracing = "0.1"
 [features]
 default = ["nightly"]
 nightly = [
+    "dep:rustc_data_structures",
+    "dep:rustc_macros",
+    "dep:rustc_serialize",
     "rustc_ast_ir/nightly",
-    "rustc_data_structures",
     "rustc_index/nightly",
-    "rustc_macros",
-    "rustc_serialize",
     "rustc_type_ir/nightly",
 ]
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 4222486034b..109d36fe689 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -660,9 +660,8 @@ pub(crate) struct RemoveLet {
 #[diag(parse_use_eq_instead)]
 pub(crate) struct UseEqInstead {
     #[primary_span]
+    #[suggestion(style = "verbose", applicability = "machine-applicable", code = "=")]
     pub span: Span,
-    #[suggestion(style = "verbose", applicability = "machine-applicable", code = "")]
-    pub suggestion: Span,
 }
 
 #[derive(Diagnostic)]
@@ -1504,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}")]
@@ -1517,7 +1530,6 @@ pub(crate) struct FnPtrWithGenericsSugg {
 
 pub(crate) struct FnTraitMissingParen {
     pub span: Span,
-    pub machine_applicable: bool,
 }
 
 impl Subdiagnostic for FnTraitMissingParen {
@@ -1527,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 1123c31f551..dc5f98f7be8 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,5 +1,5 @@
-use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken};
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor};
+use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing};
 use rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, ToAttrTokenStream};
 use rustc_ast::{self as ast};
@@ -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,44 +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 result
-    /// of the callback.
+    /// 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, TrailingToken)>,
+        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);
@@ -212,81 +222,68 @@ impl<'a> Parser<'a> {
         let has_outer_attrs = !attrs.attrs.is_empty();
         let replace_ranges_start = self.capture_state.replace_ranges.len();
 
-        let (mut ret, trailing) = {
+        // 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);
             self.capture_state.capturing = prev_capturing;
             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();
 
-        // Capture a trailing token if requested by the callback 'f'
-        let captured_trailing = match trailing {
-            TrailingToken::None => false,
-            TrailingToken::Gt => {
-                assert_eq!(self.token.kind, token::Gt);
-                false
-            }
-            TrailingToken::Semi => {
-                assert_eq!(self.token.kind, token::Semi);
-                true
-            }
-            TrailingToken::MaybeComma => self.token.kind == token::Comma,
-        };
-
         assert!(
-            !(self.break_last_token && captured_trailing),
+            !(self.break_last_token && capture_trailing),
             "Cannot set break_last_token and have trailing token"
         );
 
         let end_pos = self.num_bump_calls
-            + captured_trailing as u32
+            + capture_trailing as u32
             // If we 'broke' the last token (e.g. breaking a '>>' token to two '>' tokens), then
             // extend the range of captured tokens to include it, since the parser was not actually
             // bumped past it. When the `LazyAttrTokenStream` gets converted into an
@@ -295,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()
@@ -312,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,
@@ -325,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 0da7fefe6ed..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);
             }
         }
 
@@ -566,10 +566,7 @@ impl<'a> Parser<'a> {
             && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq)))
         {
             // Likely typo: `=` → `==` in let expr or enum item
-            return Err(self.dcx().create_err(UseEqInstead {
-                span: self.token.span,
-                suggestion: self.token.span.with_lo(self.token.span.lo() + BytePos(1)),
-            }));
+            return Err(self.dcx().create_err(UseEqInstead { span: self.token.span }));
         }
 
         if self.token.is_keyword(kw::Move) && self.prev_token.is_keyword(kw::Async) {
@@ -715,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);
             }
@@ -2240,11 +2237,11 @@ impl<'a> Parser<'a> {
                     }
                     _ => {
                         // Otherwise, try to get a type and emit a suggestion.
-                        if let Some(ty) = pat.to_ty() {
+                        if let Some(_) = pat.to_ty() {
                             err.span_suggestion_verbose(
-                                pat.span,
+                                pat.span.shrink_to_lo(),
                                 "explicitly ignore the parameter name",
-                                format!("_: {}", pprust::ty_to_string(&ty)),
+                                "_: ".to_string(),
                                 Applicability::MachineApplicable,
                             );
                             err.note(rfc_note);
@@ -2256,7 +2253,7 @@ impl<'a> Parser<'a> {
 
             // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
             if first_param {
-                err.span_suggestion(
+                err.span_suggestion_verbose(
                     self_span,
                     "if this is a `self` type, give it a parameter name",
                     self_sugg,
@@ -2266,14 +2263,14 @@ impl<'a> Parser<'a> {
             // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
             // `fn foo(HashMap: TypeName<u32>)`.
             if self.token != token::Lt {
-                err.span_suggestion(
+                err.span_suggestion_verbose(
                     param_span,
                     "if this is a parameter name, give it a type",
                     param_sugg,
                     Applicability::HasPlaceholders,
                 );
             }
-            err.span_suggestion(
+            err.span_suggestion_verbose(
                 type_span,
                 "if this is a type, explicitly ignore the parameter name",
                 type_sugg,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0ba8c66f48f..2542108728f 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -5,7 +5,7 @@ use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
     AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
-    SemiColonMode, SeqSep, TokenType, Trailing, TrailingToken,
+    SemiColonMode, SeqSep, TokenType, Trailing,
 };
 
 use crate::errors;
@@ -785,23 +785,14 @@ impl<'a> Parser<'a> {
             }
         };
 
-        self.parse_and_disallow_postfix_after_cast(cast_expr)
-    }
-
-    /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast,
-    /// then emits an error and returns the newly parsed tree.
-    /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`.
-    fn parse_and_disallow_postfix_after_cast(
-        &mut self,
-        cast_expr: P<Expr>,
-    ) -> PResult<'a, P<Expr>> {
-        if let ExprKind::Type(_, _) = cast_expr.kind {
-            panic!("ExprKind::Type must not be parsed");
-        }
+        // Try to parse a postfix operator such as `.`, `?`, or index (`[]`)
+        // after a cast. If one is present, emit an error then return a valid
+        // parse tree; For something like `&x as T[0]` will be as if it was
+        // written `((&x) as T)[0]`.
 
         let span = cast_expr.span;
 
-        let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?;
+        let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?;
 
         // Check if an illegal postfix operator has been added after the cast.
         // If the resulting expression is not a cast, it is an illegal postfix operator.
@@ -885,23 +876,63 @@ impl<'a> Parser<'a> {
         self.collect_tokens_for_expr(attrs, |this, attrs| {
             let base = this.parse_expr_bottom()?;
             let span = this.interpolated_or_expr_span(&base);
-            this.parse_expr_dot_or_call_with(base, span, attrs)
+            this.parse_expr_dot_or_call_with(attrs, base, span)
         })
     }
 
     pub(super) fn parse_expr_dot_or_call_with(
         &mut self,
-        e0: P<Expr>,
-        lo: Span,
         mut attrs: ast::AttrVec,
+        mut e: P<Expr>,
+        lo: Span,
     ) -> PResult<'a, P<Expr>> {
-        // Stitch the list of outer attributes onto the return value.
-        // A little bit ugly, but the best way given the current code
-        // structure
-        let res = ensure_sufficient_stack(
-            // this expr demonstrates the recursion it guards against
-            || self.parse_expr_dot_or_call_with_(e0, lo),
-        );
+        let res = ensure_sufficient_stack(|| {
+            loop {
+                let has_question =
+                    if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
+                        // We are using noexpect here because we don't expect a `?` directly after
+                        // a `return` which could be suggested otherwise.
+                        self.eat_noexpect(&token::Question)
+                    } else {
+                        self.eat(&token::Question)
+                    };
+                if has_question {
+                    // `expr?`
+                    e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
+                    continue;
+                }
+                let has_dot =
+                    if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
+                        // We are using noexpect here because we don't expect a `.` directly after
+                        // a `return` which could be suggested otherwise.
+                        self.eat_noexpect(&token::Dot)
+                    } else if self.token.kind == TokenKind::RArrow && self.may_recover() {
+                        // Recovery for `expr->suffix`.
+                        self.bump();
+                        let span = self.prev_token.span;
+                        self.dcx().emit_err(errors::ExprRArrowCall { span });
+                        true
+                    } else {
+                        self.eat(&token::Dot)
+                    };
+                if has_dot {
+                    // expr.f
+                    e = self.parse_dot_suffix_expr(lo, e)?;
+                    continue;
+                }
+                if self.expr_is_complete(&e) {
+                    return Ok(e);
+                }
+                e = match self.token.kind {
+                    token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
+                    token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
+                    _ => return Ok(e),
+                }
+            }
+        });
+
+        // Stitch the list of outer attributes onto the return value. A little
+        // bit ugly, but the best way given the current code structure.
         if attrs.is_empty() {
             res
         } else {
@@ -915,50 +946,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        loop {
-            let has_question =
-                if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
-                    // we are using noexpect here because we don't expect a `?` directly after a `return`
-                    // which could be suggested otherwise
-                    self.eat_noexpect(&token::Question)
-                } else {
-                    self.eat(&token::Question)
-                };
-            if has_question {
-                // `expr?`
-                e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
-                continue;
-            }
-            let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
-                // we are using noexpect here because we don't expect a `.` directly after a `return`
-                // which could be suggested otherwise
-                self.eat_noexpect(&token::Dot)
-            } else if self.token.kind == TokenKind::RArrow && self.may_recover() {
-                // Recovery for `expr->suffix`.
-                self.bump();
-                let span = self.prev_token.span;
-                self.dcx().emit_err(errors::ExprRArrowCall { span });
-                true
-            } else {
-                self.eat(&token::Dot)
-            };
-            if has_dot {
-                // expr.f
-                e = self.parse_dot_suffix_expr(lo, e)?;
-                continue;
-            }
-            if self.expr_is_complete(&e) {
-                return Ok(e);
-            }
-            e = match self.token.kind {
-                token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
-                token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
-                _ => return Ok(e),
-            }
-        }
-    }
-
     pub(super) fn parse_dot_suffix_expr(
         &mut self,
         lo: Span,
@@ -1388,7 +1375,7 @@ impl<'a> Parser<'a> {
     /// Parses things like parenthesized exprs, macros, `return`, etc.
     ///
     /// N.B., this does not parse outer attributes, and is private because it only works
-    /// correctly if called from `parse_dot_or_call_expr()`.
+    /// correctly if called from `parse_expr_dot_or_call`.
     fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
         maybe_recover_from_interpolated_ty_qpath!(self, true);
 
@@ -2487,7 +2474,7 @@ impl<'a> Parser<'a> {
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
-                TrailingToken::MaybeComma,
+                this.token == token::Comma,
             ))
         })
     }
@@ -3270,7 +3257,7 @@ impl<'a> Parser<'a> {
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
-                TrailingToken::None,
+                false,
             ))
         })
     }
@@ -3779,7 +3766,7 @@ impl<'a> Parser<'a> {
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
-                TrailingToken::MaybeComma,
+                this.token == token::Comma,
             ))
         })
     }
@@ -3875,18 +3862,12 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, P<Expr>> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let res = f(this, attrs)?;
-            let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR)
-                && this.token.kind == token::Semi
-            {
-                TrailingToken::Semi
-            } else if this.token.kind == token::Gt {
-                TrailingToken::Gt
-            } else {
-                // FIXME - pass this through from the place where we know
-                // we need a comma, rather than assuming that `#[attr] expr,`
-                // always captures a trailing comma
-                TrailingToken::MaybeComma
-            };
+            let trailing = (this.restrictions.contains(Restrictions::STMT_EXPR)
+                 && this.token.kind == token::Semi)
+            // FIXME: pass an additional condition through from the place
+            // where we know we need a comma, rather than assuming that
+            // `#[attr] expr,` always captures a trailing comma.
+            || this.token.kind == token::Comma;
             Ok((res, trailing))
         })
     }
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 10c7715c7dc..523538e9643 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -4,7 +4,7 @@ use crate::errors::{
     WhereClauseBeforeTupleStructBodySugg,
 };
 
-use super::{ForceCollect, Parser, TrailingToken};
+use super::{ForceCollect, Parser};
 
 use ast::token::Delimiter;
 use rustc_ast::token;
@@ -229,13 +229,13 @@ impl<'a> Parser<'a> {
                                     span: where_predicate.span(),
                                 });
                                 // FIXME - try to continue parsing other generics?
-                                return Ok((None, TrailingToken::None));
+                                return Ok((None, false));
                             }
                             Err(err) => {
                                 err.cancel();
                                 // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`?
                                 this.restore_snapshot(snapshot);
-                                return Ok((None, TrailingToken::None));
+                                return Ok((None, false));
                             }
                         }
                     } else {
@@ -249,14 +249,14 @@ impl<'a> Parser<'a> {
                                     .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
                             }
                         }
-                        return Ok((None, TrailingToken::None));
+                        return Ok((None, false));
                     };
 
                     if !this.eat(&token::Comma) {
                         done = true;
                     }
-                    // We just ate the comma, so no need to use `TrailingToken`
-                    Ok((param, TrailingToken::None))
+                    // We just ate the comma, so no need to capture the trailing token.
+                    Ok((param, false))
                 })?;
 
             if let Some(param) = param {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 76857cb8504..fbc5b914600 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1,8 +1,6 @@
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{
-    AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing, TrailingToken,
-};
+use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing};
 use crate::errors::{self, MacroExpandsToAdtField};
 use crate::fluent_generated as fluent;
 use crate::maybe_whole;
@@ -19,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;
@@ -128,56 +127,41 @@ impl<'a> Parser<'a> {
             Some(item.into_inner())
         });
 
-        let item =
-            self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| {
-                let item =
-                    this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode);
-                Ok((item?, TrailingToken::None))
-            })?;
-
-        Ok(item)
-    }
-
-    fn parse_item_common_(
-        &mut self,
-        mut attrs: AttrVec,
-        mac_allowed: bool,
-        attrs_allowed: bool,
-        fn_parse_mode: FnParseMode,
-    ) -> PResult<'a, Option<Item>> {
-        let lo = self.token.span;
-        let vis = self.parse_visibility(FollowedByType::No)?;
-        let mut def = self.parse_defaultness();
-        let kind = self.parse_item_kind(
-            &mut attrs,
-            mac_allowed,
-            lo,
-            &vis,
-            &mut def,
-            fn_parse_mode,
-            Case::Sensitive,
-        )?;
-        if let Some((ident, kind)) = kind {
-            self.error_on_unconsumed_default(def, &kind);
-            let span = lo.to(self.prev_token.span);
-            let id = DUMMY_NODE_ID;
-            let item = Item { ident, attrs, id, kind, vis, span, tokens: None };
-            return Ok(Some(item));
-        }
+        self.collect_tokens_trailing_token(attrs, force_collect, |this, mut attrs| {
+            let lo = this.token.span;
+            let vis = this.parse_visibility(FollowedByType::No)?;
+            let mut def = this.parse_defaultness();
+            let kind = this.parse_item_kind(
+                &mut attrs,
+                mac_allowed,
+                lo,
+                &vis,
+                &mut def,
+                fn_parse_mode,
+                Case::Sensitive,
+            )?;
+            if let Some((ident, kind)) = kind {
+                this.error_on_unconsumed_default(def, &kind);
+                let span = lo.to(this.prev_token.span);
+                let id = DUMMY_NODE_ID;
+                let item = Item { ident, attrs, id, kind, vis, span, tokens: None };
+                return Ok((Some(item), false));
+            }
 
-        // At this point, we have failed to parse an item.
-        if !matches!(vis.kind, VisibilityKind::Inherited) {
-            self.dcx().emit_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
-        }
+            // At this point, we have failed to parse an item.
+            if !matches!(vis.kind, VisibilityKind::Inherited) {
+                this.dcx().emit_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
+            }
 
-        if let Defaultness::Default(span) = def {
-            self.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
-        }
+            if let Defaultness::Default(span) = def {
+                this.dcx().emit_err(errors::DefaultNotFollowedByItem { span });
+            }
 
-        if !attrs_allowed {
-            self.recover_attrs_no_item(&attrs)?;
-        }
-        Ok(None)
+            if !attrs_allowed {
+                this.recover_attrs_no_item(&attrs)?;
+            }
+            Ok((None, false))
+        })
     }
 
     /// Error in-case `default` was parsed in an in-appropriate context.
@@ -1570,7 +1554,7 @@ impl<'a> Parser<'a> {
 
                 let vis = this.parse_visibility(FollowedByType::No)?;
                 if !this.recover_nested_adt_item(kw::Enum)? {
-                    return Ok((None, TrailingToken::None));
+                    return Ok((None, false));
                 }
                 let ident = this.parse_field_ident("enum", vlo)?;
 
@@ -1582,7 +1566,7 @@ impl<'a> Parser<'a> {
                     this.bump();
                     this.parse_delim_args()?;
 
-                    return Ok((None, TrailingToken::MaybeComma));
+                    return Ok((None, this.token == token::Comma));
                 }
 
                 let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
@@ -1639,7 +1623,7 @@ impl<'a> Parser<'a> {
                     is_placeholder: false,
                 };
 
-                Ok((Some(vr), TrailingToken::MaybeComma))
+                Ok((Some(vr), this.token == token::Comma))
             },
         )
         .map_err(|mut err| {
@@ -1831,7 +1815,7 @@ impl<'a> Parser<'a> {
                         attrs,
                         is_placeholder: false,
                     },
-                    TrailingToken::MaybeComma,
+                    p.token == token::Comma,
                 ))
             })
         })
@@ -1846,8 +1830,7 @@ impl<'a> Parser<'a> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
             let vis = this.parse_visibility(FollowedByType::No)?;
-            this.parse_single_struct_field(adt_ty, lo, vis, attrs)
-                .map(|field| (field, TrailingToken::None))
+            this.parse_single_struct_field(adt_ty, lo, vis, attrs).map(|field| (field, false))
         })
     }
 
@@ -2350,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.
@@ -2367,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
@@ -2395,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);
@@ -2750,7 +2800,7 @@ impl<'a> Parser<'a> {
             if let Some(mut param) = this.parse_self_param()? {
                 param.attrs = attrs;
                 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
-                return Ok((res?, TrailingToken::None));
+                return Ok((res?, false));
             }
 
             let is_name_required = match this.token.kind {
@@ -2766,7 +2816,7 @@ impl<'a> Parser<'a> {
                         this.parameter_without_type(&mut err, pat, is_name_required, first_param)
                     {
                         let guar = err.emit();
-                        Ok((dummy_arg(ident, guar), TrailingToken::None))
+                        Ok((dummy_arg(ident, guar), false))
                     } else {
                         Err(err)
                     };
@@ -2809,7 +2859,7 @@ impl<'a> Parser<'a> {
 
             Ok((
                 Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
-                TrailingToken::None,
+                false,
             ))
         })
     }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 958458eda9a..7326b9ec51f 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -91,17 +91,6 @@ pub enum ForceCollect {
     No,
 }
 
-#[derive(Debug, Eq, PartialEq)]
-pub enum TrailingToken {
-    None,
-    Semi,
-    Gt,
-    /// If the trailing token is a comma, then capture it
-    /// Otherwise, ignore the trailing token
-    MaybeComma,
-}
-
-/// Like `maybe_whole_expr`, but for things other than expressions.
 #[macro_export]
 macro_rules! maybe_whole {
     ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
@@ -232,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
@@ -436,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
     }
 
@@ -506,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))
         }
     }
 
@@ -953,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
@@ -1509,7 +1504,7 @@ impl<'a> Parser<'a> {
         self.collect_tokens_trailing_token(
             AttrWrapper::empty(),
             ForceCollect::Yes,
-            |this, _attrs| Ok((f(this)?, TrailingToken::None)),
+            |this, _attrs| Ok((f(this)?, false)),
         )
     }
 
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/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 8e8df9f0a84..18d531faeaa 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,4 +1,4 @@
-use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, TrailingToken};
+use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing};
 use crate::errors::{
     self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
     DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
@@ -392,9 +392,9 @@ impl<'a> Parser<'a> {
         // Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
         if let Ok(expr) = snapshot
             .parse_expr_dot_or_call_with(
+                AttrVec::new(),
                 self.mk_expr(pat_span, ExprKind::Dummy), // equivalent to transforming the parsed pattern into an `Expr`
                 pat_span,
-                AttrVec::new(),
             )
             .map_err(|err| err.cancel())
         {
@@ -1315,9 +1315,8 @@ impl<'a> Parser<'a> {
 
                     last_non_comma_dotdot_span = Some(this.prev_token.span);
 
-                    // We just ate a comma, so there's no need to use
-                    // `TrailingToken::Comma`
-                    Ok((field, TrailingToken::None))
+                    // We just ate a comma, so there's no need to capture a trailing token.
+                    Ok((field, false))
                 })?;
 
             fields.push(field)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 70d41de00a7..d8de7c1bfa1 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -3,7 +3,6 @@ use super::diagnostics::AttemptLocalParseRecovery;
 use super::expr::LhsExpr;
 use super::pat::{PatternLocation, RecoverComma};
 use super::path::PathStyle;
-use super::TrailingToken;
 use super::{
     AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
 };
@@ -73,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`
@@ -80,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`
@@ -87,6 +88,7 @@ impl<'a> Parser<'a> {
                 lo,
                 attrs,
                 errors::InvalidVariableDeclarationSub::UseLetNotVar,
+                force_collect,
             )?
         } else if self.check_path()
             && !self.token.is_qpath_start()
@@ -97,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(),
@@ -124,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.
@@ -149,11 +152,7 @@ impl<'a> Parser<'a> {
 
             if this.eat(&token::Not) {
                 let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
-                if this.token == token::Semi {
-                    return Ok((stmt_mac, TrailingToken::Semi));
-                } else {
-                    return Ok((stmt_mac, TrailingToken::None));
-                }
+                return Ok((stmt_mac, this.token == token::Semi));
             }
 
             let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
@@ -164,10 +163,10 @@ impl<'a> Parser<'a> {
             };
 
             let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_expr_dot_or_call_with(expr, lo, attrs)
+                this.parse_expr_dot_or_call_with(attrs, expr, lo)
             })?;
             // `DUMMY_SP` will get overwritten later in this function
-            Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None))
+            Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), false))
         })?;
 
         if let StmtKind::Expr(expr) = stmt.kind {
@@ -206,7 +205,7 @@ impl<'a> Parser<'a> {
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
-            let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?;
+            let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?;
             let e = self
                 .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?;
             StmtKind::Expr(e)
@@ -236,16 +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)),
-                    TrailingToken::None,
-                ))
-            })?;
+        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)
@@ -261,11 +257,7 @@ impl<'a> Parser<'a> {
         self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
             this.expect_keyword(kw::Let)?;
             let local = this.parse_local(attrs)?;
-            let trailing = if capture_semi && this.token.kind == token::Semi {
-                TrailingToken::Semi
-            } else {
-                TrailingToken::None
-            };
+            let trailing = capture_semi && this.token.kind == token::Semi;
             Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing))
         })
     }
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/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 0720efebf97..fb7529d93ed 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -452,7 +452,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         match ga {
             hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
             hir::GenericArg::Type(ty) => self.visit_ty(ty),
-            hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
+            hir::GenericArg::Const(ct) => self.visit_const_arg(ct),
             hir::GenericArg::Infer(inf) => self.visit_infer(inf),
         }
     }
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/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index d4dd4dd858c..d17ee8bff50 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -462,7 +462,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     // This is a box pattern.
                     ty::Adt(adt, ..) if adt.is_box() => Struct,
                     ty::Ref(..) => Ref,
-                    _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
+                    _ => span_bug!(
+                        pat.span,
+                        "pattern has unexpected type: pat: {:?}, ty: {:?}",
+                        pat.kind,
+                        ty.inner()
+                    ),
                 };
             }
             PatKind::DerefPattern { .. } => {
@@ -518,7 +523,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                             .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index()))
                             .collect();
                     }
-                    _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
+                    _ => span_bug!(
+                        pat.span,
+                        "pattern has unexpected type: pat: {:?}, ty: {}",
+                        pat.kind,
+                        ty.inner()
+                    ),
                 }
             }
             PatKind::Constant { value } => {
@@ -663,7 +673,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                             }
                         }
                     }
-                    _ => bug!("invalid type for range pattern: {}", ty.inner()),
+                    _ => span_bug!(pat.span, "invalid type for range pattern: {}", ty.inner()),
                 };
                 fields = vec![];
                 arity = 0;
@@ -674,7 +684,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                         Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize)
                     }
                     ty::Slice(_) => None,
-                    _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", ty),
+                    _ => span_bug!(pat.span, "bad ty {} for slice pattern", ty.inner()),
                 };
                 let kind = if slice.is_some() {
                     SliceKind::VarLen(prefix.len(), suffix.len())
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 4d845ab0d07..2f42fa47728 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -26,5 +26,5 @@ tracing = "0.1"
 
 [features]
 # tidy-alphabetical-start
-rustc_use_parallel_compiler = ["rustc-rayon-core"]
+rustc_use_parallel_compiler = ["dep:rustc-rayon-core"]
 # tidy-alphabetical-end
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/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index a4fdb4a0baf..1fb942de734 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -312,8 +312,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_anon_const(&mut self, constant: &'a AnonConst) {
-        let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
-        self.with_parent(def, |this| visit::walk_anon_const(this, constant));
+        // HACK(min_generic_const_args): don't create defs for anon consts if we think they will
+        // later be turned into ConstArgKind::Path's. because this is before resolve is done, we
+        // may accidentally identify a construction of a unit struct as a param and not create a
+        // def. we'll then create a def later in ast lowering in this case. the parent of nested
+        // items will be messed up, but that's ok because there can't be any if we're just looking
+        // for bare idents.
+        if constant.value.is_potential_trivial_const_arg() {
+            visit::walk_anon_const(self, constant)
+        } else {
+            let def =
+                self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
+            self.with_parent(def, |this| visit::walk_anon_const(this, constant));
+        }
     }
 
     fn visit_expr(&mut self, expr: &'a Expr) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e3917acce65..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();
             }
@@ -371,6 +371,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         };
 
         let mut suggestion = None;
+        let mut span = binding_span;
         match import.kind {
             ImportKind::Single { type_ns_only: true, .. } => {
                 suggestion = Some(format!("self as {suggested_name}"))
@@ -381,12 +382,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span) {
                         if pos <= snippet.len() {
-                            suggestion = Some(format!(
-                                "{} as {}{}",
-                                &snippet[..pos],
-                                suggested_name,
-                                if snippet.ends_with(';') { ";" } else { "" }
-                            ))
+                            span = binding_span
+                                .with_lo(binding_span.lo() + BytePos(pos as u32))
+                                .with_hi(
+                                    binding_span.hi()
+                                        - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
+                                );
+                            suggestion = Some(format!(" as {suggested_name}"));
                         }
                     }
                 }
@@ -402,9 +404,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         if let Some(suggestion) = suggestion {
-            err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion });
+            err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
         } else {
-            err.subdiagnostic(ChangeImportBinding { span: binding_span });
+            err.subdiagnostic(ChangeImportBinding { span });
         }
     }
 
@@ -796,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 {
@@ -2530,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);
             }
         }
@@ -2885,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 1d37264f96a..dc7200465d9 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2175,13 +2175,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // Handle `self` specially.
             if index == 0 && has_self {
                 let self_lifetime = self.find_lifetime_for_self(ty);
-                if let Set1::One(lifetime) = self_lifetime {
+                elision_lifetime = match self_lifetime {
                     // We found `self` elision.
-                    elision_lifetime = Elision::Self_(lifetime);
-                } else {
+                    Set1::One(lifetime) => Elision::Self_(lifetime),
+                    // `self` itself had ambiguous lifetimes, e.g.
+                    // &Box<&Self>. In this case we won't consider
+                    // taking an alternative parameter lifetime; just avoid elision
+                    // entirely.
+                    Set1::Many => Elision::Err,
                     // We do not have `self` elision: disregard the `Elision::Param` that we may
                     // have found.
-                    elision_lifetime = Elision::None;
+                    Set1::Empty => Elision::None,
                 }
             }
             debug!("(resolving function / closure) recorded parameter");
@@ -2201,15 +2205,55 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
     /// List all the lifetimes that appear in the provided type.
     fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
-        struct SelfVisitor<'r, 'a, 'tcx> {
+        /// Visits a type to find all the &references, and determines the
+        /// set of lifetimes for all of those references where the referent
+        /// contains Self.
+        struct FindReferenceVisitor<'r, 'a, 'tcx> {
             r: &'r Resolver<'a, 'tcx>,
             impl_self: Option<Res>,
             lifetime: Set1<LifetimeRes>,
         }
 
+        impl<'a> Visitor<'a> for FindReferenceVisitor<'_, '_, '_> {
+            fn visit_ty(&mut self, ty: &'a Ty) {
+                trace!("FindReferenceVisitor considering ty={:?}", ty);
+                if let TyKind::Ref(lt, _) = ty.kind {
+                    // See if anything inside the &thing contains Self
+                    let mut visitor =
+                        SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
+                    visitor.visit_ty(ty);
+                    trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
+                    if visitor.self_found {
+                        let lt_id = if let Some(lt) = lt {
+                            lt.id
+                        } else {
+                            let res = self.r.lifetimes_res_map[&ty.id];
+                            let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
+                            start
+                        };
+                        let lt_res = self.r.lifetimes_res_map[&lt_id];
+                        trace!("FindReferenceVisitor inserting res={:?}", lt_res);
+                        self.lifetime.insert(lt_res);
+                    }
+                }
+                visit::walk_ty(self, ty)
+            }
+
+            // A type may have an expression as a const generic argument.
+            // We do not want to recurse into those.
+            fn visit_expr(&mut self, _: &'a Expr) {}
+        }
+
+        /// Visitor which checks the referent of a &Thing to see if the
+        /// Thing contains Self
+        struct SelfVisitor<'r, 'a, 'tcx> {
+            r: &'r Resolver<'a, 'tcx>,
+            impl_self: Option<Res>,
+            self_found: bool,
+        }
+
         impl SelfVisitor<'_, '_, '_> {
-            // Look for `self: &'a Self` - also desugared from `&'a self`,
-            // and if that matches, use it for elision and return early.
+            // Look for `self: &'a Self` - also desugared from `&'a self`
             fn is_self_ty(&self, ty: &Ty) -> bool {
                 match ty.kind {
                     TyKind::ImplicitSelf => true,
@@ -2228,19 +2272,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> {
             fn visit_ty(&mut self, ty: &'a Ty) {
                 trace!("SelfVisitor considering ty={:?}", ty);
-                if let TyKind::Ref(lt, ref mt) = ty.kind
-                    && self.is_self_ty(&mt.ty)
-                {
-                    let lt_id = if let Some(lt) = lt {
-                        lt.id
-                    } else {
-                        let res = self.r.lifetimes_res_map[&ty.id];
-                        let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
-                        start
-                    };
-                    let lt_res = self.r.lifetimes_res_map[&lt_id];
-                    trace!("SelfVisitor inserting res={:?}", lt_res);
-                    self.lifetime.insert(lt_res);
+                if self.is_self_ty(ty) {
+                    trace!("SelfVisitor found Self");
+                    self.self_found = true;
                 }
                 visit::walk_ty(self, ty)
             }
@@ -2271,9 +2305,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
                 )
             });
-        let mut visitor = SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
+        let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
         visitor.visit_ty(ty);
-        trace!("SelfVisitor found={:?}", visitor.lifetime);
+        trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
         visitor.lifetime
     }
 
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 cfa4d174e7b..5ae01389116 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1928,6 +1928,7 @@ symbols! {
         type_ascription,
         type_changing_struct_update,
         type_id,
+        type_ir_inherent,
         type_length_limit,
         type_macros,
         type_name,
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index 4c67fa0f7aa..549706998d4 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -18,9 +18,7 @@ pub fn target() -> Target {
         relro_level: RelroLevel::Full,
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
-        features:
-            "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
-                .into(),
+        features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(),
         supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
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..ffc8839435e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1793,25 +1793,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 +1854,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,
         );
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index f67518a577e..ade26a40920 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -87,12 +87,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     ) -> Option<ty::Const<'tcx>> {
         use rustc_middle::mir::interpret::ErrorHandled;
         match self.const_eval_resolve(param_env, unevaluated, DUMMY_SP) {
-            Ok(Some(val)) => Some(ty::Const::new_value(
+            Ok(Ok(val)) => Some(ty::Const::new_value(
                 self.tcx,
                 val,
                 self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
             )),
-            Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None,
+            Ok(Err(_)) | Err(ErrorHandled::TooGeneric(_)) => None,
             Err(ErrorHandled::Reported(e, _)) => Some(ty::Const::new_error(self.tcx, e.into())),
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 1d32ef2ccd9..796f7fd5a54 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -765,8 +765,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                                 unevaluated,
                                 obligation.cause.span,
                             ) {
-                                Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args))),
-                                Ok(None) => {
+                                Ok(Ok(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args))),
+                                Ok(Err(_)) => {
                                     let tcx = self.tcx;
                                     let reported =
                                         tcx.dcx().emit_err(UnableToConstructConstantValue {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index d28982ed849..f7eb1730582 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -16,7 +16,6 @@ pub mod query;
 #[allow(hidden_glob_reexports)]
 mod select;
 mod specialize;
-mod structural_match;
 mod structural_normalize;
 #[allow(hidden_glob_reexports)]
 mod util;
@@ -60,7 +59,6 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{
     specialization_graph, translate_args, translate_args_with_cause, OverlapError,
 };
-pub use self::structural_match::search_for_structural_match_violation;
 pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
diff --git a/compiler/rustc_trait_selection/src/traits/select/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs
index 50d8e96aaf9..7ead65721f9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs
@@ -3,7 +3,7 @@ use rustc_infer::infer::relate::{
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
-use tracing::{debug, instrument};
+use tracing::instrument;
 
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// instantiated with values so as to make it equal to A. Matching is
@@ -32,11 +32,7 @@ impl<'tcx> MatchAgainstFreshVars<'tcx> {
 }
 
 impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
-    fn tag(&self) -> &'static str {
-        "MatchAgainstFreshVars"
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
@@ -50,7 +46,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
         self.relate(a, b)
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
@@ -59,7 +55,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
         Ok(a)
     }
 
-    #[instrument(skip(self), level = "debug")]
+    #[instrument(skip(self), level = "trace")]
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         if a == b {
             return Ok(a);
@@ -77,18 +73,18 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstFreshVars<'tcx> {
                 Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
             }
 
-            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
+            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)),
 
             _ => structurally_relate_tys(self, a, b),
         }
     }
 
+    #[instrument(skip(self), level = "trace")]
     fn consts(
         &mut self,
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        debug!("{}.consts({:?}, {:?})", self.tag(), a, b);
         if a == b {
             return Ok(a);
         }
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
deleted file mode 100644
index d4535db951e..00000000000
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ /dev/null
@@ -1,173 +0,0 @@
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_middle::bug;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use std::ops::ControlFlow;
-
-/// This method traverses the structure of `ty`, trying to find an
-/// instance of an ADT (i.e. struct or enum) that doesn't implement
-/// the structural-match traits, or a generic type parameter
-/// (which cannot be determined to be structural-match).
-///
-/// The "structure of a type" includes all components that would be
-/// considered when doing a pattern match on a constant of that
-/// type.
-///
-///  * This means this method descends into fields of structs/enums,
-///    and also descends into the inner type `T` of `&T` and `&mut T`
-///
-///  * The traversal doesn't dereference unsafe pointers (`*const T`,
-///    `*mut T`), and it does not visit the type arguments of an
-///    instantiated generic like `PhantomData<T>`.
-///
-/// The reason we do this search is Rust currently require all ADTs
-/// reachable from a constant's type to implement the
-/// structural-match traits, which essentially say that
-/// the implementation of `PartialEq::eq` behaves *equivalently* to a
-/// comparison against the unfolded structure.
-///
-/// For more background on why Rust has this requirement, and issues
-/// that arose when the requirement was not enforced completely, see
-/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
-pub fn search_for_structural_match_violation<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<Ty<'tcx>> {
-    ty.visit_with(&mut Search { tcx, seen: FxHashSet::default() }).break_value()
-}
-
-/// This implements the traversal over the structure of a given type to try to
-/// find instances of ADTs (specifically structs or enums) that do not implement
-/// `StructuralPartialEq`.
-struct Search<'tcx> {
-    tcx: TyCtxt<'tcx>,
-
-    /// Tracks ADTs previously encountered during search, so that
-    /// we will not recur on them again.
-    seen: FxHashSet<hir::def_id::DefId>,
-}
-
-impl<'tcx> Search<'tcx> {
-    fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
-        adt_ty.is_structural_eq_shallow(self.tcx)
-    }
-}
-
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
-    type Result = ControlFlow<Ty<'tcx>>;
-
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
-        debug!("Search visiting ty: {:?}", ty);
-
-        let (adt_def, args) = match *ty.kind() {
-            ty::Adt(adt_def, args) => (adt_def, args),
-            ty::Param(_) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Dynamic(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Foreign(_) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Alias(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Closure(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::CoroutineClosure(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::Coroutine(..) | ty::CoroutineWitness(..) => {
-                return ControlFlow::Break(ty);
-            }
-            ty::FnDef(..) => {
-                // Types of formals and return in `fn(_) -> _` are also irrelevant;
-                // so we do not recur into them via `super_visit_with`
-                return ControlFlow::Continue(());
-            }
-            ty::Array(_, n)
-                if { n.try_eval_target_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
-            {
-                // rust-lang/rust#62336: ignore type of contents
-                // for empty array.
-                return ControlFlow::Continue(());
-            }
-            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => {
-                // These primitive types are always structural match.
-                //
-                // `Never` is kind of special here, but as it is not inhabitable, this should be fine.
-                return ControlFlow::Continue(());
-            }
-
-            ty::FnPtr(..) => {
-                return ControlFlow::Continue(());
-            }
-
-            ty::RawPtr(..) => {
-                // structural-match ignores substructure of
-                // `*const _`/`*mut _`, so skip `super_visit_with`.
-                //
-                // For example, if you have:
-                // ```
-                // struct NonStructural;
-                // #[derive(PartialEq, Eq)]
-                // struct T(*const NonStructural);
-                // const C: T = T(std::ptr::null());
-                // ```
-                //
-                // Even though `NonStructural` does not implement `PartialEq`,
-                // structural equality on `T` does not recur into the raw
-                // pointer. Therefore, one can still use `C` in a pattern.
-                return ControlFlow::Continue(());
-            }
-
-            ty::Float(_) => {
-                return ControlFlow::Continue(());
-            }
-
-            ty::Pat(..) | ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
-                // First check all contained types and then tell the caller to continue searching.
-                return ty.super_visit_with(self);
-            }
-            ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
-                bug!("unexpected type during structural-match checking: {:?}", ty);
-            }
-            ty::Error(_) => {
-                // We still want to check other types after encountering an error,
-                // as this may still emit relevant errors.
-                return ControlFlow::Continue(());
-            }
-        };
-
-        if !self.seen.insert(adt_def.did()) {
-            debug!("Search already seen adt_def: {:?}", adt_def);
-            return ControlFlow::Continue(());
-        }
-
-        if !self.type_marked_structural(ty) {
-            debug!("Search found ty: {:?}", ty);
-            return ControlFlow::Break(ty);
-        }
-
-        // structural-match does not care about the
-        // instantiation of the generics in an ADT (it
-        // instead looks directly at its fields outside
-        // this match), so we skip super_visit_with.
-        //
-        // (Must not recur on args for `PhantomData<T>` cf
-        // rust-lang/rust#55028 and rust-lang/rust#55837; but also
-        // want to skip args when only uses of generic are
-        // behind unsafe pointers `*const T`/`*mut T`.)
-
-        // even though we skip super_visit_with, we must recur on
-        // fields of ADT.
-        let tcx = self.tcx;
-        adt_def.all_fields().map(|field| field.ty(tcx, args)).try_for_each(|field_ty| {
-            let ty = self.tcx.normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
-            debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
-            ty.visit_with(self)
-        })
-    }
-}
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_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index f071dc6c784..e77a05dd8e6 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -672,9 +672,21 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
             }
 
-            ty::Array(subty, _) => {
+            ty::Array(subty, len) => {
                 self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
-                // Note that we handle the len is implicitly checked while walking `arg`.
+                // Note that the len being WF is implicitly checked while visiting.
+                // Here we just check that it's of type usize.
+                let cause = self.cause(ObligationCauseCode::Misc);
+                self.out.push(traits::Obligation::with_depth(
+                    tcx,
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
+                        len,
+                        tcx.types.usize,
+                    ))),
+                ));
             }
 
             ty::Pat(subty, _) => {
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index 79939d62a51..4732e968f6b 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -18,13 +18,13 @@ tracing = "0.1"
 
 [features]
 rustc = [
-    "rustc_hir",
-    "rustc_infer",
-    "rustc_macros",
-    "rustc_middle",
-    "rustc_span",
-    "rustc_target",
-    "rustc_ast_ir",
+    "dep:rustc_hir",
+    "dep:rustc_infer",
+    "dep:rustc_macros",
+    "dep:rustc_middle",
+    "dep:rustc_span",
+    "dep:rustc_target",
+    "dep:rustc_ast_ir",
 ]
 
 [dev-dependencies]
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index e4bf6069caf..769e350b835 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -22,12 +22,12 @@ tracing = "0.1"
 [features]
 default = ["nightly"]
 nightly = [
+    "dep:rustc_serialize",
+    "dep:rustc_span",
+    "dep:rustc_data_structures",
+    "dep:rustc_macros",
     "smallvec/may_dangle",
     "smallvec/union",
     "rustc_index/nightly",
-    "rustc_serialize",
-    "rustc_span",
-    "rustc_data_structures",
-    "rustc_macros",
     "rustc_ast_ir/nightly"
 ]
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 2531219baec..17b35a2807a 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -49,10 +49,10 @@ where
 {
     type Lifted = Binder<U, T::Lifted>;
 
-    fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
+    fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
         Some(Binder {
-            value: self.value.lift_to_tcx(tcx)?,
-            bound_vars: self.bound_vars.lift_to_tcx(tcx)?,
+            value: self.value.lift_to_interner(cx)?,
+            bound_vars: self.bound_vars.lift_to_interner(cx)?,
         })
     }
 }
@@ -439,11 +439,11 @@ impl<I: Interner, Iter: IntoIterator> EarlyBinder<I, Iter>
 where
     Iter::Item: TypeFoldable<I>,
 {
-    pub fn iter_instantiated<A>(self, tcx: I, args: A) -> IterInstantiated<I, Iter, A>
+    pub fn iter_instantiated<A>(self, cx: I, args: A) -> IterInstantiated<I, Iter, A>
     where
         A: SliceLike<Item = I::GenericArg>,
     {
-        IterInstantiated { it: self.value.into_iter(), tcx, args }
+        IterInstantiated { it: self.value.into_iter(), cx, args }
     }
 
     /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
@@ -455,7 +455,7 @@ where
 
 pub struct IterInstantiated<I: Interner, Iter: IntoIterator, A> {
     it: Iter::IntoIter,
-    tcx: I,
+    cx: I,
     args: A,
 }
 
@@ -469,7 +469,7 @@ where
     fn next(&mut self) -> Option<Self::Item> {
         Some(
             EarlyBinder { value: self.it.next()?, _tcx: PhantomData }
-                .instantiate(self.tcx, self.args),
+                .instantiate(self.cx, self.args),
         )
     }
 
@@ -487,7 +487,7 @@ where
     fn next_back(&mut self) -> Option<Self::Item> {
         Some(
             EarlyBinder { value: self.it.next_back()?, _tcx: PhantomData }
-                .instantiate(self.tcx, self.args),
+                .instantiate(self.cx, self.args),
         )
     }
 }
@@ -507,10 +507,10 @@ where
 {
     pub fn iter_instantiated_copied(
         self,
-        tcx: I,
+        cx: I,
         args: &'s [I::GenericArg],
     ) -> IterInstantiatedCopied<'s, I, Iter> {
-        IterInstantiatedCopied { it: self.value.into_iter(), tcx, args }
+        IterInstantiatedCopied { it: self.value.into_iter(), cx, args }
     }
 
     /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
@@ -522,7 +522,7 @@ where
 
 pub struct IterInstantiatedCopied<'a, I: Interner, Iter: IntoIterator> {
     it: Iter::IntoIter,
-    tcx: I,
+    cx: I,
     args: &'a [I::GenericArg],
 }
 
@@ -535,7 +535,7 @@ where
 
     fn next(&mut self) -> Option<Self::Item> {
         self.it.next().map(|value| {
-            EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args)
+            EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.cx, self.args)
         })
     }
 
@@ -552,7 +552,7 @@ where
 {
     fn next_back(&mut self) -> Option<Self::Item> {
         self.it.next_back().map(|value| {
-            EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args)
+            EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.cx, self.args)
         })
     }
 }
@@ -589,11 +589,11 @@ impl<I: Interner, T: Iterator> Iterator for EarlyBinderIter<I, T> {
 }
 
 impl<I: Interner, T: TypeFoldable<I>> ty::EarlyBinder<I, T> {
-    pub fn instantiate<A>(self, tcx: I, args: A) -> T
+    pub fn instantiate<A>(self, cx: I, args: A) -> T
     where
         A: SliceLike<Item = I::GenericArg>,
     {
-        let mut folder = ArgFolder { tcx, args: args.as_slice(), binders_passed: 0 };
+        let mut folder = ArgFolder { cx, args: args.as_slice(), binders_passed: 0 };
         self.value.fold_with(&mut folder)
     }
 
@@ -619,7 +619,7 @@ impl<I: Interner, T: TypeFoldable<I>> ty::EarlyBinder<I, T> {
 // The actual instantiation engine itself is a type folder.
 
 struct ArgFolder<'a, I: Interner> {
-    tcx: I,
+    cx: I,
     args: &'a [I::GenericArg],
 
     /// Number of region binders we have passed through while doing the instantiation
@@ -629,7 +629,7 @@ struct ArgFolder<'a, I: Interner> {
 impl<'a, I: Interner> TypeFolder<I> for ArgFolder<'a, I> {
     #[inline]
     fn cx(&self) -> I {
-        self.tcx
+        self.cx
     }
 
     fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
@@ -858,6 +858,6 @@ impl<'a, I: Interner> ArgFolder<'a, I> {
         if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
             return region;
         }
-        ty::fold::shift_region(self.tcx, region, self.binders_passed)
+        ty::fold::shift_region(self.cx, region, self.binders_passed)
     }
 }
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 7b114f565f2..a9252711b2b 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -330,25 +330,25 @@ impl<I: Interner> CanonicalVarValues<I> {
 
     // Given a list of canonical variables, construct a set of values which are
     // the identity response.
-    pub fn make_identity(tcx: I, infos: I::CanonicalVars) -> CanonicalVarValues<I> {
+    pub fn make_identity(cx: I, infos: I::CanonicalVars) -> CanonicalVarValues<I> {
         CanonicalVarValues {
-            var_values: tcx.mk_args_from_iter(infos.iter().enumerate().map(
+            var_values: cx.mk_args_from_iter(infos.iter().enumerate().map(
                 |(i, info)| -> I::GenericArg {
                     match info.kind {
                         CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
-                            Ty::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                            Ty::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
                         CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
-                            Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                            Region::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
                         CanonicalVarKind::Effect => {
-                            Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                            Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
                         CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
-                            Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
+                            Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
                                 .into()
                         }
                     }
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 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/effects.rs b/compiler/rustc_type_ir/src/effects.rs
index f7942f2f982..a29e0a43bef 100644
--- a/compiler/rustc_type_ir/src/effects.rs
+++ b/compiler/rustc_type_ir/src/effects.rs
@@ -1,4 +1,4 @@
-use crate::inherent::{AdtDef, IntoKind, Ty};
+use crate::inherent::*;
 use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
 use crate::Interner;
 
@@ -10,38 +10,38 @@ pub enum EffectKind {
 }
 
 impl EffectKind {
-    pub fn try_from_def_id<I: Interner>(tcx: I, def_id: I::DefId) -> Option<EffectKind> {
-        if tcx.is_lang_item(def_id, EffectsMaybe) {
+    pub fn try_from_def_id<I: Interner>(cx: I, def_id: I::DefId) -> Option<EffectKind> {
+        if cx.is_lang_item(def_id, EffectsMaybe) {
             Some(EffectKind::Maybe)
-        } else if tcx.is_lang_item(def_id, EffectsRuntime) {
+        } else if cx.is_lang_item(def_id, EffectsRuntime) {
             Some(EffectKind::Runtime)
-        } else if tcx.is_lang_item(def_id, EffectsNoRuntime) {
+        } else if cx.is_lang_item(def_id, EffectsNoRuntime) {
             Some(EffectKind::NoRuntime)
         } else {
             None
         }
     }
 
-    pub fn to_def_id<I: Interner>(self, tcx: I) -> I::DefId {
+    pub fn to_def_id<I: Interner>(self, cx: I) -> I::DefId {
         let lang_item = match self {
             EffectKind::Maybe => EffectsMaybe,
             EffectKind::NoRuntime => EffectsNoRuntime,
             EffectKind::Runtime => EffectsRuntime,
         };
 
-        tcx.require_lang_item(lang_item)
+        cx.require_lang_item(lang_item)
     }
 
-    pub fn try_from_ty<I: Interner>(tcx: I, ty: I::Ty) -> Option<EffectKind> {
+    pub fn try_from_ty<I: Interner>(cx: I, ty: I::Ty) -> Option<EffectKind> {
         if let crate::Adt(def, _) = ty.kind() {
-            Self::try_from_def_id(tcx, def.def_id())
+            Self::try_from_def_id(cx, def.def_id())
         } else {
             None
         }
     }
 
-    pub fn to_ty<I: Interner>(self, tcx: I) -> I::Ty {
-        I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default())
+    pub fn to_ty<I: Interner>(self, cx: I) -> I::Ty {
+        I::Ty::new_adt(cx, cx.adt_def(self.to_def_id(cx)), Default::default())
     }
 
     /// Returns an intersection between two effect kinds. If one effect kind
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 0def7d12f74..7dd2f3de3f8 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -258,17 +258,17 @@ pub fn supertrait_def_ids<I: Interner>(
 }
 
 pub fn supertraits<I: Interner>(
-    tcx: I,
+    cx: I,
     trait_ref: ty::Binder<I, ty::TraitRef<I>>,
 ) -> FilterToTraits<I, Elaborator<I, I::Clause>> {
-    elaborate(tcx, [trait_ref.upcast(tcx)]).filter_only_self().filter_to_traits()
+    elaborate(cx, [trait_ref.upcast(cx)]).filter_only_self().filter_to_traits()
 }
 
 pub fn transitive_bounds<I: Interner>(
-    tcx: I,
+    cx: I,
     trait_refs: impl Iterator<Item = ty::Binder<I, ty::TraitRef<I>>>,
 ) -> FilterToTraits<I, Elaborator<I, I::Clause>> {
-    elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx)))
+    elaborate(cx, trait_refs.map(|trait_ref| trait_ref.upcast(cx)))
         .filter_only_self()
         .filter_to_traits()
 }
diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs
index 0810fa5c558..456accd1a1b 100644
--- a/compiler/rustc_type_ir/src/fast_reject.rs
+++ b/compiler/rustc_type_ir/src/fast_reject.rs
@@ -105,7 +105,7 @@ pub enum TreatParams {
 ///
 /// ¹ meaning that if the outermost layers are different, then the whole types are also different.
 pub fn simplify_type<I: Interner>(
-    tcx: I,
+    cx: I,
     ty: I::Ty,
     treat_params: TreatParams,
 ) -> Option<SimplifiedType<I::DefId>> {
@@ -119,10 +119,10 @@ pub fn simplify_type<I: Interner>(
         ty::Str => Some(SimplifiedType::Str),
         ty::Array(..) => Some(SimplifiedType::Array),
         ty::Slice(..) => Some(SimplifiedType::Slice),
-        ty::Pat(ty, ..) => simplify_type(tcx, ty, treat_params),
+        ty::Pat(ty, ..) => simplify_type(cx, ty, treat_params),
         ty::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(mutbl)),
         ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
-            Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
+            Some(principal_def_id) if !cx.trait_is_auto(principal_def_id) => {
                 Some(SimplifiedType::Trait(principal_def_id))
             }
             _ => Some(SimplifiedType::MarkerTraitObject),
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index 09ee12d1cc3..a4d8dafb246 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -345,20 +345,20 @@ impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix,
 // `rustc_middle/src/ty/generic_args.rs` for more details.
 
 struct Shifter<I: Interner> {
-    tcx: I,
+    cx: I,
     current_index: ty::DebruijnIndex,
     amount: u32,
 }
 
 impl<I: Interner> Shifter<I> {
-    pub fn new(tcx: I, amount: u32) -> Self {
-        Shifter { tcx, current_index: ty::INNERMOST, amount }
+    pub fn new(cx: I, amount: u32) -> Self {
+        Shifter { cx, current_index: ty::INNERMOST, amount }
     }
 }
 
 impl<I: Interner> TypeFolder<I> for Shifter<I> {
     fn cx(&self) -> I {
-        self.tcx
+        self.cx
     }
 
     fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
@@ -372,7 +372,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
         match r.kind() {
             ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                Region::new_bound(self.tcx, debruijn, br)
+                Region::new_bound(self.cx, debruijn, br)
             }
             _ => r,
         }
@@ -382,7 +382,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
         match ty.kind() {
             ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                Ty::new_bound(self.tcx, debruijn, bound_ty)
+                Ty::new_bound(self.cx, debruijn, bound_ty)
             }
 
             _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
@@ -394,7 +394,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
         match ct.kind() {
             ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                Const::new_bound(self.tcx, debruijn, bound_ct)
+                Const::new_bound(self.cx, debruijn, bound_ct)
             }
             _ => ct.super_fold_with(self),
         }
@@ -405,16 +405,16 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
     }
 }
 
-pub fn shift_region<I: Interner>(tcx: I, region: I::Region, amount: u32) -> I::Region {
+pub fn shift_region<I: Interner>(cx: I, region: I::Region, amount: u32) -> I::Region {
     match region.kind() {
         ty::ReBound(debruijn, br) if amount > 0 => {
-            Region::new_bound(tcx, debruijn.shifted_in(amount), br)
+            Region::new_bound(cx, debruijn.shifted_in(amount), br)
         }
         _ => region,
     }
 }
 
-pub fn shift_vars<I: Interner, T>(tcx: I, value: T, amount: u32) -> T
+pub fn shift_vars<I: Interner, T>(cx: I, value: T, amount: u32) -> T
 where
     T: TypeFoldable<I>,
 {
@@ -424,5 +424,5 @@ where
         return value;
     }
 
-    value.fold_with(&mut Shifter::new(tcx, amount))
+    value.fold_with(&mut Shifter::new(cx, amount))
 }
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index f05d626b470..63ad36efc85 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -475,7 +475,7 @@ pub trait Clause<I: Interner<Clause = Self>>:
     /// poly-trait-ref to supertraits that must hold if that
     /// poly-trait-ref holds. This is slightly different from a normal
     /// instantiation in terms of what happens with bound regions.
-    fn instantiate_supertrait(self, tcx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
+    fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
 }
 
 /// Common capabilities of placeholder kinds
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 37ee66fa222..80e970a23a9 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -24,6 +24,7 @@ pub mod elaborate;
 pub mod error;
 pub mod fast_reject;
 pub mod fold;
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")]
 pub mod inherent;
 pub mod ir_print;
 pub mod lang_items;
diff --git a/compiler/rustc_type_ir/src/lift.rs b/compiler/rustc_type_ir/src/lift.rs
index 839da10db5e..e5a099d1f50 100644
--- a/compiler/rustc_type_ir/src/lift.rs
+++ b/compiler/rustc_type_ir/src/lift.rs
@@ -17,5 +17,5 @@
 /// e.g., `()` or `u8`, was interned in a different context.
 pub trait Lift<I>: std::fmt::Debug {
     type Lifted: std::fmt::Debug;
-    fn lift_to_tcx(self, tcx: I) -> Option<Self::Lifted>;
+    fn lift_to_interner(self, cx: I) -> Option<Self::Lifted>;
 }
diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs
index d8ed4770e2d..e5d18fcb3d1 100644
--- a/compiler/rustc_type_ir/src/opaque_ty.rs
+++ b/compiler/rustc_type_ir/src/opaque_ty.rs
@@ -22,8 +22,8 @@ pub struct OpaqueTypeKey<I: Interner> {
 }
 
 impl<I: Interner> OpaqueTypeKey<I> {
-    pub fn iter_captured_args(self, tcx: I) -> impl Iterator<Item = (usize, I::GenericArg)> {
-        let variances = tcx.variances_of(self.def_id.into());
+    pub fn iter_captured_args(self, cx: I) -> impl Iterator<Item = (usize, I::GenericArg)> {
+        let variances = cx.variances_of(self.def_id.into());
         std::iter::zip(self.args.iter(), variances.iter()).enumerate().filter_map(
             |(i, (arg, v))| match (arg.kind(), v) {
                 (_, ty::Invariant) => Some((i, arg)),
@@ -35,18 +35,18 @@ impl<I: Interner> OpaqueTypeKey<I> {
 
     pub fn fold_captured_lifetime_args(
         self,
-        tcx: I,
+        cx: I,
         mut f: impl FnMut(I::Region) -> I::Region,
     ) -> Self {
         let Self { def_id, args } = self;
-        let variances = tcx.variances_of(def_id.into());
+        let variances = cx.variances_of(def_id.into());
         let args =
             std::iter::zip(args.iter(), variances.iter()).map(|(arg, v)| match (arg.kind(), v) {
                 (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
                 (ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(),
                 _ => arg,
             });
-        let args = tcx.mk_args_from_iter(args);
+        let args = cx.mk_args_from_iter(args);
         Self { def_id, args }
     }
 }
diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs
index 10b6f3355d9..eb84f3dd587 100644
--- a/compiler/rustc_type_ir/src/outlives.rs
+++ b/compiler/rustc_type_ir/src/outlives.rs
@@ -54,15 +54,15 @@ pub enum Component<I: Interner> {
 /// Push onto `out` all the things that must outlive `'a` for the condition
 /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
 pub fn push_outlives_components<I: Interner>(
-    tcx: I,
+    cx: I,
     ty: I::Ty,
     out: &mut SmallVec<[Component<I>; 4]>,
 ) {
-    ty.visit_with(&mut OutlivesCollector { tcx, out, visited: Default::default() });
+    ty.visit_with(&mut OutlivesCollector { cx, out, visited: Default::default() });
 }
 
 struct OutlivesCollector<'a, I: Interner> {
-    tcx: I,
+    cx: I,
     out: &'a mut SmallVec<[Component<I>; 4]>,
     visited: SsoHashSet<I::Ty>,
 }
@@ -147,7 +147,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
                     // OutlivesProjectionComponents. Continue walking
                     // through and constrain Pi.
                     let mut subcomponents = smallvec![];
-                    compute_alias_components_recursive(self.tcx, ty, &mut subcomponents);
+                    compute_alias_components_recursive(self.cx, ty, &mut subcomponents);
                     self.out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
                 }
             }
@@ -206,7 +206,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
 /// This should not be used to get the components of `parent` itself.
 /// Use [push_outlives_components] instead.
 pub fn compute_alias_components_recursive<I: Interner>(
-    tcx: I,
+    cx: I,
     alias_ty: I::Ty,
     out: &mut SmallVec<[Component<I>; 4]>,
 ) {
@@ -215,9 +215,9 @@ pub fn compute_alias_components_recursive<I: Interner>(
     };
 
     let opt_variances =
-        if kind == ty::Opaque { Some(tcx.variances_of(alias_ty.def_id)) } else { None };
+        if kind == ty::Opaque { Some(cx.variances_of(alias_ty.def_id)) } else { None };
 
-    let mut visitor = OutlivesCollector { tcx, out, visited: Default::default() };
+    let mut visitor = OutlivesCollector { cx, out, visited: Default::default() };
 
     for (index, child) in alias_ty.args.iter().enumerate() {
         if opt_variances.and_then(|variances| variances.get(index)) == Some(ty::Bivariant) {
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index e5bcbc67f94..e03f521c5b1 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -34,8 +34,8 @@ where
 {
     type Lifted = OutlivesPredicate<U, A::Lifted>;
 
-    fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
-        Some(OutlivesPredicate(self.0.lift_to_tcx(tcx)?, self.1.lift_to_tcx(tcx)?))
+    fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
+        Some(OutlivesPredicate(self.0.lift_to_interner(cx)?, self.1.lift_to_interner(cx)?))
     }
 }
 
@@ -267,25 +267,23 @@ impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
     /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
     /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
     /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
-    pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> I::Clause {
+    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
         match self.skip_binder() {
-            ExistentialPredicate::Trait(tr) => {
-                self.rebind(tr).with_self_ty(tcx, self_ty).upcast(tcx)
-            }
+            ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx),
             ExistentialPredicate::Projection(p) => {
-                self.rebind(p.with_self_ty(tcx, self_ty)).upcast(tcx)
+                self.rebind(p.with_self_ty(cx, self_ty)).upcast(cx)
             }
             ExistentialPredicate::AutoTrait(did) => {
-                let generics = tcx.generics_of(did);
+                let generics = cx.generics_of(did);
                 let trait_ref = if generics.count() == 1 {
-                    ty::TraitRef::new(tcx, did, [self_ty])
+                    ty::TraitRef::new(cx, did, [self_ty])
                 } else {
                     // If this is an ill-formed auto trait, then synthesize
                     // new error args for the missing generics.
-                    let err_args = GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
-                    ty::TraitRef::new_from_args(tcx, did, err_args)
+                    let err_args = GenericArgs::extend_with_error(cx, did, &[self_ty.into()]);
+                    ty::TraitRef::new_from_args(cx, did, err_args)
                 };
-                self.rebind(trait_ref).upcast(tcx)
+                self.rebind(trait_ref).upcast(cx)
             }
         }
     }
@@ -345,8 +343,8 @@ impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self type. A common choice is `mk_err()`
     /// or some placeholder type.
-    pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
-        self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty))
+    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
+        self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty))
     }
 }
 
@@ -406,8 +404,8 @@ impl<I: Interner> ExistentialProjection<I> {
 }
 
 impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
-    pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
-        self.map_bound(|p| p.with_self_ty(tcx, self_ty))
+    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
+        self.map_bound(|p| p.with_self_ty(cx, self_ty))
     }
 
     pub fn item_def_id(&self) -> I::DefId {
@@ -669,21 +667,21 @@ impl<I: Interner> ProjectionPredicate<I> {
 impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
     /// Returns the `DefId` of the trait of the associated item being projected.
     #[inline]
-    pub fn trait_def_id(&self, tcx: I) -> I::DefId {
-        self.skip_binder().projection_term.trait_def_id(tcx)
+    pub fn trait_def_id(&self, cx: I) -> I::DefId {
+        self.skip_binder().projection_term.trait_def_id(cx)
     }
 
     /// Get the trait ref required for this projection to be well formed.
     /// Note that for generic associated types the predicates of the associated
     /// type also need to be checked.
     #[inline]
-    pub fn required_poly_trait_ref(&self, tcx: I) -> ty::Binder<I, TraitRef<I>> {
+    pub fn required_poly_trait_ref(&self, cx: I) -> ty::Binder<I, TraitRef<I>> {
         // Note: unlike with `TraitRef::to_poly_trait_ref()`,
         // `self.0.trait_ref` is permitted to have escaping regions.
         // This is because here `self` has a `Binder` and so does our
         // return value, so we are preserving the number of binding
         // levels.
-        self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx))
+        self.map_bound(|predicate| predicate.projection_term.trait_ref(cx))
     }
 
     pub fn term(&self) -> ty::Binder<I, I::Term> {
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/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index 0439e7f857f..ae840ec0210 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -1,7 +1,7 @@
 use std::iter;
 
 use rustc_ast_ir::Mutability;
-use tracing::{debug, instrument};
+use tracing::{instrument, trace};
 
 use crate::error::{ExpectedFound, TypeError};
 use crate::fold::TypeFoldable;
@@ -56,10 +56,7 @@ impl<I: Interner> VarianceDiagInfo<I> {
 }
 
 pub trait TypeRelation<I: Interner>: Sized {
-    fn tcx(&self) -> I;
-
-    /// Returns a static string we can use for printouts.
-    fn tag(&self) -> &'static str;
+    fn cx(&self) -> I;
 
     /// Generic relation routine suitable for most anything.
     fn relate<T: Relate<I>>(&mut self, a: T, b: T) -> RelateResult<I, T> {
@@ -69,19 +66,15 @@ pub trait TypeRelation<I: Interner>: Sized {
     /// Relate the two args for the given item. The default
     /// is to look up the variance for the item and proceed
     /// accordingly.
+    #[instrument(skip(self), level = "trace")]
     fn relate_item_args(
         &mut self,
         item_def_id: I::DefId,
         a_arg: I::GenericArgs,
         b_arg: I::GenericArgs,
     ) -> RelateResult<I, I::GenericArgs> {
-        debug!(
-            "relate_item_args(item_def_id={:?}, a_arg={:?}, b_arg={:?})",
-            item_def_id, a_arg, b_arg
-        );
-
-        let tcx = self.tcx();
-        let opt_variances = tcx.variances_of(item_def_id);
+        let cx = self.cx();
+        let opt_variances = cx.variances_of(item_def_id);
         relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, true)
     }
 
@@ -128,7 +121,7 @@ pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
     a_arg: I::GenericArgs,
     b_arg: I::GenericArgs,
 ) -> RelateResult<I, I::GenericArgs> {
-    relation.tcx().mk_args_from_iter(iter::zip(a_arg.iter(), b_arg.iter()).map(|(a, b)| {
+    relation.cx().mk_args_from_iter(iter::zip(a_arg.iter(), b_arg.iter()).map(|(a, b)| {
         relation.relate_with_variance(ty::Invariant, VarianceDiagInfo::default(), a, b)
     }))
 }
@@ -141,14 +134,13 @@ pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
     b_arg: I::GenericArgs,
     fetch_ty_for_diag: bool,
 ) -> RelateResult<I, I::GenericArgs> {
-    let tcx = relation.tcx();
+    let cx = relation.cx();
 
     let mut cached_ty = None;
     let params = iter::zip(a_arg.iter(), b_arg.iter()).enumerate().map(|(i, (a, b))| {
         let variance = variances.get(i).unwrap();
         let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
-            let ty =
-                *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, a_arg));
+            let ty = *cached_ty.get_or_insert_with(|| cx.type_of(ty_def_id).instantiate(cx, a_arg));
             VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
         } else {
             VarianceDiagInfo::default()
@@ -156,7 +148,7 @@ pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
         relation.relate_with_variance(variance, variance_info, a, b)
     });
 
-    tcx.mk_args_from_iter(params)
+    cx.mk_args_from_iter(params)
 }
 
 impl<I: Interner> Relate<I> for ty::FnSig<I> {
@@ -165,7 +157,7 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
         a: ty::FnSig<I>,
         b: ty::FnSig<I>,
     ) -> RelateResult<I, ty::FnSig<I>> {
-        let tcx = relation.tcx();
+        let cx = relation.cx();
 
         if a.c_variadic != b.c_variadic {
             return Err(TypeError::VariadicMismatch({
@@ -210,7 +202,7 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
                 r => r,
             });
         Ok(ty::FnSig {
-            inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
+            inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
             c_variadic: a.c_variadic,
             safety,
             abi,
@@ -245,11 +237,11 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
                 ExpectedFound::new(true, a, b)
             }))
         } else {
-            let args = match a.kind(relation.tcx()) {
+            let args = match a.kind(relation.cx()) {
                 ty::Opaque => relate_args_with_variances(
                     relation,
                     a.def_id,
-                    relation.tcx().variances_of(a.def_id),
+                    relation.cx().variances_of(a.def_id),
                     a.args,
                     b.args,
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
@@ -258,7 +250,7 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }
             };
-            Ok(ty::AliasTy::new_from_args(relation.tcx(), a.def_id, args))
+            Ok(ty::AliasTy::new_from_args(relation.cx(), a.def_id, args))
         }
     }
 }
@@ -276,11 +268,11 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
                 ExpectedFound::new(true, a, b)
             }))
         } else {
-            let args = match a.kind(relation.tcx()) {
+            let args = match a.kind(relation.cx()) {
                 ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
                     relation,
                     a.def_id,
-                    relation.tcx().variances_of(a.def_id),
+                    relation.cx().variances_of(a.def_id),
                     a.args,
                     b.args,
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
@@ -293,7 +285,7 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }
             };
-            Ok(ty::AliasTerm::new_from_args(relation.tcx(), a.def_id, args))
+            Ok(ty::AliasTerm::new_from_args(relation.cx(), a.def_id, args))
         }
     }
 }
@@ -343,7 +335,7 @@ impl<I: Interner> Relate<I> for ty::TraitRef<I> {
             }))
         } else {
             let args = relate_args_invariantly(relation, a.args, b.args)?;
-            Ok(ty::TraitRef::new_from_args(relation.tcx(), a.def_id, args))
+            Ok(ty::TraitRef::new_from_args(relation.cx(), a.def_id, args))
         }
     }
 }
@@ -377,7 +369,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
     a: I::Ty,
     b: I::Ty,
 ) -> RelateResult<I, I::Ty> {
-    let tcx = relation.tcx();
+    let cx = relation.cx();
     match (a.kind(), b.kind()) {
         (ty::Infer(_), _) | (_, ty::Infer(_)) => {
             // The caller should handle these cases!
@@ -388,7 +380,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             panic!("bound types encountered in structurally_relate_tys")
         }
 
-        (ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
+        (ty::Error(guar), _) | (_, ty::Error(guar)) => Ok(Ty::new_error(cx, guar)),
 
         (ty::Never, _)
         | (ty::Char, _)
@@ -412,16 +404,16 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
 
         (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
             let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?;
-            Ok(Ty::new_adt(tcx, a_def, args))
+            Ok(Ty::new_adt(cx, a_def, args))
         }
 
-        (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
+        (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)),
 
         (ty::Dynamic(a_obj, a_region, a_repr), ty::Dynamic(b_obj, b_region, b_repr))
             if a_repr == b_repr =>
         {
             Ok(Ty::new_dynamic(
-                tcx,
+                cx,
                 relation.relate(a_obj, b_obj)?,
                 relation.relate(a_region, b_region)?,
                 a_repr,
@@ -433,7 +425,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             // the (anonymous) type of the same coroutine expression. So
             // all of their regions should be equated.
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine(tcx, a_id, args))
+            Ok(Ty::new_coroutine(cx, a_id, args))
         }
 
         (ty::CoroutineWitness(a_id, a_args), ty::CoroutineWitness(b_id, b_args))
@@ -443,7 +435,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             // the (anonymous) type of the same coroutine expression. So
             // all of their regions should be equated.
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine_witness(tcx, a_id, args))
+            Ok(Ty::new_coroutine_witness(cx, a_id, args))
         }
 
         (ty::Closure(a_id, a_args), ty::Closure(b_id, b_args)) if a_id == b_id => {
@@ -451,14 +443,14 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_closure(tcx, a_id, args))
+            Ok(Ty::new_closure(cx, a_id, args))
         }
 
         (ty::CoroutineClosure(a_id, a_args), ty::CoroutineClosure(b_id, b_args))
             if a_id == b_id =>
         {
             let args = relate_args_invariantly(relation, a_args, b_args)?;
-            Ok(Ty::new_coroutine_closure(tcx, a_id, args))
+            Ok(Ty::new_coroutine_closure(cx, a_id, args))
         }
 
         (ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
@@ -475,7 +467,7 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
 
             let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
 
-            Ok(Ty::new_ptr(tcx, ty, a_mutbl))
+            Ok(Ty::new_ptr(cx, ty, a_mutbl))
         }
 
         (ty::Ref(a_r, a_ty, a_mutbl), ty::Ref(b_r, b_ty, b_mutbl)) => {
@@ -493,18 +485,18 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             let r = relation.relate(a_r, b_r)?;
             let ty = relation.relate_with_variance(variance, info, a_ty, b_ty)?;
 
-            Ok(Ty::new_ref(tcx, r, ty, a_mutbl))
+            Ok(Ty::new_ref(cx, r, ty, a_mutbl))
         }
 
         (ty::Array(a_t, sz_a), ty::Array(b_t, sz_b)) => {
             let t = relation.relate(a_t, b_t)?;
             match relation.relate(sz_a, sz_b) {
-                Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
+                Ok(sz) => Ok(Ty::new_array_with_const_len(cx, t, sz)),
                 Err(err) => {
                     // Check whether the lengths are both concrete/known values,
                     // but are unequal, for better diagnostics.
-                    let sz_a = sz_a.try_to_target_usize(tcx);
-                    let sz_b = sz_b.try_to_target_usize(tcx);
+                    let sz_a = sz_a.try_to_target_usize(cx);
+                    let sz_b = sz_b.try_to_target_usize(cx);
 
                     match (sz_a, sz_b) {
                         (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
@@ -518,13 +510,13 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
 
         (ty::Slice(a_t), ty::Slice(b_t)) => {
             let t = relation.relate(a_t, b_t)?;
-            Ok(Ty::new_slice(tcx, t))
+            Ok(Ty::new_slice(cx, t))
         }
 
         (ty::Tuple(as_), ty::Tuple(bs)) => {
             if as_.len() == bs.len() {
                 Ok(Ty::new_tup_from_iter(
-                    tcx,
+                    cx,
                     iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)),
                 )?)
             } else if !(as_.is_empty() || bs.is_empty()) {
@@ -536,25 +528,25 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
 
         (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
             let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
-            Ok(Ty::new_fn_def(tcx, a_def_id, args))
+            Ok(Ty::new_fn_def(cx, a_def_id, args))
         }
 
         (ty::FnPtr(a_fty), ty::FnPtr(b_fty)) => {
             let fty = relation.relate(a_fty, b_fty)?;
-            Ok(Ty::new_fn_ptr(tcx, fty))
+            Ok(Ty::new_fn_ptr(cx, fty))
         }
 
         // Alias tend to mostly already be handled downstream due to normalization.
         (ty::Alias(a_kind, a_data), ty::Alias(b_kind, b_data)) => {
             let alias_ty = relation.relate(a_data, b_data)?;
             assert_eq!(a_kind, b_kind);
-            Ok(Ty::new_alias(tcx, a_kind, alias_ty))
+            Ok(Ty::new_alias(cx, a_kind, alias_ty))
         }
 
         (ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => {
             let ty = relation.relate(a_ty, b_ty)?;
             let pat = relation.relate(a_pat, b_pat)?;
-            Ok(Ty::new_pat(tcx, ty, pat))
+            Ok(Ty::new_pat(cx, ty, pat))
         }
 
         _ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))),
@@ -572,15 +564,25 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
     mut a: I::Const,
     mut b: I::Const,
 ) -> RelateResult<I, I::Const> {
-    debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
-    let tcx = relation.tcx();
-
-    if tcx.features().generic_const_exprs() {
-        a = tcx.expand_abstract_consts(a);
-        b = tcx.expand_abstract_consts(b);
+    trace!(
+        "structurally_relate_consts::<{}>(a = {:?}, b = {:?})",
+        std::any::type_name::<R>(),
+        a,
+        b
+    );
+    let cx = relation.cx();
+
+    if cx.features().generic_const_exprs() {
+        a = cx.expand_abstract_consts(a);
+        b = cx.expand_abstract_consts(b);
     }
 
-    debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+    trace!(
+        "structurally_relate_consts::<{}>(normed_a = {:?}, normed_b = {:?})",
+        std::any::type_name::<R>(),
+        a,
+        b
+    );
 
     // Currently, the values that can be unified are primitive types,
     // and those that derive both `PartialEq` and `Eq`, corresponding
@@ -607,8 +609,8 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
         // be stabilized.
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
             if cfg!(debug_assertions) {
-                let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args);
-                let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args);
+                let a_ty = cx.type_of(au.def).instantiate(cx, au.args);
+                let b_ty = cx.type_of(bu.def).instantiate(cx, bu.args);
                 assert_eq!(a_ty, b_ty);
             }
 
@@ -618,11 +620,11 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
                 au.args,
                 bu.args,
             )?;
-            return Ok(Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
+            return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst { def: au.def, args }));
         }
         (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
             let expr = relation.relate(ae, be)?;
-            return Ok(Const::new_expr(tcx, expr));
+            return Ok(Const::new_expr(cx, expr));
         }
         _ => false,
     };
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 7934f996f0b..2449ac47db6 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -106,13 +106,13 @@ pub struct Goal<I: Interner, P> {
 }
 
 impl<I: Interner, P> Goal<I, P> {
-    pub fn new(tcx: I, param_env: I::ParamEnv, predicate: impl Upcast<I, P>) -> Goal<I, P> {
-        Goal { param_env, predicate: predicate.upcast(tcx) }
+    pub fn new(cx: I, param_env: I::ParamEnv, predicate: impl Upcast<I, P>) -> Goal<I, P> {
+        Goal { param_env, predicate: predicate.upcast(cx) }
     }
 
     /// Updates the goal to one with a different `predicate` but the same `param_env`.
-    pub fn with<Q>(self, tcx: I, predicate: impl Upcast<I, Q>) -> Goal<I, Q> {
-        Goal { param_env: self.param_env, predicate: predicate.upcast(tcx) }
+    pub fn with<Q>(self, cx: I, predicate: impl Upcast<I, Q>) -> Goal<I, Q> {
+        Goal { param_env: self.param_env, predicate: predicate.upcast(cx) }
     }
 }
 
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/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs
index 24a7c0c67e9..6c5bbbfd59b 100644
--- a/compiler/rustc_type_ir/src/ty_kind/closure.rs
+++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs
@@ -136,9 +136,9 @@ pub struct ClosureArgsParts<I: Interner> {
 impl<I: Interner> ClosureArgs<I> {
     /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args`
     /// for the closure parent, alongside additional closure-specific components.
-    pub fn new(tcx: I, parts: ClosureArgsParts<I>) -> ClosureArgs<I> {
+    pub fn new(cx: I, parts: ClosureArgsParts<I>) -> ClosureArgs<I> {
         ClosureArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().chain([
+            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
                 parts.closure_kind_ty.into(),
                 parts.closure_sig_as_fn_ptr_ty.into(),
                 parts.tupled_upvars_ty.into(),
@@ -258,9 +258,9 @@ pub struct CoroutineClosureArgsParts<I: Interner> {
 }
 
 impl<I: Interner> CoroutineClosureArgs<I> {
-    pub fn new(tcx: I, parts: CoroutineClosureArgsParts<I>) -> CoroutineClosureArgs<I> {
+    pub fn new(cx: I, parts: CoroutineClosureArgsParts<I>) -> CoroutineClosureArgs<I> {
         CoroutineClosureArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().chain([
+            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
                 parts.closure_kind_ty.into(),
                 parts.signature_parts_ty.into(),
                 parts.tupled_upvars_ty.into(),
@@ -409,14 +409,14 @@ impl<I: Interner> CoroutineClosureSignature<I> {
     /// When the kind and upvars are known, use the other helper functions.
     pub fn to_coroutine(
         self,
-        tcx: I,
+        cx: I,
         parent_args: I::GenericArgsSlice,
         coroutine_kind_ty: I::Ty,
         coroutine_def_id: I::DefId,
         tupled_upvars_ty: I::Ty,
     ) -> I::Ty {
         let coroutine_args = ty::CoroutineArgs::new(
-            tcx,
+            cx,
             ty::CoroutineArgsParts {
                 parent_args,
                 kind_ty: coroutine_kind_ty,
@@ -428,7 +428,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
             },
         );
 
-        Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args)
+        Ty::new_coroutine(cx, coroutine_def_id, coroutine_args.args)
     }
 
     /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine
@@ -438,7 +438,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
     /// that the `ClosureKind` is actually supported by the coroutine-closure.
     pub fn to_coroutine_given_kind_and_upvars(
         self,
-        tcx: I,
+        cx: I,
         parent_args: I::GenericArgsSlice,
         coroutine_def_id: I::DefId,
         goal_kind: ty::ClosureKind,
@@ -447,7 +447,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
         coroutine_captures_by_ref_ty: I::Ty,
     ) -> I::Ty {
         let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind(
-            tcx,
+            cx,
             goal_kind,
             self.tupled_inputs_ty,
             closure_tupled_upvars_ty,
@@ -456,9 +456,9 @@ impl<I: Interner> CoroutineClosureSignature<I> {
         );
 
         self.to_coroutine(
-            tcx,
+            cx,
             parent_args,
-            Ty::from_coroutine_closure_kind(tcx, goal_kind),
+            Ty::from_coroutine_closure_kind(cx, goal_kind),
             coroutine_def_id,
             tupled_upvars_ty,
         )
@@ -474,7 +474,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
     /// lifetimes are related to the lifetime of the borrow on the closure made for
     /// the call. This allows borrowck to enforce the self-borrows correctly.
     pub fn tupled_upvars_by_closure_kind(
-        tcx: I,
+        cx: I,
         kind: ty::ClosureKind,
         tupled_inputs_ty: I::Ty,
         closure_tupled_upvars_ty: I::Ty,
@@ -488,12 +488,12 @@ impl<I: Interner> CoroutineClosureSignature<I> {
                 };
                 let coroutine_captures_by_ref_ty =
                     sig.output().skip_binder().fold_with(&mut FoldEscapingRegions {
-                        interner: tcx,
+                        interner: cx,
                         region: env_region,
                         debruijn: ty::INNERMOST,
                     });
                 Ty::new_tup_from_iter(
-                    tcx,
+                    cx,
                     tupled_inputs_ty
                         .tuple_fields()
                         .iter()
@@ -501,7 +501,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
                 )
             }
             ty::ClosureKind::FnOnce => Ty::new_tup_from_iter(
-                tcx,
+                cx,
                 tupled_inputs_ty
                     .tuple_fields()
                     .iter()
@@ -615,9 +615,9 @@ pub struct CoroutineArgsParts<I: Interner> {
 impl<I: Interner> CoroutineArgs<I> {
     /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args`
     /// for the coroutine parent, alongside additional coroutine-specific components.
-    pub fn new(tcx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
+    pub fn new(cx: I, parts: CoroutineArgsParts<I>) -> CoroutineArgs<I> {
         CoroutineArgs {
-            args: tcx.mk_args_from_iter(parts.parent_args.iter().chain([
+            args: cx.mk_args_from_iter(parts.parent_args.iter().chain([
                 parts.kind_ty.into(),
                 parts.resume_ty.into(),
                 parts.yield_ty.into(),
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index 000bcf2d3b2..f5b90424afb 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -71,7 +71,7 @@ fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
             wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift<J, Lifted = #lifted_ty> });
             let bind = &bindings[index];
             quote! {
-                #bind.lift_to_tcx(interner)?
+                #bind.lift_to_interner(interner)?
             }
         })
     });
@@ -89,7 +89,7 @@ fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
         quote! {
             type Lifted = #lifted_ty;
 
-            fn lift_to_tcx(
+            fn lift_to_interner(
                 self,
                 interner: J,
             ) -> Option<Self::Lifted> {
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/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/intrinsics.rs b/library/core/src/intrinsics.rs
index 720da0feece..c4c63883389 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -947,7 +947,6 @@ extern "rust-intrinsic" {
     #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
     #[rustc_nounwind]
     pub fn unreachable() -> !;
-
 }
 
 /// Informs the optimizer that a condition is always true.
@@ -1018,78 +1017,40 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn breakpoint();
 
-    /// The size of a type in bytes.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// More specifically, this is the offset in bytes between successive
-    /// items of the same type, including alignment padding.
-    ///
-    /// The stabilized version of this intrinsic is [`core::mem::size_of`].
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn size_of<T>() -> usize;
 
-    /// The minimum alignment of a type.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized version of this intrinsic is [`core::mem::align_of`].
+    #[cfg(bootstrap)]
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn min_align_of<T>() -> usize;
-    /// The preferred alignment of a type.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971).
+
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
     #[rustc_nounwind]
     pub fn pref_align_of<T>() -> usize;
 
-    /// The size of the referenced value in bytes.
-    ///
-    /// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
     #[rustc_nounwind]
     pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-    /// The required alignment of the referenced value.
-    ///
-    /// The stabilized version of this intrinsic is [`core::mem::align_of_val`].
+
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
     #[rustc_nounwind]
     pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
 
-    /// Gets a static string slice containing the name of a type.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized version of this intrinsic is [`core::any::type_name`].
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
-    /// Gets an identifier which is globally unique to the specified type. This
-    /// function will return the same value for a type regardless of whichever
-    /// crate it is invoked in.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2424,15 +2385,7 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
 
-    /// Returns the number of variants of the type `T` cast to a `usize`;
-    /// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
+    #[cfg(bootstrap)]
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
@@ -2773,8 +2726,11 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
     // Runtime NOP
 }
 
-/// `ptr` must point to a vtable.
 /// The intrinsic will return the size stored in that vtable.
+///
+/// # Safety
+///
+/// `ptr` must point to a vtable.
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
@@ -2783,8 +2739,11 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
     unreachable!()
 }
 
-/// `ptr` must point to a vtable.
 /// The intrinsic will return the alignment stored in that vtable.
+///
+/// # Safety
+///
+/// `ptr` must point to a vtable.
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
@@ -2793,6 +2752,150 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
     unreachable!()
 }
 
+/// The size of a type in bytes.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// More specifically, this is the offset in bytes between successive
+/// items of the same type, including alignment padding.
+///
+/// The stabilized version of this intrinsic is [`core::mem::size_of`].
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const fn size_of<T>() -> usize {
+    unreachable!()
+}
+
+/// The minimum alignment of a type.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized version of this intrinsic is [`core::mem::align_of`].
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const fn min_align_of<T>() -> usize {
+    unreachable!()
+}
+
+/// The preferred alignment of a type.
+///
+/// This intrinsic does not have a stable counterpart.
+/// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971).
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const unsafe fn pref_align_of<T>() -> usize {
+    unreachable!()
+}
+
+/// Returns the number of variants of the type `T` cast to a `usize`;
+/// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const fn variant_count<T>() -> usize {
+    unreachable!()
+}
+
+/// The size of the referenced value in bytes.
+///
+/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
+///
+/// # Safety
+///
+/// See [`crate::mem::size_of_val_raw`] for safety conditions.
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
+    unreachable!()
+}
+
+/// The required alignment of the referenced value.
+///
+/// The stabilized version of this intrinsic is [`core::mem::align_of_val`].
+///
+/// # Safety
+///
+/// See [`crate::mem::align_of_val_raw`] for safety conditions.
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
+    unreachable!()
+}
+
+/// Gets a static string slice containing the name of a type.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized version of this intrinsic is [`core::any::type_name`].
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const fn type_name<T: ?Sized>() -> &'static str {
+    unreachable!()
+}
+
+/// Gets an identifier which is globally unique to the specified type. This
+/// function will return the same value for a type regardless of whichever
+/// crate it is invoked in.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[cfg(not(bootstrap))]
+pub const fn type_id<T: ?Sized + 'static>() -> u128 {
+    unreachable!()
+}
+
 /// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.
 ///
 /// This is used to implement functions like `slice::from_raw_parts_mut` and
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 8ec7716012f..1a8fe1e6051 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -770,6 +770,13 @@ impl<T> Option<T> {
         }
     }
 
+    #[inline]
+    const fn len(&self) -> usize {
+        // Using the intrinsic avoids emitting a branch to get the 0 or 1.
+        let discriminant: isize = crate::intrinsics::discriminant_value(self);
+        discriminant as usize
+    }
+
     /// Returns a slice of the contained value, if any. If this is `None`, an
     /// empty slice is returned. This can be useful to have a single type of
     /// iterator over an `Option` or slice.
@@ -812,7 +819,7 @@ impl<T> Option<T> {
         unsafe {
             slice::from_raw_parts(
                 (self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
-                self.is_some() as usize,
+                self.len(),
             )
         }
     }
@@ -869,7 +876,7 @@ impl<T> Option<T> {
         unsafe {
             slice::from_raw_parts_mut(
                 (self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(),
-                self.is_some() as usize,
+                self.len(),
             )
         }
     }
@@ -2242,10 +2249,8 @@ impl<A> Iterator for Item<A> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        match self.opt {
-            Some(_) => (1, Some(1)),
-            None => (0, Some(0)),
-        }
+        let len = self.len();
+        (len, Some(len))
     }
 }
 
@@ -2256,7 +2261,12 @@ impl<A> DoubleEndedIterator for Item<A> {
     }
 }
 
-impl<A> ExactSizeIterator for Item<A> {}
+impl<A> ExactSizeIterator for Item<A> {
+    #[inline]
+    fn len(&self) -> usize {
+        self.opt.len()
+    }
+}
 impl<A> FusedIterator for Item<A> {}
 unsafe impl<A> TrustedLen for Item<A> {}
 
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index eb86bf66206..06f205c0f26 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -5,6 +5,7 @@ use crate::hash::{Hash, Hasher};
 use crate::intrinsics::aggregate_raw_ptr;
 use crate::intrinsics::ptr_metadata;
 use crate::marker::Freeze;
+use crate::ptr::NonNull;
 
 /// Provides the pointer metadata type of any pointed-to type.
 ///
@@ -153,7 +154,7 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
 /// compare equal (since identical vtables can be deduplicated within a codegen unit).
 #[lang = "dyn_metadata"]
 pub struct DynMetadata<Dyn: ?Sized> {
-    _vtable_ptr: &'static VTable,
+    _vtable_ptr: NonNull<VTable>,
     _phantom: crate::marker::PhantomData<Dyn>,
 }
 
@@ -166,15 +167,18 @@ extern "C" {
 }
 
 impl<Dyn: ?Sized> DynMetadata<Dyn> {
-    /// One of the things that rustc_middle does with this being a lang item is
-    /// give it `FieldsShape::Primitive`, which means that as far as codegen can
-    /// tell, it *is* a reference, and thus doesn't have any fields.
-    /// That means we can't use field access, and have to transmute it instead.
+    /// When `DynMetadata` appears as the metadata field of a wide pointer, the rustc_middle layout
+    /// computation does magic and the resulting layout is *not* a `FieldsShape::Aggregate`, instead
+    /// it is a `FieldsShape::Primitive`. This means that the same type can have different layout
+    /// depending on whether it appears as the metadata field of a wide pointer or as a stand-alone
+    /// type, which understandably confuses codegen and leads to ICEs when trying to project to a
+    /// field of `DynMetadata`. To work around that issue, we use `transmute` instead of using a
+    /// field projection.
     #[inline]
     fn vtable_ptr(self) -> *const VTable {
         // SAFETY: this layout assumption is hard-coded into the compiler.
         // If it's somehow not a size match, the transmute will error.
-        unsafe { crate::mem::transmute::<Self, &'static VTable>(self) }
+        unsafe { crate::mem::transmute::<Self, *const VTable>(self) }
     }
 
     /// Returns the size of the type associated with this vtable.
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/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/macros.rs b/library/std/src/macros.rs
index 972b6015932..ba519afc62b 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -230,7 +230,7 @@ macro_rules! eprintln {
 /// ```rust
 /// let a = 2;
 /// let b = dbg!(a * 2) + 1;
-/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
+/// //      ^-- prints: [src/main.rs:2:9] a * 2 = 4
 /// assert_eq!(b, 5);
 /// ```
 ///
@@ -281,7 +281,7 @@ macro_rules! eprintln {
 /// This prints to [stderr]:
 ///
 /// ```text,ignore
-/// [src/main.rs:4] n.checked_sub(4) = None
+/// [src/main.rs:2:22] n.checked_sub(4) = None
 /// ```
 ///
 /// Naive factorial implementation:
@@ -301,15 +301,15 @@ macro_rules! eprintln {
 /// This prints to [stderr]:
 ///
 /// ```text,ignore
-/// [src/main.rs:3] n <= 1 = false
-/// [src/main.rs:3] n <= 1 = false
-/// [src/main.rs:3] n <= 1 = false
-/// [src/main.rs:3] n <= 1 = true
-/// [src/main.rs:4] 1 = 1
-/// [src/main.rs:5] n * factorial(n - 1) = 2
-/// [src/main.rs:5] n * factorial(n - 1) = 6
-/// [src/main.rs:5] n * factorial(n - 1) = 24
-/// [src/main.rs:11] factorial(4) = 24
+/// [src/main.rs:2:8] n <= 1 = false
+/// [src/main.rs:2:8] n <= 1 = false
+/// [src/main.rs:2:8] n <= 1 = false
+/// [src/main.rs:2:8] n <= 1 = true
+/// [src/main.rs:3:9] 1 = 1
+/// [src/main.rs:7:9] n * factorial(n - 1) = 2
+/// [src/main.rs:7:9] n * factorial(n - 1) = 6
+/// [src/main.rs:7:9] n * factorial(n - 1) = 24
+/// [src/main.rs:9:1] factorial(4) = 24
 /// ```
 ///
 /// The `dbg!(..)` macro moves the input:
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index a1f83029d27..5833c597256 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -24,9 +24,14 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// passed as an argument, it is not captured or consumed, and it never has the
 /// value `-1`.
 ///
-/// This type's `.to_owned()` implementation returns another `BorrowedFd`
-/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
-/// descriptor, which is then borrowed under the same lifetime.
+/// This type does not have a [`ToOwned`][crate::borrow::ToOwned]
+/// implementation. Calling `.to_owned()` on a variable of this type will call
+/// it on `&BorrowedFd` and use `Clone::clone()` like `ToOwned` does for all
+/// types implementing `Clone`. The result will be descriptor borrowed under
+/// the same lifetime.
+///
+/// To obtain an [`OwnedFd`], you can use [`BorrowedFd::try_clone_to_owned`]
+/// instead, but this is not supported on all platforms.
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -50,6 +55,8 @@ pub struct BorrowedFd<'fd> {
 /// descriptor, so it can be used in FFI in places where a file descriptor is
 /// passed as a consumed argument or returned as an owned value, and it never
 /// has the value `-1`.
+///
+/// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`].
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
 // libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
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/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 042c439394e..84a0b36db17 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -1,12 +1,14 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
+use cfg_if::cfg_if;
+
 use crate::cell::UnsafeCell;
 use crate::fmt;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
 use crate::sys::sync as sys;
+use crate::thread::{current_id, ThreadId};
 
 /// A re-entrant mutual exclusion lock
 ///
@@ -53,8 +55,8 @@ use crate::sys::sync as sys;
 //
 // The 'owner' field tracks which thread has locked the mutex.
 //
-// We use current_thread_unique_ptr() as the thread identifier,
-// which is just the address of a thread local variable.
+// We use thread::current_id() as the thread identifier, which is just the
+// current thread's ThreadId, so it's unique across the process lifetime.
 //
 // If `owner` is set to the identifier of the current thread,
 // we assume the mutex is already locked and instead of locking it again,
@@ -72,14 +74,109 @@ use crate::sys::sync as sys;
 // since we're not dealing with multiple threads. If it's not equal,
 // synchronization is left to the mutex, making relaxed memory ordering for
 // the `owner` field fine in all cases.
+//
+// On systems without 64 bit atomics we also store the address of a TLS variable
+// along the 64-bit TID. We then first check that address against the address
+// of that variable on the current thread, and only if they compare equal do we
+// compare the actual TIDs. Because we only ever read the TID on the same thread
+// that it was written on (or a thread sharing the TLS block with that writer thread),
+// we don't need to further synchronize the TID accesses, so they can be regular 64-bit
+// non-atomic accesses.
 #[unstable(feature = "reentrant_lock", issue = "121440")]
 pub struct ReentrantLock<T: ?Sized> {
     mutex: sys::Mutex,
-    owner: AtomicUsize,
+    owner: Tid,
     lock_count: UnsafeCell<u32>,
     data: T,
 }
 
+cfg_if!(
+    if #[cfg(target_has_atomic = "64")] {
+        use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};
+
+        struct Tid(AtomicU64);
+
+        impl Tid {
+            const fn new() -> Self {
+                Self(AtomicU64::new(0))
+            }
+
+            #[inline]
+            fn contains(&self, owner: ThreadId) -> bool {
+                owner.as_u64().get() == self.0.load(Relaxed)
+            }
+
+            #[inline]
+            // This is just unsafe to match the API of the Tid type below.
+            unsafe fn set(&self, tid: Option<ThreadId>) {
+                let value = tid.map_or(0, |tid| tid.as_u64().get());
+                self.0.store(value, Relaxed);
+            }
+        }
+    } else {
+        /// Returns the address of a TLS variable. This is guaranteed to
+        /// be unique across all currently alive threads.
+        fn tls_addr() -> usize {
+            thread_local! { static X: u8 = const { 0u8 } };
+
+            X.with(|p| <*const u8>::addr(p))
+        }
+
+        use crate::sync::atomic::{
+            AtomicUsize,
+            Ordering,
+        };
+
+        struct Tid {
+            // When a thread calls `set()`, this value gets updated to
+            // the address of a thread local on that thread. This is
+            // used as a first check in `contains()`; if the `tls_addr`
+            // doesn't match the TLS address of the current thread, then
+            // the ThreadId also can't match. Only if the TLS addresses do
+            // match do we read out the actual TID.
+            // Note also that we can use relaxed atomic operations here, because
+            // we only ever read from the tid if `tls_addr` matches the current
+            // TLS address. In that case, either the the tid has been set by
+            // the current thread, or by a thread that has terminated before
+            // the current thread was created. In either case, no further
+            // synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
+            tls_addr: AtomicUsize,
+            tid: UnsafeCell<u64>,
+        }
+
+        unsafe impl Send for Tid {}
+        unsafe impl Sync for Tid {}
+
+        impl Tid {
+            const fn new() -> Self {
+                Self { tls_addr: AtomicUsize::new(0), tid: UnsafeCell::new(0) }
+            }
+
+            #[inline]
+            // NOTE: This assumes that `owner` is the ID of the current
+            // thread, and may spuriously return `false` if that's not the case.
+            fn contains(&self, owner: ThreadId) -> bool {
+                // SAFETY: See the comments in the struct definition.
+                self.tls_addr.load(Ordering::Relaxed) == tls_addr()
+                    && unsafe { *self.tid.get() } == owner.as_u64().get()
+            }
+
+            #[inline]
+            // This may only be called by one thread at a time, and can lead to
+            // race conditions otherwise.
+            unsafe fn set(&self, tid: Option<ThreadId>) {
+                // It's important that we set `self.tls_addr` to 0 if the tid is
+                // cleared. Otherwise, there might be race conditions between
+                // `set()` and `get()`.
+                let tls_addr = if tid.is_some() { tls_addr() } else { 0 };
+                let value = tid.map_or(0, |tid| tid.as_u64().get());
+                self.tls_addr.store(tls_addr, Ordering::Relaxed);
+                unsafe { *self.tid.get() = value };
+            }
+        }
+    }
+);
+
 #[unstable(feature = "reentrant_lock", issue = "121440")]
 unsafe impl<T: Send + ?Sized> Send for ReentrantLock<T> {}
 #[unstable(feature = "reentrant_lock", issue = "121440")]
@@ -134,7 +231,7 @@ impl<T> ReentrantLock<T> {
     pub const fn new(t: T) -> ReentrantLock<T> {
         ReentrantLock {
             mutex: sys::Mutex::new(),
-            owner: AtomicUsize::new(0),
+            owner: Tid::new(),
             lock_count: UnsafeCell::new(0),
             data: t,
         }
@@ -184,14 +281,16 @@ impl<T: ?Sized> ReentrantLock<T> {
     /// assert_eq!(lock.lock().get(), 10);
     /// ```
     pub fn lock(&self) -> ReentrantLockGuard<'_, T> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
+        let this_thread = current_id();
+        // Safety: We only touch lock_count when we own the inner mutex.
+        // Additionally, we only call `self.owner.set()` while holding
+        // the inner mutex, so no two threads can call it concurrently.
         unsafe {
-            if self.owner.load(Relaxed) == this_thread {
+            if self.owner.contains(this_thread) {
                 self.increment_lock_count().expect("lock count overflow in reentrant mutex");
             } else {
                 self.mutex.lock();
-                self.owner.store(this_thread, Relaxed);
+                self.owner.set(Some(this_thread));
                 debug_assert_eq!(*self.lock_count.get(), 0);
                 *self.lock_count.get() = 1;
             }
@@ -226,14 +325,16 @@ impl<T: ?Sized> ReentrantLock<T> {
     ///
     /// This function does not block.
     pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
+        let this_thread = current_id();
+        // Safety: We only touch lock_count when we own the inner mutex.
+        // Additionally, we only call `self.owner.set()` while holding
+        // the inner mutex, so no two threads can call it concurrently.
         unsafe {
-            if self.owner.load(Relaxed) == this_thread {
+            if self.owner.contains(this_thread) {
                 self.increment_lock_count()?;
                 Some(ReentrantLockGuard { lock: self })
             } else if self.mutex.try_lock() {
-                self.owner.store(this_thread, Relaxed);
+                self.owner.set(Some(this_thread));
                 debug_assert_eq!(*self.lock_count.get(), 0);
                 *self.lock_count.get() = 1;
                 Some(ReentrantLockGuard { lock: self })
@@ -308,18 +409,9 @@ impl<T: ?Sized> Drop for ReentrantLockGuard<'_, T> {
         unsafe {
             *self.lock.lock_count.get() -= 1;
             if *self.lock.lock_count.get() == 0 {
-                self.lock.owner.store(0, Relaxed);
+                self.lock.owner.set(None);
                 self.lock.mutex.unlock();
             }
         }
     }
 }
-
-/// Get an address that is unique per running thread.
-///
-/// This can be used as a non-null usize-sized ID.
-pub(crate) fn current_thread_unique_ptr() -> usize {
-    // Use a non-drop type to make sure it's still available during thread destruction.
-    thread_local! { static X: u8 = const { 0 } }
-    X.with(|x| <*const _>::addr(x))
-}
diff --git a/library/std/src/sys/os_str/mod.rs b/library/std/src/sys/os_str/mod.rs
index b509729475b..345e661586d 100644
--- a/library/std/src/sys/os_str/mod.rs
+++ b/library/std/src/sys/os_str/mod.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
 cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "windows",
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index edb923a4750..806bf033dbc 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -1,6 +1,5 @@
 //! The underlying OsString/OsStr implementation on Windows is a
 //! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
-
 use crate::borrow::Cow;
 use crate::collections::TryReserveError;
 use crate::fmt;
@@ -71,7 +70,7 @@ impl Buf {
 
     #[inline]
     pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self {
-        Self { inner: Wtf8Buf::from_bytes_unchecked(s) }
+        unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
     }
 
     pub fn with_capacity(capacity: usize) -> Buf {
@@ -190,7 +189,7 @@ impl Slice {
 
     #[inline]
     pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
-        mem::transmute(Wtf8::from_bytes_unchecked(s))
+        unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
     }
 
     #[track_caller]
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/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 2e5bd85327a..6eeec48bf5e 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -44,6 +44,7 @@ mod imp {
     use crate::ops::Range;
     use crate::ptr;
     use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
+    use crate::sync::OnceLock;
     use crate::sys::pal::unix::os;
     use crate::thread;
 
@@ -86,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.
@@ -104,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.
         }
@@ -116,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 {
@@ -186,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
@@ -222,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) };
         }
     }
 
@@ -306,9 +342,8 @@ mod imp {
         ret
     }
 
-    unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
-        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
-        let stackptr = get_stack_start()?;
+    fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> {
+        let stackptr = unsafe { get_stack_start()? };
         let stackaddr = stackptr.addr();
 
         // Ensure stackaddr is page aligned! A parent process might
@@ -325,107 +360,137 @@ mod imp {
         })
     }
 
+    #[forbid(unsafe_op_in_unsafe_fn)]
     unsafe fn install_main_guard() -> Option<Range<usize>> {
         let page_size = PAGE_SIZE.load(Ordering::Relaxed);
-        if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
-            // Linux doesn't allocate the whole stack right away, and
-            // the kernel has its own stack-guard mechanism to fault
-            // when growing too close to an existing mapping. If we map
-            // our own guard, then the kernel starts enforcing a rather
-            // large gap above that, rendering much of the possible
-            // stack space useless. See #43052.
-            //
-            // Instead, we'll just note where we expect rlimit to start
-            // faulting, so our handler can report "stack overflow", and
-            // trust that the kernel's own stack guard will work.
-            let stackptr = get_stack_start_aligned()?;
-            let stackaddr = stackptr.addr();
-            Some(stackaddr - page_size..stackaddr)
-        } else if cfg!(all(target_os = "linux", target_env = "musl")) {
-            // For the main thread, the musl's pthread_attr_getstack
-            // returns the current stack size, rather than maximum size
-            // it can eventually grow to. It cannot be used to determine
-            // the position of kernel's stack guard.
-            None
-        } else if cfg!(target_os = "freebsd") {
-            // FreeBSD's stack autogrows, and optionally includes a guard page
-            // at the bottom. If we try to remap the bottom of the stack
-            // ourselves, FreeBSD's guard page moves upwards. So we'll just use
-            // the builtin guard page.
-            let stackptr = get_stack_start_aligned()?;
-            let guardaddr = stackptr.addr();
-            // Technically the number of guard pages is tunable and controlled
-            // by the security.bsd.stack_guard_page sysctl.
-            // By default it is 1, checking once is enough since it is
-            // a boot time config value.
-            static PAGES: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new();
-
-            let pages = PAGES.get_or_init(|| {
-                use crate::sys::weak::dlsym;
-                dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
-                let mut guard: usize = 0;
-                let mut size = crate::mem::size_of_val(&guard);
-                let oid = crate::ffi::CStr::from_bytes_with_nul(
-                    b"security.bsd.stack_guard_page\0",
-                )
-                .unwrap();
-                match sysctlbyname.get() {
-                    Some(fcn) => {
-                        if fcn(oid.as_ptr(), core::ptr::addr_of_mut!(guard) as *mut _, core::ptr::addr_of_mut!(size) as *mut _, crate::ptr::null_mut(), 0) == 0 {
-                            guard
-                        } else {
-                            1
-                        }
-                    },
-                    _ => 1,
-                }
-            });
-            Some(guardaddr..guardaddr + pages * page_size)
-        } else if cfg!(any(target_os = "openbsd", target_os = "netbsd")) {
-            // OpenBSD stack already includes a guard page, and stack is
-            // immutable.
-            // NetBSD stack includes the guard page.
-            //
-            // We'll just note where we expect rlimit to start
-            // faulting, so our handler can report "stack overflow", and
-            // trust that the kernel's own stack guard will work.
-            let stackptr = get_stack_start_aligned()?;
-            let stackaddr = stackptr.addr();
-            Some(stackaddr - page_size..stackaddr)
-        } else {
-            // Reallocate the last page of the stack.
-            // This ensures SIGBUS will be raised on
-            // stack overflow.
-            // Systems which enforce strict PAX MPROTECT do not allow
-            // to mprotect() a mapping with less restrictive permissions
-            // than the initial mmap() used, so we mmap() here with
-            // read/write permissions and only then mprotect() it to
-            // no permissions at all. See issue #50313.
-            let stackptr = get_stack_start_aligned()?;
-            let result = mmap64(
+
+        unsafe {
+            // this way someone on any unix-y OS can check that all these compile
+            if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
+                install_main_guard_linux(page_size)
+            } else if cfg!(all(target_os = "linux", target_env = "musl")) {
+                install_main_guard_linux_musl(page_size)
+            } else if cfg!(target_os = "freebsd") {
+                install_main_guard_freebsd(page_size)
+            } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) {
+                install_main_guard_bsds(page_size)
+            } else {
+                install_main_guard_default(page_size)
+            }
+        }
+    }
+
+    #[forbid(unsafe_op_in_unsafe_fn)]
+    unsafe fn install_main_guard_linux(page_size: usize) -> Option<Range<usize>> {
+        // Linux doesn't allocate the whole stack right away, and
+        // the kernel has its own stack-guard mechanism to fault
+        // when growing too close to an existing mapping. If we map
+        // our own guard, then the kernel starts enforcing a rather
+        // large gap above that, rendering much of the possible
+        // stack space useless. See #43052.
+        //
+        // Instead, we'll just note where we expect rlimit to start
+        // faulting, so our handler can report "stack overflow", and
+        // trust that the kernel's own stack guard will work.
+        let stackptr = stack_start_aligned(page_size)?;
+        let stackaddr = stackptr.addr();
+        Some(stackaddr - page_size..stackaddr)
+    }
+
+    #[forbid(unsafe_op_in_unsafe_fn)]
+    unsafe fn install_main_guard_linux_musl(_page_size: usize) -> Option<Range<usize>> {
+        // For the main thread, the musl's pthread_attr_getstack
+        // returns the current stack size, rather than maximum size
+        // it can eventually grow to. It cannot be used to determine
+        // the position of kernel's stack guard.
+        None
+    }
+
+    #[forbid(unsafe_op_in_unsafe_fn)]
+    unsafe fn install_main_guard_freebsd(page_size: usize) -> Option<Range<usize>> {
+        // FreeBSD's stack autogrows, and optionally includes a guard page
+        // at the bottom. If we try to remap the bottom of the stack
+        // ourselves, FreeBSD's guard page moves upwards. So we'll just use
+        // the builtin guard page.
+        let stackptr = stack_start_aligned(page_size)?;
+        let guardaddr = stackptr.addr();
+        // Technically the number of guard pages is tunable and controlled
+        // by the security.bsd.stack_guard_page sysctl.
+        // By default it is 1, checking once is enough since it is
+        // a boot time config value.
+        static PAGES: OnceLock<usize> = OnceLock::new();
+
+        let pages = PAGES.get_or_init(|| {
+            use crate::sys::weak::dlsym;
+            dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
+            let mut guard: usize = 0;
+            let mut size = mem::size_of_val(&guard);
+            let oid = c"security.bsd.stack_guard_page";
+            match sysctlbyname.get() {
+                Some(fcn) if unsafe {
+                    fcn(oid.as_ptr(),
+                        ptr::addr_of_mut!(guard).cast(),
+                        ptr::addr_of_mut!(size),
+                        ptr::null_mut(),
+                        0) == 0
+                } => guard,
+                _ => 1,
+            }
+        });
+        Some(guardaddr..guardaddr + pages * page_size)
+    }
+
+    #[forbid(unsafe_op_in_unsafe_fn)]
+    unsafe fn install_main_guard_bsds(page_size: usize) -> Option<Range<usize>> {
+        // OpenBSD stack already includes a guard page, and stack is
+        // immutable.
+        // NetBSD stack includes the guard page.
+        //
+        // We'll just note where we expect rlimit to start
+        // faulting, so our handler can report "stack overflow", and
+        // trust that the kernel's own stack guard will work.
+        let stackptr = stack_start_aligned(page_size)?;
+        let stackaddr = stackptr.addr();
+        Some(stackaddr - page_size..stackaddr)
+    }
+
+    #[forbid(unsafe_op_in_unsafe_fn)]
+    unsafe fn install_main_guard_default(page_size: usize) -> Option<Range<usize>> {
+        // Reallocate the last page of the stack.
+        // This ensures SIGBUS will be raised on
+        // stack overflow.
+        // Systems which enforce strict PAX MPROTECT do not allow
+        // to mprotect() a mapping with less restrictive permissions
+        // than the initial mmap() used, so we mmap() here with
+        // read/write permissions and only then mprotect() it to
+        // no permissions at all. See issue #50313.
+        let stackptr = stack_start_aligned(page_size)?;
+        let result = unsafe {
+            mmap64(
                 stackptr,
                 page_size,
                 PROT_READ | PROT_WRITE,
                 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                 -1,
                 0,
-            );
-            if result != stackptr || result == MAP_FAILED {
-                panic!("failed to allocate a guard page: {}", io::Error::last_os_error());
-            }
+            )
+        };
+        if result != stackptr || result == MAP_FAILED {
+            panic!("failed to allocate a guard page: {}", io::Error::last_os_error());
+        }
 
-            let result = mprotect(stackptr, page_size, PROT_NONE);
-            if result != 0 {
-                panic!("failed to protect the guard page: {}", io::Error::last_os_error());
-            }
+        let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) };
+        if result != 0 {
+            panic!("failed to protect the guard page: {}", io::Error::last_os_error());
+        }
 
-            let guardaddr = stackptr.addr();
+        let guardaddr = stackptr.addr();
 
-            Some(guardaddr..guardaddr + page_size)
-        }
+        Some(guardaddr..guardaddr + page_size)
     }
 
     #[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();
@@ -440,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/alloc.rs b/library/std/src/sys/pal/windows/alloc.rs
index 9f0194492b0..987be6b69ee 100644
--- a/library/std/src/sys/pal/windows/alloc.rs
+++ b/library/std/src/sys/pal/windows/alloc.rs
@@ -1,5 +1,3 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::ffi::c_void;
 use crate::ptr;
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 85fd9153d53..15d446786ad 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -1,4 +1,3 @@
-#![allow(unsafe_op_in_unsafe_fn)]
 use core::ptr::addr_of;
 
 use crate::os::windows::prelude::*;
@@ -33,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>,
@@ -378,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),
@@ -414,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,
@@ -795,10 +800,12 @@ impl<'a> Iterator for DirBuffIter<'a> {
 }
 
 unsafe fn from_maybe_unaligned<'a>(p: *const u16, len: usize) -> Cow<'a, [u16]> {
-    if p.is_aligned() {
-        Cow::Borrowed(crate::slice::from_raw_parts(p, len))
-    } else {
-        Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect())
+    unsafe {
+        if p.is_aligned() {
+            Cow::Borrowed(crate::slice::from_raw_parts(p, len))
+        } else {
+            Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect())
+        }
     }
 }
 
@@ -897,7 +904,9 @@ impl IntoRawHandle for File {
 
 impl FromRawHandle for File {
     unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
-        Self { handle: FromInner::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
+        unsafe {
+            Self { handle: FromInner::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
+        }
     }
 }
 
@@ -954,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
     }
@@ -973,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
@@ -1427,10 +1441,12 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
         _hDestinationFile: c::HANDLE,
         lpData: *const c_void,
     ) -> u32 {
-        if dwStreamNumber == 1 {
-            *(lpData as *mut i64) = StreamBytesTransferred;
+        unsafe {
+            if dwStreamNumber == 1 {
+                *(lpData as *mut i64) = StreamBytesTransferred;
+            }
+            c::PROGRESS_CONTINUE
         }
-        c::PROGRESS_CONTINUE
     }
     let pfrom = maybe_verbatim(from)?;
     let pto = maybe_verbatim(to)?;
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
index cb802fdd9c9..c54810e06cd 100644
--- a/library/std/src/sys/pal/windows/futex.rs
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -15,6 +15,7 @@ pub type SmallAtomic = AtomicU8;
 /// Must be the underlying type of SmallAtomic
 pub type SmallPrimitive = u8;
 
+pub unsafe trait Futex {}
 pub unsafe trait Waitable {
     type Atomic;
 }
@@ -24,6 +25,7 @@ macro_rules! unsafe_waitable_int {
             unsafe impl Waitable for $int {
                 type Atomic = $atomic;
             }
+            unsafe impl Futex for $atomic {}
         )*
     };
 }
@@ -46,6 +48,7 @@ unsafe impl<T> Waitable for *const T {
 unsafe impl<T> Waitable for *mut T {
     type Atomic = AtomicPtr<T>;
 }
+unsafe impl<T> Futex for AtomicPtr<T> {}
 
 pub fn wait_on_address<W: Waitable>(
     address: &W::Atomic,
@@ -61,14 +64,14 @@ pub fn wait_on_address<W: Waitable>(
     }
 }
 
-pub fn wake_by_address_single<T>(address: &T) {
+pub fn wake_by_address_single<T: Futex>(address: &T) {
     unsafe {
         let addr = ptr::from_ref(address).cast::<c_void>();
         c::WakeByAddressSingle(addr);
     }
 }
 
-pub fn wake_by_address_all<T>(address: &T) {
+pub fn wake_by_address_all<T: Futex>(address: &T) {
     unsafe {
         let addr = ptr::from_ref(address).cast::<c_void>();
         c::WakeByAddressAll(addr);
@@ -80,11 +83,11 @@ pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<D
     wait_on_address(futex, expected, timeout) || api::get_last_error() != WinError::TIMEOUT
 }
 
-pub fn futex_wake<T>(futex: &T) -> bool {
+pub fn futex_wake<T: Futex>(futex: &T) -> bool {
     wake_by_address_single(futex);
     false
 }
 
-pub fn futex_wake_all<T>(futex: &T) {
+pub fn futex_wake_all<T: Futex>(futex: &T) {
     wake_by_address_all(futex)
 }
diff --git a/library/std/src/sys/pal/windows/handle.rs b/library/std/src/sys/pal/windows/handle.rs
index ae9ea8ff584..aaa1831dcc2 100644
--- a/library/std/src/sys/pal/windows/handle.rs
+++ b/library/std/src/sys/pal/windows/handle.rs
@@ -1,5 +1,4 @@
 #![unstable(issue = "none", feature = "windows_handle")]
-#![allow(unsafe_op_in_unsafe_fn)]
 
 #[cfg(test)]
 mod tests;
@@ -73,7 +72,7 @@ impl IntoRawHandle for Handle {
 
 impl FromRawHandle for Handle {
     unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
-        Self(FromRawHandle::from_raw_handle(raw_handle))
+        unsafe { Self(FromRawHandle::from_raw_handle(raw_handle)) }
     }
 }
 
@@ -139,13 +138,23 @@ impl Handle {
 
     pub unsafe fn read_overlapped(
         &self,
-        buf: &mut [u8],
+        buf: &mut [mem::MaybeUninit<u8>],
         overlapped: *mut c::OVERLAPPED,
     ) -> io::Result<Option<usize>> {
-        let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
-        let mut amt = 0;
-        let res =
-            cvt(c::ReadFile(self.as_raw_handle(), buf.as_mut_ptr(), len, &mut amt, overlapped));
+        // SAFETY: We have exclusive access to the buffer and it's up to the caller to
+        // ensure the OVERLAPPED pointer is valid for the lifetime of this function.
+        let (res, amt) = unsafe {
+            let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
+            let mut amt = 0;
+            let res = cvt(c::ReadFile(
+                self.as_raw_handle(),
+                buf.as_mut_ptr().cast::<u8>(),
+                len,
+                &mut amt,
+                overlapped,
+            ));
+            (res, amt)
+        };
         match res {
             Ok(_) => Ok(Some(amt as usize)),
             Err(e) => {
@@ -230,20 +239,24 @@ impl Handle {
 
         // The length is clamped at u32::MAX.
         let len = cmp::min(len, u32::MAX as usize) as u32;
-        let status = c::NtReadFile(
-            self.as_handle(),
-            ptr::null_mut(),
-            None,
-            ptr::null_mut(),
-            &mut io_status,
-            buf,
-            len,
-            offset.map(|n| n as _).as_ref(),
-            None,
-        );
+        // SAFETY: It's up to the caller to ensure `buf` is writeable up to
+        // the provided `len`.
+        let status = unsafe {
+            c::NtReadFile(
+                self.as_handle(),
+                ptr::null_mut(),
+                None,
+                ptr::null_mut(),
+                &mut io_status,
+                buf,
+                len,
+                offset.map(|n| n as _).as_ref(),
+                None,
+            )
+        };
 
         let status = if status == c::STATUS_PENDING {
-            c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
+            unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
             io_status.status()
         } else {
             status
@@ -261,7 +274,7 @@ impl Handle {
             status if c::nt_success(status) => Ok(io_status.Information),
 
             status => {
-                let error = c::RtlNtStatusToDosError(status);
+                let error = unsafe { c::RtlNtStatusToDosError(status) };
                 Err(io::Error::from_raw_os_error(error as _))
             }
         }
diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs
index 86d457db50a..bf3dfdfdd3e 100644
--- a/library/std/src/sys/pal/windows/io.rs
+++ b/library/std/src/sys/pal/windows/io.rs
@@ -1,4 +1,3 @@
-#![allow(unsafe_op_in_unsafe_fn)]
 use crate::marker::PhantomData;
 use crate::mem::size_of;
 use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
@@ -81,19 +80,17 @@ impl<'a> IoSliceMut<'a> {
 }
 
 pub fn is_terminal(h: &impl AsHandle) -> bool {
-    unsafe { handle_is_console(h.as_handle()) }
+    handle_is_console(h.as_handle())
 }
 
-unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
-    let handle = handle.as_raw_handle();
-
+fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
     // A null handle means the process has no console.
-    if handle.is_null() {
+    if handle.as_raw_handle().is_null() {
         return false;
     }
 
     let mut out = 0;
-    if c::GetConsoleMode(handle, &mut out) != 0 {
+    if unsafe { c::GetConsoleMode(handle.as_raw_handle(), &mut out) != 0 } {
         // False positives aren't possible. If we got a console then we definitely have a console.
         return true;
     }
@@ -102,9 +99,9 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
     msys_tty_on(handle)
 }
 
-unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
+fn msys_tty_on(handle: BorrowedHandle<'_>) -> bool {
     // Early return if the handle is not a pipe.
-    if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
+    if unsafe { c::GetFileType(handle.as_raw_handle()) != c::FILE_TYPE_PIPE } {
         return false;
     }
 
@@ -120,12 +117,14 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
     }
     let mut name_info = FILE_NAME_INFO { FileNameLength: 0, FileName: [0; c::MAX_PATH as usize] };
     // Safety: buffer length is fixed.
-    let res = c::GetFileInformationByHandleEx(
-        handle,
-        c::FileNameInfo,
-        core::ptr::addr_of_mut!(name_info) as *mut c_void,
-        size_of::<FILE_NAME_INFO>() as u32,
-    );
+    let res = unsafe {
+        c::GetFileInformationByHandleEx(
+            handle.as_raw_handle(),
+            c::FileNameInfo,
+            core::ptr::addr_of_mut!(name_info) as *mut c_void,
+            size_of::<FILE_NAME_INFO>() as u32,
+        )
+    };
     if res == 0 {
         return false;
     }
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/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 0a9279e50ba..f1f4d3a5d26 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -1,7 +1,6 @@
 //! Implementation of `std::os` functionality for Windows.
 
 #![allow(nonstandard_style)]
-#![allow(unsafe_op_in_unsafe_fn)]
 
 #[cfg(test)]
 mod tests;
@@ -305,15 +304,21 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
 }
 
 pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
-    let k = to_u16s(k)?;
-    let v = to_u16s(v)?;
+    // SAFETY: We ensure that k and v are null-terminated wide strings.
+    unsafe {
+        let k = to_u16s(k)?;
+        let v = to_u16s(v)?;
 
-    cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
+        cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
+    }
 }
 
 pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
-    let v = to_u16s(n)?;
-    cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
+    // SAFETY: We ensure that v is a null-terminated wide strings.
+    unsafe {
+        let v = to_u16s(n)?;
+        cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
+    }
 }
 
 pub fn temp_dir() -> PathBuf {
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index d8b785f027c..7a309b9638b 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -1,4 +1,3 @@
-#![allow(unsafe_op_in_unsafe_fn)]
 use crate::os::windows::prelude::*;
 
 use crate::ffi::OsStr;
@@ -6,7 +5,6 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
 use crate::mem;
 use crate::path::Path;
 use crate::ptr;
-use crate::slice;
 use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::Relaxed;
 use crate::sys::c;
@@ -325,6 +323,7 @@ impl AnonPipe {
     /// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex
     /// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex
     /// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls
+    #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn alertable_io_internal(
         &self,
         io: AlertableIoFn,
@@ -479,8 +478,11 @@ impl<'a> AsyncPipe<'a> {
     fn schedule_read(&mut self) -> io::Result<bool> {
         assert_eq!(self.state, State::NotReading);
         let amt = unsafe {
-            let slice = slice_to_end(self.dst);
-            self.pipe.read_overlapped(slice, &mut *self.overlapped)?
+            if self.dst.capacity() == self.dst.len() {
+                let additional = if self.dst.capacity() == 0 { 16 } else { 1 };
+                self.dst.reserve(additional);
+            }
+            self.pipe.read_overlapped(self.dst.spare_capacity_mut(), &mut *self.overlapped)?
         };
 
         // If this read finished immediately then our overlapped event will
@@ -560,13 +562,3 @@ impl<'a> Drop for AsyncPipe<'a> {
         }
     }
 }
-
-unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
-    if v.capacity() == 0 {
-        v.reserve(16);
-    }
-    if v.capacity() == v.len() {
-        v.reserve(1);
-    }
-    slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()), v.capacity() - v.len())
-}
diff --git a/library/std/src/sys/pal/windows/stack_overflow.rs b/library/std/src/sys/pal/windows/stack_overflow.rs
index ea89429cb83..467e21ab56a 100644
--- a/library/std/src/sys/pal/windows/stack_overflow.rs
+++ b/library/std/src/sys/pal/windows/stack_overflow.rs
@@ -1,18 +1,18 @@
 #![cfg_attr(test, allow(dead_code))]
-#![allow(unsafe_op_in_unsafe_fn)]
 
 use crate::sys::c;
 use crate::thread;
 
 /// Reserve stack space for use in stack overflow exceptions.
-pub unsafe fn reserve_stack() {
-    let result = c::SetThreadStackGuarantee(&mut 0x5000);
+pub fn reserve_stack() {
+    let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) };
     // Reserving stack space is not critical so we allow it to fail in the released build of libstd.
     // We still use debug assert here so that CI will test that we haven't made a mistake calling the function.
     debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling");
 }
 
 unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 {
+    // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid.
     unsafe {
         let rec = &(*(*ExceptionInfo).ExceptionRecord);
         let code = rec.ExceptionCode;
@@ -27,11 +27,14 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN
     }
 }
 
-pub unsafe fn init() {
-    let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
-    // Similar to the above, adding the stack overflow handler is allowed to fail
-    // but a debug assert is used so CI will still test that it normally works.
-    debug_assert!(!result.is_null(), "failed to install exception handler");
+pub fn init() {
+    // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling.
+    unsafe {
+        let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
+        // Similar to the above, adding the stack overflow handler is allowed to fail
+        // but a debug assert is used so CI will still test that it normally works.
+        debug_assert!(!result.is_null(), "failed to install exception handler");
+    }
     // Set the thread stack guarantee for the main thread.
     reserve_stack();
 }
diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index 3648272a343..668a3c05e20 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -1,4 +1,3 @@
-#![allow(unsafe_op_in_unsafe_fn)]
 use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZero;
@@ -28,21 +27,25 @@ impl Thread {
 
         // CreateThread rounds up values for the stack size to the nearest page size (at least 4kb).
         // If a value of zero is given then the default stack size is used instead.
-        let ret = c::CreateThread(
-            ptr::null_mut(),
-            stack,
-            Some(thread_start),
-            p as *mut _,
-            c::STACK_SIZE_PARAM_IS_A_RESERVATION,
-            ptr::null_mut(),
-        );
-        let ret = HandleOrNull::from_raw_handle(ret);
+        // SAFETY: `thread_start` has the right ABI for a thread's entry point.
+        // `p` is simply passed through to the new thread without being touched.
+        let ret = unsafe {
+            let ret = c::CreateThread(
+                ptr::null_mut(),
+                stack,
+                Some(thread_start),
+                p as *mut _,
+                c::STACK_SIZE_PARAM_IS_A_RESERVATION,
+                ptr::null_mut(),
+            );
+            HandleOrNull::from_raw_handle(ret)
+        };
         return if let Ok(handle) = ret.try_into() {
             Ok(Thread { handle: Handle::from_inner(handle) })
         } else {
             // The thread failed to start and as a result p was not consumed. Therefore, it is
             // safe to reconstruct the box so that it gets deallocated.
-            drop(Box::from_raw(p));
+            unsafe { drop(Box::from_raw(p)) };
             Err(io::Error::last_os_error())
         };
 
@@ -50,7 +53,9 @@ impl Thread {
             // Next, reserve some stack space for if we otherwise run out of stack.
             stack_overflow::reserve_stack();
             // Finally, let's run some code.
-            Box::from_raw(main as *mut Box<dyn FnOnce()>)();
+            // SAFETY: We are simply recreating the box that was leaked earlier.
+            // It's the responsibility of the one who call `Thread::new` to ensure this is safe to call here.
+            unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)() };
             0
         }
     }
@@ -70,7 +75,7 @@ impl Thread {
     ///
     /// `name` must end with a zero value
     pub unsafe fn set_name_wide(name: &[u16]) {
-        c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
+        unsafe { c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr()) };
     }
 
     pub fn join(self) {
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/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 609085dcd47..8a231e65ad1 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/std/src/sys/sync/once/futex.rs
@@ -57,7 +57,7 @@ impl<'a> Drop for CompletionGuard<'a> {
         // up on the Once. `futex_wake_all` does its own synchronization, hence
         // we do not need `AcqRel`.
         if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED {
-            futex_wake_all(&self.state);
+            futex_wake_all(self.state);
         }
     }
 }
diff --git a/library/std/src/sys/sync/once/mod.rs b/library/std/src/sys/sync/once/mod.rs
index 61b29713fa1..0e38937b121 100644
--- a/library/std/src/sys/sync/once/mod.rs
+++ b/library/std/src/sys/sync/once/mod.rs
@@ -9,6 +9,7 @@
 
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor="win7")),
         target_os = "linux",
         target_os = "android",
         all(target_arch = "wasm32", target_feature = "atomics"),
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 c8ee365392f..e9731bc85d6 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -159,9 +159,9 @@
 mod tests;
 
 use crate::any::Any;
-use crate::cell::{OnceCell, UnsafeCell};
+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 {
@@ -699,17 +695,22 @@ where
 }
 
 thread_local! {
+    // Invariant: `CURRENT` and `CURRENT_ID` will always be initialized together.
+    // If `CURRENT` is initialized, then `CURRENT_ID` will hold the same value
+    // as `CURRENT.id()`.
     static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
+    static CURRENT_ID: Cell<Option<ThreadId>> = const { Cell::new(None) };
 }
 
 /// Sets the thread handle for the current thread.
 ///
 /// Aborts if the handle has been set already to reduce code size.
 pub(crate) fn set_current(thread: Thread) {
+    let tid = thread.id();
     // Using `unwrap` here can add ~3kB to the binary size. We have complete
     // control over where this is called, so just abort if there is a bug.
     CURRENT.with(|current| match current.set(thread) {
-        Ok(()) => {}
+        Ok(()) => CURRENT_ID.set(Some(tid)),
         Err(_) => rtabort!("thread::set_current should only be called once per thread"),
     });
 }
@@ -719,7 +720,28 @@ pub(crate) fn set_current(thread: Thread) {
 /// In contrast to the public `current` function, this will not panic if called
 /// from inside a TLS destructor.
 pub(crate) fn try_current() -> Option<Thread> {
-    CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok()
+    CURRENT
+        .try_with(|current| {
+            current
+                .get_or_init(|| {
+                    let thread = Thread::new_unnamed();
+                    CURRENT_ID.set(Some(thread.id()));
+                    thread
+                })
+                .clone()
+        })
+        .ok()
+}
+
+/// Gets the id of the thread that invokes it.
+#[inline]
+pub(crate) fn current_id() -> ThreadId {
+    CURRENT_ID.get().unwrap_or_else(|| {
+        // If `CURRENT_ID` isn't initialized yet, then `CURRENT` must also not be initialized.
+        // `current()` will initialize both `CURRENT` and `CURRENT_ID` so subsequent calls to
+        // `current_id()` will succeed immediately.
+        current().id()
+    })
 }
 
 /// Gets a handle to the thread that invokes it.
@@ -1273,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
@@ -1316,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.
         //
@@ -1457,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/library/test/src/test_result.rs b/library/test/src/test_result.rs
index bb32c70d663..98c54f038da 100644
--- a/library/test/src/test_result.rs
+++ b/library/test/src/test_result.rs
@@ -19,7 +19,15 @@ pub const TR_OK: i32 = 50;
 // On Windows we use __fastfail to abort, which is documented to use this
 // exception code.
 #[cfg(windows)]
-const STATUS_ABORTED: i32 = 0xC0000409u32 as i32;
+const STATUS_FAIL_FAST_EXCEPTION: i32 = 0xC0000409u32 as i32;
+
+// On Zircon (the Fuchsia kernel), an abort from userspace calls the
+// LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which
+// raises a kernel exception. If a userspace process does not
+// otherwise arrange exception handling, the kernel kills the process
+// with this return code.
+#[cfg(target_os = "fuchsia")]
+const ZX_TASK_RETCODE_EXCEPTION_KILL: i32 = -1028;
 
 #[derive(Debug, Clone, PartialEq)]
 pub enum TestResult {
@@ -96,7 +104,7 @@ pub fn get_result_from_exit_code(
     let result = match status.code() {
         Some(TR_OK) => TestResult::TrOk,
         #[cfg(windows)]
-        Some(STATUS_ABORTED) => TestResult::TrFailed,
+        Some(STATUS_FAIL_FAST_EXCEPTION) => TestResult::TrFailed,
         #[cfg(unix)]
         None => match status.signal() {
             Some(libc::SIGABRT) => TestResult::TrFailed,
@@ -105,6 +113,9 @@ pub fn get_result_from_exit_code(
             }
             None => unreachable!("status.code() returned None but status.signal() was None"),
         },
+        // Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
+        #[cfg(target_os = "fuchsia")]
+        Some(ZX_TASK_RETCODE_EXCEPTION_KILL) => TestResult::TrFailed,
         #[cfg(not(unix))]
         None => TestResult::TrFailedMsg(format!("unknown return code")),
         #[cfg(any(windows, unix))]
diff --git a/rustfmt.toml b/rustfmt.toml
index e060fd8fe8b..8c1d3b94f19 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -31,7 +31,6 @@ ignore = [
     "library/backtrace",
     "library/portable-simd",
     "library/stdarch",
-    "compiler/rustc_codegen_gcc",
     "src/doc/book",
     "src/doc/edition-guide",
     "src/doc/embedded-book",
@@ -50,4 +49,8 @@ ignore = [
     # These are ignored by a standard cargo fmt run.
     "compiler/rustc_codegen_cranelift/scripts",
     "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024
+    "compiler/rustc_codegen_gcc/tests",
+    # Code automatically generated and included.
+    "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs",
+    "compiler/rustc_codegen_gcc/example",
 ]
diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml
index 6e6c3660027..75ad37ce335 100644
--- a/src/bootstrap/defaults/config.tools.toml
+++ b/src/bootstrap/defaults/config.tools.toml
@@ -1,10 +1,6 @@
 # These defaults are meant for contributors to tools which build on the
 # compiler, but do not modify it directly.
 [rust]
-# This enables `RUSTC_LOG=debug`, avoiding confusing situations
-# where adding `debug!()` appears to do nothing.
-# However, it makes running the compiler slightly slower.
-debug-logging = true
 # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
 incremental = true
 # Download rustc from CI instead of building it from source.
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/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/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 7bc410b9e88..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 {
@@ -858,6 +905,15 @@ impl Step for LlvmBitcodeLinker {
             &self.extra_features,
         );
 
+        let _guard = builder.msg_tool(
+            Kind::Build,
+            Mode::ToolRustc,
+            bin_name,
+            self.compiler.stage,
+            &self.compiler.host,
+            &self.target,
+        );
+
         cargo.into_cmd().run(builder);
 
         let tool_out = builder
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 71009d56366..6d6df650b14 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -473,9 +473,41 @@ impl StepDescription {
             return;
         }
 
-        // Handle all PathSets.
+        let mut path_lookup: Vec<(PathBuf, bool)> =
+            paths.clone().into_iter().map(|p| (p, false)).collect();
+
+        // List of `(usize, &StepDescription, Vec<PathSet>)` where `usize` is the closest index of a path
+        // compared to the given CLI paths. So we can respect to the CLI order by using this value to sort
+        // the steps.
+        let mut steps_to_run = vec![];
+
         for (desc, should_run) in v.iter().zip(&should_runs) {
             let pathsets = should_run.pathset_for_paths_removing_matches(&mut paths, desc.kind);
+
+            // This value is used for sorting the step execution order.
+            // By default, `usize::MAX` is used as the index for steps to assign them the lowest priority.
+            //
+            // If we resolve the step's path from the given CLI input, this value will be updated with
+            // the step's actual index.
+            let mut closest_index = usize::MAX;
+
+            // Find the closest index from the original list of paths given by the CLI input.
+            for (index, (path, is_used)) in path_lookup.iter_mut().enumerate() {
+                if !*is_used && !paths.contains(path) {
+                    closest_index = index;
+                    *is_used = true;
+                    break;
+                }
+            }
+
+            steps_to_run.push((closest_index, desc, pathsets));
+        }
+
+        // Sort the steps before running them to respect the CLI order.
+        steps_to_run.sort_by_key(|(index, _, _)| *index);
+
+        // Handle all PathSets.
+        for (_index, desc, pathsets) in steps_to_run {
             if !pathsets.is_empty() {
                 desc.maybe_run(builder, pathsets);
             }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f96633b059a..9d5aa795c6c 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;
@@ -2471,14 +2471,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?");
@@ -2489,7 +2488,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()
@@ -2565,14 +2564,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?");
@@ -2583,7 +2581,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/core/download.rs b/src/bootstrap/src/core/download.rs
index d01a910e815..56a8528d0a1 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -706,7 +706,7 @@ download-rustc = false
             let file_times = fs::FileTimes::new().set_accessed(now).set_modified(now);
 
             let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build));
-            let llvm_config_file = t!(File::open(llvm_config));
+            let llvm_config_file = t!(File::options().write(true).open(llvm_config));
 
             t!(llvm_config_file.set_times(file_times));
 
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index db1fa05a82c..d2910f8edc6 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -535,6 +535,7 @@ impl Build {
             // even though that has no relation to the upstream for the submodule.
             let current_branch = helpers::git(Some(&self.src))
                 .capture_stdout()
+                .allow_failure()
                 .run_always()
                 .args(["symbolic-ref", "--short", "HEAD"])
                 .run(self)
@@ -1413,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 ccab25e55a9..083418ed066 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -200,4 +200,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "`llvm.lld` is enabled by default for the dist profile. If set to false, `lld` will not be included in the dist build.",
     },
+    ChangeInfo {
+        change_id: 127913,
+        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..773a873e47c 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;
@@ -521,3 +522,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/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 0d9c21c4487..571378774be 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -37,6 +37,7 @@ RUN sh /scripts/sccache.sh
 COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
 RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt
 
+COPY host-x86_64/mingw-check/check-default-config-profiles.sh /scripts/
 COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 
@@ -46,6 +47,7 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 # We disable optimized compiler built-ins because that requires a C toolchain for the target.
 # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
 ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
+           /scripts/check-default-config-profiles.sh && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python3 ../x.py clippy bootstrap -Dwarnings && \
            python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \
diff --git a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh
new file mode 100755
index 00000000000..d706927d6d9
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Runs bootstrap (in dry-run mode) with each default config profile to ensure they are not broken.
+
+set -euo pipefail
+
+config_dir="../src/bootstrap/defaults"
+
+# Loop through each configuration file in the directory
+for config_file in "$config_dir"/*.toml;
+do
+    python3 ../x.py check --config $config_file --dry-run
+done
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/docker/run.sh b/src/ci/docker/run.sh
index 40f42171411..fad4b5af095 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -27,8 +27,11 @@ do
   shift
 done
 
+# MacOS reports "arm64" while Linux reports "aarch64". Commonize this.
+machine="$(uname -m | sed 's/arm64/aarch64/')"
+
 script_dir="`dirname $script`"
-docker_dir="${script_dir}/host-$(uname -m)"
+docker_dir="${script_dir}/host-${machine}"
 ci_dir="`dirname $script_dir`"
 src_dir="`dirname $ci_dir`"
 root_dir="`dirname $src_dir`"
@@ -68,7 +71,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
 
     # Include the architecture in the hash key, since our Linux CI does not
     # only run in x86_64 machines.
-    uname -m >> $hash_key
+    echo "$machine" >> $hash_key
 
     # Include cache version. Can be used to manually bust the Docker cache.
     echo "2" >> $hash_key
@@ -178,7 +181,7 @@ elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
       build \
       --rm \
       -t rust-ci \
-      -f "host-$(uname -m)/$image/Dockerfile" \
+      -f "host-${machine}/$image/Dockerfile" \
       -
 else
     echo Invalid image: $image
@@ -201,7 +204,7 @@ else
         else
             continue
         fi
-        echo "Note: the current host architecture is $(uname -m)"
+        echo "Note: the current host architecture is $machine"
     done
 
     exit 1
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/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index cd10168bc1c..cb43feca758 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -410,13 +410,16 @@ See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag.
 
 By default, `rustc` prefers to statically link dependencies. This option will
 indicate that dynamic linking should be used if possible if both a static and
-dynamic versions of a library are available. There is an internal algorithm
-for determining whether or not it is possible to statically or dynamically
-link with a dependency. For example, `cdylib` crate types may only use static
-linkage. This flag takes one of the following values:
+dynamic versions of a library are available.
 
-* `y`, `yes`, `on`, `true` or no value: use dynamic linking.
-* `n`, `no`, `off` or `false`: use static linking (the default).
+There is [an internal algorithm](https://github.com/rust-lang/rust/blob/master/compiler/rustc_metadata/src/dependency_format.rs)
+for determining whether or not it is possible to statically or dynamically link
+with a dependency.
+
+This flag takes one of the following values:
+
+* `y`, `yes`, `on`, `true` or no value: prefer dynamic linking.
+* `n`, `no`, `off` or `false`: prefer static linking (the default).
 
 ## profile-generate
 
diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md
index dce50ebf29c..f42b9cb5978 100644
--- a/src/doc/style-guide/src/README.md
+++ b/src/doc/style-guide/src/README.md
@@ -117,8 +117,7 @@ fn baz() {}
 In various cases, the default Rust style specifies to sort things. If not
 otherwise specified, such sorting should be "version sorting", which ensures
 that (for instance) `x8` comes before `x16` even though the character `1` comes
-before the character `8`. (If not otherwise specified, version-sorting is
-lexicographical.)
+before the character `8`.
 
 For the purposes of the Rust style, to compare two strings for version-sorting:
 
@@ -132,12 +131,13 @@ For the purposes of the Rust style, to compare two strings for version-sorting:
   these strings, treat the chunks as equal (moving on to the next chunk) but
   remember which string had more leading zeroes.
 - To compare two chunks if both are not numeric, compare them by Unicode
-  character lexicographically, except that `_` (underscore) sorts immediately
-  after ` ` (space) but before any other character. (This treats underscore as
-  a word separator, as commonly used in identifiers.)
-  - If the use of version sorting specifies further modifiers, such as sorting
-    non-lowercase before lowercase, apply those modifiers to the lexicographic
-    sort in this step.
+  character lexicographically, with two exceptions:
+  - `_` (underscore) sorts immediately after ` ` (space) but before any other
+    character. (This treats underscore as a word separator, as commonly used in
+    identifiers.)
+  - Unless otherwise specified, version-sorting should sort non-lowercase
+    characters (characters that can start an `UpperCamelCase` identifier)
+    before lowercase characters.
 - If the comparison reaches the end of the string and considers each pair of
   chunks equal:
   - If one of the numeric comparisons noted the earliest point at which one
@@ -157,7 +157,17 @@ leading zeroes.
 
 As an example, version-sorting will sort the following strings in the order
 given:
-- `_ZYWX`
+- `_ZYXW`
+- `_abcd`
+- `A2`
+- `ABCD`
+- `Z_YXW`
+- `ZY_XW`
+- `ZY_XW`
+- `ZYXW`
+- `ZYXW_`
+- `a1`
+- `abcd`
 - `u_zzz`
 - `u8`
 - `u16`
@@ -190,11 +200,7 @@ given:
 - `x86_64`
 - `x86_128`
 - `x87`
-- `Z_YWX`
-- `ZY_WX`
-- `ZYW_X`
-- `ZYWX`
-- `ZYWX_`
+- `zyxw`
 
 ### [Module-level items](items.md)
 
diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md
index c0628691b77..8e1b1d80fb6 100644
--- a/src/doc/style-guide/src/items.md
+++ b/src/doc/style-guide/src/items.md
@@ -489,10 +489,8 @@ foo::{
 A *group* of imports is a set of imports on the same or sequential lines. One or
 more blank lines or other items (e.g., a function) separate groups of imports.
 
-Within a group of imports, imports must be version-sorted, except that
-non-lowercase characters (characters that can start an `UpperCamelCase`
-identifier) must be sorted before lowercase characters. Groups of imports must
-not be merged or re-ordered.
+Within a group of imports, imports must be version-sorted. Groups of imports
+must not be merged or re-ordered.
 
 E.g., input:
 
@@ -520,9 +518,7 @@ re-ordering.
 ### Ordering list import
 
 Names in a list import must be version-sorted, except that:
-- `self` and `super` always come first if present,
-- non-lowercase characters (characters that can start an `UpperCamelCase`
-  identifier) must be sorted before lowercase characters, and
+- `self` and `super` always come first if present, and
 - groups and glob imports always come last if present.
 
 This applies recursively. For example, `a::*` comes before `b::a` but `a::b`
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/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a0e28d2f55c..2cd9b6fcd38 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -285,10 +285,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
 }
 
 pub(crate) fn clean_const<'tcx>(
-    constant: &hir::ConstArg<'_>,
+    constant: &hir::ConstArg<'tcx>,
     _cx: &mut DocContext<'tcx>,
 ) -> Constant {
-    Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
+    match &constant.kind {
+        hir::ConstArgKind::Path(qpath) => {
+            Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } }
+        }
+        hir::ConstArgKind::Anon(anon) => {
+            Constant { kind: ConstantKind::Anonymous { body: anon.body } }
+        }
+    }
 }
 
 pub(crate) fn clean_middle_const<'tcx>(
@@ -431,7 +438,7 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
     match term {
         hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
         hir::Term::Const(c) => Term::Constant(clean_middle_const(
-            ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)),
+            ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
             cx,
         )),
     }
@@ -461,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(
@@ -633,8 +634,9 @@ fn clean_generic_param<'tcx>(
             param.name.ident().name,
             GenericParamDefKind::Const {
                 ty: Box::new(clean_ty(ty, cx)),
-                default: default
-                    .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
+                default: default.map(|ct| {
+                    Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
+                }),
                 synthetic,
             },
         ),
@@ -1820,7 +1822,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         TyKind::Array(ty, ref length) => {
             let length = match length {
                 hir::ArrayLen::Infer(..) => "_".to_string(),
-                hir::ArrayLen::Body(anon_const) => {
+                hir::ArrayLen::Body(const_arg) => {
                     // NOTE(min_const_generics): We can't use `const_eval_poly` for constants
                     // as we currently do not supply the parent generics to anonymous constants
                     // but do allow `ConstKind::Param`.
@@ -1828,9 +1830,18 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
                     // `const_eval_poly` tries to first substitute generic parameters which
                     // results in an ICE while manually constructing the constant and using `eval`
                     // does nothing for `ConstKind::Param`.
-                    let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id);
-                    let param_env = cx.tcx.param_env(anon_const.def_id);
-                    print_const(cx, ct.normalize(cx.tcx, param_env))
+                    let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
+                    let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
+                        const_arg.kind
+                    {
+                        // Only anon consts can implicitly capture params.
+                        // FIXME: is this correct behavior?
+                        let param_env = cx.tcx.param_env(*def_id);
+                        ct.normalize(cx.tcx, param_env)
+                    } else {
+                        ct
+                    };
+                    print_const(cx, ct)
                 }
             };
 
@@ -2243,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 {
@@ -2272,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),
@@ -2296,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 {
@@ -2336,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/clean/types.rs b/src/librustdoc/clean/types.rs
index a31adc9949a..37099531596 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2395,6 +2395,9 @@ pub(crate) enum ConstantKind {
     /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
     /// by a DefId. So this field must be different from `Extern`.
     TyConst { expr: Box<str> },
+    /// A constant that is just a path (i.e., referring to a const param, free const, etc.).
+    // FIXME: this is an unfortunate representation. rustdoc's logic around consts needs to be improved.
+    Path { path: Box<str> },
     /// A constant (expression) that's not an item or associated item. These are usually found
     /// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
     /// used to define explicit discriminant values for enum variants.
@@ -2423,6 +2426,7 @@ impl ConstantKind {
     pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
         match *self {
             ConstantKind::TyConst { ref expr } => expr.to_string(),
+            ConstantKind::Path { ref path } => path.to_string(),
             ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
                 rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
@@ -2432,7 +2436,9 @@ impl ConstantKind {
 
     pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
         match *self {
-            ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
+            ConstantKind::TyConst { .. }
+            | ConstantKind::Path { .. }
+            | ConstantKind::Anonymous { .. } => None,
             ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
                 print_evaluated_const(tcx, def_id, true, true)
             }
@@ -2441,7 +2447,9 @@ impl ConstantKind {
 
     pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
         match *self {
-            ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } => false,
+            ConstantKind::TyConst { .. }
+            | ConstantKind::Extern { .. }
+            | ConstantKind::Path { .. } => false,
             ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
                 is_literal_expr(tcx, body.hir_id)
             }
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/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 00973865915..9256330ac7c 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -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/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 4c0ba75d261..28ed94432c8 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -15,6 +15,7 @@
 	--desktop-sidebar-width: 200px;
 	--src-sidebar-width: 300px;
 	--desktop-sidebar-z-index: 100;
+	--sidebar-elems-left-padding: 24px;
 }
 
 /* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -559,8 +560,11 @@ ul.block, .block li {
 .sidebar > h2 a {
 	display: block;
 	padding: 0.25rem; /* 4px */
-	margin-left: -0.25rem;
 	margin-right: 0.25rem;
+	/* extend click target to far edge of screen (mile wide bar) */
+	border-left: solid var(--sidebar-elems-left-padding) transparent;
+	margin-left: calc(-0.25rem - var(--sidebar-elems-left-padding));
+	background-clip: border-box;
 }
 
 .sidebar h2 {
@@ -578,7 +582,7 @@ ul.block, .block li {
 .sidebar-elems,
 .sidebar > .version,
 .sidebar > h2 {
-	padding-left: 24px;
+	padding-left: var(--sidebar-elems-left-padding);
 }
 
 .sidebar a {
@@ -632,13 +636,55 @@ ul.block, .block li {
 .sidebar-crate .logo-container {
 	/* The logo is expected to have 8px "slop" along its edges, so we can optically
 		center it. */
-	margin: 0 -16px 0 -16px;
+	margin: 0 calc(-16px - var(--sidebar-elems-left-padding));
+	padding: 0 var(--sidebar-elems-left-padding);
 	text-align: center;
 }
 
+.sidebar-crate .logo-container img {
+	/* When in a horizontal logo lockup, the highlight color of the crate name menu item
+		extends underneath the actual logo (in a vertical lockup, that background highlight
+		extends to the left edge of the screen).
+
+		To prevent a weird-looking colored band from appearing under the logo, cover it up
+		with the sidebar's background. Additionally, the crate name extends slightly above
+		the logo, so that its highlight has a bit of space to let the ascenders breath while
+		also having those ascenders meet exactly with the top of the logo.
+
+		In ANSI art, make it look like this:
+		|        ┌─────┐
+		|    (R) │ std │
+		|        └─────┘
+
+		Not like this (which would happen without the z-index):
+		|     ┌────────┐
+		|    (│    std │
+		|     └────────┘
+
+		Not like this (which would happen without the background):
+		|     ┌────────┐
+		|    (R)   std │
+		|     └────────┘
+
+		Nor like this (which would happen without the negative margin):
+		|     ─────────┐
+		|    (R) │ std │
+		|        └─────┘
+		*/
+	margin-top: -16px;
+	border-top: solid 16px transparent;
+	box-sizing: content-box;
+	position: relative;
+	background-clip: border-box;
+	z-index: 1;
+}
+
 .sidebar-crate h2 a {
 	display: block;
-	margin: 0 calc(-24px + 0.25rem) 0 -0.2rem;
+	/* extend click target to far edge of screen (mile wide bar) */
+	border-left: solid var(--sidebar-elems-left-padding) transparent;
+	background-clip: border-box;
+	margin: 0 calc(-24px + 0.25rem) 0 calc(-0.2rem - var(--sidebar-elems-left-padding));
 	/* Align the sidebar crate link with the search bar, which have different
 		font sizes.
 
@@ -2127,6 +2173,14 @@ in src-script.js and main.js
 		padding: 2px 4px;
 		box-shadow: 0 0 4px var(--main-background-color);
 	}
+
+	.item-table > li > .item-name {
+		width: 33%;
+	}
+	.item-table > li > div {
+		padding-bottom: 5px;
+		word-break: break-all;
+	}
 }
 
 @media print {
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/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/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index c9bfc9c85d9..d94b0cce948 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
     ///
     /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
     /// correct result.
-    fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
-        let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else {
+    fn repeat_expr_might_be_expanded<'tcx>(expr: &Expr<'tcx>) -> bool {
+        let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
             return false;
         };
-        let len_span = cx.tcx.def_span(anon_const.def_id);
-        !expr.span.contains(len_span)
+        !expr.span.contains(len_ct.span())
     }
 
-    expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr)
+    expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr)
 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 09225ac3246..6f5505e8a63 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -235,7 +235,7 @@ impl<'tcx> NonCopyConst<'tcx> {
 
     fn is_value_unfrozen_raw(
         cx: &LateContext<'tcx>,
-        result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
+        result: Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>,
         ty: Ty<'tcx>,
     ) -> bool {
         result.map_or_else(
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 462084e96a8..db8c63892b8 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::has_repr_attr;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Const;
+use rustc_middle::ty::{Const, FeedConstTy};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
     }
 }
 
-fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
+fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
     if let ItemKind::Struct(data, _) = &item.kind
         // First check if last field is an array
         && let Some(last_field) = data.fields().last()
         && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
 
         // Then check if that array is zero-sized
-        && let length = Const::from_anon_const(cx.tcx, length.def_id)
+        && let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
         && let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
         && let Some(length) = length
     {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index e9d69407df8..316c1f32d3a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher};
 use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_ast::LitIntType;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
 use rustc_hir::{
-    ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind,
-    QPath, StmtKind, TyKind,
+    self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
+    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -270,6 +269,21 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
         }
     }
 
+    fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
+        match const_arg.value.kind {
+            ConstArgKind::Path(ref qpath) => {
+                bind!(self, qpath);
+                chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
+                self.qpath(qpath);
+            },
+            ConstArgKind::Anon(anon_const) => {
+                bind!(self, anon_const);
+                chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
+                self.body(field!(anon_const.body));
+            },
+        }
+    }
+
     fn lit(&self, lit: &Binding<&Lit>) {
         let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
         macro_rules! kind {
@@ -602,10 +616,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 self.expr(value);
                 match length.value {
                     ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
-                    ArrayLen::Body(anon_const) => {
-                        bind!(self, anon_const);
-                        chain!(self, "let ArrayLen::Body({anon_const}) = {length}");
-                        self.body(field!(anon_const.body));
+                    ArrayLen::Body(const_arg) => {
+                        bind!(self, const_arg);
+                        chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
+                        self.const_arg(const_arg);
                     },
                 }
             },
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 8706cec5d38..6c6a237a8b1 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
 use rustc_hir::MatchSource::TryDesugar;
 use rustc_hir::{
-    ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy,
-    GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField,
-    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
+    ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
+    ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
+    LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
@@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
         match (left, right) {
             (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
-            (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body),
+            (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
             (_, _) => false,
         }
     }
@@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
         match (left, right) {
-            (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
+            (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
             (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
             (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
             (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
@@ -419,6 +419,17 @@ impl HirEqInterExpr<'_, '_, '_> {
         }
     }
 
+    fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
+        match (&left.kind, &right.kind) {
+            (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
+            (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
+            // Use explicit match for now since ConstArg is undergoing flux.
+            (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
+                false
+            },
+        }
+    }
+
     fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
         left.res == right.res
     }
@@ -1123,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
         match length {
             ArrayLen::Infer(..) => {},
-            ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
+            ArrayLen::Body(ct) => self.hash_const_arg(ct),
         }
     }
 
@@ -1134,12 +1145,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
+    fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
+        match &const_arg.kind {
+            ConstArgKind::Path(path) => self.hash_qpath(path),
+            ConstArgKind::Anon(anon) => self.hash_body(anon.body),
+        }
+    }
+
     fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
         for arg in arg_list {
             match *arg {
                 GenericArg::Lifetime(l) => self.hash_lifetime(l),
                 GenericArg::Type(ty) => self.hash_ty(ty),
-                GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
+                GenericArg::Const(ref ca) => self.hash_const_arg(ca),
                 GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
             }
         }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index bdb3b5e45c4..8c33c34fa1c 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{
-    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
-    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
-    ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
-    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
-    TyKind, UnOp,
+    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
+    ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
+    ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
+    Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
+    TraitRef, TyKind, UnOp,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -904,7 +904,8 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
         },
         ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
         ExprKind::Repeat(x, ArrayLen::Body(len)) => {
-            if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
+            if let ConstArgKind::Anon(anon_const) = len.kind
+                && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
                 && let LitKind::Int(v, _) = const_lit.node
                 && v <= 32
                 && is_default_equivalent(cx, x)
@@ -933,7 +934,8 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
             }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
             ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
             ExprKind::Repeat(_, ArrayLen::Body(len)) => {
-                if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
+                if let ConstArgKind::Anon(anon_const) = len.kind
+                    && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
                     && let LitKind::Int(v, _) = const_lit.node
                 {
                     return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout
index c2a369610cc..d9e3f864f12 100644
--- a/src/tools/clippy/tests/ui/author/repeat.stdout
+++ b/src/tools/clippy/tests/ui/author/repeat.stdout
@@ -1,7 +1,8 @@
 if let ExprKind::Repeat(value, length) = expr.kind
     && let ExprKind::Lit(ref lit) = value.kind
     && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
-    && let ArrayLen::Body(anon_const) = length
+    && let ArrayLen::Body(const_arg) = length
+    && let ConstArgKind::Anon(anon_const) = const_arg.kind
     && expr1 = &cx.tcx.hir().body(anon_const.body).value
     && let ExprKind::Lit(ref lit1) = expr1.kind
     && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr
index 3dd5c9561fd..7fbd8462fdc 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.stderr
+++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr
@@ -193,5 +193,11 @@ error: this ident consists of a single char
 LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
    |                             ^
 
-error: aborting due to 32 previous errors
+error: this ident consists of a single char
+  --> tests/ui/min_ident_chars.rs:93:41
+   |
+LL |     struct Array<T, const N: usize>([T; N]);
+   |                                         ^
+
+error: aborting due to 33 previous errors
 
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..53988203136 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -94,6 +94,8 @@ fn get_lib_name(lib: &str, aux_type: AuxType) -> Option<String> {
             format!("{}.dll", lib)
         } else if cfg!(target_vendor = "apple") {
             format!("lib{}.dylib", lib)
+        } else if cfg!(target_os = "aix") {
+            format!("lib{}.a", lib)
         } else {
             format!("lib{}.so", lib)
         }),
@@ -3431,29 +3433,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 +3499,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.
+
+        // Compute stage-specific standard library paths.
+        let stage_std_path = build_root.join(&stage).join("lib");
 
-        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 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
+        };
 
-        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 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 {
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/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/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs
new file mode 100644
index 00000000000..bc6ec7566e5
--- /dev/null
+++ b/src/tools/run-make-support/src/artifact_names.rs
@@ -0,0 +1,57 @@
+//! A collection of helpers to construct artifact names, such as names of dynamic or static
+//! librarys which are target-dependent.
+
+// 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]
+pub fn static_lib_name(name: &str) -> String {
+    // See tools.mk (irrelevant lines omitted):
+    //
+    // ```makefile
+    // ifeq ($(UNAME),Darwin)
+    //     STATICLIB = $(TMPDIR)/lib$(1).a
+    // else
+    //     ifdef IS_WINDOWS
+    //         ifdef IS_MSVC
+    //             STATICLIB = $(TMPDIR)/$(1).lib
+    //         else
+    //             STATICLIB = $(TMPDIR)/lib$(1).a
+    //         endif
+    //     else
+    //         STATICLIB = $(TMPDIR)/lib$(1).a
+    //     endif
+    // endif
+    // ```
+    assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
+
+    if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
+}
+
+/// Construct the dynamic library name based on the target.
+#[must_use]
+pub fn dynamic_lib_name(name: &str) -> String {
+    assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
+
+    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 {
+    std::env::consts::DLL_EXTENSION
+}
+
+/// Construct the name of a rust library (rlib).
+#[must_use]
+pub fn rust_lib_name(name: &str) -> String {
+    format!("lib{name}.rlib")
+}
+
+/// Construct the binary (executable) name based on the target.
+#[must_use]
+pub fn bin_name(name: &str) -> String {
+    format!("{name}{}", std::env::consts::EXE_SUFFIX)
+}
diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs
new file mode 100644
index 00000000000..4b5b349431d
--- /dev/null
+++ b/src/tools/run-make-support/src/assertion_helpers.rs
@@ -0,0 +1,73 @@
+//! Collection of assertions and assertion-related helpers.
+
+use std::panic;
+use std::path::Path;
+
+use crate::fs;
+
+/// Assert that `actual` is equal to `expected`.
+#[track_caller]
+pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
+    let actual = actual.as_ref();
+    let expected = expected.as_ref();
+    if actual != expected {
+        eprintln!("=== ACTUAL TEXT ===");
+        eprintln!("{}", actual);
+        eprintln!("=== EXPECTED ===");
+        eprintln!("{}", expected);
+        panic!("expected text was not found in actual text");
+    }
+}
+
+/// Assert that `haystack` contains `needle`.
+#[track_caller]
+pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    if !haystack.contains(needle) {
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", needle);
+        panic!("needle was not found in haystack");
+    }
+}
+
+/// Assert that `haystack` does not contain `needle`.
+#[track_caller]
+pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    if haystack.contains(needle) {
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", needle);
+        panic!("needle was unexpectedly found in haystack");
+    }
+}
+
+/// Assert that all files in `dir1` exist and have the same content in `dir2`
+pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
+    let dir2 = dir2.as_ref();
+    fs::read_dir_entries(dir1, |entry_path| {
+        let entry_name = entry_path.file_name().unwrap();
+        if entry_path.is_dir() {
+            assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
+        } else {
+            let path2 = dir2.join(entry_name);
+            let file1 = fs::read(&entry_path);
+            let file2 = fs::read(&path2);
+
+            // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
+            // Why not using String? Because there might be minified files or even potentially
+            // binary ones, so that would display useless output.
+            assert!(
+                file1 == file2,
+                "`{}` and `{}` have different content",
+                entry_path.display(),
+                path2.display(),
+            );
+        }
+    });
+}
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 5017a4b88da..47376c401bb 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -5,7 +5,9 @@ use std::panic;
 use std::path::Path;
 use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
 
-use crate::{assert_contains, assert_equals, assert_not_contains, handle_failed_output};
+use crate::util::handle_failed_output;
+use crate::{assert_contains, assert_equals, assert_not_contains};
+
 use build_helper::drop_bomb::DropBomb;
 
 /// This is a custom command wrapper that simplifies working with commands and makes it easier to
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index ad989b74e4d..ac662331606 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -1,10 +1,12 @@
+use std::path::{Path, PathBuf};
+
 use regex::Regex;
 use similar::TextDiff;
-use std::path::{Path, PathBuf};
 
-use crate::fs_wrapper;
 use build_helper::drop_bomb::DropBomb;
 
+use crate::fs;
+
 #[cfg(test)]
 mod tests;
 
@@ -43,7 +45,7 @@ impl Diff {
     /// Specify the expected output for the diff from a file.
     pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = fs_wrapper::read_to_string(path);
+        let content = fs::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
         self.expected_file = Some(path.into());
@@ -62,7 +64,7 @@ impl Diff {
     /// Specify the actual output for the diff from a file.
     pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = fs_wrapper::read_to_string(path);
+        let content = fs::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
         self.actual = Some(content);
@@ -116,7 +118,7 @@ impl Diff {
             if let Some(ref expected_file) = self.expected_file {
                 if std::env::var("RUSTC_BLESS_TEST").is_ok() {
                     println!("Blessing `{}`", expected_file.display());
-                    fs_wrapper::write(expected_file, actual);
+                    fs::write(expected_file, actual);
                     return;
                 }
             }
@@ -138,7 +140,7 @@ impl Diff {
             if let Some(ref expected_file) = self.expected_file {
                 if std::env::var("RUSTC_BLESS_TEST").is_ok() {
                     println!("Blessing `{}`", expected_file.display());
-                    fs_wrapper::write(expected_file, actual);
+                    fs::write(expected_file, actual);
                     return;
                 }
             }
diff --git a/src/tools/run-make-support/src/env.rs b/src/tools/run-make-support/src/env.rs
new file mode 100644
index 00000000000..f52524e7d54
--- /dev/null
+++ b/src/tools/run-make-support/src/env.rs
@@ -0,0 +1,19 @@
+use std::ffi::OsString;
+
+#[track_caller]
+#[must_use]
+pub fn env_var(name: &str) -> String {
+    match std::env::var(name) {
+        Ok(v) => v,
+        Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"),
+    }
+}
+
+#[track_caller]
+#[must_use]
+pub fn env_var_os(name: &str) -> OsString {
+    match std::env::var_os(name) {
+        Some(v) => v,
+        None => panic!("failed to retrieve environment variable {name:?}"),
+    }
+}
diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs
new file mode 100644
index 00000000000..35b2bf75c95
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/c_build.rs
@@ -0,0 +1,27 @@
+use std::path::PathBuf;
+
+use crate::artifact_names::static_lib_name;
+use crate::external_deps::cc::cc;
+use crate::external_deps::llvm::llvm_ar;
+use crate::path_helpers::path;
+use crate::targets::is_msvc;
+
+/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
+#[track_caller]
+pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
+    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
+    let src = format!("{lib_name}.c");
+    let lib_path = static_lib_name(lib_name);
+    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();
+    };
+    let obj_file = if is_msvc() {
+        PathBuf::from(format!("{lib_name}.obj"))
+    } else {
+        PathBuf::from(format!("{lib_name}.o"))
+    };
+    llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
+    path(lib_path)
+}
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs
index 75a20a21a31..840bfa0d2b4 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/external_deps/cc.rs
@@ -1,7 +1,10 @@
 use std::path::Path;
 
 use crate::command::Command;
-use crate::{cygpath_windows, env_var, is_msvc, is_windows, uname};
+use crate::{env_var, is_msvc, is_windows, uname};
+
+// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency?
+use super::cygpath::get_windows_path;
 
 /// Construct a new platform-specific C compiler invocation.
 ///
@@ -20,7 +23,7 @@ pub struct Cc {
     cmd: Command,
 }
 
-crate::impl_common_helpers!(Cc);
+crate::macros::impl_common_helpers!(Cc);
 
 impl Cc {
     /// Construct a new platform-specific C compiler invocation.
@@ -72,10 +75,10 @@ impl Cc {
 
         if is_msvc() {
             path.set_extension("exe");
-            let fe_path = cygpath_windows(&path);
+            let fe_path = get_windows_path(&path);
             path.set_extension("");
             path.set_extension("obj");
-            let fo_path = cygpath_windows(path);
+            let fo_path = get_windows_path(path);
             self.cmd.arg(format!("-Fe:{fe_path}"));
             self.cmd.arg(format!("-Fo:{fo_path}"));
         } else {
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/external_deps/clang.rs
index c23e41ebe21..2b0712541cd 100644
--- a/src/tools/run-make-support/src/clang.rs
+++ b/src/tools/run-make-support/src/external_deps/clang.rs
@@ -16,7 +16,7 @@ pub struct Clang {
     cmd: Command,
 }
 
-crate::impl_common_helpers!(Clang);
+crate::macros::impl_common_helpers!(Clang);
 
 impl Clang {
     /// Construct a new `clang` invocation. `clang` is not always available for all targets.
diff --git a/src/tools/run-make-support/src/external_deps/cygpath.rs b/src/tools/run-make-support/src/external_deps/cygpath.rs
new file mode 100644
index 00000000000..07d8e840a63
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/cygpath.rs
@@ -0,0 +1,35 @@
+use std::panic;
+use std::path::Path;
+
+use crate::command::Command;
+use crate::util::handle_failed_output;
+
+/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
+/// available on the platform!
+///
+/// # FIXME
+///
+/// FIXME(jieyouxu): we should consider not depending on `cygpath`.
+///
+/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style
+/// > pathnames and vice versa.
+/// >
+/// > [irrelevant entries omitted...]
+/// >
+/// > `-w, --windows         print Windows form of NAMEs (C:\WINNT)`
+/// >
+/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*.
+#[track_caller]
+#[must_use]
+pub fn get_windows_path<P: AsRef<Path>>(path: P) -> String {
+    let caller = panic::Location::caller();
+    let mut cygpath = Command::new("cygpath");
+    cygpath.arg("-w");
+    cygpath.arg(path.as_ref());
+    let output = cygpath.run();
+    if !output.status().success() {
+        handle_failed_output(&cygpath, output, caller.line());
+    }
+    // cygpath -w can attach a newline
+    output.stdout_utf8().trim().to_string()
+}
diff --git a/src/tools/run-make-support/src/external_deps/htmldocck.rs b/src/tools/run-make-support/src/external_deps/htmldocck.rs
new file mode 100644
index 00000000000..afd0711ee04
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/htmldocck.rs
@@ -0,0 +1,14 @@
+use crate::command::Command;
+use crate::source_root;
+
+use super::python::python_command;
+
+/// `htmldocck` is a python script which is used for rustdoc test suites, it is assumed to be
+/// available at `$SOURCE_ROOT/src/etc/htmldocck.py`.
+#[track_caller]
+#[must_use]
+pub fn htmldocck() -> Command {
+    let mut python = python_command();
+    python.arg(source_root().join("src/etc/htmldocck.py"));
+    python
+}
diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index 064dc62a4af..5e8ad7ed312 100644
--- a/src/tools/run-make-support/src/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -1,6 +1,7 @@
 use std::path::{Path, PathBuf};
 
-use crate::{env_var, Command};
+use crate::command::Command;
+use crate::env::env_var;
 
 /// Construct a new `llvm-readobj` invocation with the `GNU` output style.
 /// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
@@ -70,11 +71,11 @@ pub struct LlvmAr {
     cmd: Command,
 }
 
-crate::impl_common_helpers!(LlvmReadobj);
-crate::impl_common_helpers!(LlvmProfdata);
-crate::impl_common_helpers!(LlvmFilecheck);
-crate::impl_common_helpers!(LlvmObjdump);
-crate::impl_common_helpers!(LlvmAr);
+crate::macros::impl_common_helpers!(LlvmReadobj);
+crate::macros::impl_common_helpers!(LlvmProfdata);
+crate::macros::impl_common_helpers!(LlvmFilecheck);
+crate::macros::impl_common_helpers!(LlvmObjdump);
+crate::macros::impl_common_helpers!(LlvmAr);
 
 /// Generate the path to the bin directory of LLVM.
 #[must_use]
diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs
new file mode 100644
index 00000000000..a2dc426f3f2
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/mod.rs
@@ -0,0 +1,14 @@
+//! This module contains external tool dependencies that we assume are available in the environment,
+//! such as `cc` or `python`.
+
+pub mod c_build;
+pub mod cc;
+pub mod clang;
+pub mod htmldocck;
+pub mod llvm;
+pub mod python;
+pub mod rustc;
+pub mod rustdoc;
+
+// Library-internal external dependency.
+mod cygpath;
diff --git a/src/tools/run-make-support/src/external_deps/python.rs b/src/tools/run-make-support/src/external_deps/python.rs
new file mode 100644
index 00000000000..fb885069371
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/python.rs
@@ -0,0 +1,11 @@
+use crate::command::Command;
+use crate::env::env_var;
+
+/// Obtain path of python as provided by the `PYTHON` environment variable. It is up to the caller
+/// to document and check if the python version is compatible with its intended usage.
+#[track_caller]
+#[must_use]
+pub fn python_command() -> Command {
+    let python_path = env_var("PYTHON");
+    Command::new(python_path)
+}
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 6b08608cc62..71d28dd9675 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -1,8 +1,10 @@
-use command::Command;
 use std::ffi::{OsStr, OsString};
 use std::path::Path;
 
-use crate::{command, cwd, env_var, set_host_rpath};
+use crate::command::Command;
+use crate::env::env_var;
+use crate::path_helpers::cwd;
+use crate::util::set_host_rpath;
 
 /// Construct a new `rustc` invocation. This will automatically set the library
 /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
@@ -31,7 +33,7 @@ pub struct Rustc {
     cmd: Command,
 }
 
-crate::impl_common_helpers!(Rustc);
+crate::macros::impl_common_helpers!(Rustc);
 
 #[track_caller]
 fn setup_common() -> Command {
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs
index 2be962ad888..96c2218a563 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -2,7 +2,8 @@ use std::ffi::OsStr;
 use std::path::Path;
 
 use crate::command::Command;
-use crate::{env_var, env_var_os, set_host_rpath};
+use crate::env::{env_var, env_var_os};
+use crate::util::set_host_rpath;
 
 /// Construct a plain `rustdoc` invocation with no flags set.
 #[track_caller]
@@ -22,7 +23,7 @@ pub struct Rustdoc {
     cmd: Command,
 }
 
-crate::impl_common_helpers!(Rustdoc);
+crate::macros::impl_common_helpers!(Rustdoc);
 
 #[track_caller]
 fn setup_common() -> Command {
diff --git a/src/tools/run-make-support/src/fs_wrapper.rs b/src/tools/run-make-support/src/fs.rs
index 0f0d6f6618c..f346e983aea 100644
--- a/src/tools/run-make-support/src/fs_wrapper.rs
+++ b/src/tools/run-make-support/src/fs.rs
@@ -1,17 +1,82 @@
-use std::fs;
+use std::io;
 use std::path::Path;
 
+// FIXME(jieyouxu): modify create_symlink to panic on windows.
+
+/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
+#[cfg(target_family = "windows")]
+pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
+    if link.as_ref().exists() {
+        std::fs::remove_dir(link.as_ref()).unwrap();
+    }
+    std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
+        "failed to create symlink {:?} for {:?}",
+        link.as_ref().display(),
+        original.as_ref().display(),
+    ));
+}
+
+/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
+#[cfg(target_family = "unix")]
+pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
+    if link.as_ref().exists() {
+        std::fs::remove_dir(link.as_ref()).unwrap();
+    }
+    std::os::unix::fs::symlink(original.as_ref(), link.as_ref()).expect(&format!(
+        "failed to create symlink {:?} for {:?}",
+        link.as_ref().display(),
+        original.as_ref().display(),
+    ));
+}
+
+/// Copy a directory into another.
+pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
+    fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
+        let dst = dst.as_ref();
+        if !dst.is_dir() {
+            std::fs::create_dir_all(&dst)?;
+        }
+        for entry in std::fs::read_dir(src)? {
+            let entry = entry?;
+            let ty = entry.file_type()?;
+            if ty.is_dir() {
+                copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
+            } else {
+                std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
+            }
+        }
+        Ok(())
+    }
+
+    if let Err(e) = copy_dir_all_inner(&src, &dst) {
+        // Trying to give more context about what exactly caused the failure
+        panic!(
+            "failed to copy `{}` to `{}`: {:?}",
+            src.as_ref().display(),
+            dst.as_ref().display(),
+            e
+        );
+    }
+}
+
+/// Helper for reading entries in a given directory.
+pub fn read_dir_entries<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
+    for entry in read_dir(dir) {
+        callback(&entry.unwrap().path());
+    }
+}
+
 /// A wrapper around [`std::fs::remove_file`] which includes the file path in the panic message.
 #[track_caller]
 pub fn remove_file<P: AsRef<Path>>(path: P) {
-    fs::remove_file(path.as_ref())
+    std::fs::remove_file(path.as_ref())
         .expect(&format!("the file in path \"{}\" could not be removed", path.as_ref().display()));
 }
 
 /// A wrapper around [`std::fs::copy`] which includes the file path in the panic message.
 #[track_caller]
 pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
-    fs::copy(from.as_ref(), to.as_ref()).expect(&format!(
+    std::fs::copy(from.as_ref(), to.as_ref()).expect(&format!(
         "the file \"{}\" could not be copied over to \"{}\"",
         from.as_ref().display(),
         to.as_ref().display(),
@@ -21,21 +86,21 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
 /// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message.
 #[track_caller]
 pub fn create_file<P: AsRef<Path>>(path: P) {
-    fs::File::create(path.as_ref())
+    std::fs::File::create(path.as_ref())
         .expect(&format!("the file in path \"{}\" could not be created", path.as_ref().display()));
 }
 
 /// A wrapper around [`std::fs::read`] which includes the file path in the panic message.
 #[track_caller]
 pub fn read<P: AsRef<Path>>(path: P) -> Vec<u8> {
-    fs::read(path.as_ref())
+    std::fs::read(path.as_ref())
         .expect(&format!("the file in path \"{}\" could not be read", path.as_ref().display()))
 }
 
 /// A wrapper around [`std::fs::read_to_string`] which includes the file path in the panic message.
 #[track_caller]
 pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
-    fs::read_to_string(path.as_ref()).expect(&format!(
+    std::fs::read_to_string(path.as_ref()).expect(&format!(
         "the file in path \"{}\" could not be read into a String",
         path.as_ref().display()
     ))
@@ -43,15 +108,15 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> String {
 
 /// A wrapper around [`std::fs::read_dir`] which includes the file path in the panic message.
 #[track_caller]
-pub fn read_dir<P: AsRef<Path>>(path: P) -> fs::ReadDir {
-    fs::read_dir(path.as_ref())
+pub fn read_dir<P: AsRef<Path>>(path: P) -> std::fs::ReadDir {
+    std::fs::read_dir(path.as_ref())
         .expect(&format!("the directory in path \"{}\" could not be read", path.as_ref().display()))
 }
 
 /// A wrapper around [`std::fs::write`] which includes the file path in the panic message.
 #[track_caller]
 pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) {
-    fs::write(path.as_ref(), contents.as_ref()).expect(&format!(
+    std::fs::write(path.as_ref(), contents.as_ref()).expect(&format!(
         "the file in path \"{}\" could not be written to",
         path.as_ref().display()
     ));
@@ -60,7 +125,7 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) {
 /// A wrapper around [`std::fs::remove_dir_all`] which includes the file path in the panic message.
 #[track_caller]
 pub fn remove_dir_all<P: AsRef<Path>>(path: P) {
-    fs::remove_dir_all(path.as_ref()).expect(&format!(
+    std::fs::remove_dir_all(path.as_ref()).expect(&format!(
         "the directory in path \"{}\" could not be removed alongside all its contents",
         path.as_ref().display(),
     ));
@@ -69,7 +134,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) {
 /// A wrapper around [`std::fs::create_dir`] which includes the file path in the panic message.
 #[track_caller]
 pub fn create_dir<P: AsRef<Path>>(path: P) {
-    fs::create_dir(path.as_ref()).expect(&format!(
+    std::fs::create_dir(path.as_ref()).expect(&format!(
         "the directory in path \"{}\" could not be created",
         path.as_ref().display()
     ));
@@ -78,7 +143,7 @@ pub fn create_dir<P: AsRef<Path>>(path: P) {
 /// A wrapper around [`std::fs::create_dir_all`] which includes the file path in the panic message.
 #[track_caller]
 pub fn create_dir_all<P: AsRef<Path>>(path: P) {
-    fs::create_dir_all(path.as_ref()).expect(&format!(
+    std::fs::create_dir_all(path.as_ref()).expect(&format!(
         "the directory (and all its parents) in path \"{}\" could not be created",
         path.as_ref().display()
     ));
@@ -86,8 +151,8 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) {
 
 /// A wrapper around [`std::fs::metadata`] which includes the file path in the panic message.
 #[track_caller]
-pub fn metadata<P: AsRef<Path>>(path: P) -> fs::Metadata {
-    fs::metadata(path.as_ref()).expect(&format!(
+pub fn metadata<P: AsRef<Path>>(path: P) -> std::fs::Metadata {
+    std::fs::metadata(path.as_ref()).expect(&format!(
         "the file's metadata in path \"{}\" could not be read",
         path.as_ref().display()
     ))
@@ -96,7 +161,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> fs::Metadata {
 /// A wrapper around [`std::fs::rename`] which includes the file path in the panic message.
 #[track_caller]
 pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
-    fs::rename(from.as_ref(), to.as_ref()).expect(&format!(
+    std::fs::rename(from.as_ref(), to.as_ref()).expect(&format!(
         "the file \"{}\" could not be moved over to \"{}\"",
         from.as_ref().display(),
         to.as_ref().display(),
@@ -105,8 +170,8 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) {
 
 /// A wrapper around [`std::fs::set_permissions`] which includes the file path in the panic message.
 #[track_caller]
-pub fn set_permissions<P: AsRef<Path>>(path: P, perm: fs::Permissions) {
-    fs::set_permissions(path.as_ref(), perm).expect(&format!(
+pub fn set_permissions<P: AsRef<Path>>(path: P, perm: std::fs::Permissions) {
+    std::fs::set_permissions(path.as_ref(), perm).expect(&format!(
         "the file's permissions in path \"{}\" could not be changed",
         path.as_ref().display()
     ));
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index cec2cedd15c..b85191970de 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -3,651 +3,90 @@
 //! 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.
 
-pub mod cc;
-pub mod clang;
+// 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;
+
+pub mod artifact_names;
+pub mod assertion_helpers;
 pub mod diff;
-pub mod fs_wrapper;
-pub mod llvm;
+pub mod env;
+pub mod external_deps;
+pub mod path_helpers;
 pub mod run;
-pub mod rustc;
-pub mod rustdoc;
+pub mod scoped_run;
+pub mod string;
+pub mod targets;
 
-use std::env;
-use std::ffi::OsString;
-use std::fs;
-use std::io;
-use std::panic;
-use std::path::{Path, PathBuf};
+// 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
+/// confused with [`std::fs`].
+pub mod rfs {
+    pub use crate::fs::*;
+}
 
+// Re-exports of third-party library crates.
 pub use bstr;
 pub use gimli;
 pub use object;
 pub use regex;
 pub use wasmparser;
 
+// Re-exports of external dependencies.
+pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc};
+
+// These rely on external dependencies.
+pub use c_build::build_native_static_lib;
 pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
-pub use diff::{diff, Diff};
+pub use htmldocck::htmldocck;
 pub use llvm::{
     llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck,
     LlvmObjdump, LlvmProfdata, LlvmReadobj,
 };
-pub use run::{cmd, run, run_fail, run_with_args};
+pub use python::python_command;
 pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
 
-#[track_caller]
-#[must_use]
-pub fn env_var(name: &str) -> String {
-    match env::var(name) {
-        Ok(v) => v,
-        Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"),
-    }
-}
-
-#[track_caller]
-#[must_use]
-pub fn env_var_os(name: &str) -> OsString {
-    match env::var_os(name) {
-        Some(v) => v,
-        None => panic!("failed to retrieve environment variable {name:?}"),
-    }
-}
-
-/// `TARGET`
-#[must_use]
-pub fn target() -> String {
-    env_var("TARGET")
-}
-
-/// Check if target is windows-like.
-#[must_use]
-pub fn is_windows() -> bool {
-    target().contains("windows")
-}
-
-/// Check if target uses msvc.
-#[must_use]
-pub fn is_msvc() -> bool {
-    target().contains("msvc")
-}
-
-/// Check if target uses macOS.
-#[must_use]
-pub fn is_darwin() -> bool {
-    target().contains("darwin")
-}
-
-#[track_caller]
-#[must_use]
-pub fn python_command() -> Command {
-    let python_path = env_var("PYTHON");
-    Command::new(python_path)
-}
-
-#[track_caller]
-#[must_use]
-pub fn htmldocck() -> Command {
-    let mut python = python_command();
-    python.arg(source_root().join("src/etc/htmldocck.py"));
-    python
-}
-
-/// Returns the path for a local test file.
-pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
-    cwd().join(p.as_ref())
-}
-
-/// Path to the root rust-lang/rust source checkout.
-#[must_use]
-pub fn source_root() -> PathBuf {
-    env_var("SOURCE_ROOT").into()
-}
-
-/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
-#[cfg(target_family = "windows")]
-pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
-    if link.as_ref().exists() {
-        std::fs::remove_dir(link.as_ref()).unwrap();
-    }
-    use std::os::windows::fs;
-    fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
-        "failed to create symlink {:?} for {:?}",
-        link.as_ref().display(),
-        original.as_ref().display(),
-    ));
-}
-
-/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
-#[cfg(target_family = "unix")]
-pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
-    if link.as_ref().exists() {
-        std::fs::remove_dir(link.as_ref()).unwrap();
-    }
-    use std::os::unix::fs;
-    fs::symlink(original.as_ref(), link.as_ref()).expect(&format!(
-        "failed to create symlink {:?} for {:?}",
-        link.as_ref().display(),
-        original.as_ref().display(),
-    ));
-}
-
-/// Construct the static library name based on the platform.
-#[must_use]
-pub fn static_lib_name(name: &str) -> String {
-    // See tools.mk (irrelevant lines omitted):
-    //
-    // ```makefile
-    // ifeq ($(UNAME),Darwin)
-    //     STATICLIB = $(TMPDIR)/lib$(1).a
-    // else
-    //     ifdef IS_WINDOWS
-    //         ifdef IS_MSVC
-    //             STATICLIB = $(TMPDIR)/$(1).lib
-    //         else
-    //             STATICLIB = $(TMPDIR)/lib$(1).a
-    //         endif
-    //     else
-    //         STATICLIB = $(TMPDIR)/lib$(1).a
-    //     endif
-    // endif
-    // ```
-    assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
-
-    if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
-}
-
-/// Construct the dynamic library name based on the platform.
-#[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}")
-    }
-}
-
-#[must_use]
-pub fn dynamic_lib_extension() -> &'static str {
-    if is_darwin() {
-        "dylib"
-    } else if is_windows() {
-        "dll"
-    } else {
-        "so"
-    }
-}
-
-/// Generate the name a rust library (rlib) would have.
-#[must_use]
-pub fn rust_lib_name(name: &str) -> String {
-    format!("lib{name}.rlib")
-}
-
-/// Construct the binary name based on platform.
-#[must_use]
-pub fn bin_name(name: &str) -> String {
-    if is_windows() { format!("{name}.exe") } else { name.to_string() }
-}
-
-/// Return the current working directory.
-#[must_use]
-pub fn cwd() -> PathBuf {
-    env::current_dir().unwrap()
-}
-
-// FIXME(Oneirical): This will no longer be required after compiletest receives the ability
-// to manipulate read-only files. See https://github.com/rust-lang/rust/issues/126334
-/// Ensure that the path P is read-only while the test runs, and restore original permissions
-/// at the end so compiletest can clean up.
-/// This will panic on Windows if the path is a directory (as it would otherwise do nothing)
-#[track_caller]
-pub fn test_while_readonly<P: AsRef<Path>, F: FnOnce() + std::panic::UnwindSafe>(
-    path: P,
-    closure: F,
-) {
-    let path = path.as_ref();
-    if is_windows() && path.is_dir() {
-        eprintln!("This helper function cannot be used on Windows to make directories readonly.");
-        eprintln!(
-            "See the official documentation:
-            https://doc.rust-lang.org/std/fs/struct.Permissions.html#method.set_readonly"
-        );
-        panic!("`test_while_readonly` on directory detected while on Windows.");
-    }
-    let metadata = fs_wrapper::metadata(&path);
-    let original_perms = metadata.permissions();
-
-    let mut new_perms = original_perms.clone();
-    new_perms.set_readonly(true);
-    fs_wrapper::set_permissions(&path, new_perms);
-
-    let success = std::panic::catch_unwind(closure);
-
-    fs_wrapper::set_permissions(&path, original_perms);
-    success.unwrap();
-}
-
-/// Browse the directory `path` non-recursively and return all files which respect the parameters
-/// outlined by `closure`.
-#[track_caller]
-pub fn shallow_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
-    path: P,
-    filter: F,
-) -> Vec<PathBuf> {
-    let mut matching_files = Vec::new();
-    for entry in fs_wrapper::read_dir(path) {
-        let entry = entry.expect("failed to read directory entry.");
-        let path = entry.path();
-
-        if path.is_file() && filter(&path) {
-            matching_files.push(path);
-        }
-    }
-    matching_files
-}
-
-/// Returns true if the filename at `path` starts with `prefix`.
-pub fn has_prefix<P: AsRef<Path>>(path: P, prefix: &str) -> bool {
-    path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().starts_with(prefix))
-}
-
-/// Returns true if the filename at `path` has the extension `extension`.
-pub fn has_extension<P: AsRef<Path>>(path: P, extension: &str) -> bool {
-    path.as_ref().extension().is_some_and(|ext| ext == extension)
-}
-
-/// Returns true if the filename at `path` does not contain `expected`.
-pub fn not_contains<P: AsRef<Path>>(path: P, expected: &str) -> bool {
-    !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected))
-}
-
-/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
-#[track_caller]
-pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
-    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
-    let src = format!("{lib_name}.c");
-    let lib_path = static_lib_name(lib_name);
-    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();
-    };
-    let obj_file = if is_msvc() {
-        PathBuf::from(format!("{lib_name}.obj"))
-    } else {
-        PathBuf::from(format!("{lib_name}.o"))
-    };
-    llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
-    path(lib_path)
-}
-
-/// Returns true if the filename at `path` is not in `expected`.
-pub fn filename_not_in_denylist<P: AsRef<Path>, V: AsRef<[String]>>(path: P, expected: V) -> bool {
-    let expected = expected.as_ref();
-    path.as_ref()
-        .file_name()
-        .is_some_and(|name| !expected.contains(&name.to_str().unwrap().to_owned()))
-}
-
-/// Returns true if the filename at `path` ends with `suffix`.
-pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
-    path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().ends_with(suffix))
-}
-
-/// Gathers all files in the current working directory that have the extension `ext`, and counts
-/// the number of lines within that contain a match with the regex pattern `re`.
-pub fn count_regex_matches_in_files_with_extension(re: &regex::Regex, ext: &str) -> usize {
-    let fetched_files = shallow_find_files(cwd(), |path| has_extension(path, ext));
-
-    let mut count = 0;
-    for file in fetched_files {
-        let content = fs_wrapper::read_to_string(file);
-        count += content.lines().filter(|line| re.is_match(&line)).count();
-    }
-
-    count
-}
-
-/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
-/// available on the platform!
-#[track_caller]
-#[must_use]
-pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
-    let caller = panic::Location::caller();
-    let mut cygpath = Command::new("cygpath");
-    cygpath.arg("-w");
-    cygpath.arg(path.as_ref());
-    let output = cygpath.run();
-    if !output.status().success() {
-        handle_failed_output(&cygpath, output, caller.line());
-    }
-    // cygpath -w can attach a newline
-    output.stdout_utf8().trim().to_string()
-}
-
-/// Run `uname`. This assumes that `uname` is available on the platform!
-#[track_caller]
-#[must_use]
-pub fn uname() -> String {
-    let caller = panic::Location::caller();
-    let mut uname = Command::new("uname");
-    let output = uname.run();
-    if !output.status().success() {
-        handle_failed_output(&uname, output, caller.line());
-    }
-    output.stdout_utf8()
-}
-
-fn handle_failed_output(cmd: &Command, output: CompletedProcess, caller_line_number: u32) -> ! {
-    if output.status().success() {
-        eprintln!("command unexpectedly succeeded at line {caller_line_number}");
-    } else {
-        eprintln!("command failed at line {caller_line_number}");
-    }
-    eprintln!("{cmd:?}");
-    eprintln!("output status: `{}`", output.status());
-    eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
-    eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
-    std::process::exit(1)
-}
-
-/// Set the runtime library path as needed for running the host rustc/rustdoc/etc.
-pub fn set_host_rpath(cmd: &mut Command) {
-    let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
-    cmd.env(&ld_lib_path_envvar, {
-        let mut paths = vec![];
-        paths.push(cwd());
-        paths.push(PathBuf::from(env_var("HOST_RPATH_DIR")));
-        for p in env::split_paths(&env_var(&ld_lib_path_envvar)) {
-            paths.push(p.to_path_buf());
-        }
-        env::join_paths(paths.iter()).unwrap()
-    });
-}
-
-/// Read the contents of a file that cannot simply be read by
-/// read_to_string, due to invalid utf8 data, then assert that it contains `expected`.
-#[track_caller]
-pub fn invalid_utf8_contains<P: AsRef<Path>, S: AsRef<str>>(path: P, expected: S) {
-    let buffer = fs_wrapper::read(path.as_ref());
-    let expected = expected.as_ref();
-    if !String::from_utf8_lossy(&buffer).contains(expected) {
-        eprintln!("=== FILE CONTENTS (LOSSY) ===");
-        eprintln!("{}", String::from_utf8_lossy(&buffer));
-        eprintln!("=== SPECIFIED TEXT ===");
-        eprintln!("{}", expected);
-        panic!("specified text was not found in file");
-    }
-}
-
-/// Read the contents of a file that cannot simply be read by
-/// read_to_string, due to invalid utf8 data, then assert that it does not contain `expected`.
-#[track_caller]
-pub fn invalid_utf8_not_contains<P: AsRef<Path>, S: AsRef<str>>(path: P, expected: S) {
-    let buffer = fs_wrapper::read(path.as_ref());
-    let expected = expected.as_ref();
-    if String::from_utf8_lossy(&buffer).contains(expected) {
-        eprintln!("=== FILE CONTENTS (LOSSY) ===");
-        eprintln!("{}", String::from_utf8_lossy(&buffer));
-        eprintln!("=== SPECIFIED TEXT ===");
-        eprintln!("{}", expected);
-        panic!("specified text was unexpectedly found in file");
-    }
-}
-
-/// Copy a directory into another.
-pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
-    fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
-        let dst = dst.as_ref();
-        if !dst.is_dir() {
-            std::fs::create_dir_all(&dst)?;
-        }
-        for entry in std::fs::read_dir(src)? {
-            let entry = entry?;
-            let ty = entry.file_type()?;
-            if ty.is_dir() {
-                copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
-            } else {
-                std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
-            }
-        }
-        Ok(())
-    }
-
-    if let Err(e) = copy_dir_all_inner(&src, &dst) {
-        // Trying to give more context about what exactly caused the failure
-        panic!(
-            "failed to copy `{}` to `{}`: {:?}",
-            src.as_ref().display(),
-            dst.as_ref().display(),
-            e
-        );
-    }
-}
-
-/// Check that all files in `dir1` exist and have the same content in `dir2`. Panic otherwise.
-pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
-    let dir2 = dir2.as_ref();
-    read_dir(dir1, |entry_path| {
-        let entry_name = entry_path.file_name().unwrap();
-        if entry_path.is_dir() {
-            recursive_diff(&entry_path, &dir2.join(entry_name));
-        } else {
-            let path2 = dir2.join(entry_name);
-            let file1 = fs_wrapper::read(&entry_path);
-            let file2 = fs_wrapper::read(&path2);
-
-            // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
-            // Why not using String? Because there might be minified files or even potentially
-            // binary ones, so that would display useless output.
-            assert!(
-                file1 == file2,
-                "`{}` and `{}` have different content",
-                entry_path.display(),
-                path2.display(),
-            );
-        }
-    });
-}
-
-pub fn read_dir<F: FnMut(&Path)>(dir: impl AsRef<Path>, mut callback: F) {
-    for entry in fs_wrapper::read_dir(dir) {
-        callback(&entry.unwrap().path());
-    }
-}
-
-/// Check that `actual` is equal to `expected`. Panic otherwise.
-#[track_caller]
-pub fn assert_equals<S1: AsRef<str>, S2: AsRef<str>>(actual: S1, expected: S2) {
-    let actual = actual.as_ref();
-    let expected = expected.as_ref();
-    if actual != expected {
-        eprintln!("=== ACTUAL TEXT ===");
-        eprintln!("{}", actual);
-        eprintln!("=== EXPECTED ===");
-        eprintln!("{}", expected);
-        panic!("expected text was not found in actual text");
-    }
-}
-
-/// Check that `haystack` contains `needle`. Panic otherwise.
-#[track_caller]
-pub fn assert_contains<S1: AsRef<str>, S2: AsRef<str>>(haystack: S1, needle: S2) {
-    let haystack = haystack.as_ref();
-    let needle = needle.as_ref();
-    if !haystack.contains(needle) {
-        eprintln!("=== HAYSTACK ===");
-        eprintln!("{}", haystack);
-        eprintln!("=== NEEDLE ===");
-        eprintln!("{}", needle);
-        panic!("needle was not found in haystack");
-    }
-}
-
-/// Check that `haystack` does not contain `needle`. Panic otherwise.
-#[track_caller]
-pub fn assert_not_contains<S1: AsRef<str>, S2: AsRef<str>>(haystack: S1, needle: S2) {
-    let haystack = haystack.as_ref();
-    let needle = needle.as_ref();
-    if haystack.contains(needle) {
-        eprintln!("=== HAYSTACK ===");
-        eprintln!("{}", haystack);
-        eprintln!("=== NEEDLE ===");
-        eprintln!("{}", needle);
-        panic!("needle was unexpectedly found in haystack");
-    }
-}
-
-/// This function is designed for running commands in a temporary directory
-/// that is cleared after the function ends.
+/// [`diff`][mod@diff] is implemented in terms of the [similar] library.
 ///
-/// What this function does:
-/// 1) Creates a temporary directory (`tmpdir`)
-/// 2) Copies all files from the current directory to `tmpdir`
-/// 3) Changes the current working directory to `tmpdir`
-/// 4) Calls `callback`
-/// 5) Switches working directory back to the original one
-/// 6) Removes `tmpdir`
-pub fn run_in_tmpdir<F: FnOnce()>(callback: F) {
-    let original_dir = cwd();
-    let tmpdir = original_dir.join("../temporary-directory");
-    copy_dir_all(".", &tmpdir);
-
-    env::set_current_dir(&tmpdir).unwrap();
-    callback();
-    env::set_current_dir(original_dir).unwrap();
-    fs::remove_dir_all(tmpdir).unwrap();
-}
-
-/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
-/// containing a `cmd: Command` field. The provided helpers are:
-///
-/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
-///    to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
-///    new specific helper methods over relying on these generic argument providers.
-/// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
-///    methods of the same name on [`Command`].
-/// 3. Output and execution: `run` and `run_fail` are provided. These are
-///    higher-level convenience methods which wait for the command to finish running and assert
-///    that the command successfully ran or failed as expected. They return
-///    [`CompletedProcess`], which can be used to assert the stdout/stderr/exit code of the executed
-///    process.
-///
-/// Example usage:
-///
-/// ```ignore (illustrative)
-/// struct CommandWrapper { cmd: Command } // <- required `cmd` field
-///
-/// crate::impl_common_helpers!(CommandWrapper);
-///
-/// impl CommandWrapper {
-///     // ... additional specific helper methods
-/// }
-/// ```
-macro_rules! impl_common_helpers {
-    ($wrapper: ident) => {
-        impl $wrapper {
-            /// Specify an environment variable.
-            pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
-            where
-                K: AsRef<::std::ffi::OsStr>,
-                V: AsRef<::std::ffi::OsStr>,
-            {
-                self.cmd.env(key, value);
-                self
-            }
-
-            /// Remove an environmental variable.
-            pub fn env_remove<K>(&mut self, key: K) -> &mut Self
-            where
-                K: AsRef<::std::ffi::OsStr>,
-            {
-                self.cmd.env_remove(key);
-                self
-            }
+/// [similar]: https://github.com/mitsuhiko/similar
+pub use diff::{diff, Diff};
 
-            /// Generic command argument provider. Prefer specific helper methods if possible.
-            /// Note that for some executables, arguments might be platform specific. For C/C++
-            /// compilers, arguments might be platform *and* compiler specific.
-            pub fn arg<S>(&mut self, arg: S) -> &mut Self
-            where
-                S: AsRef<::std::ffi::OsStr>,
-            {
-                self.cmd.arg(arg);
-                self
-            }
+/// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers.
+pub use env::{env_var, env_var_os};
 
-            /// Generic command arguments provider. Prefer specific helper methods if possible.
-            /// Note that for some executables, arguments might be platform specific. For C/C++
-            /// compilers, arguments might be platform *and* compiler specific.
-            pub fn args<V, S>(&mut self, args: V) -> &mut Self
-            where
-                V: AsRef<[S]>,
-                S: AsRef<::std::ffi::OsStr>,
-            {
-                self.cmd.args(args.as_ref());
-                self
-            }
+/// Convenience helpers for running binaries and other commands.
+pub use run::{cmd, run, run_fail, run_with_args};
 
-            /// Inspect what the underlying [`Command`] is up to the
-            /// current construction.
-            pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
-            where
-                I: FnOnce(&::std::process::Command),
-            {
-                self.cmd.inspect(inspector);
-                self
-            }
+/// Helpers for checking target information.
+pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname};
 
-            /// Run the constructed command and assert that it is successfully run.
-            #[track_caller]
-            pub fn run(&mut self) -> crate::command::CompletedProcess {
-                self.cmd.run()
-            }
+/// Helpers for building names of output artifacts that are potentially target-specific.
+pub use artifact_names::{
+    bin_name, dynamic_lib_extension, dynamic_lib_name, rust_lib_name, static_lib_name,
+};
 
-            /// Run the constructed command and assert that it does not successfully run.
-            #[track_caller]
-            pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
-                self.cmd.run_fail()
-            }
+/// Path-related helpers.
+pub use path_helpers::{
+    cwd, filename_not_in_denylist, has_extension, has_prefix, has_suffix, not_contains, path,
+    shallow_find_files, source_root,
+};
 
-            /// Run the command but do not check its exit status.
-            /// Only use if you explicitly don't care about the exit status.
-            /// Prefer to use [`Self::run`] and [`Self::run_fail`]
-            /// whenever possible.
-            #[track_caller]
-            pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess {
-                self.cmd.run_unchecked()
-            }
+/// Helpers for scoped test execution where certain properties are attempted to be maintained.
+pub use scoped_run::{run_in_tmpdir, test_while_readonly};
 
-            /// Set the path where the command will be run.
-            pub fn current_dir<P: AsRef<::std::path::Path>>(&mut self, path: P) -> &mut Self {
-                self.cmd.current_dir(path);
-                self
-            }
-        }
-    };
-}
+pub use assertion_helpers::{
+    assert_contains, assert_dirs_are_equal, assert_equals, assert_not_contains,
+};
 
-use crate::command::{Command, CompletedProcess};
-pub(crate) use impl_common_helpers;
+pub use string::{
+    count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains,
+};
diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs
new file mode 100644
index 00000000000..f7fe4f54223
--- /dev/null
+++ b/src/tools/run-make-support/src/macros.rs
@@ -0,0 +1,113 @@
+/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
+/// containing a `cmd: Command` field. The provided helpers are:
+///
+/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
+///    to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
+///    new specific helper methods over relying on these generic argument providers.
+/// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
+///    methods of the same name on [`Command`].
+/// 3. Output and execution: `run` and `run_fail` are provided. These are higher-level convenience
+///    methods which wait for the command to finish running and assert that the command successfully
+///    ran or failed as expected. They return [`CompletedProcess`], which can be used to assert the
+///    stdout/stderr/exit code of the executed process.
+///
+/// Example usage:
+///
+/// ```ignore (illustrative)
+/// struct CommandWrapper { cmd: Command } // <- required `cmd` field
+///
+/// crate::macros::impl_common_helpers!(CommandWrapper);
+///
+/// impl CommandWrapper {
+///     // ... additional specific helper methods
+/// }
+/// ```
+///
+/// [`Command`]: crate::command::Command
+/// [`CompletedProcess`]: crate::command::CompletedProcess
+macro_rules! impl_common_helpers {
+    ($wrapper: ident) => {
+        impl $wrapper {
+            /// Specify an environment variable.
+            pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
+            where
+                K: AsRef<::std::ffi::OsStr>,
+                V: AsRef<::std::ffi::OsStr>,
+            {
+                self.cmd.env(key, value);
+                self
+            }
+
+            /// Remove an environmental variable.
+            pub fn env_remove<K>(&mut self, key: K) -> &mut Self
+            where
+                K: AsRef<::std::ffi::OsStr>,
+            {
+                self.cmd.env_remove(key);
+                self
+            }
+
+            /// Generic command argument provider. Prefer specific helper methods if possible.
+            /// Note that for some executables, arguments might be platform specific. For C/C++
+            /// compilers, arguments might be platform *and* compiler specific.
+            pub fn arg<S>(&mut self, arg: S) -> &mut Self
+            where
+                S: AsRef<::std::ffi::OsStr>,
+            {
+                self.cmd.arg(arg);
+                self
+            }
+
+            /// Generic command arguments provider. Prefer specific helper methods if possible.
+            /// Note that for some executables, arguments might be platform specific. For C/C++
+            /// compilers, arguments might be platform *and* compiler specific.
+            pub fn args<V, S>(&mut self, args: V) -> &mut Self
+            where
+                V: AsRef<[S]>,
+                S: AsRef<::std::ffi::OsStr>,
+            {
+                self.cmd.args(args.as_ref());
+                self
+            }
+
+            /// Inspect what the underlying [`Command`] is up to the
+            /// current construction.
+            pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
+            where
+                I: FnOnce(&::std::process::Command),
+            {
+                self.cmd.inspect(inspector);
+                self
+            }
+
+            /// Run the constructed command and assert that it is successfully run.
+            #[track_caller]
+            pub fn run(&mut self) -> crate::command::CompletedProcess {
+                self.cmd.run()
+            }
+
+            /// Run the constructed command and assert that it does not successfully run.
+            #[track_caller]
+            pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
+                self.cmd.run_fail()
+            }
+
+            /// Run the command but do not check its exit status.
+            /// Only use if you explicitly don't care about the exit status.
+            /// Prefer to use [`Self::run`] and [`Self::run_fail`]
+            /// whenever possible.
+            #[track_caller]
+            pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess {
+                self.cmd.run_unchecked()
+            }
+
+            /// Set the path where the command will be run.
+            pub fn current_dir<P: AsRef<::std::path::Path>>(&mut self, path: P) -> &mut Self {
+                self.cmd.current_dir(path);
+                self
+            }
+        }
+    };
+}
+
+pub(crate) use impl_common_helpers;
diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs
new file mode 100644
index 00000000000..f37ea8dfef8
--- /dev/null
+++ b/src/tools/run-make-support/src/path_helpers.rs
@@ -0,0 +1,80 @@
+//! Collection of path-related helpers.
+
+use std::path::{Path, PathBuf};
+
+use crate::env::env_var;
+
+/// Return the current working directory.
+///
+/// This forwards to [`std::env::current_dir`], please see its docs regarding platform-specific
+/// behavior.
+#[must_use]
+pub fn cwd() -> PathBuf {
+    std::env::current_dir().unwrap()
+}
+
+/// Construct a `PathBuf` relative to the current working directory by joining `cwd()` with the
+/// relative path. This is mostly a convenience helper so the test writer does not need to write
+/// `PathBuf::from(path_like_string)`.
+///
+/// # Example
+///
+/// ```rust
+/// let p = path("support_file.txt");
+/// ```
+pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
+    cwd().join(p.as_ref())
+}
+
+/// Path to the root `rust-lang/rust` source checkout.
+#[must_use]
+pub fn source_root() -> PathBuf {
+    env_var("SOURCE_ROOT").into()
+}
+
+/// Browse the directory `path` non-recursively and return all files which respect the parameters
+/// outlined by `closure`.
+#[track_caller]
+pub fn shallow_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
+    path: P,
+    filter: F,
+) -> Vec<PathBuf> {
+    let mut matching_files = Vec::new();
+    for entry in std::fs::read_dir(path).unwrap() {
+        let entry = entry.expect("failed to read directory entry.");
+        let path = entry.path();
+
+        if path.is_file() && filter(&path) {
+            matching_files.push(path);
+        }
+    }
+    matching_files
+}
+
+/// Returns true if the filename at `path` does not contain `expected`.
+pub fn not_contains<P: AsRef<Path>>(path: P, expected: &str) -> bool {
+    !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected))
+}
+
+/// Returns true if the filename at `path` is not in `expected`.
+pub fn filename_not_in_denylist<P: AsRef<Path>, V: AsRef<[String]>>(path: P, expected: V) -> bool {
+    let expected = expected.as_ref();
+    path.as_ref()
+        .file_name()
+        .is_some_and(|name| !expected.contains(&name.to_str().unwrap().to_owned()))
+}
+
+/// Returns true if the filename at `path` starts with `prefix`.
+pub fn has_prefix<P: AsRef<Path>>(path: P, prefix: &str) -> bool {
+    path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().starts_with(prefix))
+}
+
+/// Returns true if the filename at `path` has the extension `extension`.
+pub fn has_extension<P: AsRef<Path>>(path: P, extension: &str) -> bool {
+    path.as_ref().extension().is_some_and(|ext| ext == extension)
+}
+
+/// Returns true if the filename at `path` ends with `suffix`.
+pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
+    path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().ends_with(suffix))
+}
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 54730bb7de7..17f8ce34f19 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -4,9 +4,8 @@ use std::panic;
 use std::path::{Path, PathBuf};
 
 use crate::command::{Command, CompletedProcess};
-use crate::{cwd, env_var, is_windows, set_host_rpath};
-
-use super::handle_failed_output;
+use crate::util::{handle_failed_output, set_host_rpath};
+use crate::{cwd, env_var, is_windows};
 
 #[track_caller]
 fn run_common(name: &str, args: Option<&[&str]>) -> Command {
diff --git a/src/tools/run-make-support/src/scoped_run.rs b/src/tools/run-make-support/src/scoped_run.rs
new file mode 100644
index 00000000000..074a83922c5
--- /dev/null
+++ b/src/tools/run-make-support/src/scoped_run.rs
@@ -0,0 +1,69 @@
+//! Collection of helpers that try to maintain certain properties while running a test closure.
+
+use std::path::Path;
+
+use crate::fs;
+use crate::path_helpers::cwd;
+use crate::targets::is_windows;
+
+/// Ensure that the path P is read-only while the test runs, and restore original permissions at the
+/// end so compiletest can clean up. This will panic on Windows if the path is a directory (as it
+/// would otherwise do nothing)
+///
+/// # Pitfalls
+///
+/// - Some CI runners are ran as root which may bypass read-only permission restrictions. Unclear
+///   exactly when such scenarios occur.
+///
+/// # FIXME
+///
+/// FIXME(Oneirical): This will no longer be required after compiletest receives the ability to
+/// manipulate read-only files. See <https://github.com/rust-lang/rust/issues/126334>.
+#[track_caller]
+pub fn test_while_readonly<P, F>(path: P, closure: F)
+where
+    P: AsRef<Path>,
+    F: FnOnce() + std::panic::UnwindSafe,
+{
+    let path = path.as_ref();
+    if is_windows() && path.is_dir() {
+        eprintln!("This helper function cannot be used on Windows to make directories readonly.");
+        eprintln!(
+            "See the official documentation:
+            https://doc.rust-lang.org/std/fs/struct.Permissions.html#method.set_readonly"
+        );
+        panic!("`test_while_readonly` on directory detected while on Windows.");
+    }
+    let metadata = fs::metadata(&path);
+    let original_perms = metadata.permissions();
+
+    let mut new_perms = original_perms.clone();
+    new_perms.set_readonly(true);
+    fs::set_permissions(&path, new_perms);
+
+    let success = std::panic::catch_unwind(closure);
+
+    fs::set_permissions(&path, original_perms);
+    success.unwrap();
+}
+
+/// This function is designed for running commands in a temporary directory that is cleared after
+/// the function ends.
+///
+/// What this function does:
+/// 1. Creates a temporary directory (`tmpdir`)
+/// 2. Copies all files from the current directory to `tmpdir`
+/// 3. Changes the current working directory to `tmpdir`
+/// 4. Calls `callback`
+/// 5. Switches working directory back to the original one
+/// 6. Removes `tmpdir`
+pub fn run_in_tmpdir<F: FnOnce()>(callback: F) {
+    let original_dir = cwd();
+    let tmpdir = original_dir.join("../temporary-directory");
+    fs::copy_dir_all(".", &tmpdir);
+
+    std::env::set_current_dir(&tmpdir).unwrap();
+    callback();
+    std::env::set_current_dir(original_dir).unwrap();
+    fs::remove_dir_all(tmpdir);
+}
diff --git a/src/tools/run-make-support/src/string.rs b/src/tools/run-make-support/src/string.rs
new file mode 100644
index 00000000000..a79004b8ec6
--- /dev/null
+++ b/src/tools/run-make-support/src/string.rs
@@ -0,0 +1,50 @@
+use std::path::Path;
+
+use crate::fs;
+use crate::path_helpers::{cwd, has_extension, shallow_find_files};
+
+/// Gathers all files in the current working directory that have the extension `ext`, and counts
+/// the number of lines within that contain a match with the regex pattern `re`.
+pub fn count_regex_matches_in_files_with_extension(re: &regex::Regex, ext: &str) -> usize {
+    let fetched_files = shallow_find_files(cwd(), |path| has_extension(path, ext));
+
+    let mut count = 0;
+    for file in fetched_files {
+        let content = fs::read_to_string(file);
+        count += content.lines().filter(|line| re.is_match(&line)).count();
+    }
+
+    count
+}
+
+/// Read the contents of a file that cannot simply be read by
+/// [`read_to_string`][crate::fs::read_to_string], due to invalid UTF-8 data, then assert
+/// that it contains `expected`.
+#[track_caller]
+pub fn invalid_utf8_contains<P: AsRef<Path>, S: AsRef<str>>(path: P, expected: S) {
+    let buffer = fs::read(path.as_ref());
+    let expected = expected.as_ref();
+    if !String::from_utf8_lossy(&buffer).contains(expected) {
+        eprintln!("=== FILE CONTENTS (LOSSY) ===");
+        eprintln!("{}", String::from_utf8_lossy(&buffer));
+        eprintln!("=== SPECIFIED TEXT ===");
+        eprintln!("{}", expected);
+        panic!("specified text was not found in file");
+    }
+}
+
+/// Read the contents of a file that cannot simply be read by
+/// [`read_to_string`][crate::fs::read_to_string], due to invalid UTF-8 data, then assert
+/// that it does not contain `expected`.
+#[track_caller]
+pub fn invalid_utf8_not_contains<P: AsRef<Path>, S: AsRef<str>>(path: P, expected: S) {
+    let buffer = fs::read(path.as_ref());
+    let expected = expected.as_ref();
+    if String::from_utf8_lossy(&buffer).contains(expected) {
+        eprintln!("=== FILE CONTENTS (LOSSY) ===");
+        eprintln!("{}", String::from_utf8_lossy(&buffer));
+        eprintln!("=== SPECIFIED TEXT ===");
+        eprintln!("{}", expected);
+        panic!("specified text was unexpectedly found in file");
+    }
+}
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
new file mode 100644
index 00000000000..5dcb0b83430
--- /dev/null
+++ b/src/tools/run-make-support/src/targets.rs
@@ -0,0 +1,49 @@
+use std::panic;
+
+use crate::command::Command;
+use crate::env_var;
+use crate::util::handle_failed_output;
+
+/// `TARGET`
+#[must_use]
+pub fn target() -> String {
+    env_var("TARGET")
+}
+
+/// Check if target is windows-like.
+#[must_use]
+pub fn is_windows() -> bool {
+    target().contains("windows")
+}
+
+/// Check if target uses msvc.
+#[must_use]
+pub fn is_msvc() -> bool {
+    target().contains("msvc")
+}
+
+/// Check if target uses macOS.
+#[must_use]
+pub fn is_darwin() -> bool {
+    target().contains("darwin")
+}
+
+/// Check if `component` is within `LLVM_COMPONENTS`
+#[must_use]
+pub fn llvm_components_contain(component: &str) -> bool {
+    // `LLVM_COMPONENTS` is a space-separated list of words
+    env_var("LLVM_COMPONENTS").split_whitespace().find(|s| s == &component).is_some()
+}
+
+/// Run `uname`. This assumes that `uname` is available on the platform!
+#[track_caller]
+#[must_use]
+pub fn uname() -> String {
+    let caller = panic::Location::caller();
+    let mut uname = Command::new("uname");
+    let output = uname.run();
+    if !output.status().success() {
+        handle_failed_output(&uname, output, caller.line());
+    }
+    output.stdout_utf8()
+}
diff --git a/src/tools/run-make-support/src/util.rs b/src/tools/run-make-support/src/util.rs
new file mode 100644
index 00000000000..703e3ad1c6c
--- /dev/null
+++ b/src/tools/run-make-support/src/util.rs
@@ -0,0 +1,39 @@
+use std::path::PathBuf;
+
+use crate::command::{Command, CompletedProcess};
+use crate::env::env_var;
+use crate::path_helpers::cwd;
+
+/// If a given [`Command`] failed (as indicated by its [`CompletedProcess`]), verbose print the
+/// executed command, failure location, output status and stdout/stderr, and abort the process with
+/// exit code `1`.
+pub(crate) fn handle_failed_output(
+    cmd: &Command,
+    output: CompletedProcess,
+    caller_line_number: u32,
+) -> ! {
+    if output.status().success() {
+        eprintln!("command unexpectedly succeeded at line {caller_line_number}");
+    } else {
+        eprintln!("command failed at line {caller_line_number}");
+    }
+    eprintln!("{cmd:?}");
+    eprintln!("output status: `{}`", output.status());
+    eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
+    eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
+    std::process::exit(1)
+}
+
+/// Set the runtime library path as needed for running the host rustc/rustdoc/etc.
+pub(crate) fn set_host_rpath(cmd: &mut Command) {
+    let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
+    cmd.env(&ld_lib_path_envvar, {
+        let mut paths = vec![];
+        paths.push(cwd());
+        paths.push(PathBuf::from(env_var("HOST_RPATH_DIR")));
+        for p in std::env::split_paths(&env_var(&ld_lib_path_envvar)) {
+            paths.push(p.to_path_buf());
+        }
+        std::env::join_paths(paths.iter()).unwrap()
+    });
+}
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/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 2e26f9344b8..1cb52ea91f9 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,17 +1,12 @@
-run-make/archive-duplicate-names/Makefile
-run-make/atomic-lock-free/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
@@ -24,14 +19,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-explicit-align/Makefile
-run-make/extern-fn-generic/Makefile
-run-make/extern-fn-mangle/Makefile
 run-make/extern-fn-reachable/Makefile
-run-make/extern-fn-struct-passing-abi/Makefile
-run-make/extern-fn-with-extern-types/Makefile
-run-make/extern-fn-with-packed-struct/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
@@ -44,17 +32,12 @@ 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-25581/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-85401-static-mir/Makefile
 run-make/issue-88756-default-output/Makefile
 run-make/issue-97463-abi-param-passing/Makefile
 run-make/jobserver-error/Makefile
@@ -64,26 +47,17 @@ 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/longjmp-across-rust/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/missing-crate-dependency/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
@@ -100,7 +74,6 @@ 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
@@ -112,7 +85,6 @@ 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/static-extern-type/Makefile
 run-make/staticlib-blank-lib/Makefile
 run-make/staticlib-dylib-linkage/Makefile
 run-make/symbol-mangling-hashed/Makefile
@@ -122,5 +94,4 @@ run-make/test-benches/Makefile
 run-make/thumb-none-cortex-m/Makefile
 run-make/thumb-none-qemu/Makefile
 run-make/translation/Makefile
-run-make/unstable-flag-required/Makefile
 run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 3c7284ce6db..57310977704 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -3449,7 +3449,6 @@ ui/pattern/issue-6449.rs
 ui/pattern/issue-66270-pat-struct-parser-recovery.rs
 ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
 ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs
-ui/pattern/issue-68393-let-pat-assoc-constant.rs
 ui/pattern/issue-72565.rs
 ui/pattern/issue-72574-1.rs
 ui/pattern/issue-72574-2.rs
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/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/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index 65637a2495d..cfa479aa4b2 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -14,6 +14,14 @@ pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
+    // CHECK: %[[LEN:.+]] = load i64,{{.+}} !range ![[META_U64:.+]], !noundef
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
     o.as_slice()
 }
 
@@ -25,10 +33,35 @@ pub fn nonzero_u64_opt_as_slice(o: &Option<NonZero<u64>>) -> &[NonZero<u64>] {
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
     // CHECK: %[[NZ:.+]] = icmp ne i64 %{{.+}}, 0
-    // CHECK-NEXT: zext i1 %[[NZ]] to i64
+    // CHECK-NEXT: %[[LEN:.+]] = zext i1 %[[NZ]] to i64
     // CHECK-NOT: select
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %o, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
     o.as_slice()
 }
+
+// CHECK-LABEL: @u8_opt_as_slice
+#[no_mangle]
+pub fn u8_opt_as_slice(o: &Option<u8>) -> &[u8] {
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[TAG:.+]] = load i8,{{.+}} !range ![[META_U8:.+]], !noundef
+    // CHECK: %[[LEN:.+]] = zext{{.*}} i8 %[[TAG]] to i64
+    // CHECK-NOT: select
+    // CHECK-NOT: br
+    // CHECK-NOT: switch
+    // CHECK-NOT: icmp
+    // CHECK: %[[T0:.+]] = insertvalue { ptr, i64 } poison, ptr %{{.+}}, 0
+    // CHECK-NEXT: %[[T1:.+]] = insertvalue { ptr, i64 } %[[T0]], i64 %[[LEN]], 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[T1]]
+    o.as_slice()
+}
+
+// CHECK: ![[META_U64]] = !{i64 0, i64 2}
+// CHECK: ![[META_U8]] = !{i8 0, i8 2}
diff --git a/tests/crashes/122903-1.rs b/tests/crashes/122903-1.rs
index 9323c435851..0953962ed9e 100644
--- a/tests/crashes/122903-1.rs
+++ b/tests/crashes/122903-1.rs
@@ -1,7 +1,7 @@
 //@ known-bug: #122903
 impl Struct {
-    async fn box_box_ref_Struct(
-        self: Box<Box<Self, impl FnMut(&mut Box<Box<Self, impl FnMut(&mut Self)>>)>>,
+    fn box_box_ref_Struct(
+        self: impl FnMut(Box<impl FnMut(&mut Self)>),
     ) -> &u32 {
         f
     }
diff --git a/tests/crashes/122903-2.rs b/tests/crashes/122903-2.rs
deleted file mode 100644
index 0d5d93014c1..00000000000
--- a/tests/crashes/122903-2.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #122903
-
-impl Struct {
-    async fn box_box_ref_Struct(
-        self: Box<Box<Self, impl FnMut(&mut Box<Box<Self, impl FnMut(&mut Self)>>)>>
-    ) -> &u32 {
-        f
-    }
-}
diff --git a/tests/crashes/127009.rs b/tests/crashes/127009.rs
new file mode 100644
index 00000000000..74ca14393e4
--- /dev/null
+++ b/tests/crashes/127009.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #127009
+
+#![feature(non_lifetime_binders)]
+
+fn b()
+where
+    for<const C: usize> [(); C]: Copy,
+{
+}
+
+fn main() {}
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/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff
index 801e28ff2f4..069a82b9521 100644
--- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff
+++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-abort.diff
@@ -3,8 +3,8 @@
   
   fn non_const() -> usize {
       let mut _0: usize;
-      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>};
-      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>};
+      let _1: fn() -> usize {std::intrinsics::size_of::<T>};
+      let mut _2: fn() -> usize {std::intrinsics::size_of::<T>};
       scope 1 {
           debug size_of_t => _1;
       }
diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff
index 801e28ff2f4..069a82b9521 100644
--- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.panic-unwind.diff
@@ -3,8 +3,8 @@
   
   fn non_const() -> usize {
       let mut _0: usize;
-      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>};
-      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>};
+      let _1: fn() -> usize {std::intrinsics::size_of::<T>};
+      let mut _2: fn() -> usize {std::intrinsics::size_of::<T>};
       scope 1 {
           debug size_of_t => _1;
       }
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index d937514c2ca..fec4a4bb90b 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -5,14 +5,14 @@
 
 use std::path::PathBuf;
 
-use run_make_support::{aux_build, fs_wrapper, rustc, source_root};
+use run_make_support::{aux_build, rfs, rustc, source_root};
 
 fn main() {
     aux_build().input("stable.rs").emit("metadata").run();
 
     let output =
         rustc().input("main.rs").emit("metadata").extern_("stable", "libstable.rmeta").run();
-    let version = fs_wrapper::read_to_string(source_root().join("src/version"));
+    let version = rfs::read_to_string(source_root().join("src/version"));
     let expected_string = format!("stable since {}", version.trim());
     output.assert_stderr_contains(expected_string);
 }
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/atomic-lock-free/Makefile b/tests/run-make/atomic-lock-free/Makefile
deleted file mode 100644
index 37e59624a25..00000000000
--- a/tests/run-make/atomic-lock-free/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-include ../tools.mk
-
-# This tests ensure that atomic types are never lowered into runtime library calls that are not
-# guaranteed to be lock-free.
-
-all:
-ifeq ($(UNAME),Linux)
-ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86)
-	$(RUSTC) --target=i686-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=x86_64-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm)
-	$(RUSTC) --target=arm-unknown-linux-gnueabi atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=arm-unknown-linux-gnueabihf atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=armv7-unknown-linux-gnueabihf atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=thumbv7neon-unknown-linux-gnueabihf atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-ifeq ($(filter aarch64,$(LLVM_COMPONENTS)),aarch64)
-	$(RUSTC) --target=aarch64-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips)
-	$(RUSTC) --target=mips-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=mipsel-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-ifeq ($(filter powerpc,$(LLVM_COMPONENTS)),powerpc)
-	$(RUSTC) --target=powerpc-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=powerpc-unknown-linux-gnuspe atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=powerpc64-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-	$(RUSTC) --target=powerpc64le-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-ifeq ($(filter systemz,$(LLVM_COMPONENTS)),systemz)
-	$(RUSTC) --target=s390x-unknown-linux-gnu atomic_lock_free.rs
-	nm "$(TMPDIR)/libatomic_lock_free.rlib" | $(CGREP) -v __atomic_fetch_add
-endif
-endif
diff --git a/tests/run-make/atomic-lock-free/rmake.rs b/tests/run-make/atomic-lock-free/rmake.rs
new file mode 100644
index 00000000000..77e136e8487
--- /dev/null
+++ b/tests/run-make/atomic-lock-free/rmake.rs
@@ -0,0 +1,52 @@
+// This tests ensure that atomic types are never lowered into runtime library calls that are not
+// guaranteed to be lock-free.
+
+//@ only-linux
+
+use run_make_support::{llvm_components_contain, llvm_readobj, rustc};
+
+fn compile(target: &str) {
+    rustc().input("atomic_lock_free.rs").target(target).run();
+}
+
+fn check() {
+    llvm_readobj()
+        .symbols()
+        .input("libatomic_lock_free.rlib")
+        .run()
+        .assert_stdout_not_contains("__atomic_fetch_add");
+}
+
+fn compile_and_check(target: &str) {
+    compile(target);
+    check();
+}
+
+fn main() {
+    if llvm_components_contain("x86") {
+        compile_and_check("i686-unknown-linux-gnu");
+        compile_and_check("x86_64-unknown-linux-gnu");
+    }
+    if llvm_components_contain("arm") {
+        compile_and_check("arm-unknown-linux-gnueabi");
+        compile_and_check("arm-unknown-linux-gnueabihf");
+        compile_and_check("armv7-unknown-linux-gnueabihf");
+        compile_and_check("thumbv7neon-unknown-linux-gnueabihf");
+    }
+    if llvm_components_contain("aarch64") {
+        compile_and_check("aarch64-unknown-linux-gnu");
+    }
+    if llvm_components_contain("mips") {
+        compile_and_check("mips-unknown-linux-gnu");
+        compile_and_check("mipsel-unknown-linux-gnu");
+    }
+    if llvm_components_contain("powerpc") {
+        compile_and_check("powerpc-unknown-linux-gnu");
+        compile_and_check("powerpc-unknown-linux-gnuspe");
+        compile_and_check("powerpc64-unknown-linux-gnu");
+        compile_and_check("powerpc64le-unknown-linux-gnu");
+    }
+    if llvm_components_contain("systemz") {
+        compile_and_check("s390x-unknown-linux-gnu");
+    }
+}
diff --git a/tests/run-make/c-link-to-rust-dylib/rmake.rs b/tests/run-make/c-link-to-rust-dylib/rmake.rs
index b8ea0b6b345..ab9aa445402 100644
--- a/tests/run-make/c-link-to-rust-dylib/rmake.rs
+++ b/tests/run-make/c-link-to-rust-dylib/rmake.rs
@@ -3,9 +3,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{
-    cc, cwd, dynamic_lib_extension, fs_wrapper, is_msvc, read_dir, run, run_fail, rustc,
-};
+use run_make_support::{cc, cwd, dynamic_lib_extension, is_msvc, rfs, run, run_fail, rustc};
 
 fn main() {
     rustc().input("foo.rs").run();
@@ -21,14 +19,14 @@ fn main() {
     run("bar");
 
     let expected_extension = dynamic_lib_extension();
-    read_dir(cwd(), |path| {
+    rfs::read_dir_entries(cwd(), |path| {
         if path.is_file()
             && path.extension().is_some_and(|ext| ext == expected_extension)
             && path.file_name().and_then(|name| name.to_str()).is_some_and(|name| {
                 name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib")
             })
         {
-            fs_wrapper::remove_file(path);
+            rfs::remove_file(path);
         }
     });
     run_fail("bar");
diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
index d60b37524f4..ee35350da66 100644
--- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs
+++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
@@ -3,7 +3,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::fs_wrapper::remove_file;
+use run_make_support::rfs::remove_file;
 use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};
 use std::fs;
 
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/cdylib/rmake.rs b/tests/run-make/cdylib/rmake.rs
index 55ea227ab51..21b83d1b1a9 100644
--- a/tests/run-make/cdylib/rmake.rs
+++ b/tests/run-make/cdylib/rmake.rs
@@ -10,7 +10,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{cc, cwd, dynamic_lib_name, fs_wrapper, is_msvc, run, rustc};
+use run_make_support::{cc, cwd, dynamic_lib_name, is_msvc, rfs, run, rustc};
 
 fn main() {
     rustc().input("bar.rs").run();
@@ -23,7 +23,7 @@ fn main() {
     }
 
     run("foo");
-    fs_wrapper::remove_file(dynamic_lib_name("foo"));
+    rfs::remove_file(dynamic_lib_name("foo"));
 
     rustc().input("foo.rs").arg("-Clto").run();
     run("foo");
diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs
index 188c6dcb25d..a16adea7162 100644
--- a/tests/run-make/comment-section/rmake.rs
+++ b/tests/run-make/comment-section/rmake.rs
@@ -10,8 +10,9 @@
 use std::path::PathBuf;
 
 use run_make_support::llvm_readobj;
+use run_make_support::rfs;
 use run_make_support::rustc;
-use run_make_support::{cwd, env_var, read_dir, run_in_tmpdir};
+use run_make_support::{cwd, env_var, run_in_tmpdir};
 
 fn main() {
     let target = env_var("TARGET");
@@ -33,7 +34,7 @@ fn main() {
 
     // Check all object files (including temporary outputs) have a `.comment`
     // section with the expected content.
-    read_dir(cwd(), |f| {
+    rfs::read_dir_entries(cwd(), |f| {
         if !f.extension().is_some_and(|ext| ext == "o") {
             return;
         }
diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs
index 10ff9cd282d..43d1d69b245 100644
--- a/tests/run-make/compiler-builtins/rmake.rs
+++ b/tests/run-make/compiler-builtins/rmake.rs
@@ -14,12 +14,12 @@
 
 #![deny(warnings)]
 
-use run_make_support::fs_wrapper::{read, read_dir};
 use run_make_support::object::read::archive::ArchiveFile;
 use run_make_support::object::read::Object;
 use run_make_support::object::ObjectSection;
 use run_make_support::object::ObjectSymbol;
 use run_make_support::object::RelocationTarget;
+use run_make_support::rfs::{read, read_dir};
 use run_make_support::{cmd, env_var, object};
 use std::collections::HashSet;
 use std::path::PathBuf;
diff --git a/tests/run-make/compiler-lookup-paths/rmake.rs b/tests/run-make/compiler-lookup-paths/rmake.rs
index 0f791852821..3ffa6e0592f 100644
--- a/tests/run-make/compiler-lookup-paths/rmake.rs
+++ b/tests/run-make/compiler-lookup-paths/rmake.rs
@@ -9,16 +9,16 @@
 //@ ignore-wasm64
 // Reason: a C compiler is required for build_native_static_lib
 
-use run_make_support::{build_native_static_lib, fs_wrapper, rustc, static_lib_name};
+use run_make_support::{build_native_static_lib, rfs, rustc, static_lib_name};
 
 fn main() {
     build_native_static_lib("native");
     let lib_native = static_lib_name("native");
-    fs_wrapper::create_dir_all("crate");
-    fs_wrapper::create_dir_all("native");
-    fs_wrapper::rename(&lib_native, format!("native/{}", &lib_native));
+    rfs::create_dir_all("crate");
+    rfs::create_dir_all("native");
+    rfs::rename(&lib_native, format!("native/{}", &lib_native));
     rustc().input("a.rs").run();
-    fs_wrapper::rename("liba.rlib", "crate/liba.rlib");
+    rfs::rename("liba.rlib", "crate/liba.rlib");
     rustc().input("b.rs").specific_library_search_path("native", "crate").run_fail();
     rustc().input("b.rs").specific_library_search_path("dependency", "crate").run_fail();
     rustc().input("b.rs").specific_library_search_path("crate", "crate").run();
@@ -35,8 +35,8 @@ fn main() {
     rustc().input("d.rs").specific_library_search_path("all", "native").run();
 
     // Deduplication tests.
-    fs_wrapper::create_dir_all("e1");
-    fs_wrapper::create_dir_all("e2");
+    rfs::create_dir_all("e1");
+    rfs::create_dir_all("e2");
 
     rustc().input("e.rs").output("e1/libe.rlib").run();
     rustc().input("e.rs").output("e2/libe.rlib").run();
diff --git a/tests/run-make/const-prop-lint/rmake.rs b/tests/run-make/const-prop-lint/rmake.rs
index d194f70d916..17e4b0c77f3 100644
--- a/tests/run-make/const-prop-lint/rmake.rs
+++ b/tests/run-make/const-prop-lint/rmake.rs
@@ -1,11 +1,11 @@
 // Tests that const prop lints interrupting codegen don't leave `.o` files around.
 
-use run_make_support::{cwd, fs_wrapper, rustc};
+use run_make_support::{cwd, rfs, rustc};
 
 fn main() {
     rustc().input("input.rs").run_fail().assert_exit_code(1);
 
-    for entry in fs_wrapper::read_dir(cwd()) {
+    for entry in rfs::read_dir(cwd()) {
         let entry = entry.unwrap();
         let path = entry.path();
 
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/crate-name-priority/rmake.rs b/tests/run-make/crate-name-priority/rmake.rs
index b7cb2c99711..5bdb49b33ce 100644
--- a/tests/run-make/crate-name-priority/rmake.rs
+++ b/tests/run-make/crate-name-priority/rmake.rs
@@ -4,15 +4,15 @@
 // and the compiler flags, and checks that the flag is favoured each time.
 // See https://github.com/rust-lang/rust/pull/15518
 
-use run_make_support::{bin_name, fs_wrapper, rustc};
+use run_make_support::{bin_name, rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").run();
-    fs_wrapper::remove_file(bin_name("foo"));
+    rfs::remove_file(bin_name("foo"));
     rustc().input("foo.rs").crate_name("bar").run();
-    fs_wrapper::remove_file(bin_name("bar"));
+    rfs::remove_file(bin_name("bar"));
     rustc().input("foo1.rs").run();
-    fs_wrapper::remove_file(bin_name("foo"));
+    rfs::remove_file(bin_name("foo"));
     rustc().input("foo1.rs").output(bin_name("bar1")).run();
-    fs_wrapper::remove_file(bin_name("bar1"));
+    rfs::remove_file(bin_name("bar1"));
 }
diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs
index e48c8a0cef3..6bff5c0c8d0 100644
--- a/tests/run-make/doctests-keep-binaries/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries/rmake.rs
@@ -1,7 +1,7 @@
 // Check that valid binaries are persisted by running them, regardless of whether the
 // --run or --no-run option is used.
 
-use run_make_support::fs_wrapper::{create_dir, remove_dir_all};
+use run_make_support::rfs::{create_dir, remove_dir_all};
 use run_make_support::{run, rustc, rustdoc};
 use std::path::Path;
 
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
index 5208730d336..5d829b9e88b 100644
--- a/tests/run-make/doctests-runtool/rmake.rs
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -1,6 +1,6 @@
 // Tests behavior of rustdoc `--runtool`.
 
-use run_make_support::fs_wrapper::{create_dir, remove_dir_all};
+use run_make_support::rfs::{create_dir, remove_dir_all};
 use run_make_support::{rustc, rustdoc};
 use std::path::PathBuf;
 
diff --git a/tests/run-make/dump-mono-stats/rmake.rs b/tests/run-make/dump-mono-stats/rmake.rs
index 05ba2e6b8ff..f4142e0a31c 100644
--- a/tests/run-make/dump-mono-stats/rmake.rs
+++ b/tests/run-make/dump-mono-stats/rmake.rs
@@ -4,7 +4,7 @@
 // a specific expected string.
 // See https://github.com/rust-lang/rust/pull/105481
 
-use run_make_support::{cwd, fs_wrapper, rustc};
+use run_make_support::{cwd, rfs, rustc};
 
 fn main() {
     rustc()
@@ -13,5 +13,5 @@ fn main() {
         .arg(format!("-Zdump-mono-stats={}", cwd().display()))
         .arg("-Zdump-mono-stats-format=json")
         .run();
-    assert!(fs_wrapper::read_to_string("foo.mono_items.json").contains(r#""name":"bar""#));
+    assert!(rfs::read_to_string("foo.mono_items.json").contains(r#""name":"bar""#));
 }
diff --git a/tests/run-make/dylib-chain/rmake.rs b/tests/run-make/dylib-chain/rmake.rs
index a96cc350875..54d53d47092 100644
--- a/tests/run-make/dylib-chain/rmake.rs
+++ b/tests/run-make/dylib-chain/rmake.rs
@@ -8,7 +8,7 @@
 //@ ignore-cross-compile
 // Reason: the compiled binary is executed
 
-use run_make_support::{dynamic_lib_name, fs_wrapper, run, run_fail, rustc};
+use run_make_support::{dynamic_lib_name, rfs, run, run_fail, rustc};
 
 fn main() {
     rustc().input("m1.rs").arg("-Cprefer-dynamic").run();
@@ -16,8 +16,8 @@ fn main() {
     rustc().input("m3.rs").arg("-Cprefer-dynamic").run();
     rustc().input("m4.rs").run();
     run("m4");
-    fs_wrapper::remove_file(dynamic_lib_name("m1"));
-    fs_wrapper::remove_file(dynamic_lib_name("m2"));
-    fs_wrapper::remove_file(dynamic_lib_name("m3"));
+    rfs::remove_file(dynamic_lib_name("m1"));
+    rfs::remove_file(dynamic_lib_name("m2"));
+    rfs::remove_file(dynamic_lib_name("m3"));
     run_fail("m4");
 }
diff --git a/tests/run-make/emit-named-files/rmake.rs b/tests/run-make/emit-named-files/rmake.rs
index a02c97fec4c..1570e1adc25 100644
--- a/tests/run-make/emit-named-files/rmake.rs
+++ b/tests/run-make/emit-named-files/rmake.rs
@@ -1,6 +1,6 @@
 use std::path::Path;
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) {
     let out_file = out_dir.join(out_file);
@@ -11,7 +11,7 @@ fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) {
 fn main() {
     let out_dir = Path::new("emit");
 
-    fs_wrapper::create_dir(&out_dir);
+    rfs::create_dir(&out_dir);
 
     emit_and_check(&out_dir, "libfoo.s", "asm");
     emit_and_check(&out_dir, "libfoo.bc", "llvm-bc");
diff --git a/tests/run-make/emit-path-unhashed/rmake.rs b/tests/run-make/emit-path-unhashed/rmake.rs
index ce56c197588..a97153e37dd 100644
--- a/tests/run-make/emit-path-unhashed/rmake.rs
+++ b/tests/run-make/emit-path-unhashed/rmake.rs
@@ -6,13 +6,13 @@
 // adding a new output type (in this test, metadata).
 // See https://github.com/rust-lang/rust/issues/86044
 
-use run_make_support::{diff, fs_wrapper, rustc};
+use run_make_support::{diff, rfs, rustc};
 
 fn main() {
-    fs_wrapper::create_dir("emit");
-    fs_wrapper::create_dir("emit/a");
-    fs_wrapper::create_dir("emit/b");
-    fs_wrapper::create_dir("emit/c");
+    rfs::create_dir("emit");
+    rfs::create_dir("emit/a");
+    rfs::create_dir("emit/b");
+    rfs::create_dir("emit/c");
     // The default output name.
     rustc().emit("link").input("foo.rs").run();
     // The output is named with the output flag.
diff --git a/tests/run-make/extern-flag-pathless/rmake.rs b/tests/run-make/extern-flag-pathless/rmake.rs
index 9cf828abcb8..ec380feae46 100644
--- a/tests/run-make/extern-flag-pathless/rmake.rs
+++ b/tests/run-make/extern-flag-pathless/rmake.rs
@@ -8,21 +8,21 @@
 //@ ignore-cross-compile
 // Reason: the compiled binary is executed
 
-use run_make_support::{dynamic_lib_name, fs_wrapper, run, run_fail, rust_lib_name, rustc};
+use run_make_support::{dynamic_lib_name, rfs, run, run_fail, rust_lib_name, rustc};
 
 fn main() {
     rustc().input("bar.rs").crate_type("rlib").crate_type("dylib").arg("-Cprefer-dynamic").run();
 
     // By default, the rlib has priority over the dylib.
     rustc().input("foo.rs").arg("--extern").arg("bar").run();
-    fs_wrapper::rename(dynamic_lib_name("bar"), "bar.tmp");
+    rfs::rename(dynamic_lib_name("bar"), "bar.tmp");
     run("foo");
-    fs_wrapper::rename("bar.tmp", dynamic_lib_name("bar"));
+    rfs::rename("bar.tmp", dynamic_lib_name("bar"));
 
     rustc().input("foo.rs").extern_("bar", rust_lib_name("bar")).arg("--extern").arg("bar").run();
-    fs_wrapper::rename(dynamic_lib_name("bar"), "bar.tmp");
+    rfs::rename(dynamic_lib_name("bar"), "bar.tmp");
     run("foo");
-    fs_wrapper::rename("bar.tmp", dynamic_lib_name("bar"));
+    rfs::rename("bar.tmp", dynamic_lib_name("bar"));
 
     // The first explicit usage of extern overrides the second pathless --extern bar.
     rustc()
@@ -31,13 +31,13 @@ fn main() {
         .arg("--extern")
         .arg("bar")
         .run();
-    fs_wrapper::rename(dynamic_lib_name("bar"), "bar.tmp");
+    rfs::rename(dynamic_lib_name("bar"), "bar.tmp");
     run_fail("foo");
-    fs_wrapper::rename("bar.tmp", dynamic_lib_name("bar"));
+    rfs::rename("bar.tmp", dynamic_lib_name("bar"));
 
     // With prefer-dynamic, execution fails as it refuses to use the rlib.
     rustc().input("foo.rs").arg("--extern").arg("bar").arg("-Cprefer-dynamic").run();
-    fs_wrapper::rename(dynamic_lib_name("bar"), "bar.tmp");
+    rfs::rename(dynamic_lib_name("bar"), "bar.tmp");
     run_fail("foo");
-    fs_wrapper::rename("bar.tmp", dynamic_lib_name("bar"));
+    rfs::rename("bar.tmp", dynamic_lib_name("bar"));
 }
diff --git a/tests/run-make/extern-fn-explicit-align/Makefile b/tests/run-make/extern-fn-explicit-align/Makefile
deleted file mode 100644
index 3cbbf383996..00000000000
--- a/tests/run-make/extern-fn-explicit-align/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-explicit-align/rmake.rs b/tests/run-make/extern-fn-explicit-align/rmake.rs
new file mode 100644
index 00000000000..fb153f92103
--- /dev/null
+++ b/tests/run-make/extern-fn-explicit-align/rmake.rs
@@ -0,0 +1,17 @@
+// The compiler's rules of alignment for indirectly passed values in a 16-byte aligned argument,
+// in a C external function, used to be arbitrary. Unexpected behavior would occasionally occur
+// and cause memory corruption. This was fixed in #112157, streamlining the way alignment occurs,
+// and this test reproduces the case featured in the issue, checking that it compiles and executes
+// successfully.
+// See https://github.com/rust-lang/rust/issues/80127
+
+//@ 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("test.rs").run();
+    run("test");
+}
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-mangle/Makefile b/tests/run-make/extern-fn-mangle/Makefile
deleted file mode 100644
index 3cbbf383996..00000000000
--- a/tests/run-make/extern-fn-mangle/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-mangle/rmake.rs b/tests/run-make/extern-fn-mangle/rmake.rs
new file mode 100644
index 00000000000..3db8b2a0db0
--- /dev/null
+++ b/tests/run-make/extern-fn-mangle/rmake.rs
@@ -0,0 +1,16 @@
+// In this test, the functions foo() and bar() must avoid being mangled, as
+// the external C function depends on them to return the correct sum of 3 + 5 = 8.
+// This test therefore checks that the compiled and executed program respects the
+// #[no_mangle] flags successfully.
+// 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("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/extern-fn-slice-no-ice/rmake.rs b/tests/run-make/extern-fn-slice-no-ice/rmake.rs
new file mode 100644
index 00000000000..1f1bbd33127
--- /dev/null
+++ b/tests/run-make/extern-fn-slice-no-ice/rmake.rs
@@ -0,0 +1,17 @@
+// Slices were broken when implicated in foreign-function interface (FFI) with
+// a C library, with something as simple as measuring the length or returning
+// an item at a certain index of a slice would cause an internal compiler error (ICE).
+// This was fixed in #25653, and this test checks that slices in Rust-C FFI can be part
+// of a program that compiles and executes successfully.
+// See https://github.com/rust-lang/rust/issues/25581
+
+//@ 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("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/issue-25581/test.c b/tests/run-make/extern-fn-slice-no-ice/test.c
index 52fbf78510a..52fbf78510a 100644
--- a/tests/run-make/issue-25581/test.c
+++ b/tests/run-make/extern-fn-slice-no-ice/test.c
diff --git a/tests/run-make/issue-25581/test.rs b/tests/run-make/extern-fn-slice-no-ice/test.rs
index ba6749c9722..ba6749c9722 100644
--- a/tests/run-make/issue-25581/test.rs
+++ b/tests/run-make/extern-fn-slice-no-ice/test.rs
diff --git a/tests/run-make/extern-fn-struct-passing-abi/Makefile b/tests/run-make/extern-fn-struct-passing-abi/Makefile
deleted file mode 100644
index 3cbbf383996..00000000000
--- a/tests/run-make/extern-fn-struct-passing-abi/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-struct-passing-abi/rmake.rs b/tests/run-make/extern-fn-struct-passing-abi/rmake.rs
new file mode 100644
index 00000000000..5c4ddb7f58e
--- /dev/null
+++ b/tests/run-make/extern-fn-struct-passing-abi/rmake.rs
@@ -0,0 +1,16 @@
+// Functions with more than 6 arguments using foreign function interfaces (FFI) with C libraries
+// would have their arguments unexpectedly swapped, causing unexpected behaviour in Rust-C FFI
+// programs. This test compiles and executes Rust code with bulky functions of up to 7 arguments
+// and uses assertions to check for unexpected swaps.
+// See https://github.com/rust-lang/rust/issues/25594
+
+//@ 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("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/extern-fn-with-extern-types/Makefile b/tests/run-make/extern-fn-with-extern-types/Makefile
deleted file mode 100644
index 07ec503aaae..00000000000
--- a/tests/run-make/extern-fn-with-extern-types/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,ctest)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-with-extern-types/rmake.rs b/tests/run-make/extern-fn-with-extern-types/rmake.rs
new file mode 100644
index 00000000000..02521ae2cdb
--- /dev/null
+++ b/tests/run-make/extern-fn-with-extern-types/rmake.rs
@@ -0,0 +1,16 @@
+// This test checks the functionality of foreign function interface (FFI) where Rust
+// must call upon a C library defining functions, where these functions also use custom
+// types defined by the C file. In addition to compilation being successful, the binary
+// should also successfully execute.
+// See https://github.com/rust-lang/rust/pull/44295
+
+//@ 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("test.rs").run();
+    run("test");
+}
diff --git a/tests/run-make/extern-fn-with-packed-struct/Makefile b/tests/run-make/extern-fn-with-packed-struct/Makefile
deleted file mode 100644
index 3cbbf383996..00000000000
--- a/tests/run-make/extern-fn-with-packed-struct/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
diff --git a/tests/run-make/extern-fn-with-packed-struct/rmake.rs b/tests/run-make/extern-fn-with-packed-struct/rmake.rs
new file mode 100644
index 00000000000..e6d8cecd24a
--- /dev/null
+++ b/tests/run-make/extern-fn-with-packed-struct/rmake.rs
@@ -0,0 +1,17 @@
+// Packed structs, in C, occupy less bytes in memory, but are more
+// vulnerable to alignment errors. Passing them around in a Rust-C foreign
+// function interface (FFI) would cause unexpected behavior, until this was
+// fixed in #16584. This test checks that a Rust program with a C library
+// compiles and executes successfully, even with usage of a packed struct.
+// See https://github.com/rust-lang/rust/issues/16574
+
+//@ 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("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/extra-filename-with-temp-outputs/rmake.rs b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
index c39e397a7cb..0910045bb85 100644
--- a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
+++ b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
@@ -6,9 +6,7 @@
 // are named as expected.
 // See https://github.com/rust-lang/rust/pull/15686
 
-use run_make_support::{
-    bin_name, cwd, fs_wrapper, has_prefix, has_suffix, rustc, shallow_find_files,
-};
+use run_make_support::{bin_name, cwd, has_prefix, has_suffix, rfs, rustc, shallow_find_files};
 
 fn main() {
     rustc().extra_filename("bar").input("foo.rs").arg("-Csave-temps").run();
@@ -16,6 +14,6 @@ fn main() {
         has_prefix(path, "foobar.foo") && has_suffix(path, "0.rcgu.o")
     });
     let object_file = object_files.get(0).unwrap();
-    fs_wrapper::remove_file(object_file);
-    fs_wrapper::remove_file(bin_name("foobar"));
+    rfs::remove_file(object_file);
+    rfs::remove_file(bin_name("foobar"));
 }
diff --git a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
index 33c755bddd7..8ba3a0366b0 100644
--- a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
+++ b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
@@ -16,7 +16,7 @@
 //       If we used `rustc` the additional '-L rmake_out' option would allow rustc to
 //       actually find the crate.
 
-use run_make_support::{bare_rustc, fs_wrapper, rust_lib_name, rustc};
+use run_make_support::{bare_rustc, rfs, rust_lib_name, rustc};
 
 fn main() {
     rustc().crate_name("a").crate_type("rlib").input("a.rs").arg("--verbose").run();
diff --git a/tests/run-make/issue-85401-static-mir/bar.rs b/tests/run-make/ice-static-mir/bar.rs
index 15b12ecf36f..15b12ecf36f 100644
--- a/tests/run-make/issue-85401-static-mir/bar.rs
+++ b/tests/run-make/ice-static-mir/bar.rs
diff --git a/tests/run-make/issue-85401-static-mir/baz.rs b/tests/run-make/ice-static-mir/baz.rs
index 2ff4c51e5d2..2ff4c51e5d2 100644
--- a/tests/run-make/issue-85401-static-mir/baz.rs
+++ b/tests/run-make/ice-static-mir/baz.rs
diff --git a/tests/run-make/issue-85401-static-mir/foo.rs b/tests/run-make/ice-static-mir/foo.rs
index d064c454600..d064c454600 100644
--- a/tests/run-make/issue-85401-static-mir/foo.rs
+++ b/tests/run-make/ice-static-mir/foo.rs
diff --git a/tests/run-make/ice-static-mir/rmake.rs b/tests/run-make/ice-static-mir/rmake.rs
new file mode 100644
index 00000000000..2d4ffa379b6
--- /dev/null
+++ b/tests/run-make/ice-static-mir/rmake.rs
@@ -0,0 +1,42 @@
+// Trying to access mid-level internal representation (MIR) in statics
+// used to cause an internal compiler error (ICE), now handled as a proper
+// error since #100211. This test checks that the correct error is printed
+// during the linking process, and not the ICE.
+// See https://github.com/rust-lang/rust/issues/85401
+
+use run_make_support::{bin_name, rust_lib_name, rustc};
+
+fn main() {
+    rustc()
+        .crate_type("rlib")
+        .crate_name("foo")
+        .arg("-Crelocation-model=pic")
+        .edition("2018")
+        .input("foo.rs")
+        .arg("-Zalways-encode-mir=yes")
+        .emit("metadata")
+        .output("libfoo.rmeta")
+        .run();
+    rustc()
+        .crate_type("rlib")
+        .crate_name("bar")
+        .arg("-Crelocation-model=pic")
+        .edition("2018")
+        .input("bar.rs")
+        .output(rust_lib_name("bar"))
+        .extern_("foo", "libfoo.rmeta")
+        .run();
+    rustc()
+        .crate_type("bin")
+        .crate_name("baz")
+        .arg("-Crelocation-model=pic")
+        .edition("2018")
+        .input("baz.rs")
+        .output(bin_name("baz"))
+        .extern_("bar", rust_lib_name("bar"))
+        .run_fail()
+        .assert_stderr_contains(
+            "crate `foo` required to be available in rlib format, but was not found in this form",
+        )
+        .assert_stdout_not_contains("internal compiler error");
+}
diff --git a/tests/run-make/inaccessible-temp-dir/rmake.rs b/tests/run-make/inaccessible-temp-dir/rmake.rs
index 62b8479c328..b6624f37f96 100644
--- a/tests/run-make/inaccessible-temp-dir/rmake.rs
+++ b/tests/run-make/inaccessible-temp-dir/rmake.rs
@@ -24,11 +24,11 @@
 // Reason: `set_readonly` has no effect on directories
 // and does not prevent modification.
 
-use run_make_support::{fs_wrapper, rustc, test_while_readonly};
+use run_make_support::{rfs, rustc, test_while_readonly};
 
 fn main() {
     // Create an inaccessible directory.
-    fs_wrapper::create_dir("inaccessible");
+    rfs::create_dir("inaccessible");
     test_while_readonly("inaccessible", || {
         // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one,
         // so that it can't create `tmp`.
diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
index e6d6ae95aaa..14e75671df8 100644
--- a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
+++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
@@ -13,14 +13,14 @@
 //@ ignore-nvptx64-nvidia-cuda
 // FIXME: can't find crate for `std`
 
-use run_make_support::fs_wrapper as fs;
+use run_make_support::rfs;
 use run_make_support::rustc;
 
 fn main() {
-    fs::create_dir("src");
-    fs::create_dir("incr");
-    fs::copy("a.rs", "src/main.rs");
+    rfs::create_dir("src");
+    rfs::create_dir("incr");
+    rfs::copy("a.rs", "src/main.rs");
     rustc().incremental("incr").input("src/main.rs").run();
-    fs::copy("b.rs", "src/main.rs");
+    rfs::copy("b.rs", "src/main.rs");
     rustc().incremental("incr").input("src/main.rs").run();
 }
diff --git a/tests/run-make/incr-test-moved-file/rmake.rs b/tests/run-make/incr-test-moved-file/rmake.rs
index ae142a0d22e..f314e110a8c 100644
--- a/tests/run-make/incr-test-moved-file/rmake.rs
+++ b/tests/run-make/incr-test-moved-file/rmake.rs
@@ -14,14 +14,14 @@
 //@ ignore-nvptx64-nvidia-cuda
 // FIXME: can't find crate for 'std'
 
-use run_make_support::{fs_wrapper, rust_lib_name, rustc};
+use run_make_support::{rfs, rust_lib_name, rustc};
 
 fn main() {
-    fs_wrapper::create_dir("incr");
-    fs_wrapper::create_dir("src");
-    fs_wrapper::create_dir("src/mydir");
-    fs_wrapper::copy("main.rs", "src/main.rs");
+    rfs::create_dir("incr");
+    rfs::create_dir("src");
+    rfs::create_dir("src/mydir");
+    rfs::copy("main.rs", "src/main.rs");
     rustc().input("src/main.rs").incremental("incr").arg("--test").run();
-    fs_wrapper::rename("src/main.rs", "src/mydir/main.rs");
+    rfs::rename("src/main.rs", "src/mydir/main.rs");
     rustc().input("src/mydir/main.rs").incremental("incr").arg("--test").run();
 }
diff --git a/tests/run-make/incremental-debugger-visualizer/rmake.rs b/tests/run-make/incremental-debugger-visualizer/rmake.rs
index 1ef3af87353..985816ff5d7 100644
--- a/tests/run-make/incremental-debugger-visualizer/rmake.rs
+++ b/tests/run-make/incremental-debugger-visualizer/rmake.rs
@@ -2,14 +2,14 @@
 // (in this case, foo.py and foo.natvis) are picked up when compiling incrementally.
 // See https://github.com/rust-lang/rust/pull/111641
 
-use run_make_support::{fs_wrapper, invalid_utf8_contains, invalid_utf8_not_contains, rustc};
+use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rfs, rustc};
 use std::io::Read;
 
 fn main() {
-    fs_wrapper::create_file("foo.py");
-    fs_wrapper::write("foo.py", "GDB script v1");
-    fs_wrapper::create_file("foo.natvis");
-    fs_wrapper::write("foo.natvis", "Natvis v1");
+    rfs::create_file("foo.py");
+    rfs::write("foo.py", "GDB script v1");
+    rfs::create_file("foo.natvis");
+    rfs::write("foo.natvis", "Natvis v1");
     rustc()
         .input("foo.rs")
         .crate_type("rlib")
@@ -22,9 +22,9 @@ fn main() {
     invalid_utf8_contains("libfoo.rmeta", "Natvis v1");
 
     // Change only the GDB script and check that the change has been picked up
-    fs_wrapper::remove_file("foo.py");
-    fs_wrapper::create_file("foo.py");
-    fs_wrapper::write("foo.py", "GDB script v2");
+    rfs::remove_file("foo.py");
+    rfs::create_file("foo.py");
+    rfs::write("foo.py", "GDB script v2");
     rustc()
         .input("foo.rs")
         .crate_type("rlib")
@@ -38,9 +38,9 @@ fn main() {
     invalid_utf8_contains("libfoo.rmeta", "Natvis v1");
 
     // Now change the Natvis version and check that the change has been picked up
-    fs_wrapper::remove_file("foo.natvis");
-    fs_wrapper::create_file("foo.natvis");
-    fs_wrapper::write("foo.natvis", "Natvis v2");
+    rfs::remove_file("foo.natvis");
+    rfs::create_file("foo.natvis");
+    rfs::write("foo.natvis", "Natvis v2");
     rustc()
         .input("foo.rs")
         .crate_type("rlib")
diff --git a/tests/run-make/incremental-session-fail/rmake.rs b/tests/run-make/incremental-session-fail/rmake.rs
index 0283709f2cf..c6927c8a9f1 100644
--- a/tests/run-make/incremental-session-fail/rmake.rs
+++ b/tests/run-make/incremental-session-fail/rmake.rs
@@ -4,10 +4,10 @@
 // the ensuing compilation failure is not an ICE.
 // See https://github.com/rust-lang/rust/pull/85698
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
-    fs_wrapper::create_file("session");
+    rfs::create_file("session");
     // rustc should fail to create the session directory here.
     let out = rustc().input("foo.rs").crate_type("rlib").incremental("session").run_fail();
     out.assert_stderr_contains("could not create incremental compilation crate directory");
diff --git a/tests/run-make/inline-always-many-cgu/rmake.rs b/tests/run-make/inline-always-many-cgu/rmake.rs
index c55ea69f3b9..5a6929c855b 100644
--- a/tests/run-make/inline-always-many-cgu/rmake.rs
+++ b/tests/run-make/inline-always-many-cgu/rmake.rs
@@ -1,6 +1,6 @@
-use run_make_support::fs_wrapper::read_to_string;
 use run_make_support::regex::Regex;
-use run_make_support::{read_dir, rustc};
+use run_make_support::rfs;
+use run_make_support::rustc;
 
 use std::ffi::OsStr;
 
@@ -8,9 +8,9 @@ fn main() {
     rustc().input("foo.rs").emit("llvm-ir").codegen_units(2).run();
     let re = Regex::new(r"\bcall\b").unwrap();
     let mut nb_ll = 0;
-    read_dir(".", |path| {
+    rfs::read_dir_entries(".", |path| {
         if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("ll")) {
-            assert!(!re.is_match(&read_to_string(path)));
+            assert!(!re.is_match(&rfs::read_to_string(path)));
             nb_ll += 1;
         }
     });
diff --git a/tests/run-make/intrinsic-unreachable/rmake.rs b/tests/run-make/intrinsic-unreachable/rmake.rs
index 7e78c8288b8..bb189fbdcb5 100644
--- a/tests/run-make/intrinsic-unreachable/rmake.rs
+++ b/tests/run-make/intrinsic-unreachable/rmake.rs
@@ -8,13 +8,13 @@
 //@ ignore-windows
 // Reason: Because of Windows exception handling, the code is not necessarily any shorter.
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     rustc().opt().emit("asm").input("exit-ret.rs").run();
     rustc().opt().emit("asm").input("exit-unreachable.rs").run();
     assert!(
-        fs_wrapper::read_to_string("exit-unreachable.s").lines().count()
-            < fs_wrapper::read_to_string("exit-ret.s").lines().count()
+        rfs::read_to_string("exit-unreachable.s").lines().count()
+            < rfs::read_to_string("exit-ret.s").lines().count()
     );
 }
diff --git a/tests/run-make/invalid-library/rmake.rs b/tests/run-make/invalid-library/rmake.rs
index 9ebab1c8b0f..42afb74a59e 100644
--- a/tests/run-make/invalid-library/rmake.rs
+++ b/tests/run-make/invalid-library/rmake.rs
@@ -4,11 +4,11 @@
 // one appearing in stderr in this scenario.
 // See https://github.com/rust-lang/rust/pull/12645
 
-use run_make_support::fs_wrapper::create_file;
+use run_make_support::rfs;
 use run_make_support::{llvm_ar, rustc};
 
 fn main() {
-    create_file("lib.rmeta");
+    rfs::create_file("lib.rmeta");
     llvm_ar().obj_to_ar().output_input("libfoo-ffffffff-1.0.rlib", "lib.rmeta").run();
     rustc().input("foo.rs").run_fail().assert_stderr_contains("found invalid metadata");
 }
diff --git a/tests/run-make/invalid-so/rmake.rs b/tests/run-make/invalid-so/rmake.rs
index 5cfda05334e..754c53a49b9 100644
--- a/tests/run-make/invalid-so/rmake.rs
+++ b/tests/run-make/invalid-so/rmake.rs
@@ -4,10 +4,10 @@
 // explains that the file exists, but that its metadata is incorrect.
 // See https://github.com/rust-lang/rust/pull/88368
 
-use run_make_support::{dynamic_lib_name, fs_wrapper, rustc};
+use run_make_support::{dynamic_lib_name, rfs, rustc};
 
 fn main() {
-    fs_wrapper::create_file(dynamic_lib_name("foo"));
+    rfs::create_file(dynamic_lib_name("foo"));
     rustc()
         .crate_type("lib")
         .extern_("foo", dynamic_lib_name("foo"))
diff --git a/tests/run-make/invalid-staticlib/rmake.rs b/tests/run-make/invalid-staticlib/rmake.rs
index 45129293247..ba9e07dd07b 100644
--- a/tests/run-make/invalid-staticlib/rmake.rs
+++ b/tests/run-make/invalid-staticlib/rmake.rs
@@ -4,10 +4,10 @@
 // an internal compiler error (ICE).
 // See https://github.com/rust-lang/rust/pull/28673
 
-use run_make_support::{fs_wrapper, rustc, static_lib_name};
+use run_make_support::{rfs, rustc, static_lib_name};
 
 fn main() {
-    fs_wrapper::create_file(static_lib_name("foo"));
+    rfs::create_file(static_lib_name("foo"));
     rustc()
         .arg("-")
         .crate_type("rlib")
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-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs
index ee281fe0a5f..f47b8d7190f 100644
--- a/tests/run-make/issue-107495-archive-permissions/rmake.rs
+++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs
@@ -3,7 +3,7 @@
 #[cfg(unix)]
 extern crate libc;
 
-use run_make_support::{aux_build, fs_wrapper};
+use run_make_support::{aux_build, rfs};
 
 #[cfg(unix)]
 use std::os::unix::fs::PermissionsExt;
@@ -20,7 +20,7 @@ fn main() {
 }
 
 fn verify(path: &Path) {
-    let perm = fs_wrapper::metadata(path).permissions();
+    let perm = rfs::metadata(path).permissions();
 
     assert!(!perm.readonly());
 
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-25581/Makefile b/tests/run-make/issue-25581/Makefile
deleted file mode 100644
index 3cbbf383996..00000000000
--- a/tests/run-make/issue-25581/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,test)
-	$(RUSTC) test.rs
-	$(call RUN,test) || exit 1
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-85401-static-mir/Makefile b/tests/run-make/issue-85401-static-mir/Makefile
deleted file mode 100644
index 47a36b6e453..00000000000
--- a/tests/run-make/issue-85401-static-mir/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-include ../tools.mk
-
-# Regression test for issue #85401
-# Verify that we do not ICE when trying to access MIR for statics,
-# but emit an error when linking.
-
-OUTPUT_FILE := $(TMPDIR)/build-output
-
-all:
-	$(RUSTC) --crate-type rlib --crate-name foo -Crelocation-model=pic --edition=2018 foo.rs -Zalways-encode-mir=yes --emit metadata -o $(TMPDIR)/libfoo.rmeta
-	$(RUSTC) --crate-type rlib --crate-name bar -Crelocation-model=pic --edition=2018 bar.rs -o $(TMPDIR)/libbar.rlib --extern=foo=$(TMPDIR)/libfoo.rmeta
-	$(RUSTC) --crate-type bin --crate-name baz -Crelocation-model=pic --edition=2018 baz.rs -o $(TMPDIR)/baz -L $(TMPDIR) --extern=bar=$(TMPDIR)/libbar.rlib > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
-	cat  $(OUTPUT_FILE)
-	$(CGREP) 'crate `foo` required to be available in rlib format, but was not found in this form' < $(OUTPUT_FILE)
-	# -v tests are fragile, hopefully this text won't change
-	$(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
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/longjmp-across-rust/Makefile b/tests/run-make/longjmp-across-rust/Makefile
deleted file mode 100644
index 5fd2d4f855f..00000000000
--- a/tests/run-make/longjmp-across-rust/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,foo)
-	$(RUSTC) main.rs
-	$(call RUN,main)
diff --git a/tests/run-make/longjmp-across-rust/rmake.rs b/tests/run-make/longjmp-across-rust/rmake.rs
new file mode 100644
index 00000000000..90a527077d2
--- /dev/null
+++ b/tests/run-make/longjmp-across-rust/rmake.rs
@@ -0,0 +1,18 @@
+// longjmp, an error handling function used in C, is useful
+// for jumping out of nested call chains... but it used to accidentally
+// trigger Rust's cleanup system in a way that caused an unexpected abortion
+// of the program. After this was fixed in #48572, this test compiles and executes
+// a program that jumps between Rust and its C library, with longjmp included. For
+// the test to succeed, no unexpected abortion should occur.
+// See https://github.com/rust-lang/rust/pull/48572
+
+//@ 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("main.rs").run();
+    run("main");
+}
diff --git a/tests/run-make/ls-metadata/rmake.rs b/tests/run-make/ls-metadata/rmake.rs
index 0e60f2c4678..45299a48c11 100644
--- a/tests/run-make/ls-metadata/rmake.rs
+++ b/tests/run-make/ls-metadata/rmake.rs
@@ -6,12 +6,12 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::fs_wrapper;
+use run_make_support::rfs;
 use run_make_support::rustc;
 
 fn main() {
     rustc().input("foo.rs").run();
     rustc().arg("-Zls=root").input("foo").run();
-    fs_wrapper::create_file("bar");
+    rfs::create_file("bar");
     rustc().arg("-Zls=root").input("bar").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-readonly-lib/rmake.rs b/tests/run-make/lto-readonly-lib/rmake.rs
index 9eb135addd9..d0ba3fb37a2 100644
--- a/tests/run-make/lto-readonly-lib/rmake.rs
+++ b/tests/run-make/lto-readonly-lib/rmake.rs
@@ -7,7 +7,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::fs_wrapper;
+use run_make_support::rfs;
 use run_make_support::{run, rust_lib_name, rustc, test_while_readonly};
 
 fn 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/many-crates-but-no-match/rmake.rs b/tests/run-make/many-crates-but-no-match/rmake.rs
index ea4f166b2bd..938ffce6a03 100644
--- a/tests/run-make/many-crates-but-no-match/rmake.rs
+++ b/tests/run-make/many-crates-but-no-match/rmake.rs
@@ -4,12 +4,12 @@
 // what should be done to fix the issue.
 // See https://github.com/rust-lang/rust/issues/13266
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
-    fs_wrapper::create_dir("a1");
-    fs_wrapper::create_dir("a2");
-    fs_wrapper::create_dir("a3");
+    rfs::create_dir("a1");
+    rfs::create_dir("a2");
+    rfs::create_dir("a3");
     rustc().crate_type("rlib").out_dir("a1").input("crateA1.rs").run();
     rustc().crate_type("rlib").library_search_path("a1").input("crateB.rs").run();
     rustc().crate_type("rlib").out_dir("a2").input("crateA2.rs").run();
diff --git a/tests/run-make/missing-crate-dependency/Makefile b/tests/run-make/missing-crate-dependency/Makefile
deleted file mode 100644
index 7c271ab8a90..00000000000
--- a/tests/run-make/missing-crate-dependency/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type=rlib crateA.rs
-	$(RUSTC) --crate-type=rlib crateB.rs
-	$(call REMOVE_RLIBS,crateA)
-	# Ensure crateC fails to compile since dependency crateA is missing
-	$(RUSTC) crateC.rs 2>&1 | \
-		$(CGREP) 'can'"'"'t find crate for `crateA` which `crateB` depends on'
diff --git a/tests/run-make/missing-crate-dependency/rmake.rs b/tests/run-make/missing-crate-dependency/rmake.rs
new file mode 100644
index 00000000000..dae77032f7d
--- /dev/null
+++ b/tests/run-make/missing-crate-dependency/rmake.rs
@@ -0,0 +1,17 @@
+// A simple smoke test to check that rustc fails compilation
+// and outputs a helpful message when a dependency is missing
+// in a dependency chain.
+// See https://github.com/rust-lang/rust/issues/12146
+
+use run_make_support::{rfs, rust_lib_name, rustc};
+
+fn main() {
+    rustc().crate_type("rlib").input("crateA.rs").run();
+    rustc().crate_type("rlib").input("crateB.rs").run();
+    rfs::remove_file(rust_lib_name("crateA"));
+    // Ensure that crateC fails to compile, as the crateA dependency is missing.
+    rustc()
+        .input("crateC.rs")
+        .run_fail()
+        .assert_stderr_contains("can't find crate for `crateA` which `crateB` depends on");
+}
diff --git a/tests/run-make/mixing-libs/rmake.rs b/tests/run-make/mixing-libs/rmake.rs
index 06ef6ab00f5..89fbf5589e3 100644
--- a/tests/run-make/mixing-libs/rmake.rs
+++ b/tests/run-make/mixing-libs/rmake.rs
@@ -6,7 +6,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{dynamic_lib_name, fs_wrapper, rustc};
+use run_make_support::{dynamic_lib_name, rfs, rustc};
 
 fn main() {
     rustc().input("rlib.rs").crate_type("rlib").crate_type("dylib").run();
@@ -16,6 +16,6 @@ fn main() {
 
     // librlib's dynamic version needs to be removed here to prevent prog.rs from fetching
     // the wrong one.
-    fs_wrapper::remove_file(dynamic_lib_name("rlib"));
+    rfs::remove_file(dynamic_lib_name("rlib"));
     rustc().input("prog.rs").run_fail();
 }
diff --git a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs
index c6426029989..f63146e692a 100644
--- a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs
+++ b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs
@@ -17,20 +17,20 @@
 //@ ignore-nvptx64-nvidia-cuda
 // FIXME: can't find crate for 'std'
 
-use run_make_support::{fs_wrapper, rust_lib_name, rustc};
+use run_make_support::{rfs, rust_lib_name, rustc};
 
 fn main() {
-    fs_wrapper::create_dir("incr");
-    fs_wrapper::create_dir("first_src");
-    fs_wrapper::create_dir("output");
-    fs_wrapper::rename("my_lib.rs", "first_src/my_lib.rs");
-    fs_wrapper::rename("main.rs", "first_src/main.rs");
+    rfs::create_dir("incr");
+    rfs::create_dir("first_src");
+    rfs::create_dir("output");
+    rfs::rename("my_lib.rs", "first_src/my_lib.rs");
+    rfs::rename("main.rs", "first_src/main.rs");
     // Build from "first_src"
     std::env::set_current_dir("first_src").unwrap();
     rustc().input("my_lib.rs").incremental("incr").crate_type("lib").run();
     rustc().input("main.rs").incremental("incr").extern_("my_lib", rust_lib_name("my_lib")).run();
     std::env::set_current_dir("..").unwrap();
-    fs_wrapper::rename("first_src", "second_src");
+    rfs::rename("first_src", "second_src");
     std::env::set_current_dir("second_src").unwrap();
     // Build from "second_src" - the output and incremental directory remain identical
     rustc().input("my_lib.rs").incremental("incr").crate_type("lib").run();
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/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs
index bffd9477f8f..0042e4d1e17 100644
--- a/tests/run-make/non-unicode-env/rmake.rs
+++ b/tests/run-make/non-unicode-env/rmake.rs
@@ -1,4 +1,4 @@
-use run_make_support::fs_wrapper;
+use run_make_support::rfs;
 use run_make_support::rustc;
 
 fn main() {
@@ -7,6 +7,6 @@ fn main() {
     #[cfg(windows)]
     let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]);
     let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail();
-    let expected = fs_wrapper::read_to_string("non_unicode_env.stderr");
+    let expected = rfs::read_to_string("non_unicode_env.stderr");
     output.assert_stderr_equals(expected);
 }
diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
index 895d9e00a2d..ef316f11036 100644
--- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
+++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
@@ -1,4 +1,4 @@
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     #[cfg(unix)]
@@ -17,8 +17,8 @@ fn main() {
     }
     let incr_dir = "incr-dir";
     rustc().input("foo.rs").incremental(&incr_dir).run();
-    for crate_dir in fs_wrapper::read_dir(&incr_dir) {
-        fs_wrapper::create_dir(crate_dir.unwrap().path().join(&non_unicode));
+    for crate_dir in rfs::read_dir(&incr_dir) {
+        rfs::create_dir(crate_dir.unwrap().path().join(&non_unicode));
     }
     rustc().input("foo.rs").incremental(&incr_dir).run();
 }
diff --git a/tests/run-make/obey-crate-type-flag/rmake.rs b/tests/run-make/obey-crate-type-flag/rmake.rs
index 8aa78cccbb2..8d6eb237982 100644
--- a/tests/run-make/obey-crate-type-flag/rmake.rs
+++ b/tests/run-make/obey-crate-type-flag/rmake.rs
@@ -6,7 +6,7 @@
 //@ ignore-cross-compile
 
 use run_make_support::{
-    cwd, dynamic_lib_name, fs_wrapper, has_extension, rust_lib_name, rustc, shallow_find_files,
+    cwd, dynamic_lib_name, has_extension, rfs, rust_lib_name, rustc, shallow_find_files,
 };
 use std::path::Path;
 
@@ -15,7 +15,7 @@ fn main() {
     assert!(Path::new(&dynamic_lib_name("test")).exists());
     assert!(Path::new(&rust_lib_name("test")).exists());
 
-    fs_wrapper::remove_file(rust_lib_name("test"));
+    rfs::remove_file(rust_lib_name("test"));
     rustc().crate_type("dylib").input("test.rs").run();
     assert!(shallow_find_files(cwd(), |path| { has_extension(path, "rlib") }).is_empty());
 }
diff --git a/tests/run-make/output-filename-conflicts-with-directory/rmake.rs b/tests/run-make/output-filename-conflicts-with-directory/rmake.rs
index 4b5c9e8d118..e49b5005fa0 100644
--- a/tests/run-make/output-filename-conflicts-with-directory/rmake.rs
+++ b/tests/run-make/output-filename-conflicts-with-directory/rmake.rs
@@ -4,10 +4,10 @@
 // potentially-confusing linker error.
 // See https://github.com/rust-lang/rust/pull/47203
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
-    fs_wrapper::create_dir("foo");
+    rfs::create_dir("foo");
     rustc().input("foo.rs").output("foo").run_fail().assert_stderr_contains(
         r#"the generated executable for the input file "foo.rs" conflicts with the existing directory "foo""#,
     );
diff --git a/tests/run-make/output-filename-overwrites-input/rmake.rs b/tests/run-make/output-filename-overwrites-input/rmake.rs
index c6055e818a1..1fa12259faf 100644
--- a/tests/run-make/output-filename-overwrites-input/rmake.rs
+++ b/tests/run-make/output-filename-overwrites-input/rmake.rs
@@ -4,14 +4,14 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
-    fs_wrapper::copy("foo.rs", "foo");
+    rfs::copy("foo.rs", "foo");
     rustc().input("foo").output("foo").run_fail().assert_stderr_contains(
         r#"the input file "foo" would be overwritten by the generated executable"#,
     );
-    fs_wrapper::copy("bar.rs", "bar.rlib");
+    rfs::copy("bar.rs", "bar.rlib");
     rustc().input("bar.rlib").output("bar.rlib").run_fail().assert_stderr_contains(
         r#"the input file "bar.rlib" would be overwritten by the generated executable"#,
     );
diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs
index 1d1637a744e..c51b2153945 100644
--- a/tests/run-make/output-type-permutations/rmake.rs
+++ b/tests/run-make/output-type-permutations/rmake.rs
@@ -5,7 +5,7 @@
 // See https://github.com/rust-lang/rust/pull/12020
 
 use run_make_support::{
-    bin_name, dynamic_lib_name, filename_not_in_denylist, fs_wrapper, rust_lib_name, rustc,
+    bin_name, dynamic_lib_name, filename_not_in_denylist, rfs, rust_lib_name, rustc,
     shallow_find_files, static_lib_name,
 };
 use std::path::PathBuf;
@@ -20,10 +20,10 @@ fn assert_expected_output_files(expectations: Expectations, rustc_invocation: im
     let Expectations { expected_files: must_exist, allowed_files: can_exist, test_dir: dir } =
         expectations;
 
-    fs_wrapper::create_dir(&dir);
+    rfs::create_dir(&dir);
     rustc_invocation();
     for file in must_exist {
-        fs_wrapper::remove_file(PathBuf::from(&dir).join(&file));
+        rfs::remove_file(PathBuf::from(&dir).join(&file));
     }
     let actual_output_files =
         shallow_find_files(dir, |path| filename_not_in_denylist(path, &can_exist));
@@ -526,17 +526,14 @@ fn main() {
             test_dir: "rlib-emits".to_string(),
         },
         || {
-            fs_wrapper::rename("staticlib-all3/bar.bc", "rlib-emits/foo.bc");
+            rfs::rename("staticlib-all3/bar.bc", "rlib-emits/foo.bc");
             rustc()
                 .input("foo.rs")
                 .emit("llvm-bc,link")
                 .crate_type("rlib")
                 .out_dir("rlib-emits")
                 .run();
-            assert_eq!(
-                fs_wrapper::read("rlib-emits/foo.bc"),
-                fs_wrapper::read("rlib-emits/bar.bc")
-            );
+            assert_eq!(rfs::read("rlib-emits/foo.bc"), rfs::read("rlib-emits/bar.bc"));
         },
     );
 }
diff --git a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
index 3f032cf3762..3f412bfefc8 100644
--- a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
+++ b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
@@ -5,12 +5,12 @@
 // conflicts. This test uses this flag and checks for successful compilation.
 // See https://github.com/rust-lang/rust/pull/83846
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 use std::sync::{Arc, Barrier};
 use std::thread;
 
 fn main() {
-    fs_wrapper::create_file("lib.rs");
+    rfs::create_file("lib.rs");
     let barrier = Arc::new(Barrier::new(2));
     let handle = {
         let barrier = Arc::clone(&barrier);
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-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs
index d3cb79c39af..588c5c6dc31 100644
--- a/tests/run-make/pgo-branch-weights/rmake.rs
+++ b/tests/run-make/pgo-branch-weights/rmake.rs
@@ -10,14 +10,14 @@
 //@ needs-profiler-support
 //@ ignore-cross-compile
 
-use run_make_support::{fs_wrapper, llvm_filecheck, llvm_profdata, run_with_args, rustc};
+use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run_with_args, rustc};
 use std::path::Path;
 
 fn main() {
     let path_prof_data_dir = Path::new("prof_data_dir");
     let path_merged_profdata = path_prof_data_dir.join("merged.profdata");
     rustc().input("opaque.rs").run();
-    fs_wrapper::create_dir_all(&path_prof_data_dir);
+    rfs::create_dir_all(&path_prof_data_dir);
     rustc()
         .input("interesting.rs")
         .profile_generate(&path_prof_data_dir)
@@ -34,8 +34,5 @@ fn main() {
         .codegen_units(1)
         .emit("llvm-ir")
         .run();
-    llvm_filecheck()
-        .patterns("filecheck-patterns.txt")
-        .stdin(fs_wrapper::read("interesting.ll"))
-        .run();
+    llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
 }
diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs
index 0f76aff80d0..cad49372266 100644
--- a/tests/run-make/pgo-use/rmake.rs
+++ b/tests/run-make/pgo-use/rmake.rs
@@ -9,8 +9,8 @@
 //@ ignore-cross-compile
 
 use run_make_support::{
-    cwd, fs_wrapper, has_extension, has_prefix, llvm_filecheck, llvm_profdata, run_with_args,
-    rustc, shallow_find_files,
+    cwd, has_extension, has_prefix, llvm_filecheck, llvm_profdata, rfs, run_with_args, rustc,
+    shallow_find_files,
 };
 
 fn main() {
@@ -47,7 +47,7 @@ fn main() {
     // line with the function name before the line with the function attributes.
     // FileCheck only supports checking that something matches on the next line,
     // but not if something matches on the previous line.
-    let ir = fs_wrapper::read_to_string("main.ll");
+    let ir = rfs::read_to_string("main.ll");
     let lines: Vec<_> = ir.lines().rev().collect();
     let mut reversed_ir = lines.join("\n");
     reversed_ir.push('\n');
diff --git a/tests/run-make/prefer-dylib/rmake.rs b/tests/run-make/prefer-dylib/rmake.rs
index 6b3b3ad6d3b..264d184a6c7 100644
--- a/tests/run-make/prefer-dylib/rmake.rs
+++ b/tests/run-make/prefer-dylib/rmake.rs
@@ -1,6 +1,6 @@
 //@ ignore-cross-compile
 
-use run_make_support::{cwd, dynamic_lib_name, fs_wrapper, read_dir, run, run_fail, rustc};
+use run_make_support::{dynamic_lib_name, rfs, run, run_fail, rustc};
 
 fn main() {
     rustc().input("bar.rs").crate_type("dylib").crate_type("rlib").arg("-Cprefer-dynamic").run();
@@ -8,7 +8,7 @@ fn main() {
 
     run("foo");
 
-    fs_wrapper::remove_file(dynamic_lib_name("bar"));
+    rfs::remove_file(dynamic_lib_name("bar"));
     // This time the command should fail.
     run_fail("foo");
 }
diff --git a/tests/run-make/prefer-rlib/rmake.rs b/tests/run-make/prefer-rlib/rmake.rs
index 96861a264e6..6d38282c2e3 100644
--- a/tests/run-make/prefer-rlib/rmake.rs
+++ b/tests/run-make/prefer-rlib/rmake.rs
@@ -3,13 +3,13 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{dynamic_lib_name, fs_wrapper, path, run, rust_lib_name, rustc};
+use run_make_support::{dynamic_lib_name, path, rfs, run, rust_lib_name, rustc};
 
 fn main() {
     rustc().input("bar.rs").crate_type("dylib").crate_type("rlib").run();
     assert!(path(rust_lib_name("bar")).exists());
     rustc().input("foo.rs").run();
-    fs_wrapper::remove_file(rust_lib_name("bar"));
-    fs_wrapper::remove_file(dynamic_lib_name("bar"));
+    rfs::remove_file(rust_lib_name("bar"));
+    rfs::remove_file(dynamic_lib_name("bar"));
     run("foo");
 }
diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs
index 859a9781bb6..d7a29ff7d19 100644
--- a/tests/run-make/pretty-print-with-dep-file/rmake.rs
+++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs
@@ -5,13 +5,13 @@
 // does not get an unexpected dep-info file.
 // See https://github.com/rust-lang/rust/issues/112898
 
-use run_make_support::{fs_wrapper, invalid_utf8_contains, rustc};
+use run_make_support::{invalid_utf8_contains, rfs, rustc};
 use std::path::Path;
 
 fn main() {
     rustc().emit("dep-info").arg("-Zunpretty=expanded").input("with-dep.rs").run();
     invalid_utf8_contains("with-dep.d", "with-dep.rs");
-    fs_wrapper::remove_file("with-dep.d");
+    rfs::remove_file("with-dep.d");
     rustc().emit("dep-info").arg("-Zunpretty=normal").input("with-dep.rs").run();
     assert!(!Path::new("with-dep.d").exists());
 }
diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs
index d11eda1db2a..d83e8a36f2c 100644
--- a/tests/run-make/print-cfg/rmake.rs
+++ b/tests/run-make/print-cfg/rmake.rs
@@ -10,7 +10,7 @@ use std::ffi::OsString;
 use std::iter::FromIterator;
 use std::path::PathBuf;
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 struct PrintCfg {
     target: &'static str,
@@ -96,7 +96,7 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) {
 
         rustc().target(target).arg(print_arg).run();
 
-        let output = fs_wrapper::read_to_string(&tmp_path);
+        let output = rfs::read_to_string(&tmp_path);
 
         check_(&output, includes, disallow);
     }
diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs
index 66f62a7015a..d0cba725b36 100644
--- a/tests/run-make/print-to-output/rmake.rs
+++ b/tests/run-make/print-to-output/rmake.rs
@@ -4,7 +4,7 @@
 use std::ffi::OsString;
 use std::path::PathBuf;
 
-use run_make_support::{fs_wrapper, rustc, target};
+use run_make_support::{rfs, rustc, target};
 
 struct Option<'a> {
     target: &'a str,
@@ -49,7 +49,7 @@ fn check(args: Option) {
 
         rustc().target(args.target).arg(print_arg).run();
 
-        fs_wrapper::read_to_string(&tmp_path)
+        rfs::read_to_string(&tmp_path)
     };
 
     check_(&stdout, args.includes);
diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs
index 62c0368e4b3..aeb30e72d5b 100644
--- a/tests/run-make/remap-path-prefix/rmake.rs
+++ b/tests/run-make/remap-path-prefix/rmake.rs
@@ -4,7 +4,7 @@
 // See https://github.com/rust-lang/rust/pull/85344
 
 use run_make_support::bstr::ByteSlice;
-use run_make_support::{bstr, fs_wrapper, is_darwin, rustc};
+use run_make_support::{bstr, is_darwin, rfs, rustc};
 
 fn main() {
     let mut out_simple = rustc();
@@ -60,12 +60,9 @@ fn main() {
 // helper functions.
 fn rmeta_contains(expected: &str) {
     // Normalize to account for path differences in Windows.
-    if !bstr::BString::from(fs_wrapper::read("liblib.rmeta"))
-        .replace(b"\\", b"/")
-        .contains_str(expected)
-    {
+    if !bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) {
         eprintln!("=== FILE CONTENTS (LOSSY) ===");
-        eprintln!("{}", String::from_utf8_lossy(&fs_wrapper::read("liblib.rmeta")));
+        eprintln!("{}", String::from_utf8_lossy(&rfs::read("liblib.rmeta")));
         eprintln!("=== SPECIFIED TEXT ===");
         eprintln!("{}", expected);
         panic!("specified text was not found in file");
@@ -74,12 +71,9 @@ fn rmeta_contains(expected: &str) {
 
 fn rmeta_not_contains(expected: &str) {
     // Normalize to account for path differences in Windows.
-    if bstr::BString::from(fs_wrapper::read("liblib.rmeta"))
-        .replace(b"\\", b"/")
-        .contains_str(expected)
-    {
+    if bstr::BString::from(rfs::read("liblib.rmeta")).replace(b"\\", b"/").contains_str(expected) {
         eprintln!("=== FILE CONTENTS (LOSSY) ===");
-        eprintln!("{}", String::from_utf8_lossy(&fs_wrapper::read("liblib.rmeta")));
+        eprintln!("{}", String::from_utf8_lossy(&rfs::read("liblib.rmeta")));
         eprintln!("=== SPECIFIED TEXT ===");
         eprintln!("{}", expected);
         panic!("specified text was not found in file");
diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs
index a65cf234edf..824ca6e1876 100644
--- a/tests/run-make/repr128-dwarf/rmake.rs
+++ b/tests/run-make/repr128-dwarf/rmake.rs
@@ -3,7 +3,7 @@
 
 use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian};
 use object::{Object, ObjectSection};
-use run_make_support::{fs_wrapper, gimli, object, rustc};
+use run_make_support::{gimli, object, rfs, rustc};
 use std::collections::HashMap;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -19,7 +19,7 @@ fn main() {
         .join("DWARF")
         .join("repr128");
     let output =
-        fs_wrapper::read(if dsym_location.try_exists().unwrap() { dsym_location } else { output });
+        rfs::read(if dsym_location.try_exists().unwrap() { dsym_location } else { output });
     let obj = object::File::parse(output.as_slice()).unwrap();
     let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big };
     let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> {
diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs
index 19d42b3d6d5..cc6bb7d5e39 100644
--- a/tests/run-make/reset-codegen-1/rmake.rs
+++ b/tests/run-make/reset-codegen-1/rmake.rs
@@ -7,7 +7,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{bin_name, fs_wrapper, rustc};
+use run_make_support::{bin_name, rfs, rustc};
 use std::path::Path;
 
 fn compile(output_file: &str, emit: Option<&str>) {
diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs
index 09bd4165b2a..16ee7b02885 100644
--- a/tests/run-make/resolve-rename/rmake.rs
+++ b/tests/run-make/resolve-rename/rmake.rs
@@ -5,12 +5,12 @@
 // the renamed library.
 // See https://github.com/rust-lang/rust/pull/49253
 
-use run_make_support::fs_wrapper;
+use run_make_support::rfs;
 use run_make_support::rustc;
 
 fn main() {
     rustc().extra_filename("-hash").input("foo.rs").run();
     rustc().input("bar.rs").run();
-    fs_wrapper::rename("libfoo-hash.rlib", "libfoo-another-hash.rlib");
+    rfs::rename("libfoo-hash.rlib", "libfoo-another-hash.rlib");
     rustc().input("baz.rs").run();
 }
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-chain/rmake.rs b/tests/run-make/rlib-chain/rmake.rs
index 0947262bf62..306a472f473 100644
--- a/tests/run-make/rlib-chain/rmake.rs
+++ b/tests/run-make/rlib-chain/rmake.rs
@@ -8,7 +8,7 @@
 //@ ignore-cross-compile
 // Reason: the compiled binary is executed
 
-use run_make_support::{fs_wrapper, run, rust_lib_name, rustc};
+use run_make_support::{rfs, run, rust_lib_name, rustc};
 
 fn main() {
     rustc().input("m1.rs").run();
@@ -16,8 +16,8 @@ fn main() {
     rustc().input("m3.rs").run();
     rustc().input("m4.rs").run();
     run("m4");
-    fs_wrapper::remove_file(rust_lib_name("m1"));
-    fs_wrapper::remove_file(rust_lib_name("m2"));
-    fs_wrapper::remove_file(rust_lib_name("m3"));
+    rfs::remove_file(rust_lib_name("m1"));
+    rfs::remove_file(rust_lib_name("m2"));
+    rfs::remove_file(rust_lib_name("m3"));
     run("m4");
 }
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/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
index 5d67ee2580f..3feee78f2e1 100644
--- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
+++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
@@ -1,10 +1,10 @@
-use run_make_support::{fs_wrapper, htmldocck, rustc, rustdoc, source_root};
+use run_make_support::{htmldocck, rfs, rustc, rustdoc, source_root};
 use std::path::Path;
 
 pub fn scrape(extra_args: &[&str]) {
     let out_dir = Path::new("rustdoc");
     let crate_name = "foobar";
-    let deps = fs_wrapper::read_dir("examples")
+    let deps = rfs::read_dir("examples")
         .filter_map(|entry| entry.ok().map(|e| e.path()))
         .filter(|path| path.is_file() && path.extension().is_some_and(|ext| ext == "rs"))
         .collect::<Vec<_>>();
diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs
index 80eb768c14c..69dea83de4f 100644
--- a/tests/run-make/rustdoc-test-args/rmake.rs
+++ b/tests/run-make/rustdoc-test-args/rmake.rs
@@ -1,10 +1,10 @@
-use run_make_support::{fs_wrapper, rustdoc};
+use run_make_support::{rfs, rustdoc};
 use std::iter;
 use std::path::Path;
 
 fn generate_a_lot_of_cfgs(path: &Path) {
     let content = iter::repeat("--cfg=a\n").take(100_000).collect::<String>();
-    fs_wrapper::write(path, content.as_bytes());
+    rfs::write(path, content.as_bytes());
 }
 
 fn main() {
diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs
index 4174c0552be..981db358f29 100644
--- a/tests/run-make/rustdoc-themes/rmake.rs
+++ b/tests/run-make/rustdoc-themes/rmake.rs
@@ -1,15 +1,14 @@
 // Test that rustdoc will properly load in a theme file and display it in the theme selector.
 
-use run_make_support::{fs_wrapper, htmldocck, rustdoc, source_root};
+use run_make_support::{htmldocck, rfs, rustdoc, source_root};
 use std::path::Path;
 
 fn main() {
     let out_dir = Path::new("rustdoc-themes");
     let test_css = "test.css";
 
-    let no_script = fs_wrapper::read_to_string(
-        source_root().join("src/librustdoc/html/static/css/noscript.css"),
-    );
+    let no_script =
+        rfs::read_to_string(source_root().join("src/librustdoc/html/static/css/noscript.css"));
 
     let mut test_content = String::new();
     let mut found_begin_light = false;
@@ -24,8 +23,8 @@ fn main() {
         }
     }
     assert!(!test_content.is_empty());
-    fs_wrapper::create_dir_all(&out_dir);
-    fs_wrapper::write(&test_css, test_content);
+    rfs::create_dir_all(&out_dir);
+    rfs::write(&test_css, test_content);
 
     rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run();
     htmldocck().arg(out_dir).arg("foo.rs").run();
diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs
index 1bf41c68114..d1ff2e330f5 100644
--- a/tests/run-make/rustdoc-verify-output-files/rmake.rs
+++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs
@@ -1,7 +1,7 @@
-use run_make_support::fs_wrapper::copy;
+use run_make_support::rfs;
 use std::path::{Path, PathBuf};
 
-use run_make_support::{copy_dir_all, recursive_diff, rustdoc};
+use run_make_support::{assert_dirs_are_equal, rustdoc};
 
 #[derive(PartialEq)]
 enum JsonOutput {
@@ -26,7 +26,7 @@ fn main() {
     generate_docs(&out_dir, JsonOutput::No);
 
     // Copy first output for to check if it's exactly same after second compilation.
-    copy_dir_all(&out_dir, &tmp_out_dir);
+    rfs::copy_dir_all(&out_dir, &tmp_out_dir);
 
     // Generate html docs once again on same output.
     generate_docs(&out_dir, JsonOutput::No);
@@ -38,12 +38,12 @@ fn main() {
     assert!(out_dir.join("foobar.json").is_file());
 
     // Copy first json output to check if it's exactly same after second compilation.
-    copy(out_dir.join("foobar.json"), tmp_out_dir.join("foobar.json"));
+    rfs::copy(out_dir.join("foobar.json"), tmp_out_dir.join("foobar.json"));
 
     // Generate json doc on the same output.
     generate_docs(&out_dir, JsonOutput::Yes);
 
     // Check if all docs(including both json and html formats) are still the same after multiple
     // compilations.
-    recursive_diff(&out_dir, &tmp_out_dir);
+    assert_dirs_are_equal(&out_dir, &tmp_out_dir);
 }
diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs
index 612a73977fe..e244f546580 100644
--- a/tests/run-make/sepcomp-cci-copies/rmake.rs
+++ b/tests/run-make/sepcomp-cci-copies/rmake.rs
@@ -5,7 +5,7 @@
 // See https://github.com/rust-lang/rust/pull/16367
 
 use run_make_support::{
-    count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc,
+    count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
     shallow_find_files,
 };
 
diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs
index de7551b9a51..b7a6bed05b8 100644
--- a/tests/run-make/sepcomp-inlining/rmake.rs
+++ b/tests/run-make/sepcomp-inlining/rmake.rs
@@ -6,7 +6,7 @@
 // See https://github.com/rust-lang/rust/pull/16367
 
 use run_make_support::{
-    count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc,
+    count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
     shallow_find_files,
 };
 
diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs
index 6f1d22424b5..90017572c4c 100644
--- a/tests/run-make/sepcomp-separate/rmake.rs
+++ b/tests/run-make/sepcomp-separate/rmake.rs
@@ -4,7 +4,7 @@
 // See https://github.com/rust-lang/rust/pull/16367
 
 use run_make_support::{
-    count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc,
+    count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
     shallow_find_files,
 };
 
diff --git a/tests/run-make/silly-file-names/rmake.rs b/tests/run-make/silly-file-names/rmake.rs
index 9df116146fe..2acf2be8648 100644
--- a/tests/run-make/silly-file-names/rmake.rs
+++ b/tests/run-make/silly-file-names/rmake.rs
@@ -11,13 +11,13 @@
 //@ ignore-windows
 // Reason: Windows refuses files with < and > in their names
 
-use run_make_support::{diff, fs_wrapper, run, rustc};
+use run_make_support::{diff, rfs, run, rustc};
 
 fn main() {
-    fs_wrapper::create_file("<leading-lt");
-    fs_wrapper::write("<leading-lt", r#""comes from a file with a name that begins with <""#);
-    fs_wrapper::create_file("trailing-gt>");
-    fs_wrapper::write("trailing-gt>", r#""comes from a file with a name that ends with >""#);
+    rfs::create_file("<leading-lt");
+    rfs::write("<leading-lt", r#""comes from a file with a name that begins with <""#);
+    rfs::create_file("trailing-gt>");
+    rfs::write("trailing-gt>", r#""comes from a file with a name that ends with >""#);
     rustc().input("silly-file-names.rs").output("silly-file-names").run();
     let out = run("silly-file-names").stdout_utf8();
     diff().expected_file("silly-file-names.run.stdout").actual_text("actual-stdout", out).run();
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/static-extern-type/Makefile b/tests/run-make/static-extern-type/Makefile
deleted file mode 100644
index 77897154322..00000000000
--- a/tests/run-make/static-extern-type/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call NATIVE_STATICLIB,define-foo)
-	$(RUSTC) -ldefine-foo use-foo.rs
-	$(call RUN,use-foo) || exit 1
diff --git a/tests/run-make/static-extern-type/rmake.rs b/tests/run-make/static-extern-type/rmake.rs
new file mode 100644
index 00000000000..d30153f9c68
--- /dev/null
+++ b/tests/run-make/static-extern-type/rmake.rs
@@ -0,0 +1,16 @@
+// Static variables coming from a C library through foreign function interface (FFI) are unsized
+// at compile time - and assuming they are sized used to cause an internal compiler error (ICE).
+// After this was fixed in #58192, this test checks that external statics can be safely used in
+// a program that both compiles and executes successfully.
+// See https://github.com/rust-lang/rust/issues/57876
+
+//@ 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("define-foo");
+    rustc().arg("-ldefine-foo").input("use-foo.rs").run();
+    run("use-foo");
+}
diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs
index 9ed5b76edcb..7a4a8ce18cb 100644
--- a/tests/run-make/symlinked-extern/rmake.rs
+++ b/tests/run-make/symlinked-extern/rmake.rs
@@ -11,12 +11,12 @@
 //@ ignore-cross-compile
 //@ needs-symlink
 
-use run_make_support::{create_symlink, cwd, fs_wrapper, rustc};
+use run_make_support::{cwd, rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").run();
-    fs_wrapper::create_dir_all("other");
-    create_symlink("libfoo.rlib", "other");
+    rfs::create_dir_all("other");
+    rfs::create_symlink("libfoo.rlib", "other");
     rustc().input("bar.rs").library_search_path(cwd()).run();
     rustc().input("baz.rs").extern_("foo", "other").library_search_path(cwd()).run();
 }
diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs
index 1d1dce5b5cf..e6449b61a1c 100644
--- a/tests/run-make/symlinked-libraries/rmake.rs
+++ b/tests/run-make/symlinked-libraries/rmake.rs
@@ -8,11 +8,11 @@
 //@ ignore-cross-compile
 //@ needs-symlink
 
-use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc};
+use run_make_support::{dynamic_lib_name, rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
-    fs_wrapper::create_dir_all("other");
-    create_symlink(dynamic_lib_name("foo"), "other");
+    rfs::create_dir_all("other");
+    rfs::create_symlink(dynamic_lib_name("foo"), "other");
     rustc().input("bar.rs").library_search_path("other").run();
 }
diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs
index 65ebb191428..10ba6ba7cbb 100644
--- a/tests/run-make/symlinked-rlib/rmake.rs
+++ b/tests/run-make/symlinked-rlib/rmake.rs
@@ -8,10 +8,10 @@
 //@ ignore-cross-compile
 //@ needs-symlink
 
-use run_make_support::{create_symlink, cwd, rustc};
+use run_make_support::{cwd, rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").crate_type("rlib").output("foo.xxx").run();
-    create_symlink("foo.xxx", "libfoo.rlib");
+    rfs::create_symlink("foo.xxx", "libfoo.rlib");
     rustc().input("bar.rs").library_search_path(cwd()).run();
 }
diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs
index d2b5f650838..499c6c2079a 100644
--- a/tests/run-make/target-specs/rmake.rs
+++ b/tests/run-make/target-specs/rmake.rs
@@ -5,11 +5,11 @@
 // using them correctly, or fails with the right error message when using them improperly.
 // See https://github.com/rust-lang/rust/pull/16156
 
-use run_make_support::{diff, fs_wrapper, rustc};
+use run_make_support::{diff, rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").target("my-awesome-platform.json").crate_type("lib").emit("asm").run();
-    assert!(!fs_wrapper::read_to_string("foo.s").contains("morestack"));
+    assert!(!rfs::read_to_string("foo.s").contains("morestack"));
     rustc()
         .input("foo.rs")
         .target("my-invalid-platform.json")
@@ -40,8 +40,8 @@ fn main() {
         .print("target-spec-json")
         .run()
         .stdout_utf8();
-    fs_wrapper::create_file("test-platform.json");
-    fs_wrapper::write("test-platform.json", test_platform.as_bytes());
+    rfs::create_file("test-platform.json");
+    rfs::write("test-platform.json", test_platform.as_bytes());
     let test_platform_2 = rustc()
         .arg("-Zunstable-options")
         .target("test-platform.json")
diff --git a/tests/run-make/track-path-dep-info/rmake.rs b/tests/run-make/track-path-dep-info/rmake.rs
index f108dc66051..9b21644c41b 100644
--- a/tests/run-make/track-path-dep-info/rmake.rs
+++ b/tests/run-make/track-path-dep-info/rmake.rs
@@ -4,10 +4,10 @@
 // output successfully added the file as a dependency.
 // See https://github.com/rust-lang/rust/pull/84029
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     rustc().input("macro_def.rs").run();
     rustc().env("EXISTING_PROC_MACRO_ENV", "1").emit("dep-info").input("macro_use.rs").run();
-    assert!(fs_wrapper::read_to_string("macro_use.d").contains("emojis.txt:"));
+    assert!(rfs::read_to_string("macro_use.d").contains("emojis.txt:"));
 }
diff --git a/tests/run-make/track-pgo-dep-info/rmake.rs b/tests/run-make/track-pgo-dep-info/rmake.rs
index acfe05cf8ea..84f4e0bd383 100644
--- a/tests/run-make/track-pgo-dep-info/rmake.rs
+++ b/tests/run-make/track-pgo-dep-info/rmake.rs
@@ -8,7 +8,7 @@
 // Reason: the binary is executed
 //@ needs-profiler-support
 
-use run_make_support::{fs_wrapper, llvm_profdata, run, rustc};
+use run_make_support::{llvm_profdata, rfs, run, rustc};
 
 fn main() {
     // Generate the profile-guided-optimization (PGO) profiles
@@ -19,5 +19,5 @@ fn main() {
     // Use the profiles in compilation
     rustc().profile_use("merged.profdata").emit("dep-info").input("main.rs").run();
     // Check that the profile file is in the dep-info emit file
-    assert!(fs_wrapper::read_to_string("main.d").contains("merged.profdata"));
+    assert!(rfs::read_to_string("main.d").contains("merged.profdata"));
 }
diff --git a/tests/run-make/unstable-flag-required/Makefile b/tests/run-make/unstable-flag-required/Makefile
deleted file mode 100644
index 17dd15b079c..00000000000
--- a/tests/run-make/unstable-flag-required/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
diff --git a/tests/run-make/unstable-flag-required/rmake.rs b/tests/run-make/unstable-flag-required/rmake.rs
new file mode 100644
index 00000000000..c521436c203
--- /dev/null
+++ b/tests/run-make/unstable-flag-required/rmake.rs
@@ -0,0 +1,12 @@
+// The flag `--output-format` is unauthorized on beta and stable releases, which led
+// to confusion for maintainers doing testing on nightly. Tying it to an unstable flag
+// elucidates this, and this test checks that `--output-format` cannot be passed on its
+// own.
+// See https://github.com/rust-lang/rust/pull/82497
+
+use run_make_support::{diff, rustdoc};
+
+fn main() {
+    let out = rustdoc().output_format("json").input("x.html").run_fail().stderr_utf8();
+    diff().expected_file("output-format-json.stderr").actual_text("actual-json", out).run();
+}
diff --git a/tests/run-make/volatile-intrinsics/rmake.rs b/tests/run-make/volatile-intrinsics/rmake.rs
index fb9be4bb9ba..66bc6f953c2 100644
--- a/tests/run-make/volatile-intrinsics/rmake.rs
+++ b/tests/run-make/volatile-intrinsics/rmake.rs
@@ -1,6 +1,6 @@
 //@ ignore-cross-compile
 
-use run_make_support::fs_wrapper::read;
+use run_make_support::rfs;
 use run_make_support::{assert_contains, run, rustc};
 
 fn main() {
@@ -11,7 +11,7 @@ fn main() {
     // ... and the loads/stores must not be optimized out.
     rustc().input("main.rs").emit("llvm-ir").run();
 
-    let raw_llvm_ir = read("main.ll");
+    let raw_llvm_ir = rfs::read("main.ll");
     let llvm_ir = String::from_utf8_lossy(&raw_llvm_ir);
     assert_contains(&llvm_ir, "load volatile");
     assert_contains(&llvm_ir, "store volatile");
diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs
index e958f5086ac..756a72f11b1 100644
--- a/tests/run-make/wasm-custom-section/rmake.rs
+++ b/tests/run-make/wasm-custom-section/rmake.rs
@@ -1,13 +1,13 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::HashMap;
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
     rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let file = fs_wrapper::read("bar.wasm");
+    let file = rfs::read("bar.wasm");
 
     let mut custom = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs
index 346cffecc77..0be863fdb6e 100644
--- a/tests/run-make/wasm-custom-sections-opt/rmake.rs
+++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::HashMap;
 use std::path::Path;
 
@@ -12,7 +12,7 @@ fn main() {
 
 fn verify(path: &Path) {
     eprintln!("verify {path:?}");
-    let file = fs_wrapper::read(&path);
+    let file = rfs::read(&path);
 
     let mut custom = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs
index 41a2eaaafc3..9ea541a1752 100644
--- a/tests/run-make/wasm-export-all-symbols/rmake.rs
+++ b/tests/run-make/wasm-export-all-symbols/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::HashMap;
 use std::path::Path;
 use wasmparser::ExternalKind::*;
@@ -33,7 +33,7 @@ fn test(args: &[&str]) {
 
 fn verify_exports(path: &Path, exports: &[(&str, wasmparser::ExternalKind)]) {
     println!("verify {path:?}");
-    let file = fs_wrapper::read(path);
+    let file = rfs::read(path);
     let mut wasm_exports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
         let payload = payload.unwrap();
diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs
index 881242c59a2..c240d4780b2 100644
--- a/tests/run-make/wasm-import-module/rmake.rs
+++ b/tests/run-make/wasm-import-module/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::HashMap;
 use wasmparser::TypeRef::Func;
 
@@ -8,7 +8,7 @@ fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").run();
     rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let file = fs_wrapper::read("bar.wasm");
+    let file = rfs::read("bar.wasm");
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs
index 891cac4bc9f..8d0944ed98d 100644
--- a/tests/run-make/wasm-panic-small/rmake.rs
+++ b/tests/run-make/wasm-panic-small/rmake.rs
@@ -1,7 +1,7 @@
 //@ only-wasm32-wasip1
 #![deny(warnings)]
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     test("a");
@@ -15,7 +15,7 @@ fn test(cfg: &str) {
 
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().cfg(cfg).run();
 
-    let bytes = fs_wrapper::read("foo.wasm");
+    let bytes = rfs::read("foo.wasm");
     println!("{}", bytes.len());
     assert!(bytes.len() < 40_000);
 }
diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs
index 88e4c83c94c..9cfd202eae1 100644
--- a/tests/run-make/wasm-spurious-import/rmake.rs
+++ b/tests/run-make/wasm-spurious-import/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::HashMap;
 
 fn main() {
@@ -13,7 +13,7 @@ fn main() {
         .arg("-Copt-level=z")
         .run();
 
-    let file = fs_wrapper::read("main.wasm");
+    let file = rfs::read("main.wasm");
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs
index 42e415b3a86..93eb38b0987 100644
--- a/tests/run-make/wasm-stringify-ints-small/rmake.rs
+++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs
@@ -1,12 +1,12 @@
 //@ only-wasm32-wasip1
 #![deny(warnings)]
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     rustc().input("foo.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
 
-    let bytes = fs_wrapper::read("foo.wasm");
+    let bytes = rfs::read("foo.wasm");
     println!("{}", bytes.len());
     assert!(bytes.len() < 50_000);
 }
diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs
index 734f79d834a..6b69f76ee17 100644
--- a/tests/run-make/wasm-symbols-different-module/rmake.rs
+++ b/tests/run-make/wasm-symbols-different-module/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::collections::{HashMap, HashSet};
 use std::path::Path;
 
@@ -23,7 +23,7 @@ fn test(file: &str, args: &[&str], expected_imports: &[(&str, &[&str])]) {
 
     rustc().input(file).target("wasm32-wasip1").args(args).run();
 
-    let file = fs_wrapper::read(Path::new(file).with_extension("wasm"));
+    let file = rfs::read(Path::new(file).with_extension("wasm"));
 
     let mut imports = HashMap::new();
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs
index 4c817a6fd82..ad31351ba95 100644
--- a/tests/run-make/wasm-symbols-not-exported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::path::Path;
 
 fn main() {
@@ -17,7 +17,7 @@ fn main() {
 
 fn verify_symbols(path: &Path) {
     eprintln!("verify {path:?}");
-    let file = fs_wrapper::read(&path);
+    let file = rfs::read(&path);
 
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
         let payload = payload.unwrap();
diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs
index 58c9f9c6f45..36c600c49f5 100644
--- a/tests/run-make/wasm-symbols-not-imported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs
@@ -1,6 +1,6 @@
 //@ only-wasm32-wasip1
 
-use run_make_support::{fs_wrapper, rustc, wasmparser};
+use run_make_support::{rfs, rustc, wasmparser};
 use std::path::Path;
 
 fn main() {
@@ -16,7 +16,7 @@ fn main() {
 
 fn verify_symbols(path: &Path) {
     eprintln!("verify {path:?}");
-    let file = fs_wrapper::read(&path);
+    let file = rfs::read(&path);
 
     for payload in wasmparser::Parser::new(0).parse_all(&file) {
         let payload = payload.unwrap();
diff --git a/tests/run-make/weird-output-filenames/rmake.rs b/tests/run-make/weird-output-filenames/rmake.rs
index ed331a0b8d4..3d1b5f4007c 100644
--- a/tests/run-make/weird-output-filenames/rmake.rs
+++ b/tests/run-make/weird-output-filenames/rmake.rs
@@ -1,17 +1,17 @@
-use run_make_support::fs_wrapper::copy;
 use run_make_support::regex::Regex;
+use run_make_support::rfs;
 use run_make_support::{cwd, rustc};
 
 fn main() {
     let invalid_characters = [".foo.rs", ".foo.bar", "+foo+bar.rs"];
     let re = Regex::new(r"invalid character.*in crate name:").unwrap();
     for f in invalid_characters {
-        copy("foo.rs", f);
+        rfs::copy("foo.rs", f);
         let stderr = rustc().input(f).run_fail().stderr_utf8();
         assert!(re.is_match(&stderr));
     }
 
-    copy("foo.rs", "-foo.rs");
+    rfs::copy("foo.rs", "-foo.rs");
     rustc()
         .input(cwd().join("-foo.rs"))
         .run_fail()
diff --git a/tests/run-make/windows-ws2_32/rmake.rs b/tests/run-make/windows-ws2_32/rmake.rs
index fde59452bc5..6457d74f97e 100644
--- a/tests/run-make/windows-ws2_32/rmake.rs
+++ b/tests/run-make/windows-ws2_32/rmake.rs
@@ -3,7 +3,7 @@
 // Tests that WS2_32.dll is not unnecessarily linked, see issue #85441
 
 use run_make_support::object::{self, read::Object};
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     rustc().input("empty.rs").run();
@@ -14,7 +14,7 @@ fn main() {
 }
 
 fn links_ws2_32(exe: &str) -> bool {
-    let binary_data = fs_wrapper::read(exe);
+    let binary_data = rfs::read(exe);
     let file = object::File::parse(&*binary_data).unwrap();
     for import in file.imports().unwrap() {
         if import.library().eq_ignore_ascii_case(b"WS2_32.dll") {
diff --git a/tests/rustdoc-gui/huge-logo.goml b/tests/rustdoc-gui/huge-logo.goml
index e4e5cb1ec74..d207ab5bb37 100644
--- a/tests/rustdoc-gui/huge-logo.goml
+++ b/tests/rustdoc-gui/huge-logo.goml
@@ -3,9 +3,11 @@
 go-to: "file://" + |DOC_PATH| + "/huge_logo/index.html"
 
 set-window-size: (1280, 1024)
-// offsetWidth = width of sidebar
-assert-property: (".sidebar-crate .logo-container", {"offsetWidth": "48", "offsetHeight": 48})
-assert-property: (".sidebar-crate .logo-container img", {"offsetWidth": "48", "offsetHeight": 48})
+// offsetWidth = width of sidebar + left and right margins
+assert-property: (".sidebar-crate .logo-container", {"offsetWidth": "96", "offsetHeight": 48})
+// offsetWidth = width of sidebar, offsetHeight = height + top padding
+assert-property: (".sidebar-crate .logo-container img", {"offsetWidth": "48", "offsetHeight": 64})
+assert-css: (".sidebar-crate .logo-container img", {"border-top-width": "16px", "margin-top": "-16px"})
 
 set-window-size: (400, 600)
 // offset = size + margin
diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml
index 452545958f9..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")
@@ -179,3 +183,18 @@ assert-property: (".sidebar .sidebar-crate h2 a", {
     "offsetTop": |index_sidebar_y|,
     "offsetLeft": |index_sidebar_x|,
 })
+
+// Check that the sidebar links touch the left side of the box
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+assert-position: (".sidebar .block a", {"x": -4})
+assert-position: (".sidebar-crate > h2 > a", {"x": -3})
+
+// Check that the main sidebar links touch the left side of the box
+// but the crate name doesn't, because the logo takes that space
+go-to: "file://" + |DOC_PATH| + "/huge_logo/index.html"
+assert-position: (".sidebar .block a", {"x": -4})
+// when side-by-side, it's not line wrapped
+assert-position-false: (".sidebar-crate > h2 > a", {"x": -3})
+// when line-wrapped, see that it becomes flush-left again
+drag-and-drop: ((205, 100), (108, 100))
+assert-position: (".sidebar-crate > h2 > a", {"x": -3})
diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs
index b467b044052..2467c7adae1 100644
--- a/tests/rustdoc-gui/src/lib2/lib.rs
+++ b/tests/rustdoc-gui/src/lib2/lib.rs
@@ -117,6 +117,7 @@ pub mod too_long {
     pub type ReallyLongTypeNameLongLongLong =
         Option<unsafe extern "C" fn(a: *const u8, b: *const u8) -> *const u8>;
 
+    /// Short doc.
     pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0;
 
     /// This also has a really long doccomment. Lorem ipsum dolor sit amet,
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 7e34178e56f..6c638dc3b9d 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -614,3 +614,9 @@ pub mod private {
         B,
     }
 }
+
+pub mod trait_bounds {
+    pub trait OneBound: Sized {}
+    pub trait TwoBounds: Sized + Copy {}
+    pub trait ThreeBounds: Sized + Copy + Eq {}
+}
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 3709aa10266..8df946c6f39 100644
--- a/tests/rustdoc-gui/type-declation-overflow.goml
+++ b/tests/rustdoc-gui/type-declation-overflow.goml
@@ -8,30 +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"
-assert-property: (".item-table .struct", {"offsetWidth": "684"})
+
+// 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| == "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/ice-unresolved-import-100241.stderr b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr
new file mode 100644
index 00000000000..57fbbb59c8d
--- /dev/null
+++ b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `inner`
+  --> $DIR/ice-unresolved-import-100241.rs:9:13
+   |
+LL |     pub use inner::S;
+   |             ^^^^^ maybe a missing crate `inner`?
+   |
+   = help: consider adding `extern crate inner` to use the `inner` crate
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr
index 6e5ddc44982..66f8ffe6d72 100644
--- a/tests/rustdoc-ui/invalid_associated_const.stderr
+++ b/tests/rustdoc-ui/invalid_associated_const.stderr
@@ -6,8 +6,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/invalid_associated_const.rs:4:17
@@ -18,8 +19,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr
index 99f91102319..5fcdba782e7 100644
--- a/tests/rustdoc-ui/issue-102467.stderr
+++ b/tests/rustdoc-ui/issue-102467.stderr
@@ -6,8 +6,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102467.rs:7:17
@@ -18,8 +19,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error: aborting due to 2 previous errors
 
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/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-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
new file mode 100644
index 00000000000..33e10a00713
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
@@ -0,0 +1,38 @@
+//@ compile-flags: -Z unstable-options
+//@ ignore-stage1 (can be removed after beta bump, #[cfg(bootstrap)])
+#![feature(rustc_private)]
+#![deny(rustc::non_glob_import_of_type_ir_inherent)]
+
+extern crate rustc_type_ir;
+
+mod ok {
+    use rustc_type_ir::inherent::*; // OK
+    use rustc_type_ir::inherent::{}; // OK
+    use rustc_type_ir::inherent::{*}; // OK
+
+    fn usage<T: rustc_type_ir::inherent::SliceLike>() {} // OK
+}
+
+mod direct {
+    use rustc_type_ir::inherent::Predicate; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::{AdtDef, Ty};
+    //~^ ERROR non-glob import of `rustc_type_ir::inherent`
+    //~| ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::ParamEnv as _; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+}
+
+mod indirect0 {
+    use rustc_type_ir::inherent; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent as inh; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::{inherent as _}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+
+    fn usage0<T: inherent::SliceLike>() {}
+    fn usage1<T: inh::SliceLike>() {}
+}
+
+mod indirect1 {
+    use rustc_type_ir::inherent::{self}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+    use rustc_type_ir::inherent::{self as innate}; //~ ERROR non-glob import of `rustc_type_ir::inherent`
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
new file mode 100644
index 00000000000..84e3867c95b
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
@@ -0,0 +1,68 @@
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:9
+   |
+LL |     use rustc_type_ir::inherent::Predicate;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^---------
+   |                                  |
+   |                                  help: try using a glob import instead: `*`
+   |
+note: the lint level is defined here
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:4:9
+   |
+LL | #![deny(rustc::non_glob_import_of_type_ir_inherent)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:35
+   |
+LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
+   |                                   ^^^^^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:43
+   |
+LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
+   |                                           ^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:21:9
+   |
+LL |     use rustc_type_ir::inherent::ParamEnv as _;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^-------------
+   |                                  |
+   |                                  help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
+   |
+LL |     use rustc_type_ir::inherent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:9
+   |
+LL |     use rustc_type_ir::inherent as inh;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^------- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:27:25
+   |
+LL |     use rustc_type_ir::{inherent as _};
+   |                         ^^^^^^^^----- help: try using a glob import instead: `::*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
+   |
+LL |     use rustc_type_ir::inherent::{self};
+   |                                   ^^^^ help: try using a glob import instead: `*`
+
+error: non-glob import of `rustc_type_ir::inherent`
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:35:35
+   |
+LL |     use rustc_type_ir::inherent::{self as innate};
+   |                                   ^^^^----------
+   |                                   |
+   |                                   help: try using a glob import instead: `*`
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index f971426723f..5e3f2557566 100644
--- a/tests/ui-fulldeps/stable-mir/check_instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -33,7 +33,7 @@ fn test_stable_mir() -> ControlFlow<()> {
     // Get all items and split generic vs monomorphic items.
     let (generic, mono): (Vec<_>, Vec<_>) =
         items.into_iter().partition(|item| item.requires_monomorphization());
-    assert_eq!(mono.len(), 4, "Expected 2 mono functions and one constant");
+    assert_eq!(mono.len(), 3, "Expected 3 mono functions");
     assert_eq!(generic.len(), 2, "Expected 2 generic functions");
 
     // For all monomorphic items, get the correspondent instances.
diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr
index 983325c1abd..0c4bd5382a1 100644
--- a/tests/ui/abi/statics/static-mut-foreign.stderr
+++ b/tests/ui/abi/statics/static-mut-foreign.stderr
@@ -11,7 +11,7 @@ LL |     static_bound(&rust_dbg_static_mut);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     static_bound(addr_of!(rust_dbg_static_mut));
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                  ~~~~~~~~~                   +
 
 warning: creating a mutable reference to mutable static is discouraged
   --> $DIR/static-mut-foreign.rs:33:22
@@ -25,7 +25,7 @@ LL |     static_bound_set(&mut rust_dbg_static_mut);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |     static_bound_set(addr_of_mut!(rust_dbg_static_mut));
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ~~~~~~~~~~~~~                   +
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/anon-params/anon-params-denied-2018.stderr b/tests/ui/anon-params/anon-params-denied-2018.stderr
index bb60c898e81..2d6356ffcb1 100644
--- a/tests/ui/anon-params/anon-params-denied-2018.stderr
+++ b/tests/ui/anon-params/anon-params-denied-2018.stderr
@@ -48,7 +48,7 @@ LL |     fn foo_with_qualified_path(<Bar as T>::Baz);
 help: explicitly ignore the parameter name
    |
 LL |     fn foo_with_qualified_path(_: <Bar as T>::Baz);
-   |                                ~~~~~~~~~~~~~~~~~~
+   |                                ++
 
 error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:15:56
@@ -60,7 +60,7 @@ LL |     fn foo_with_qualified_path_and_ref(&<Bar as T>::Baz);
 help: explicitly ignore the parameter name
    |
 LL |     fn foo_with_qualified_path_and_ref(_: &<Bar as T>::Baz);
-   |                                        ~~~~~~~~~~~~~~~~~~~
+   |                                        ++
 
 error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `,`
   --> $DIR/anon-params-denied-2018.rs:18:57
@@ -72,7 +72,7 @@ LL |     fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
 help: explicitly ignore the parameter name
    |
 LL |     fn foo_with_multiple_qualified_paths(_: <Bar as T>::Baz, <Bar as T>::Baz);
-   |                                          ~~~~~~~~~~~~~~~~~~
+   |                                          ++
 
 error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:18:74
@@ -84,7 +84,7 @@ LL |     fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
 help: explicitly ignore the parameter name
    |
 LL |     fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, _: <Bar as T>::Baz);
-   |                                                           ~~~~~~~~~~~~~~~~~~
+   |                                                           ++
 
 error: expected one of `:`, `@`, or `|`, found `,`
   --> $DIR/anon-params-denied-2018.rs:22:36
diff --git a/tests/ui/argument-suggestions/basic.stderr b/tests/ui/argument-suggestions/basic.stderr
index ea58ca97cfa..2d52df21233 100644
--- a/tests/ui/argument-suggestions/basic.stderr
+++ b/tests/ui/argument-suggestions/basic.stderr
@@ -33,7 +33,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:22:5
    |
 LL |     missing();
-   |     ^^^^^^^-- an argument of type `u32` is missing
+   |     ^^^^^^^-- argument #1 of type `u32` is missing
    |
 note: function defined here
   --> $DIR/basic.rs:15:4
@@ -86,7 +86,7 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:27:5
    |
 LL |     closure();
-   |     ^^^^^^^-- an argument is missing
+   |     ^^^^^^^-- argument #1 is missing
    |
 note: closure defined here
   --> $DIR/basic.rs:26:19
diff --git a/tests/ui/argument-suggestions/display-is-suggestable.stderr b/tests/ui/argument-suggestions/display-is-suggestable.stderr
index bde87475e0a..eea88c3e78d 100644
--- a/tests/ui/argument-suggestions/display-is-suggestable.stderr
+++ b/tests/ui/argument-suggestions/display-is-suggestable.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/display-is-suggestable.rs:6:5
    |
 LL |     foo();
-   |     ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing
+   |     ^^^-- argument #1 of type `&dyn std::fmt::Display + Send` is missing
    |
 note: function defined here
   --> $DIR/display-is-suggestable.rs:3:4
diff --git a/tests/ui/argument-suggestions/extern-fn-arg-names.stderr b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr
index f6bc84c1203..47fbfc98c67 100644
--- a/tests/ui/argument-suggestions/extern-fn-arg-names.stderr
+++ b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr
@@ -8,7 +8,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/extern-fn-arg-names.rs:7:5
    |
 LL |     dstfn(1);
-   |     ^^^^^--- an argument is missing
+   |     ^^^^^--- argument #2 is missing
    |
 note: function defined here
   --> $DIR/extern-fn-arg-names.rs:2:8
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index dec3da75186..8c95cc86a27 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -19,9 +19,9 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:20:3
    |
 LL |   empty(1, 1);
-   |   ^^^^^ -  - unexpected argument of type `{integer}`
+   |   ^^^^^ -  - unexpected argument #2 of type `{integer}`
    |         |
-   |         unexpected argument of type `{integer}`
+   |         unexpected argument #1 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:1:4
@@ -38,7 +38,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:22:3
    |
 LL |   one_arg(1, 1);
-   |   ^^^^^^^    - unexpected argument of type `{integer}`
+   |   ^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -55,7 +55,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:23:3
    |
 LL |   one_arg(1, "");
-   |   ^^^^^^^    -- unexpected argument of type `&'static str`
+   |   ^^^^^^^    -- unexpected argument #2 of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -72,9 +72,9 @@ error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:24:3
    |
 LL |   one_arg(1, "", 1.0);
-   |   ^^^^^^^    --  --- unexpected argument of type `{float}`
+   |   ^^^^^^^    --  --- unexpected argument #3 of type `{float}`
    |              |
-   |              unexpected argument of type `&'static str`
+   |              unexpected argument #2 of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -91,7 +91,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:26:3
    |
 LL |   two_arg_same(1, 1, 1);
-   |   ^^^^^^^^^^^^       - unexpected argument of type `{integer}`
+   |   ^^^^^^^^^^^^       - unexpected argument #3 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
@@ -108,7 +108,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:27:3
    |
 LL |   two_arg_same(1, 1, 1.0);
-   |   ^^^^^^^^^^^^       --- unexpected argument of type `{float}`
+   |   ^^^^^^^^^^^^       --- unexpected argument #3 of type `{float}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
@@ -125,7 +125,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:29:3
    |
 LL |   two_arg_diff(1, 1, "");
-   |   ^^^^^^^^^^^^    - unexpected argument of type `{integer}`
+   |   ^^^^^^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -142,7 +142,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:30:3
    |
 LL |   two_arg_diff(1, "", "");
-   |   ^^^^^^^^^^^^        -- unexpected argument of type `&'static str`
+   |   ^^^^^^^^^^^^        -- unexpected argument #3 of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -159,9 +159,9 @@ error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:31:3
    |
 LL |   two_arg_diff(1, 1, "", "");
-   |   ^^^^^^^^^^^^    -      -- unexpected argument of type `&'static str`
+   |   ^^^^^^^^^^^^    -      -- unexpected argument #4 of type `&'static str`
    |                   |
-   |                   unexpected argument of type `{integer}`
+   |                   unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -178,9 +178,9 @@ error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:32:3
    |
 LL |   two_arg_diff(1, "", 1, "");
-   |   ^^^^^^^^^^^^        -  -- unexpected argument of type `&'static str`
+   |   ^^^^^^^^^^^^        -  -- unexpected argument #4 of type `&'static str`
    |                       |
-   |                       unexpected argument of type `{integer}`
+   |                       unexpected argument #3 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -197,7 +197,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:35:3
    |
 LL |   two_arg_same(1, 1,     "");
-   |   ^^^^^^^^^^^^           -- unexpected argument of type `&'static str`
+   |   ^^^^^^^^^^^^           -- unexpected argument #3 of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
@@ -214,7 +214,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:36:3
    |
 LL |   two_arg_diff(1, 1,     "");
-   |   ^^^^^^^^^^^^    - unexpected argument of type `{integer}`
+   |   ^^^^^^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -234,7 +234,7 @@ LL |   two_arg_same(
    |   ^^^^^^^^^^^^
 ...
 LL |     ""
-   |     -- unexpected argument of type `&'static str`
+   |     -- unexpected argument #3 of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
@@ -255,7 +255,7 @@ LL |   two_arg_diff(
    |   ^^^^^^^^^^^^
 LL |     1,
 LL |     1,
-   |     - unexpected argument of type `{integer}`
+   |     - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -271,12 +271,12 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:8:9
    |
 LL |         empty($x, 1);
-   |         ^^^^^     - unexpected argument of type `{integer}`
+   |         ^^^^^     - unexpected argument #2 of type `{integer}`
 ...
 LL |   foo!(1, ~);
    |   ----------
    |   |    |
-   |   |    unexpected argument of type `{integer}`
+   |   |    unexpected argument #1 of type `{integer}`
    |   in this macro invocation
    |
 note: function defined here
@@ -290,12 +290,12 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:14:9
    |
 LL |         empty(1, $y);
-   |         ^^^^^ - unexpected argument of type `{integer}`
+   |         ^^^^^ - unexpected argument #1 of type `{integer}`
 ...
 LL |   foo!(~, 1);
    |   ----------
    |   |       |
-   |   |       unexpected argument of type `{integer}`
+   |   |       unexpected argument #2 of type `{integer}`
    |   in this macro invocation
    |
 note: function defined here
@@ -314,8 +314,8 @@ LL |         empty($x, $y);
 LL |   foo!(1, 1);
    |   ----------
    |   |    |  |
-   |   |    |  unexpected argument of type `{integer}`
-   |   |    unexpected argument of type `{integer}`
+   |   |    |  unexpected argument #2 of type `{integer}`
+   |   |    unexpected argument #1 of type `{integer}`
    |   in this macro invocation
    |
 note: function defined here
@@ -329,7 +329,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:53:3
    |
 LL |   one_arg(1, panic!());
-   |   ^^^^^^^    -------- unexpected argument
+   |   ^^^^^^^    -------- unexpected argument #2
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -346,7 +346,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:54:3
    |
 LL |   one_arg(panic!(), 1);
-   |   ^^^^^^^           - unexpected argument of type `{integer}`
+   |   ^^^^^^^           - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -363,7 +363,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:55:3
    |
 LL |   one_arg(stringify!($e), 1);
-   |   ^^^^^^^                 - unexpected argument of type `{integer}`
+   |   ^^^^^^^                 - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -380,7 +380,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:60:3
    |
 LL |   one_arg(for _ in 1.. {}, 1);
-   |   ^^^^^^^                  - unexpected argument of type `{integer}`
+   |   ^^^^^^^                  - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
diff --git a/tests/ui/argument-suggestions/issue-100478.stderr b/tests/ui/argument-suggestions/issue-100478.stderr
index e4304988f9b..94709f0ebc6 100644
--- a/tests/ui/argument-suggestions/issue-100478.stderr
+++ b/tests/ui/argument-suggestions/issue-100478.stderr
@@ -4,8 +4,8 @@ error[E0061]: this function takes 3 arguments but 1 argument was supplied
 LL |     three_diff(T2::new(0));
    |     ^^^^^^^^^^------------
    |               ||
-   |               |an argument of type `T1` is missing
-   |               an argument of type `T3` is missing
+   |               |argument #1 of type `T1` is missing
+   |               argument #3 of type `T3` is missing
    |
 note: function defined here
   --> $DIR/issue-100478.rs:30:4
@@ -63,7 +63,7 @@ LL |     foo(
    |     ^^^
 ...
 LL |         p3, p4, p5, p6, p7, p8,
-   |         -- an argument of type `Arc<T2>` is missing
+   |         -- argument #2 of type `Arc<T2>` is missing
    |
 note: function defined here
   --> $DIR/issue-100478.rs:29:4
diff --git a/tests/ui/argument-suggestions/issue-101097.stderr b/tests/ui/argument-suggestions/issue-101097.stderr
index 061f510144b..6e21f19ab4f 100644
--- a/tests/ui/argument-suggestions/issue-101097.stderr
+++ b/tests/ui/argument-suggestions/issue-101097.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 6 arguments but 7 arguments were supplied
 LL |     f(C, A, A, A, B, B, C);
    |     ^ -     -  -  - expected `C`, found `B`
    |       |     |  |
-   |       |     |  unexpected argument of type `A`
+   |       |     |  unexpected argument #4 of type `A`
    |       |     expected `B`, found `A`
    |       expected `A`, found `C`
    |
@@ -64,8 +64,8 @@ error[E0308]: arguments to this function are incorrect
 LL |     f(A, A, D, D, B, B);
    |     ^       -  -  ---- two arguments of type `C` and `C` are missing
    |             |  |
-   |             |  unexpected argument of type `D`
-   |             unexpected argument of type `D`
+   |             |  unexpected argument #4 of type `D`
+   |             unexpected argument #3 of type `D`
    |
 note: function defined here
   --> $DIR/issue-101097.rs:6:4
diff --git a/tests/ui/argument-suggestions/issue-109425.stderr b/tests/ui/argument-suggestions/issue-109425.stderr
index 1514f1cb487..bfe007793d4 100644
--- a/tests/ui/argument-suggestions/issue-109425.stderr
+++ b/tests/ui/argument-suggestions/issue-109425.stderr
@@ -2,9 +2,9 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied
   --> $DIR/issue-109425.rs:10:5
    |
 LL |     f(0, 1,);        // f()
-   |     ^ -  - unexpected argument of type `{integer}`
+   |     ^ -  - unexpected argument #2 of type `{integer}`
    |       |
-   |       unexpected argument of type `{integer}`
+   |       unexpected argument #1 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-109425.rs:3:4
@@ -21,9 +21,9 @@ error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/issue-109425.rs:12:5
    |
 LL |     i(0, 1, 2,);     // i(0,)
-   |     ^    -  - unexpected argument of type `{integer}`
+   |     ^    -  - unexpected argument #3 of type `{integer}`
    |          |
-   |          unexpected argument of type `{integer}`
+   |          unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-109425.rs:4:4
@@ -40,9 +40,9 @@ error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/issue-109425.rs:14:5
    |
 LL |     i(0, 1, 2);      // i(0)
-   |     ^    -  - unexpected argument of type `{integer}`
+   |     ^    -  - unexpected argument #3 of type `{integer}`
    |          |
-   |          unexpected argument of type `{integer}`
+   |          unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-109425.rs:4:4
@@ -59,9 +59,9 @@ error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/issue-109425.rs:16:5
    |
 LL |     is(0, 1, 2, ""); // is(0, "")
-   |     ^^    -  - unexpected argument of type `{integer}`
+   |     ^^    -  - unexpected argument #3 of type `{integer}`
    |           |
-   |           unexpected argument of type `{integer}`
+   |           unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-109425.rs:5:4
@@ -78,9 +78,9 @@ error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/issue-109425.rs:18:5
    |
 LL |     s(0, 1, "");     // s("")
-   |     ^ -  - unexpected argument of type `{integer}`
+   |     ^ -  - unexpected argument #2 of type `{integer}`
    |       |
-   |       unexpected argument of type `{integer}`
+   |       unexpected argument #1 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-109425.rs:6:4
diff --git a/tests/ui/argument-suggestions/issue-109831.stderr b/tests/ui/argument-suggestions/issue-109831.stderr
index 7b9a3c9ef2c..12be0887121 100644
--- a/tests/ui/argument-suggestions/issue-109831.stderr
+++ b/tests/ui/argument-suggestions/issue-109831.stderr
@@ -29,7 +29,7 @@ error[E0061]: this function takes 3 arguments but 4 arguments were supplied
   --> $DIR/issue-109831.rs:7:5
    |
 LL |     f(A, A, B, C);
-   |     ^ -  -     - unexpected argument
+   |     ^ -  -     - unexpected argument #4
    |       |  |
    |       |  expected `B`, found `A`
    |       expected `B`, found `A`
diff --git a/tests/ui/argument-suggestions/issue-112507.stderr b/tests/ui/argument-suggestions/issue-112507.stderr
index 17bde4d9743..908ed35c669 100644
--- a/tests/ui/argument-suggestions/issue-112507.stderr
+++ b/tests/ui/argument-suggestions/issue-112507.stderr
@@ -4,12 +4,12 @@ error[E0061]: this enum variant takes 1 argument but 4 arguments were supplied
 LL |     let _a = Value::Float(
    |              ^^^^^^^^^^^^
 LL |         0,
-   |         - unexpected argument of type `{integer}`
+   |         - unexpected argument #1 of type `{integer}`
 LL |         None,
 LL |         None,
-   |         ---- unexpected argument of type `Option<_>`
+   |         ---- unexpected argument #3 of type `Option<_>`
 LL |         0,
-   |         - unexpected argument of type `{integer}`
+   |         - unexpected argument #4 of type `{integer}`
    |
 note: tuple variant defined here
   --> $DIR/issue-112507.rs:2:5
diff --git a/tests/ui/argument-suggestions/issue-96638.stderr b/tests/ui/argument-suggestions/issue-96638.stderr
index 887bf82a2f6..6492acbad94 100644
--- a/tests/ui/argument-suggestions/issue-96638.stderr
+++ b/tests/ui/argument-suggestions/issue-96638.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
 LL |     f(&x, "");
    |     ^ --  -- expected `usize`, found `&str`
    |       |
-   |       an argument of type `usize` is missing
+   |       argument #1 of type `usize` is missing
    |
 note: function defined here
   --> $DIR/issue-96638.rs:1:4
diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr
index 6bdb734fddf..a7708f6e0d7 100644
--- a/tests/ui/argument-suggestions/issue-97484.stderr
+++ b/tests/ui/argument-suggestions/issue-97484.stderr
@@ -2,11 +2,11 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied
   --> $DIR/issue-97484.rs:12:5
    |
 LL |     foo(&&A, B, C, D, E, F, G);
-   |     ^^^      -  -     -  - unexpected argument of type `F`
+   |     ^^^      -  -     -  - unexpected argument #6 of type `F`
    |              |  |     |
    |              |  |     expected `&E`, found `E`
-   |              |  unexpected argument of type `C`
-   |              unexpected argument of type `B`
+   |              |  unexpected argument #3 of type `C`
+   |              unexpected argument #2 of type `B`
    |
 note: function defined here
   --> $DIR/issue-97484.rs:9:4
diff --git a/tests/ui/argument-suggestions/issue-98894.stderr b/tests/ui/argument-suggestions/issue-98894.stderr
index 72e6fec27e6..93e604c3101 100644
--- a/tests/ui/argument-suggestions/issue-98894.stderr
+++ b/tests/ui/argument-suggestions/issue-98894.stderr
@@ -2,7 +2,7 @@ error[E0057]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-98894.rs:2:5
    |
 LL |     (|_, ()| ())(if true {} else {return;});
-   |     ^^^^^^^^^^^^--------------------------- an argument of type `()` is missing
+   |     ^^^^^^^^^^^^--------------------------- argument #2 of type `()` is missing
    |
 note: closure defined here
   --> $DIR/issue-98894.rs:2:6
diff --git a/tests/ui/argument-suggestions/issue-98897.stderr b/tests/ui/argument-suggestions/issue-98897.stderr
index eed3964559a..671e3d99d85 100644
--- a/tests/ui/argument-suggestions/issue-98897.stderr
+++ b/tests/ui/argument-suggestions/issue-98897.stderr
@@ -2,7 +2,7 @@ error[E0057]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-98897.rs:2:5
    |
 LL |     (|_, ()| ())([return, ()]);
-   |     ^^^^^^^^^^^^-------------- an argument of type `()` is missing
+   |     ^^^^^^^^^^^^-------------- argument #2 of type `()` is missing
    |
 note: closure defined here
   --> $DIR/issue-98897.rs:2:6
diff --git a/tests/ui/argument-suggestions/issue-99482.stderr b/tests/ui/argument-suggestions/issue-99482.stderr
index 9c83b47f8b6..be407874615 100644
--- a/tests/ui/argument-suggestions/issue-99482.stderr
+++ b/tests/ui/argument-suggestions/issue-99482.stderr
@@ -2,7 +2,7 @@ error[E0057]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-99482.rs:3:14
    |
 LL |     let _f = f(main);
-   |              ^ ---- an argument of type `()` is missing
+   |              ^ ---- argument #1 of type `()` is missing
    |
 note: closure defined here
   --> $DIR/issue-99482.rs:2:13
diff --git a/tests/ui/argument-suggestions/missing_arguments.stderr b/tests/ui/argument-suggestions/missing_arguments.stderr
index ba9ece040be..3a27a51d032 100644
--- a/tests/ui/argument-suggestions/missing_arguments.stderr
+++ b/tests/ui/argument-suggestions/missing_arguments.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing_arguments.rs:10:3
    |
 LL |   one_arg();
-   |   ^^^^^^^-- an argument of type `i32` is missing
+   |   ^^^^^^^-- argument #1 of type `i32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:1:4
@@ -34,7 +34,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:15:3
    |
 LL |   two_same(   1           );
-   |   ^^^^^^^^----------------- an argument of type `i32` is missing
+   |   ^^^^^^^^----------------- argument #2 of type `i32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:2:4
@@ -66,7 +66,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:17:3
    |
 LL |   two_diff(   1           );
-   |   ^^^^^^^^----------------- an argument of type `f32` is missing
+   |   ^^^^^^^^----------------- argument #2 of type `f32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:3:4
@@ -82,7 +82,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing_arguments.rs:18:3
    |
 LL |   two_diff(          1.0  );
-   |   ^^^^^^^^           --- an argument of type `i32` is missing
+   |   ^^^^^^^^           --- argument #1 of type `i32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:3:4
@@ -130,7 +130,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:23:3
    |
 LL |   three_same(   1,      1           );
-   |   ^^^^^^^^^^------------------------- an argument of type `i32` is missing
+   |   ^^^^^^^^^^------------------------- argument #3 of type `i32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:4:4
@@ -146,7 +146,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:26:3
    |
 LL |   three_diff(          1.0,     ""  );
-   |   ^^^^^^^^^^           --- an argument of type `i32` is missing
+   |   ^^^^^^^^^^           --- argument #1 of type `i32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:5:4
@@ -162,7 +162,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:27:3
    |
 LL |   three_diff(   1,              ""  );
-   |   ^^^^^^^^^^                    -- an argument of type `f32` is missing
+   |   ^^^^^^^^^^                    -- argument #2 of type `f32` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:5:4
@@ -178,7 +178,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/missing_arguments.rs:28:3
    |
 LL |   three_diff(   1,     1.0          );
-   |   ^^^^^^^^^^------------------------- an argument of type `&str` is missing
+   |   ^^^^^^^^^^------------------------- argument #3 of type `&str` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:5:4
@@ -212,8 +212,8 @@ error[E0061]: this function takes 3 arguments but 1 argument was supplied
 LL |   three_diff(          1.0          );
    |   ^^^^^^^^^^-------------------------
    |             |          |
-   |             |          an argument of type `i32` is missing
-   |             an argument of type `&str` is missing
+   |             |          argument #1 of type `i32` is missing
+   |             argument #3 of type `&str` is missing
    |
 note: function defined here
   --> $DIR/missing_arguments.rs:5:4
diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr
index c645dd38179..bec5d4dc16b 100644
--- a/tests/ui/argument-suggestions/mixed_cases.stderr
+++ b/tests/ui/argument-suggestions/mixed_cases.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/mixed_cases.rs:10:3
    |
 LL |   two_args(1, "", X {});
-   |   ^^^^^^^^    --  ---- unexpected argument of type `X`
+   |   ^^^^^^^^    --  ---- unexpected argument #3 of type `X`
    |               |
    |               expected `f32`, found `&str`
    |
@@ -21,10 +21,10 @@ error[E0061]: this function takes 3 arguments but 4 arguments were supplied
   --> $DIR/mixed_cases.rs:11:3
    |
 LL |   three_args(1, "", X {}, "");
-   |   ^^^^^^^^^^    --  ----  -- unexpected argument of type `&'static str`
+   |   ^^^^^^^^^^    --  ----  -- unexpected argument #4 of type `&'static str`
    |                 |   |
-   |                 |   unexpected argument of type `X`
-   |                 an argument of type `f32` is missing
+   |                 |   unexpected argument #3 of type `X`
+   |                 argument #2 of type `f32` is missing
    |
 note: function defined here
   --> $DIR/mixed_cases.rs:6:4
@@ -43,7 +43,7 @@ LL |   three_args(1, X {});
    |   ^^^^^^^^^^---------
    |             |   |
    |             |   expected `f32`, found `X`
-   |             an argument of type `&str` is missing
+   |             argument #3 of type `&str` is missing
    |
 note: function defined here
   --> $DIR/mixed_cases.rs:6:4
@@ -59,9 +59,9 @@ error[E0308]: arguments to this function are incorrect
   --> $DIR/mixed_cases.rs:17:3
    |
 LL |   three_args(1, "", X {});
-   |   ^^^^^^^^^^    --  ---- unexpected argument of type `X`
+   |   ^^^^^^^^^^    --  ---- unexpected argument #3 of type `X`
    |                 |
-   |                 an argument of type `f32` is missing
+   |                 argument #2 of type `f32` is missing
    |
 note: function defined here
   --> $DIR/mixed_cases.rs:6:4
@@ -98,7 +98,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
 LL |   three_args("", 1);
    |   ^^^^^^^^^^ --  -
    |              |   |
-   |              |   an argument of type `f32` is missing
+   |              |   argument #2 of type `f32` is missing
    |              |   expected `&str`, found `{integer}`
    |              expected `i32`, found `&'static str`
    |
diff --git a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr
index dc293945eb6..730f20cfb88 100644
--- a/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr
+++ b/tests/ui/argument-suggestions/suggest-better-removing-issue-126246.stderr
@@ -32,7 +32,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:10:5
    |
 LL |     add_one(2, 2);
-   |     ^^^^^^^    - unexpected argument of type `{integer}`
+   |     ^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:1:4
@@ -49,7 +49,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:11:5
    |
 LL |     add_one(no_such_local, 10);
-   |     ^^^^^^^ ------------- unexpected argument
+   |     ^^^^^^^ ------------- unexpected argument #1
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:1:4
@@ -66,7 +66,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:13:5
    |
 LL |     add_one(10, no_such_local);
-   |     ^^^^^^^     ------------- unexpected argument
+   |     ^^^^^^^     ------------- unexpected argument #2
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:1:4
@@ -83,7 +83,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:15:5
    |
 LL |     add_two(10, no_such_local, 10);
-   |     ^^^^^^^     ------------- unexpected argument
+   |     ^^^^^^^     ------------- unexpected argument #2
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:5:4
@@ -100,7 +100,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:17:5
    |
 LL |     add_two(no_such_local, 10, 10);
-   |     ^^^^^^^ ------------- unexpected argument
+   |     ^^^^^^^ ------------- unexpected argument #1
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:5:4
@@ -117,7 +117,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/suggest-better-removing-issue-126246.rs:19:5
    |
 LL |     add_two(10, 10, no_such_local);
-   |     ^^^^^^^         ------------- unexpected argument
+   |     ^^^^^^^         ------------- unexpected argument #3
    |
 note: function defined here
   --> $DIR/suggest-better-removing-issue-126246.rs:5:4
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/associated-consts/associated-const-type-parameter-arms.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr
deleted file mode 100644
index 1ccf9febd4b..00000000000
--- a/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0158]: associated consts cannot be referenced in patterns
-  --> $DIR/associated-const-type-parameter-arms.rs:20:9
-   |
-LL |         A::X => println!("A::X"),
-   |         ^^^^
-
-error[E0158]: associated consts cannot be referenced in patterns
-  --> $DIR/associated-const-type-parameter-arms.rs:22:9
-   |
-LL |         B::X => println!("B::X"),
-   |         ^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arms.rs b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs
index 3f260d84e4c..b5798adc71c 100644
--- a/tests/ui/associated-consts/associated-const-type-parameter-arms.rs
+++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs
@@ -18,12 +18,18 @@ impl Foo for Def {
 pub fn test<A: Foo, B: Foo>(arg: EFoo) {
     match arg {
         A::X => println!("A::X"),
-        //~^ error: associated consts cannot be referenced in patterns [E0158]
+        //~^ error: constant pattern depends on a generic parameter
         B::X => println!("B::X"),
-        //~^ error: associated consts cannot be referenced in patterns [E0158]
+        //~^ error: constant pattern depends on a generic parameter
         _ => (),
     }
 }
 
+pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+    //~^ ERROR constant pattern depends on a generic parameter
+    let A::X = arg;
+    //~^ ERROR constant pattern depends on a generic parameter
+}
+
 fn main() {
 }
diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr
new file mode 100644
index 00000000000..adc8f399207
--- /dev/null
+++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr
@@ -0,0 +1,27 @@
+error[E0158]: constant pattern depends on a generic parameter
+  --> $DIR/associated-const-type-parameter-pattern.rs:20:9
+   |
+LL |         A::X => println!("A::X"),
+   |         ^^^^
+
+error[E0158]: constant pattern depends on a generic parameter
+  --> $DIR/associated-const-type-parameter-pattern.rs:22:9
+   |
+LL |         B::X => println!("B::X"),
+   |         ^^^^
+
+error[E0158]: constant pattern depends on a generic parameter
+  --> $DIR/associated-const-type-parameter-pattern.rs:30:9
+   |
+LL |     let A::X = arg;
+   |         ^^^^
+
+error[E0158]: constant pattern depends on a generic parameter
+  --> $DIR/associated-const-type-parameter-pattern.rs:28:48
+   |
+LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+   |                                                ^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr
index dc1631220e2..cf96c8cf8eb 100644
--- a/tests/ui/associated-consts/issue-102335-const.stderr
+++ b/tests/ui/associated-consts/issue-102335-const.stderr
@@ -6,8 +6,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102335-const.rs:4:17
@@ -18,8 +19,9 @@ LL |     type A: S<C<X = 0i32> = 34>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<X = 0i32> = 34>;
-   |                ~~~~~~~~~~
+LL -     type A: S<C<X = 0i32> = 34>;
+LL +     type A: S<C = 34>;
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-inherent-types/issue-109768.stderr b/tests/ui/associated-inherent-types/issue-109768.stderr
index e960f4fb5d1..e71551f9e73 100644
--- a/tests/ui/associated-inherent-types/issue-109768.stderr
+++ b/tests/ui/associated-inherent-types/issue-109768.stderr
@@ -34,7 +34,7 @@ error[E0061]: this struct takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-109768.rs:10:56
    |
 LL |     const WRAPPED_ASSOC_3: Wrapper<Self::AssocType3> = Wrapper();
-   |                                                        ^^^^^^^-- an argument is missing
+   |                                                        ^^^^^^^-- argument #1 is missing
    |
 note: tuple struct defined here
   --> $DIR/issue-109768.rs:3:8
diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
index cd585f7f7d8..259b0ca00e1 100644
--- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr
+++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr
@@ -6,8 +6,9 @@ LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
-   |                ~~~~~~~~~~~
+LL -     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+LL +     type A: S<C = ()>; // Just one erroneous equality constraint
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102335-ty.rs:2:17
@@ -18,8 +19,9 @@ LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
-   |                ~~~~~~~~~~~
+LL -     type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
+LL +     type A: S<C = ()>; // Just one erroneous equality constraint
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102335-ty.rs:8:17
@@ -29,8 +31,9 @@ LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equal
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
-   |                 ~~~~~~~~~~
+LL -     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+LL +     type A: S<C<X = i32> = ()>; // More than one erroneous equality constraints
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102335-ty.rs:8:17
@@ -41,8 +44,9 @@ LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equal
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
-   |                 ~~~~~~~~~~
+LL -     type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
+LL +     type A: S<C<X = i32> = ()>; // More than one erroneous equality constraints
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/associated-type-bounds/no-gat-position.stderr b/tests/ui/associated-type-bounds/no-gat-position.stderr
index 39a2f89f9ac..03dc752c533 100644
--- a/tests/ui/associated-type-bounds/no-gat-position.stderr
+++ b/tests/ui/associated-type-bounds/no-gat-position.stderr
@@ -6,8 +6,9 @@ LL |     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
    |
 help: consider removing this associated item constraint
    |
-LL |     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
-   |                                                      ~~~~~~~~~~~
+LL -     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
+LL +     fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
index dde7036231e..e9fd8503296 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr
@@ -13,12 +13,12 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo::<T>());
    |             ^^^^^^^^^^ future returned by `foo` is not `Send`
    |
-   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>> { <T as Foo>::method() }`, which is required by `impl Future<Output = Result<(), ()>>: Send`
+   = help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>> { <T as Foo>::method(..) }`, which is required by `impl Future<Output = Result<(), ()>>: Send`
 note: future is not `Send` as it awaits another future which is not `Send`
   --> $DIR/basic.rs:13:5
    |
 LL |     T::method().await?;
-   |     ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>> { <T as Foo>::method() }`, which is not `Send`
+   |     ^^^^^^^^^^^ await occurs here on type `impl Future<Output = Result<(), ()>> { <T as Foo>::method(..) }`, which is not `Send`
 note: required by a bound in `is_send`
   --> $DIR/basic.rs:17:20
    |
diff --git a/tests/ui/associated-type-bounds/return-type-notation/display.rs b/tests/ui/associated-type-bounds/return-type-notation/display.rs
new file mode 100644
index 00000000000..c5be2ca00ea
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/display.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {}
+fn needs_trait(_: impl Trait) {}
+
+trait Assoc {
+    fn method() -> impl Sized;
+    fn method_with_lt() -> impl Sized;
+    fn method_with_ty<T>() -> impl Sized;
+    fn method_with_ct<const N: usize>() -> impl Sized;
+}
+
+fn foo<T: Assoc>(t: T) {
+    needs_trait(T::method());
+    //~^ ERROR the trait bound
+    needs_trait(T::method_with_lt());
+    //~^ ERROR the trait bound
+    needs_trait(T::method_with_ty());
+    //~^ ERROR the trait bound
+    needs_trait(T::method_with_ct());
+    //~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/display.stderr b/tests/ui/associated-type-bounds/return-type-notation/display.stderr
new file mode 100644
index 00000000000..4915ec1aa83
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/display.stderr
@@ -0,0 +1,78 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/display.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `impl Sized { <T as Assoc>::method(..) }: Trait` is not satisfied
+  --> $DIR/display.rs:15:17
+   |
+LL |     needs_trait(T::method());
+   |     ----------- ^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Sized { <T as Assoc>::method(..) }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `needs_trait`
+  --> $DIR/display.rs:5:24
+   |
+LL | fn needs_trait(_: impl Trait) {}
+   |                        ^^^^^ required by this bound in `needs_trait`
+
+error[E0277]: the trait bound `impl Sized { <T as Assoc>::method_with_lt(..) }: Trait` is not satisfied
+  --> $DIR/display.rs:17:17
+   |
+LL |     needs_trait(T::method_with_lt());
+   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Sized { <T as Assoc>::method_with_lt(..) }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `needs_trait`
+  --> $DIR/display.rs:5:24
+   |
+LL | fn needs_trait(_: impl Trait) {}
+   |                        ^^^^^ required by this bound in `needs_trait`
+
+error[E0277]: the trait bound `impl Sized: Trait` is not satisfied
+  --> $DIR/display.rs:19:17
+   |
+LL |     needs_trait(T::method_with_ty());
+   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Sized`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/display.rs:4:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
+note: required by a bound in `needs_trait`
+  --> $DIR/display.rs:5:24
+   |
+LL | fn needs_trait(_: impl Trait) {}
+   |                        ^^^^^ required by this bound in `needs_trait`
+
+error[E0277]: the trait bound `impl Sized: Trait` is not satisfied
+  --> $DIR/display.rs:21:17
+   |
+LL |     needs_trait(T::method_with_ct());
+   |     ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Sized`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/display.rs:4:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
+note: required by a bound in `needs_trait`
+  --> $DIR/display.rs:5:24
+   |
+LL | fn needs_trait(_: impl Trait) {}
+   |                        ^^^^^ required by this bound in `needs_trait`
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr
index 69b1b533450..e5013a35d45 100644
--- a/tests/ui/associated-types/associated-types-eq-2.stderr
+++ b/tests/ui/associated-types/associated-types-eq-2.stderr
@@ -50,8 +50,9 @@ LL | impl Tr1<A = usize> for usize {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr1<A = usize> for usize {
-   |         ~~~~~~~~~~~
+LL - impl Tr1<A = usize> for usize {
+LL + impl Tr1 for usize {
+   |
 
 error[E0046]: not all trait items implemented, missing: `A`
   --> $DIR/associated-types-eq-2.rs:20:1
@@ -70,8 +71,9 @@ LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
    |
 help: consider removing this associated item binding
    |
-LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
-   |                              ~~~~~~~
+LL - fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
+LL + fn baz<I: Tr1>(_x: &<I as Tr1>::A) {}
+   |
 
 error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
   --> $DIR/associated-types-eq-2.rs:40:6
@@ -128,8 +130,9 @@ LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
-   |             ~~~~~~~~~~
+LL - impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
+LL + impl Tr2<i32, T3 = usize> for Qux {
+   |
 
 error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
   --> $DIR/associated-types-eq-2.rs:54:6
@@ -157,8 +160,9 @@ LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
-   |             ~~~~~~~~~
+LL - impl Tr2<i32, X = Qux, Y = usize> for Bar {
+LL + impl Tr2<i32, Y = usize> for Bar {
+   |
 
 error[E0107]: trait takes 3 generic arguments but 2 generic arguments were supplied
   --> $DIR/associated-types-eq-2.rs:61:6
@@ -228,8 +232,9 @@ LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
-   |          ~~~~~~~
+LL - impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
+LL + impl Tr3<T2 = Qux, T3 = usize> for Qux {
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/associated-types-eq-2.rs:92:10
@@ -239,8 +244,9 @@ LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
-   |          ~~~~~~~~
+LL - impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
+LL + impl Tr3<T2 = Qux, T3 = usize> for Bar {
+   |
 
 error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
   --> $DIR/associated-types-eq-2.rs:98:6
@@ -268,8 +274,9 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
-   |            ~~~~~~~~~
+LL - impl Tr3<42, T2 = 42, T3 = usize> for Bar {
+LL + impl Tr3<42, T3 = usize> for Bar {
+   |
 
 error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
   --> $DIR/associated-types-eq-2.rs:106:6
@@ -295,8 +302,9 @@ LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
    |
 help: consider removing this associated item binding
    |
-LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
-   |          ~~~~~~~
+LL - impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
+LL + impl Tr3<Y = Qux, Z = usize> for Bar {
+   |
 
 error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/associated-types-eq-2.rs:117:13
diff --git a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr
index adde31b4a32..b4012d2a5b9 100644
--- a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr
+++ b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr
@@ -3,11 +3,6 @@ error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
    |
 LL |     let u: <T as Foo<usize>>::Bar = t.get_bar();
    |             ^ the trait `Foo<usize>` is not implemented for `T`
-   |
-help: consider further restricting this bound
-   |
-LL | fn f<T:Foo<isize> + Foo<usize>>(t: &T) {
-   |                   ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs
new file mode 100644
index 00000000000..6083cc7d96d
--- /dev/null
+++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs
@@ -0,0 +1,23 @@
+//@ edition:2021
+// issue: rust-lang/rust#127555
+
+pub trait Foo {
+    fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
+    where
+        F: FnMut();
+}
+
+struct Baz {}
+
+impl Foo for Baz {
+    async fn bar<F>(&mut self, _func: F) -> ()
+    //~^ ERROR `F` cannot be sent between threads safely
+    where
+        F: FnMut() + Send,
+        //~^ ERROR impl has stricter requirements than trait
+    {
+        ()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr
new file mode 100644
index 00000000000..7f3cd2a5900
--- /dev/null
+++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr
@@ -0,0 +1,33 @@
+error[E0277]: `F` cannot be sent between threads safely
+  --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:13:5
+   |
+LL | /     async fn bar<F>(&mut self, _func: F) -> ()
+LL | |
+LL | |     where
+LL | |         F: FnMut() + Send,
+   | |__________________________^ `F` cannot be sent between threads safely
+   |
+note: required by a bound in `<Baz as Foo>::bar`
+  --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22
+   |
+LL |     async fn bar<F>(&mut self, _func: F) -> ()
+   |              --- required by a bound in this associated function
+...
+LL |         F: FnMut() + Send,
+   |                      ^^^^ required by this bound in `<Baz as Foo>::bar`
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22
+   |
+LL | /     fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
+LL | |     where
+LL | |         F: FnMut();
+   | |___________________- definition of `bar` from trait
+...
+LL |           F: FnMut() + Send,
+   |                        ^^^^ impl has extra requirement `F: Send`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0276, E0277.
+For more information about an error, try `rustc --explain E0276`.
diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
index 66819d1fcf7..80dc5fdc747 100644
--- a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
+++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr
@@ -9,10 +9,6 @@ note: required by a bound in `<() as Actor>::on_mount`
    |
 LL |     async fn on_mount(self, _: impl Inbox<&'a ()>) {}
    |                                     ^^^^^^^^^^^^^ required by this bound in `<() as Actor>::on_mount`
-help: consider further restricting this bound
-   |
-LL |     async fn on_mount(self, _: impl Inbox<&'a ()> + Inbox<&'a ()>) {}
-   |                                                   +++++++++++++++
 
 error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
   --> $DIR/unconstrained-impl-region.rs:13:6
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
index 23ede089b5a..acad8bd3791 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
@@ -18,8 +18,8 @@ LL | |         }
 LL | |     });
    | |______^ implementation of `Send` is not general enough
    |
-   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>() }`, for any two lifetimes `'0` and `'1`...
-   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>() }`, for some specific lifetime `'2`
+   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>(..) }`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>(..) }`, for some specific lifetime `'2`
 
 error: implementation of `Send` is not general enough
   --> $DIR/issue-110963-early.rs:14:5
@@ -32,8 +32,8 @@ LL | |         }
 LL | |     });
    | |______^ implementation of `Send` is not general enough
    |
-   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>() }`, for any two lifetimes `'0` and `'1`...
-   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>() }`, for some specific lifetime `'2`
+   = note: `Send` would have to be implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'0>(..) }`, for any two lifetimes `'0` and `'1`...
+   = note: ...but `Send` is actually implemented for the type `impl Future<Output = bool> { <HC as HealthCheck>::check<'2>(..) }`, for some specific lifetime `'2`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors; 1 warning emitted
diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
index b23dbc37a55..e061587f491 100644
--- a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
+++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
@@ -15,8 +15,9 @@ LL | impl Super1<'_, bar(..): Send> for () {}
    |
 help: consider removing this associated item constraint
    |
-LL | impl Super1<'_, bar(..): Send> for () {}
-   |               ~~~~~~~~~~~~~~~
+LL - impl Super1<'_, bar(..): Send> for () {}
+LL + impl Super1<'_> for () {}
+   |
 
 error[E0046]: not all trait items implemented, missing: `bar`
   --> $DIR/rtn-in-impl-signature.rs:10:1
diff --git a/tests/ui/blind/blind-item-block-item-shadow.stderr b/tests/ui/blind/blind-item-block-item-shadow.stderr
index 2e24ef453c2..38e3087ca34 100644
--- a/tests/ui/blind/blind-item-block-item-shadow.stderr
+++ b/tests/ui/blind/blind-item-block-item-shadow.stderr
@@ -10,7 +10,7 @@ LL |         use foo::Bar;
 help: you can use `as` to change the binding name of the import
    |
 LL |         use foo::Bar as OtherBar;
-   |             ~~~~~~~~~~~~~~~~~~~~
+   |                      +++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/blind/blind-item-item-shadow.stderr b/tests/ui/blind/blind-item-item-shadow.stderr
index 84b273c7338..08f5f5b47ed 100644
--- a/tests/ui/blind/blind-item-item-shadow.stderr
+++ b/tests/ui/blind/blind-item-item-shadow.stderr
@@ -11,7 +11,7 @@ LL | use foo::foo;
 help: you can use `as` to change the binding name of the import
    |
 LL | use foo::foo as other_foo;
-   |     ~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr
index 11e2b63bd6c..36e259fa6e8 100644
--- a/tests/ui/borrowck/borrowck-access-permissions.stderr
+++ b/tests/ui/borrowck/borrowck-access-permissions.stderr
@@ -11,7 +11,7 @@ LL |             let _y2 = &mut static_x_mut;
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |             let _y2 = addr_of_mut!(static_x_mut);
-   |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ~~~~~~~~~~~~~            +
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-access-permissions.rs:10:19
diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
index 354d70eb1ad..a727c9414c5 100644
--- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
+++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
@@ -11,7 +11,7 @@ LL |         let sfoo: *mut Foo = &mut SFOO;
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         let sfoo: *mut Foo = addr_of_mut!(SFOO);
-   |                              ~~~~~~~~~~~~~~~~~~
+   |                              ~~~~~~~~~~~~~    +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr
index c1d06ac3e21..769b34831c1 100644
--- a/tests/ui/borrowck/issue-20801.stderr
+++ b/tests/ui/borrowck/issue-20801.stderr
@@ -11,7 +11,7 @@ LL |     unsafe { &mut GLOBAL_MUT_T }
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |     unsafe { addr_of_mut!(GLOBAL_MUT_T) }
-   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |              ~~~~~~~~~~~~~            +
 
 error[E0507]: cannot move out of a mutable reference
   --> $DIR/issue-20801.rs:27:22
diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
index ff5ec1db346..72fd0d8ce16 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
@@ -11,7 +11,7 @@ LL |             c1(&mut Y);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |             c1(addr_of_mut!(Y));
-   |                ~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~ +
 
 warning: creating a mutable reference to mutable static is discouraged
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16
@@ -25,7 +25,7 @@ LL |             c1(&mut Z);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |             c1(addr_of_mut!(Z));
-   |                ~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~ +
 
 warning: creating a mutable reference to mutable static is discouraged
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37
@@ -39,7 +39,7 @@ LL |         borrowck_closures_unique::e(&mut X);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         borrowck_closures_unique::e(addr_of_mut!(X));
-   |                                     ~~~~~~~~~~~~~~~
+   |                                     ~~~~~~~~~~~~~ +
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46
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/borrowck/moved-value-suggest-reborrow-issue-127285.fixed b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed
new file mode 100644
index 00000000000..cec52272fee
--- /dev/null
+++ b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![allow(dead_code)]
+
+struct X(u32);
+
+impl X {
+    fn f(&mut self) {
+        generic(&mut *self);
+        self.0 += 1;
+        //~^ ERROR: use of moved value: `self` [E0382]
+    }
+}
+
+fn generic<T>(_x: T) {}
+
+fn main() {}
diff --git a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs
new file mode 100644
index 00000000000..dd015697fdc
--- /dev/null
+++ b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs
@@ -0,0 +1,17 @@
+//@ run-rustfix
+
+#![allow(dead_code)]
+
+struct X(u32);
+
+impl X {
+    fn f(&mut self) {
+        generic(self);
+        self.0 += 1;
+        //~^ ERROR: use of moved value: `self` [E0382]
+    }
+}
+
+fn generic<T>(_x: T) {}
+
+fn main() {}
diff --git a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr
new file mode 100644
index 00000000000..3da8b6e9dff
--- /dev/null
+++ b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr
@@ -0,0 +1,18 @@
+error[E0382]: use of moved value: `self`
+  --> $DIR/moved-value-suggest-reborrow-issue-127285.rs:10:9
+   |
+LL |     fn f(&mut self) {
+   |          --------- move occurs because `self` has type `&mut X`, which does not implement the `Copy` trait
+LL |         generic(self);
+   |                 ---- value moved here
+LL |         self.0 += 1;
+   |         ^^^^^^^^^^^ value used here after move
+   |
+help: consider creating a fresh reborrow of `self` here
+   |
+LL |         generic(&mut *self);
+   |                 ++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr
index 7a569d1da41..4f32df1eb24 100644
--- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr
+++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr
@@ -8,19 +8,10 @@ LL |     for _ in 0..3 {
 LL |         Other::handle(value);
    |                       ^^^^^ value moved here, in previous iteration of loop
    |
-note: consider changing this parameter type in function `handle` to borrow instead if owning the value isn't necessary
-  --> $DIR/mut-borrow-in-loop-2.rs:8:22
-   |
-LL |     fn handle(value: T) -> Self;
-   |        ------        ^ this parameter takes ownership of the value
-   |        |
-   |        in this function
-help: consider moving the expression out of the loop so it is only moved once
-   |
-LL ~     let mut value = Other::handle(value);
-LL ~     for _ in 0..3 {
-LL ~         value;
+help: consider creating a fresh reborrow of `value` here
    |
+LL |         Other::handle(&mut *value);
+   |                       ++++++
 help: consider creating a fresh reborrow of `value` here
    |
 LL |         Other::handle(&mut *value);
diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr
index 4beea83d8a5..72d60a1439a 100644
--- a/tests/ui/c-variadic/variadic-ffi-1.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-1.stderr
@@ -24,7 +24,7 @@ error[E0060]: this function takes at least 2 arguments but 1 argument was suppli
   --> $DIR/variadic-ffi-1.rs:23:9
    |
 LL |         foo(1);
-   |         ^^^--- an argument of type `u8` is missing
+   |         ^^^--- argument #2 of type `u8` is missing
    |
 note: function defined here
   --> $DIR/variadic-ffi-1.rs:15:8
diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.stderr b/tests/ui/cast/ice-cast-type-with-error-124848.stderr
index 2d86bf76d11..1e2adcc7d9e 100644
--- a/tests/ui/cast/ice-cast-type-with-error-124848.stderr
+++ b/tests/ui/cast/ice-cast-type-with-error-124848.stderr
@@ -39,7 +39,7 @@ error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/ice-cast-type-with-error-124848.rs:12:24
    |
 LL |     let mut unpinned = MyType(Cell::new(None));
-   |                        ^^^^^^----------------- an argument is missing
+   |                        ^^^^^^----------------- argument #2 is missing
    |
 note: tuple struct defined here
   --> $DIR/ice-cast-type-with-error-124848.rs:7:8
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/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/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs
index fa0b0fdc136..e07fa78463c 100644
--- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs
+++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs
@@ -5,9 +5,7 @@
 #![feature(with_negative_coherence)]
 trait Trait {}
 impl<const N: u8> Trait for [(); N] {}
-//~^ ERROR: mismatched types
 impl<const N: i8> Trait for [(); N] {}
-//~^ ERROR: mismatched types
-//~| ERROR: conflicting implementations of trait `Trait`
+//~^ ERROR: conflicting implementations of trait `Trait`
 
 fn main() {}
diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr
index d65450845bc..2087be8e711 100644
--- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr
+++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr
@@ -1,25 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]`
-  --> $DIR/generic_const_type_mismatch.rs:9:1
+  --> $DIR/generic_const_type_mismatch.rs:8:1
    |
 LL | impl<const N: u8> Trait for [(); N] {}
    | ----------------------------------- first implementation here
-LL |
 LL | impl<const N: i8> Trait for [(); N] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]`
 
-error[E0308]: mismatched types
-  --> $DIR/generic_const_type_mismatch.rs:7:34
-   |
-LL | impl<const N: u8> Trait for [(); N] {}
-   |                                  ^ expected `usize`, found `u8`
-
-error[E0308]: mismatched types
-  --> $DIR/generic_const_type_mismatch.rs:9:34
-   |
-LL | impl<const N: i8> Trait for [(); N] {}
-   |                                  ^ expected `usize`, found `i8`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0119, E0308.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs
index d5913879191..cc2ff9b8dea 100644
--- a/tests/ui/const-generics/bad-subst-const-kind.rs
+++ b/tests/ui/const-generics/bad-subst-const-kind.rs
@@ -6,7 +6,7 @@ trait Q {
 }
 
 impl<const N: u64> Q for [u8; N] {
-    //~^ ERROR mismatched types
+    //~^ ERROR: the constant `N` is not of type `usize`
     const ASSOC: usize = 1;
 }
 
diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr
index 6725f6762e4..5c8d9c90363 100644
--- a/tests/ui/const-generics/bad-subst-const-kind.stderr
+++ b/tests/ui/const-generics/bad-subst-const-kind.stderr
@@ -1,3 +1,9 @@
+error: the constant `N` is not of type `usize`
+  --> $DIR/bad-subst-const-kind.rs:8:26
+   |
+LL | impl<const N: u64> Q for [u8; N] {
+   |                          ^^^^^^^ expected `usize`, found `u64`
+
 error: the constant `13` is not of type `u64`
   --> $DIR/bad-subst-const-kind.rs:13:24
    |
@@ -12,12 +18,5 @@ LL | impl<const N: u64> Q for [u8; N] {
    |      |
    |      unsatisfied trait bound introduced here
 
-error[E0308]: mismatched types
-  --> $DIR/bad-subst-const-kind.rs:8:31
-   |
-LL | impl<const N: u64> Q for [u8; N] {
-   |                               ^ expected `usize`, found `u64`
-
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
index 6b0d9e047db..8e5e23b2337 100644
--- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
+++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
@@ -7,7 +7,7 @@ trait Q {
 
 impl<const N: u64> Q for [u8; N] {}
 //~^ ERROR not all trait items implemented
-//~| ERROR mismatched types
+//~| ERROR the constant `N` is not of type `usize`
 
 pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
 //~^ ERROR the constant `13` is not of type `u64`
diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
index bb6d650b7ab..e03580ec007 100644
--- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
@@ -1,3 +1,9 @@
+error: the constant `N` is not of type `usize`
+  --> $DIR/type_mismatch.rs:8:26
+   |
+LL | impl<const N: u64> Q for [u8; N] {}
+   |                          ^^^^^^^ expected `usize`, found `u64`
+
 error[E0046]: not all trait items implemented, missing: `ASSOC`
   --> $DIR/type_mismatch.rs:8:1
    |
@@ -29,12 +35,6 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
    |        |
    |        implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:8:31
-   |
-LL | impl<const N: u64> Q for [u8; N] {}
-   |                               ^ expected `usize`, found `u64`
-
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0046, E0308.
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
index 51cae20df84..8b7ee577569 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
@@ -25,8 +25,8 @@ mod v20 {
     }
 
     impl<const v10: usize> v17<v10, v2> {
-    //~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
-    //~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
+    //~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
+    //~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
         pub const fn v21() -> v18 {
         //~^ ERROR cannot find type `v18` in this scope
             v18 { _p: () }
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
index 39f022fbee9..15d3c472585 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
@@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
 LL + #![feature(adt_const_params)]
    |
 
-error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
+error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
   --> $DIR/unevaluated-const-ice-119731.rs:27:37
    |
 LL |     impl<const v10: usize> v17<v10, v2> {
    |                                     ^^
 
-error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
+error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
   --> $DIR/unevaluated-const-ice-119731.rs:27:37
    |
 LL |     impl<const v10: usize> v17<v10, v2> {
diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr
index c17a7d5d9fa..b5eec3046fd 100644
--- a/tests/ui/const-generics/issues/issue-88119.stderr
+++ b/tests/ui/const-generics/issues/issue-88119.stderr
@@ -1,26 +1,32 @@
-error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
-  --> $DIR/issue-88119.rs:21:5
+error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}`
+  --> $DIR/issue-88119.rs:19:49
    |
-LL |     [(); name_len::<T>()]:,
-   |     ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
+LL | impl<T: ?Sized + ConstName> const ConstName for &T
+   |                                                 ^^ cannot normalize `<&T as ConstName>::{constant#0}`
    |
-note: required by a bound in `<&T as ConstName>`
-  --> $DIR/issue-88119.rs:21:10
+note: required for `&T` to implement `ConstName`
+  --> $DIR/issue-88119.rs:19:35
    |
+LL | impl<T: ?Sized + ConstName> const ConstName for &T
+   |                                   ^^^^^^^^^     ^^
+LL | where
 LL |     [(); name_len::<T>()]:,
-   |          ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
+   |     --------------------- unsatisfied trait bound introduced here
 
-error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
-  --> $DIR/issue-88119.rs:28:5
+error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
+  --> $DIR/issue-88119.rs:26:49
    |
-LL |     [(); name_len::<T>()]:,
-   |     ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
+LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
+   |                                                 ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
    |
-note: required by a bound in `<&mut T as ConstName>`
-  --> $DIR/issue-88119.rs:28:10
+note: required for `&mut T` to implement `ConstName`
+  --> $DIR/issue-88119.rs:26:35
    |
+LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
+   |                                   ^^^^^^^^^     ^^^^^^
+LL | where
 LL |     [(); name_len::<T>()]:,
-   |          ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
+   |     --------------------- unsatisfied trait bound introduced here
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs
index e7ae2ea1d5a..def4611f94b 100644
--- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs
+++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs
@@ -19,6 +19,8 @@ fn bar<const N: usize>() {}
 fn foo<const N: usize>() {
     bar::<{ [1; N] }>();
     //~^ ERROR: generic parameters may not be used in const operations
+    bar::<{ [1; { N + 1 }] }>();
+    //~^ ERROR: generic parameters may not be used in const operations
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr
index 72a6e6977f5..ead6c621d60 100644
--- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr
+++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr
@@ -7,5 +7,14 @@ LL |     bar::<{ [1; N] }>();
    = help: const parameters may only be used as standalone arguments, i.e. `N`
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: aborting due to 1 previous error
+error: generic parameters may not be used in const operations
+  --> $DIR/repeat_expr_hack_gives_right_generics.rs:22:19
+   |
+LL |     bar::<{ [1; { N + 1 }] }>();
+   |                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs
index 90afd232534..59b77c678e8 100644
--- a/tests/ui/const-generics/transmute-fail.rs
+++ b/tests/ui/const-generics/transmute-fail.rs
@@ -10,11 +10,10 @@ fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] {
 }
 
 fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
-  //~^ ERROR mismatched types
-  //~| ERROR mismatched types
+  //~^ ERROR the constant `W` is not of type `usize`
   unsafe {
     std::mem::transmute(v)
-    //~^ ERROR cannot transmute between types
+    //~^ ERROR the constant `W` is not of type `usize`
   }
 }
 
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index b76ec10bd3f..b40fb23c331 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -1,3 +1,9 @@
+error: the constant `W` is not of type `usize`
+  --> $DIR/transmute-fail.rs:12:42
+   |
+LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+   |                                          ^^^^^^^^^^^^^ expected `usize`, found `bool`
+
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:7:5
    |
@@ -7,17 +13,14 @@ LL |     std::mem::transmute(v)
    = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
    = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
 
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:16:5
+error: the constant `W` is not of type `usize`
+  --> $DIR/transmute-fail.rs:15:5
    |
 LL |     std::mem::transmute(v)
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
-   = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
+   |     ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:23:5
+  --> $DIR/transmute-fail.rs:22:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -26,7 +29,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:30:5
+  --> $DIR/transmute-fail.rs:29:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -35,7 +38,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:37:5
+  --> $DIR/transmute-fail.rs:36:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -44,7 +47,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:50:5
+  --> $DIR/transmute-fail.rs:49:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -53,7 +56,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[u32; W * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:57:5
+  --> $DIR/transmute-fail.rs:56:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -62,7 +65,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:66:5
+  --> $DIR/transmute-fail.rs:65:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -71,7 +74,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:75:5
+  --> $DIR/transmute-fail.rs:74:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -80,7 +83,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:82:5
+  --> $DIR/transmute-fail.rs:81:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -89,7 +92,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:89:5
+  --> $DIR/transmute-fail.rs:88:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -98,7 +101,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[u16; L]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:96:5
+  --> $DIR/transmute-fail.rs:95:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -107,7 +110,7 @@ LL |     std::mem::transmute(v)
    = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:105:5
+  --> $DIR/transmute-fail.rs:104:5
    |
 LL |     std::mem::transmute(v)
    |     ^^^^^^^^^^^^^^^^^^^
@@ -115,19 +118,6 @@ LL |     std::mem::transmute(v)
    = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
    = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
 
-error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:12:53
-   |
-LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
-   |                                                     ^ expected `usize`, found `bool`
-
-error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:12:67
-   |
-LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
-   |                                                                   ^ expected `usize`, found `bool`
-
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
 
-Some errors have detailed explanations: E0308, E0512.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs
index daa13277be0..8187c785cd1 100644
--- a/tests/ui/const-generics/type_mismatch.rs
+++ b/tests/ui/const-generics/type_mismatch.rs
@@ -1,10 +1,10 @@
 fn foo<const N: usize>() -> [u8; N] {
-    bar::<N>() //~ ERROR mismatched types
+    bar::<N>()
     //~^ ERROR the constant `N` is not of type `u8`
 }
 
 fn bar<const N: u8>() -> [u8; N] {}
-//~^ ERROR mismatched types
+//~^ ERROR the constant `N` is not of type `usize`
 //~| ERROR mismatched types
 
 fn main() {}
diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr
index 026999827c0..d1bb5c1242f 100644
--- a/tests/ui/const-generics/type_mismatch.stderr
+++ b/tests/ui/const-generics/type_mismatch.stderr
@@ -1,3 +1,9 @@
+error: the constant `N` is not of type `usize`
+  --> $DIR/type_mismatch.rs:6:26
+   |
+LL | fn bar<const N: u8>() -> [u8; N] {}
+   |                          ^^^^^^^ expected `usize`, found `u8`
+
 error: the constant `N` is not of type `u8`
   --> $DIR/type_mismatch.rs:2:11
    |
@@ -18,18 +24,6 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:2:11
-   |
-LL |     bar::<N>()
-   |           ^ expected `u8`, found `usize`
-
-error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:6:31
-   |
-LL | fn bar<const N: u8>() -> [u8; N] {}
-   |                               ^ expected `usize`, found `u8`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
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_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
index 2e7061e7c4b..ab8eec876bc 100644
--- a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
+++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
@@ -23,9 +23,20 @@ const BAR_BAZ: Foo = if 42 == 42 {
     Foo::Qux(CustomEq) // dead arm
 };
 
+const EMPTY: &[CustomEq] = &[];
+
 fn main() {
+    // BAR_BAZ itself is fine but the enum has other variants
+    // that are non-structural. Still, this should be accepted.
     match Foo::Qux(CustomEq) {
         BAR_BAZ => panic!(),
         _ => {}
     }
+
+    // Similarly, an empty slice of a type that is non-structural
+    // is accepted.
+    match &[CustomEq] as &[CustomEq] {
+        EMPTY => panic!(),
+        _ => {},
+    }
 }
diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
index 86d971044fe..645e1418912 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
+++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
@@ -26,7 +26,7 @@ fn main() {
 
     match None {
         NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR must implement `PartialEq`
         _ => panic!("whoops"),
     }
 }
diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
index 88b82d5004b..ed531a1fead 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
+++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
@@ -1,11 +1,8 @@
-error: to use a constant of type `NoPartialEq` in a pattern, `NoPartialEq` must be annotated with `#[derive(PartialEq)]`
+error: to use a constant of type `Option<NoPartialEq>` in a pattern, the type must implement `PartialEq`
   --> $DIR/reject_non_partial_eq.rs:28:9
    |
 LL |         NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
    |         ^^^^^^^^^^^^^^^^^^
-   |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr
index 5ae8fd353dd..87b94a7be67 100644
--- a/tests/ui/consts/const_let_assign2.stderr
+++ b/tests/ui/consts/const_let_assign2.stderr
@@ -11,7 +11,7 @@ LL |     let ptr = unsafe { &mut BB };
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |     let ptr = unsafe { addr_of_mut!(BB) };
-   |                        ~~~~~~~~~~~~~~~~
+   |                        ~~~~~~~~~~~~~  +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs
index 0654fd82fbc..4fe4b0d33c8 100644
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs
+++ b/tests/ui/consts/invalid-inline-const-in-match-arm.rs
@@ -4,5 +4,6 @@ fn main() {
     match () {
         const { (|| {})() } => {}
         //~^ ERROR cannot call non-const closure in constants
+        //~| ERROR could not evaluate constant pattern
     }
 }
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
index 7579f7f9692..0e41053a29d 100644
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
+++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
@@ -11,6 +11,12 @@ help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
 LL + #![feature(const_trait_impl)]
    |
 
-error: aborting due to 1 previous error
+error: could not evaluate constant pattern
+  --> $DIR/invalid-inline-const-in-match-arm.rs:5:9
+   |
+LL |         const { (|| {})() } => {}
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr
index 8a7a0981f41..52d3e003f0a 100644
--- a/tests/ui/consts/issue-36163.stderr
+++ b/tests/ui/consts/issue-36163.stderr
@@ -1,10 +1,10 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
+error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
    |         ^
    |
-note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
+note: ...which requires const-evaluating + checking `Foo::{constant#0}`...
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
@@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`...
    |
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^^^^^^^^^^
-   = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
+   = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
   --> $DIR/issue-36163.rs:3:1
    |
diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr
index 97a5fbc5747..8a44eb9854f 100644
--- a/tests/ui/consts/issue-73976-polymorphic.stderr
+++ b/tests/ui/consts/issue-73976-polymorphic.stderr
@@ -1,10 +1,10 @@
-error: constant pattern depends on a generic parameter
+error[E0158]: constant pattern depends on a generic parameter
   --> $DIR/issue-73976-polymorphic.rs:20:37
    |
 LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
    |                                     ^^^^^^^^^^^^^^^^^^^^^
 
-error: constant pattern depends on a generic parameter
+error[E0158]: constant pattern depends on a generic parameter
   --> $DIR/issue-73976-polymorphic.rs:31:42
    |
 LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
@@ -12,3 +12,4 @@ LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr
index 18bdde45e2c..de81512ec6d 100644
--- a/tests/ui/consts/issue-79137-toogeneric.stderr
+++ b/tests/ui/consts/issue-79137-toogeneric.stderr
@@ -1,4 +1,4 @@
-error: constant pattern depends on a generic parameter
+error[E0158]: constant pattern depends on a generic parameter
   --> $DIR/issue-79137-toogeneric.rs:12:43
    |
 LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
@@ -6,3 +6,4 @@ LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/coroutine/issue-102645.stderr b/tests/ui/coroutine/issue-102645.stderr
index ab5e4a8459f..1ef37d3f7d1 100644
--- a/tests/ui/coroutine/issue-102645.stderr
+++ b/tests/ui/coroutine/issue-102645.stderr
@@ -2,7 +2,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-102645.rs:15:22
    |
 LL |     Pin::new(&mut b).resume();
-   |                      ^^^^^^-- an argument of type `()` is missing
+   |                      ^^^^^^-- argument #1 of type `()` is missing
    |
 note: method defined here
   --> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL
diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
index de1194e74b4..9126e602391 100644
--- a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
+++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
@@ -11,7 +11,7 @@ LL |             (mem::size_of_val(&trails) * 8) as u32
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
-   |                               ~~~~~~~~~~~~~~~~
+   |                               ~~~~~~~~~      +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr
index bdf46abea8a..6da87416802 100644
--- a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr
+++ b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr
@@ -11,7 +11,7 @@ LL |             (mem::size_of_val(&trails) * 8) as u32
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
-   |                               ~~~~~~~~~~~~~~~~
+   |                               ~~~~~~~~~      +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/duplicate/duplicate-check-macro-exports.stderr b/tests/ui/duplicate/duplicate-check-macro-exports.stderr
index eff19c09062..470a516ecbc 100644
--- a/tests/ui/duplicate/duplicate-check-macro-exports.stderr
+++ b/tests/ui/duplicate/duplicate-check-macro-exports.stderr
@@ -11,7 +11,7 @@ LL | macro_rules! panic { () => {} }
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use std::panic as other_panic;
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++
 
 error: aborting due to 1 previous error
 
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/E0057.stderr b/tests/ui/error-codes/E0057.stderr
index efd2af6d609..ef6e2908b93 100644
--- a/tests/ui/error-codes/E0057.stderr
+++ b/tests/ui/error-codes/E0057.stderr
@@ -2,7 +2,7 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0057.rs:3:13
    |
 LL |     let a = f();
-   |             ^-- an argument is missing
+   |             ^-- argument #1 is missing
    |
 note: closure defined here
   --> $DIR/E0057.rs:2:13
@@ -18,7 +18,7 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^    - unexpected argument of type `{integer}`
+   |             ^    - unexpected argument #2 of type `{integer}`
    |
 note: closure defined here
   --> $DIR/E0057.rs:2:13
diff --git a/tests/ui/error-codes/E0060.stderr b/tests/ui/error-codes/E0060.stderr
index 88c1f1bbb2a..8387b15b970 100644
--- a/tests/ui/error-codes/E0060.stderr
+++ b/tests/ui/error-codes/E0060.stderr
@@ -2,7 +2,7 @@ error[E0060]: this function takes at least 1 argument but 0 arguments were suppl
   --> $DIR/E0060.rs:6:14
    |
 LL |     unsafe { printf(); }
-   |              ^^^^^^-- an argument of type `*const u8` is missing
+   |              ^^^^^^-- argument #1 of type `*const u8` is missing
    |
 note: function defined here
   --> $DIR/E0060.rs:2:8
diff --git a/tests/ui/error-codes/E0061.stderr b/tests/ui/error-codes/E0061.stderr
index fa4ccbe6677..7b180c07120 100644
--- a/tests/ui/error-codes/E0061.stderr
+++ b/tests/ui/error-codes/E0061.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/E0061.rs:6:5
    |
 LL |     f(0);
-   |     ^--- an argument of type `&str` is missing
+   |     ^--- argument #2 of type `&str` is missing
    |
 note: function defined here
   --> $DIR/E0061.rs:1:4
@@ -18,7 +18,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0061.rs:9:5
    |
 LL |     f2();
-   |     ^^-- an argument of type `u16` is missing
+   |     ^^-- argument #1 of type `u16` is missing
    |
 note: function defined here
   --> $DIR/E0061.rs:3:4
diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr
index 7d9cedc3bdc..038f44e8b14 100644
--- a/tests/ui/error-codes/E0229.stderr
+++ b/tests/ui/error-codes/E0229.stderr
@@ -6,8 +6,9 @@ LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
    |
 help: consider removing this associated item binding
    |
-LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
-   |                        ~~~~~~~~~
+LL - fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
+LL + fn baz<I>(x: &<I as Foo>::A) {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -18,8 +19,9 @@ LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
-   |                        ~~~~~~~~~
+LL - fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
+LL + fn baz<I>(x: &<I as Foo>::A) {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/E0229.rs:13:25
@@ -30,8 +32,9 @@ LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
-   |                        ~~~~~~~~~
+LL - fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
+LL + fn baz<I>(x: &<I as Foo>::A) {}
+   |
 
 error[E0277]: the trait bound `I: Foo` is not satisfied
   --> $DIR/E0229.rs:13:15
diff --git a/tests/ui/error-codes/E0252.stderr b/tests/ui/error-codes/E0252.stderr
index efbb9ec96de..16574964eb3 100644
--- a/tests/ui/error-codes/E0252.stderr
+++ b/tests/ui/error-codes/E0252.stderr
@@ -10,7 +10,7 @@ LL | use bar::baz;
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::baz as other_baz;
-   |     ~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0254.stderr b/tests/ui/error-codes/E0254.stderr
index d89497b2804..592b8766d6b 100644
--- a/tests/ui/error-codes/E0254.stderr
+++ b/tests/ui/error-codes/E0254.stderr
@@ -11,7 +11,7 @@ LL | use foo::alloc;
 help: you can use `as` to change the binding name of the import
    |
 LL | use foo::alloc as other_alloc;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0255.stderr b/tests/ui/error-codes/E0255.stderr
index e5f908217e1..b67a334f02c 100644
--- a/tests/ui/error-codes/E0255.stderr
+++ b/tests/ui/error-codes/E0255.stderr
@@ -11,7 +11,7 @@ LL | fn foo() {}
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::foo as other_foo;
-   |     ~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++
 
 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/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/extern/issue-18819.stderr b/tests/ui/extern/issue-18819.stderr
index b2cf0bad1df..6de0ebfe9ae 100644
--- a/tests/ui/extern/issue-18819.stderr
+++ b/tests/ui/extern/issue-18819.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-18819.rs:16:5
    |
 LL |     print_x(X);
-   |     ^^^^^^^--- an argument of type `&str` is missing
+   |     ^^^^^^^--- argument #2 of type `&str` is missing
    |
 note: expected `&dyn Foo<Item = bool>`, found `X`
   --> $DIR/issue-18819.rs:16:13
diff --git a/tests/ui/fn/issue-3044.stderr b/tests/ui/fn/issue-3044.stderr
index 06254775b74..8351818dc89 100644
--- a/tests/ui/fn/issue-3044.stderr
+++ b/tests/ui/fn/issue-3044.stderr
@@ -5,7 +5,7 @@ LL |       needlesArr.iter().fold(|x, y| {
    |  _______________________^^^^-
 LL | |
 LL | |     });
-   | |______- an argument is missing
+   | |______- argument #2 is missing
    |
 note: method defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr
index b4772486e6e..bcef76290fc 100644
--- a/tests/ui/generic-associated-types/issue-102335-gat.stderr
+++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr
@@ -6,8 +6,9 @@ LL |     type A: S<C<(), i32 = ()> = ()>;
    |
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<(), i32 = ()> = ()>;
-   |                   ~~~~~~~~~~
+LL -     type A: S<C<(), i32 = ()> = ()>;
+LL +     type A: S<C<()> = ()>;
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-102335-gat.rs:2:21
@@ -18,8 +19,9 @@ LL |     type A: S<C<(), i32 = ()> = ()>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type A: S<C<(), i32 = ()> = ()>;
-   |                   ~~~~~~~~~~
+LL -     type A: S<C<(), i32 = ()> = ()>;
+LL +     type A: S<C<()> = ()>;
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-91139.migrate.stderr b/tests/ui/generic-associated-types/issue-91139.migrate.stderr
index 23b7bf45afb..e3b658558e3 100644
--- a/tests/ui/generic-associated-types/issue-91139.migrate.stderr
+++ b/tests/ui/generic-associated-types/issue-91139.migrate.stderr
@@ -1,7 +1,6 @@
 error: expected identifier, found `<<`
   --> $DIR/issue-91139.rs:1:1
    |
-LL | <<<<<<< HEAD
    | ^^ expected identifier
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr
index dfc6761e17e..c60c4c72a21 100644
--- a/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr
+++ b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr
@@ -14,8 +14,9 @@ LL | impl Foo<T: Default> for String {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<T: Default> Foo<T> for String {}
-   |     ++++++++++++     ~
+LL - impl Foo<T: Default> for String {}
+LL + impl<T: Default> Foo<T> for String {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:7:10
@@ -25,8 +26,9 @@ LL | impl Foo<T: 'a + Default> for u8 {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<'a, T: 'a + Default> Foo<T> for u8 {}
-   |     +++++++++++++++++++++     ~
+LL - impl Foo<T: 'a + Default> for u8 {}
+LL + impl<'a, T: 'a + Default> Foo<T> for u8 {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:13:13
@@ -36,8 +38,9 @@ LL | impl<T> Foo<T: Default> for u16 {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<T, T: Default> Foo<T> for u16 {}
-   |       ++++++++++++      ~
+LL - impl<T> Foo<T: Default> for u16 {}
+LL + impl<T, T: Default> Foo<T> for u16 {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:17:14
@@ -47,8 +50,9 @@ LL | impl<'a> Foo<T: 'a + Default> for u32 {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<'a, 'a, T: 'a + Default> Foo<T> for u32 {}
-   |        +++++++++++++++++++++      ~
+LL - impl<'a> Foo<T: 'a + Default> for u32 {}
+LL + impl<'a, 'a, T: 'a + Default> Foo<T> for u32 {}
+   |
 
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:23:10
@@ -58,8 +62,9 @@ LL | impl Bar<T: Default, K: Default> for String {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<T: Default> Bar<T, K: Default> for String {}
-   |     ++++++++++++     ~
+LL - impl Bar<T: Default, K: Default> for String {}
+LL + impl<T: Default> Bar<T, K: Default> for String {}
+   |
 
 error[E0107]: trait takes 2 generic arguments but 1 generic argument was supplied
   --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:27:9
@@ -87,8 +92,9 @@ LL | impl<T> Bar<T, K: Default> for u8 {}
    |
 help: declare the type parameter right after the `impl` keyword
    |
-LL | impl<T, K: Default> Bar<T, K> for u8 {}
-   |       ++++++++++++         ~
+LL - impl<T> Bar<T, K: Default> for u8 {}
+LL + impl<T, K: Default> Bar<T, K> for u8 {}
+   |
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr
index 8771de85c19..3697bd9cf02 100644
--- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr
@@ -9,10 +9,6 @@ note: required by a bound in `impl_hr`
    |
 LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {}
    |                   ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr`
-help: consider further restricting this bound
-   |
-LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static> + for<'a> Trait<'a, '_>>() {
-   |                                                              +++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr
index 90df487c07e..6e0ec5620da 100644
--- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr
@@ -9,10 +9,6 @@ note: required by a bound in `trait_bound`
    |
 LL | fn trait_bound<T: for<'a> Trait<'a>>() {}
    |                   ^^^^^^^^^^^^^^^^^ required by this bound in `trait_bound`
-help: consider further restricting this bound
-   |
-LL | fn function1<T: Trait<'static> + for<'a> Trait<'a>>() {
-   |                                +++++++++++++++++++
 
 error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied
   --> $DIR/candidate-from-env-universe-err-project.rs:38:24
@@ -25,10 +21,6 @@ note: required by a bound in `projection_bound`
    |
 LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound`
-help: consider further restricting this bound
-   |
-LL | fn function2<T: Trait<'static, Assoc = usize> + for<'a> Trait<'a>>() {
-   |                                               +++++++++++++++++++
 
 error[E0271]: type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
   --> $DIR/candidate-from-env-universe-err-project.rs:38:24
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
index af76377de85..dc1a4c9b983 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
@@ -11,10 +11,6 @@ note: required by a bound in `want_foo_for_any_tcx`
    |
 LL | fn want_foo_for_any_tcx<F: for<'tcx> Foo<'tcx>>(f: &F) {
    |                            ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx`
-help: consider further restricting this bound
-   |
-LL | fn want_foo_for_some_tcx<'x, F: Foo<'x> + for<'tcx> Foo<'tcx>>(f: &'x F) {
-   |                                         +++++++++++++++++++++
 
 error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:28:26
@@ -29,10 +25,6 @@ note: required by a bound in `want_bar_for_any_ccx`
    |
 LL | fn want_bar_for_any_ccx<B: for<'ccx> Bar<'ccx>>(b: &B) {
    |                            ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
-help: consider further restricting this bound
-   |
-LL | fn want_bar_for_some_ccx<'x, B: Bar<'x> + for<'ccx> Bar<'ccx>>(b: &B) {
-   |                                         +++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr
index 99d088799fb..34d7db9b3cf 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-58451.rs:12:9
    |
 LL |     f(&[f()]);
-   |         ^-- an argument is missing
+   |         ^-- argument #1 is missing
    |
 note: function defined here
   --> $DIR/issue-58451.rs:5:4
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/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
index fbf82a24b50..ae449099987 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -22,10 +22,6 @@ note: required by a bound in `<Bar as Foo<char>>::foo`
    |
 LL |     fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
    |                ^^^^^^^ required by this bound in `<Bar as Foo<char>>::foo`
-help: consider further restricting this bound
-   |
-LL |     fn foo<F2: Foo<u8> + Foo<u8>>(self) -> impl Foo<u8> {
-   |                        +++++++++
 
 error[E0276]: impl has stricter requirements than trait
   --> $DIR/return-dont-satisfy-bounds.rs:8:16
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/precise-capturing/hidden-type-suggestion.rs b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
index e0b115b0ce4..b50780643f1 100644
--- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
+++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
@@ -27,4 +27,16 @@ fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'
 //~^ ERROR hidden type for
 }
 
+fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
+//~^ HELP add a `use<...>` bound
+    y
+//~^ ERROR hidden type for
+}
+
+fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
+//~^ HELP add a `use<...>` bound
+    y
+//~^ ERROR hidden type for
+}
+
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr
index 391f16d012e..1007a835894 100644
--- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr
+++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr
@@ -62,6 +62,48 @@ help: add a `use<...>` bound to explicitly capture `'a`
 LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> + use<'captured, 'a, Captured> {
    |                                                                                           ++++++++++++++++++++++++++++++
 
-error: aborting due to 4 previous errors
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/hidden-type-suggestion.rs:32:5
+   |
+LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
+   |                                    ---     ---------- opaque type defined here
+   |                                    |
+   |                                    hidden type `&()` captures the anonymous lifetime defined here
+LL |
+LL |     y
+   |     ^
+   |
+note: you could use a `use<...>` bound to explicitly capture `'_`, but argument-position `impl Trait`s are not nameable
+  --> $DIR/hidden-type-suggestion.rs:30:21
+   |
+LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
+   |                     ^^^^^^^^^^
+help: add a `use<...>` bound to explicitly capture `'_` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
+   |
+LL | fn no_params_yet<T: Sized>(_: T, y: &()) -> impl Sized + use<'_, T> {
+   |                 ++++++++++    ~                        ++++++++++++
+
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/hidden-type-suggestion.rs:38:5
+   |
+LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
+   |                   --                                  ---------- opaque type defined here
+   |                   |
+   |                   hidden type `&'a ()` captures the lifetime `'a` as defined here
+LL |
+LL |     y
+   |     ^
+   |
+note: you could use a `use<...>` bound to explicitly capture `'a`, but argument-position `impl Trait`s are not nameable
+  --> $DIR/hidden-type-suggestion.rs:36:29
+   |
+LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
+   |                             ^^^^^^^^^^
+help: add a `use<...>` bound to explicitly capture `'a` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate
+   |
+LL | fn yes_params_yet<'a, T, U: Sized>(_: U, y: &'a ()) -> impl Sized + use<'a, T, U> {
+   |                        ++++++++++     ~                           +++++++++++++++
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/imports/double-import.stderr b/tests/ui/imports/double-import.stderr
index 73bb73e3490..15b8620909f 100644
--- a/tests/ui/imports/double-import.stderr
+++ b/tests/ui/imports/double-import.stderr
@@ -10,7 +10,7 @@ LL | use sub2::foo;
 help: you can use `as` to change the binding name of the import
    |
 LL | use sub2::foo as other_foo;
-   |     ~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-19498.stderr b/tests/ui/imports/issue-19498.stderr
index 9d26022098f..69bdb67d389 100644
--- a/tests/ui/imports/issue-19498.stderr
+++ b/tests/ui/imports/issue-19498.stderr
@@ -11,7 +11,7 @@ LL | mod A {}
 help: you can use `as` to change the binding name of the import
    |
 LL | use self::A as OtherA;
-   |     ~~~~~~~~~~~~~~~~~
+   |             +++++++++
 
 error[E0255]: the name `B` is defined multiple times
   --> $DIR/issue-19498.rs:5:1
@@ -26,7 +26,7 @@ LL | pub mod B {}
 help: you can use `as` to change the binding name of the import
    |
 LL | use self::B as OtherB;
-   |     ~~~~~~~~~~~~~~~~~
+   |             +++++++++
 
 error[E0255]: the name `D` is defined multiple times
   --> $DIR/issue-19498.rs:9:5
@@ -40,7 +40,7 @@ LL |     mod D {}
 help: you can use `as` to change the binding name of the import
    |
 LL |     use C::D as OtherD;
-   |         ~~~~~~~~~~~~~~
+   |              +++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/imports/issue-24081.stderr b/tests/ui/imports/issue-24081.stderr
index e5ed6b10a54..6ceba6c7013 100644
--- a/tests/ui/imports/issue-24081.stderr
+++ b/tests/ui/imports/issue-24081.stderr
@@ -11,7 +11,7 @@ LL | type Add = bool;
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::ops::Add as OtherAdd;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +++++++++++
 
 error[E0255]: the name `Sub` is defined multiple times
   --> $DIR/issue-24081.rs:9:1
@@ -26,7 +26,7 @@ LL | struct Sub { x: f32 }
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::ops::Sub as OtherSub;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +++++++++++
 
 error[E0255]: the name `Mul` is defined multiple times
   --> $DIR/issue-24081.rs:11:1
@@ -41,7 +41,7 @@ LL | enum Mul { A, B }
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::ops::Mul as OtherMul;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +++++++++++
 
 error[E0255]: the name `Div` is defined multiple times
   --> $DIR/issue-24081.rs:13:1
@@ -56,7 +56,7 @@ LL | mod Div { }
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::ops::Div as OtherDiv;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +++++++++++
 
 error[E0255]: the name `Rem` is defined multiple times
   --> $DIR/issue-24081.rs:15:1
@@ -71,7 +71,7 @@ LL | trait Rem {  }
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::ops::Rem as OtherRem;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +++++++++++
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/imports/issue-25396.stderr b/tests/ui/imports/issue-25396.stderr
index 518d2be7841..6f9b080f3c5 100644
--- a/tests/ui/imports/issue-25396.stderr
+++ b/tests/ui/imports/issue-25396.stderr
@@ -10,7 +10,7 @@ LL | use bar::baz;
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::baz as other_baz;
-   |     ~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++
 
 error[E0252]: the name `Quux` is defined multiple times
   --> $DIR/issue-25396.rs:7:5
@@ -24,7 +24,7 @@ LL | use bar::Quux;
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::Quux as OtherQuux;
-   |     ~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++
 
 error[E0252]: the name `blah` is defined multiple times
   --> $DIR/issue-25396.rs:10:5
@@ -38,7 +38,7 @@ LL | use bar::blah;
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::blah as other_blah;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~
+   |               +++++++++++++
 
 error[E0252]: the name `WOMP` is defined multiple times
   --> $DIR/issue-25396.rs:13:5
@@ -52,7 +52,7 @@ LL | use bar::WOMP;
 help: you can use `as` to change the binding name of the import
    |
 LL | use bar::WOMP as OtherWOMP;
-   |     ~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/imports/issue-32354-suggest-import-rename.stderr b/tests/ui/imports/issue-32354-suggest-import-rename.stderr
index de9bdc4f2cc..753fa434ffb 100644
--- a/tests/ui/imports/issue-32354-suggest-import-rename.stderr
+++ b/tests/ui/imports/issue-32354-suggest-import-rename.stderr
@@ -10,7 +10,7 @@ LL | use extension2::ConstructorExtension;
 help: you can use `as` to change the binding name of the import
    |
 LL | use extension2::ConstructorExtension as OtherConstructorExtension;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                      ++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-45829/import-self.stderr b/tests/ui/imports/issue-45829/import-self.stderr
index 0c9424f3083..3c9d4fe6ba6 100644
--- a/tests/ui/imports/issue-45829/import-self.stderr
+++ b/tests/ui/imports/issue-45829/import-self.stderr
@@ -48,7 +48,7 @@ LL | use foo::self;
 help: you can use `as` to change the binding name of the import
    |
 LL | use foo as other_foo;
-   |     ~~~~~~~~~~~~~~~~
+   |         ~~~~~~~~~~~~
 
 error[E0252]: the name `A` is defined multiple times
   --> $DIR/import-self.rs:16:11
diff --git a/tests/ui/imports/issue-45829/issue-45829.stderr b/tests/ui/imports/issue-45829/issue-45829.stderr
index 627a09a07b8..c6835c3bd7a 100644
--- a/tests/ui/imports/issue-45829/issue-45829.stderr
+++ b/tests/ui/imports/issue-45829/issue-45829.stderr
@@ -10,7 +10,7 @@ LL | use foo::{A, B as A};
 help: you can use `as` to change the binding name of the import
    |
 LL | use foo::{A, B as OtherA};
-   |              ~~~~~~~~~~~
+   |                ~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr
index 9b0a2534a1d..fd4fb9db0b6 100644
--- a/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr
+++ b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr
@@ -10,7 +10,7 @@ LL | use std as issue_45829_b;
 help: you can use `as` to change the binding name of the import
    |
 LL | use std as other_issue_45829_b;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         ~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr
index 5751f41ae9d..178303bbc1d 100644
--- a/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr
+++ b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr
@@ -10,7 +10,7 @@ LL | use foo::{A, bar::B    as    A};
 help: you can use `as` to change the binding name of the import
    |
 LL | use foo::{A, bar::B as OtherA};
-   |              ~~~~~~~~~~~~~~~~
+   |                     ~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-45829/rename-with-path.stderr b/tests/ui/imports/issue-45829/rename-with-path.stderr
index 69e084db6ff..a83fdb37324 100644
--- a/tests/ui/imports/issue-45829/rename-with-path.stderr
+++ b/tests/ui/imports/issue-45829/rename-with-path.stderr
@@ -10,7 +10,7 @@ LL | use std::{collections::HashMap as A, sync::Arc as A};
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::{collections::HashMap as A, sync::Arc as OtherA};
-   |                                      ~~~~~~~~~~~~~~~~~~~
+   |                                                ~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-45829/rename.stderr b/tests/ui/imports/issue-45829/rename.stderr
index f1ee5112dc1..4977909487c 100644
--- a/tests/ui/imports/issue-45829/rename.stderr
+++ b/tests/ui/imports/issue-45829/rename.stderr
@@ -10,7 +10,7 @@ LL | use std as core;
 help: you can use `as` to change the binding name of the import
    |
 LL | use std as other_core;
-   |     ~~~~~~~~~~~~~~~~~
+   |         ~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/issue-52891.stderr b/tests/ui/imports/issue-52891.stderr
index 7bb1301edf2..730962d702a 100644
--- a/tests/ui/imports/issue-52891.stderr
+++ b/tests/ui/imports/issue-52891.stderr
@@ -98,7 +98,7 @@ LL | use issue_52891::b::inner;
 help: you can use `as` to change the binding name of the import
    |
 LL | use issue_52891::b::inner as other_inner;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                           ++++++++++++++
 
 error[E0254]: the name `issue_52891` is defined multiple times
   --> $DIR/issue-52891.rs:31:19
diff --git a/tests/ui/imports/issue-8640.stderr b/tests/ui/imports/issue-8640.stderr
index ea350e97e64..d22fddb1a69 100644
--- a/tests/ui/imports/issue-8640.stderr
+++ b/tests/ui/imports/issue-8640.stderr
@@ -10,7 +10,7 @@ LL |     mod bar {}
 help: you can use `as` to change the binding name of the import
    |
 LL |     use baz::bar as other_bar;
-   |         ~~~~~~~~~~~~~~~~~~~~~
+   |                  ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr
index 15c3a876afc..26f72b34eca 100644
--- a/tests/ui/inline-const/const-match-pat-generic.stderr
+++ b/tests/ui/inline-const/const-match-pat-generic.stderr
@@ -1,10 +1,10 @@
-error: constant pattern depends on a generic parameter
+error[E0158]: constant pattern depends on a generic parameter
   --> $DIR/const-match-pat-generic.rs:7:9
    |
 LL |         const { V } => {},
    |         ^^^^^^^^^^^
 
-error: constant pattern depends on a generic parameter
+error[E0158]: constant pattern depends on a generic parameter
   --> $DIR/const-match-pat-generic.rs:19:9
    |
 LL |         const { f(V) } => {},
@@ -12,3 +12,4 @@ LL |         const { f(V) } => {},
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0158`.
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-4935.stderr b/tests/ui/issues/issue-4935.stderr
index f18cf66f14d..7ee895d91c7 100644
--- a/tests/ui/issues/issue-4935.stderr
+++ b/tests/ui/issues/issue-4935.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
 LL | fn main() { foo(5, 6) }
-   |             ^^^    - unexpected argument of type `{integer}`
+   |             ^^^    - unexpected argument #2 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-4935.rs:3:4
diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr
index 7cc67ab72c3..6cc5cd95e2f 100644
--- a/tests/ui/issues/issue-54410.stderr
+++ b/tests/ui/issues/issue-54410.stderr
@@ -19,7 +19,7 @@ LL |     println!("{:p}", unsafe { &symbol });
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     println!("{:p}", unsafe { addr_of!(symbol) });
-   |                               ~~~~~~~~~~~~~~~~
+   |                               ~~~~~~~~~      +
 
 error: aborting due to 1 previous error; 1 warning emitted
 
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 944fe8aa8e5..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,23 +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,)>;
-   |            ^ 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,)>;
-   |            ^ 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
@@ -32,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/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr
index 403a8c67ccb..dc18e0f1f7a 100644
--- a/tests/ui/lifetimes/issue-26638.stderr
+++ b/tests/ui/lifetimes/issue-26638.stderr
@@ -50,7 +50,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-26638.rs:4:47
    |
 LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-   |                                               ^^^^-- an argument of type `&u8` is missing
+   |                                               ^^^^-- argument #1 of type `&u8` is missing
    |
 help: provide the argument
    |
diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
index f8d919fd68b..4ea14cdf042 100644
--- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
+++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr
@@ -6,8 +6,9 @@ LL |     fn bar(foo: Foo<Target = usize>) {}
    |
 help: consider removing this associated item binding
    |
-LL |     fn bar(foo: Foo<Target = usize>) {}
-   |                    ~~~~~~~~~~~~~~~~
+LL -     fn bar(foo: Foo<Target = usize>) {}
+LL +     fn bar(foo: Foo) {}
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs
index 7a67297c763..bcacd01474f 100644
--- a/tests/ui/lifetimes/issue-95023.rs
+++ b/tests/ui/lifetimes/issue-95023.rs
@@ -9,6 +9,5 @@ impl Fn(&isize) for Error {
     //~^ ERROR associated function in `impl` without body
     //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407]
     //~^^^ ERROR associated type `B` not found for `Self` [E0220]
-    //~| ERROR associated type `B` not found for `Self` [E0220]
 }
 fn main() {}
diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr
index 310dee51406..cbc0eeebee1 100644
--- a/tests/ui/lifetimes/issue-95023.stderr
+++ b/tests/ui/lifetimes/issue-95023.stderr
@@ -56,15 +56,7 @@ error[E0220]: associated type `B` not found for `Self`
 LL |     fn foo<const N: usize>(&self) -> Self::B<{ N }>;
    |                                            ^ help: `Self` has the following associated type: `Output`
 
-error[E0220]: associated type `B` not found for `Self`
-  --> $DIR/issue-95023.rs:8:44
-   |
-LL |     fn foo<const N: usize>(&self) -> Self::B<{ N }>;
-   |                                            ^ help: `Self` has the following associated type: `Output`
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407.
 For more information about an error, try `rustc --explain E0046`.
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/allowed-operations.rs b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
index 1acefa314aa..695a752fe17 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![allow(dead_code, non_camel_case_types, non_upper_case_globals)]
+#![allow(dead_code, non_camel_case_types, non_upper_case_globals, unused_variables)]
 #![feature(macro_metavar_expr_concat)]
 
 macro_rules! create_things {
@@ -37,13 +37,58 @@ macro_rules! without_dollar_sign_is_an_ident {
     };
 }
 
-macro_rules! literals {
-    ($ident:ident) => {{
-        let ${concat(_a, "_b")}: () = ();
-        let ${concat("_b", _a)}: () = ();
+macro_rules! combinations {
+    ($ident:ident, $literal:literal, $tt_ident:tt, $tt_literal:tt) => {{
+        // tt ident
+        let ${concat($tt_ident, b)} = ();
+        let ${concat($tt_ident, _b)} = ();
+        let ${concat($tt_ident, "b")} = ();
+        let ${concat($tt_ident, $tt_ident)} = ();
+        let ${concat($tt_ident, $tt_literal)} = ();
+        let ${concat($tt_ident, $ident)} = ();
+        let ${concat($tt_ident, $literal)} = ();
+        // tt literal
+        let ${concat($tt_literal, b)} = ();
+        let ${concat($tt_literal, _b)} = ();
+        let ${concat($tt_literal, "b")} = ();
+        let ${concat($tt_literal, $tt_ident)} = ();
+        let ${concat($tt_literal, $tt_literal)} = ();
+        let ${concat($tt_literal, $ident)} = ();
+        let ${concat($tt_literal, $literal)} = ();
 
-        let ${concat($ident, "_b")}: () = ();
-        let ${concat("_b", $ident)}: () = ();
+        // ident (adhoc)
+        let ${concat(_b, b)} = ();
+        let ${concat(_b, _b)} = ();
+        let ${concat(_b, "b")} = ();
+        let ${concat(_b, $tt_ident)} = ();
+        let ${concat(_b, $tt_literal)} = ();
+        let ${concat(_b, $ident)} = ();
+        let ${concat(_b, $literal)} = ();
+        // ident (param)
+        let ${concat($ident, b)} = ();
+        let ${concat($ident, _b)} = ();
+        let ${concat($ident, "b")} = ();
+        let ${concat($ident, $tt_ident)} = ();
+        let ${concat($ident, $tt_literal)} = ();
+        let ${concat($ident, $ident)} = ();
+        let ${concat($ident, $literal)} = ();
+
+        // literal (adhoc)
+        let ${concat("a", b)} = ();
+        let ${concat("a", _b)} = ();
+        let ${concat("a", "b")} = ();
+        let ${concat("a", $tt_ident)} = ();
+        let ${concat("a", $tt_literal)} = ();
+        let ${concat("a", $ident)} = ();
+        let ${concat("a", $literal)} = ();
+        // literal (param)
+        let ${concat($literal, b)} = ();
+        let ${concat($literal, _b)} = ();
+        let ${concat($literal, "b")} = ();
+        let ${concat($literal, $tt_ident)} = ();
+        let ${concat($literal, $tt_literal)} = ();
+        let ${concat($literal, $ident)} = ();
+        let ${concat($literal, $literal)} = ();
     }};
 }
 
@@ -66,5 +111,5 @@ fn main() {
     assert_eq!(VARident, 1);
     assert_eq!(VAR_123, 2);
 
-    literals!(_hello);
+    combinations!(_hello, "a", b, "b");
 }
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-metavar-expr-concat/syntax-errors.rs b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
index b2845c8d1c1..7673bd3200f 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
@@ -20,7 +20,7 @@ macro_rules! wrong_concat_declarations {
         //~^ ERROR `concat` must have at least two elements
 
         ${concat($ex, aaaa)}
-        //~^ ERROR `${concat(..)}` currently only accepts identifiers
+        //~^ ERROR metavariables of `${concat(..)}` must be of type
 
         ${concat($ex, aaaa 123)}
         //~^ ERROR expected comma
@@ -98,6 +98,39 @@ macro_rules! unsupported_literals {
     }};
 }
 
+macro_rules! bad_literal_string {
+    ($literal:literal) => {
+        const ${concat(_foo, $literal)}: () = ();
+        //~^ ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+        //~| ERROR `${concat(..)}` is not generating a valid identifier
+    }
+}
+
+macro_rules! bad_literal_non_string {
+    ($literal:literal) => {
+        const ${concat(_foo, $literal)}: () = ();
+        //~^ ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+    }
+}
+
+macro_rules! bad_tt_literal {
+    ($tt:tt) => {
+        const ${concat(_foo, $tt)}: () = ();
+        //~^ ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR metavariables of `${concat(..)}` must be of type
+    }
+}
+
 fn main() {
     wrong_concat_declarations!(1);
 
@@ -113,4 +146,23 @@ fn main() {
     unsupported_literals!(_abc);
 
     empty!();
+
+    bad_literal_string!("\u{00BD}");
+    bad_literal_string!("\x41");
+    bad_literal_string!("🤷");
+    bad_literal_string!("d[-_-]b");
+
+    bad_literal_string!("-1");
+    bad_literal_string!("1.0");
+    bad_literal_string!("'1'");
+
+    bad_literal_non_string!(1);
+    bad_literal_non_string!(-1);
+    bad_literal_non_string!(1.0);
+    bad_literal_non_string!('1');
+    bad_literal_non_string!(false);
+
+    bad_tt_literal!(1);
+    bad_tt_literal!(1.0);
+    bad_tt_literal!('1');
 }
diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
index 2fe5842b39e..2de6d2b3ce3 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
@@ -64,11 +64,13 @@ error: expected identifier or string literal
 LL |         let ${concat($ident, 1)}: () = ();
    |                              ^
 
-error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
   --> $DIR/syntax-errors.rs:22:19
    |
 LL |         ${concat($ex, aaaa)}
    |                   ^^
+   |
+   = note: currently only string literals are supported
 
 error: variable `foo` is not recognized in meta-variable expression
   --> $DIR/syntax-errors.rs:35:30
@@ -131,5 +133,152 @@ LL |     empty!();
    |
    = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 18 previous errors
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("\u{00BD}");
+   |     ------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("\x41");
+   |     --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("🤷");
+   |     ------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("d[-_-]b");
+   |     ------------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("-1");
+   |     ------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("1.0");
+   |     -------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:103:16
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     bad_literal_string!("'1'");
+   |     -------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:116:31
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
+   |
+   = note: currently only string literals are supported
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:116:31
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:116:31
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:116:31
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:116:31
+   |
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:127:31
+   |
+LL |         const ${concat(_foo, $tt)}: () = ();
+   |                               ^^
+   |
+   = note: currently only string literals are supported
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:127:31
+   |
+LL |         const ${concat(_foo, $tt)}: () = ();
+   |                               ^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+  --> $DIR/syntax-errors.rs:127:31
+   |
+LL |         const ${concat(_foo, $tt)}: () = ();
+   |                               ^^
+   |
+   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 33 previous errors
 
diff --git a/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs b/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs
index b2cfb211e2d..4eeb2384deb 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs
@@ -3,12 +3,17 @@
 #![feature(macro_metavar_expr_concat)]
 
 macro_rules! turn_to_page {
-    ($ident:ident) => {
+    ($ident:ident, $literal:literal, $tt:tt) => {
         const ${concat("Ḧ", $ident)}: i32 = 394;
+        const ${concat("Ḧ", $literal)}: i32 = 394;
+        const ${concat("Ḧ", $tt)}: i32 = 394;
     };
 }
 
 fn main() {
-    turn_to_page!(P);
-    assert_eq!(ḦP, 394);
+    turn_to_page!(P1, "Ṕ2", Ṕ);
+    assert_eq!(ḦṔ, 394);
+    assert_eq!(ḦP1, 394);
+    assert_eq!(ḦṔ2, 394);
+
 }
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/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index 0855a17b333..84005119a87 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -19,7 +19,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
    |
 LL |      .one()
-   |       ^^^-- an argument of type `isize` is missing
+   |       ^^^-- argument #1 of type `isize` is missing
    |
 note: method defined here
   --> $DIR/method-call-err-msg.rs:6:8
@@ -35,7 +35,7 @@ error[E0061]: this method takes 2 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:15:7
    |
 LL |      .two(0);
-   |       ^^^--- an argument of type `isize` is missing
+   |       ^^^--- argument #2 of type `isize` is missing
    |
 note: method defined here
   --> $DIR/method-call-err-msg.rs:7:8
diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
index cd483e7ad2c..c52fa713615 100644
--- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -16,7 +16,7 @@ error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:35:15
    |
 LL |     let ans = s();
-   |               ^-- an argument of type `isize` is missing
+   |               ^-- argument #1 of type `isize` is missing
    |
 note: implementation defined here
   --> $DIR/overloaded-calls-bad.rs:10:1
@@ -32,7 +32,7 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:37:15
    |
 LL |     let ans = s("burma", "shave");
-   |               ^ -------  ------- unexpected argument of type `&'static str`
+   |               ^ -------  ------- unexpected argument #2 of type `&'static str`
    |                 |
    |                 expected `isize`, found `&str`
    |
diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
index 82065cc06ea..a6d4f9a2a5c 100644
--- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
+++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
@@ -11,7 +11,7 @@ LL |         S1 { a: unsafe { &mut X1 } }
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         S1 { a: unsafe { addr_of_mut!(X1) } }
-   |                          ~~~~~~~~~~~~~~~~
+   |                          ~~~~~~~~~~~~~  +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/not-enough-arguments.stderr
index 8b2dafb4e1d..89e98866667 100644
--- a/tests/ui/not-enough-arguments.stderr
+++ b/tests/ui/not-enough-arguments.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 4 arguments but 3 arguments were supplied
   --> $DIR/not-enough-arguments.rs:27:3
    |
 LL |   foo(1, 2, 3);
-   |   ^^^--------- an argument of type `isize` is missing
+   |   ^^^--------- argument #4 of type `isize` is missing
    |
 note: function defined here
   --> $DIR/not-enough-arguments.rs:5:4
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/issue-101477-enum.stderr b/tests/ui/parser/issues/issue-101477-enum.stderr
index c6dadeab8b3..8d4efdd17f7 100644
--- a/tests/ui/parser/issues/issue-101477-enum.stderr
+++ b/tests/ui/parser/issues/issue-101477-enum.stderr
@@ -7,9 +7,8 @@ LL |     B == 2
    = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
 help: try using `=` instead
    |
-LL -     B == 2
-LL +     B = 2
-   |
+LL |     B = 2
+   |       ~
 
 error: expected item, found `==`
   --> $DIR/issue-101477-enum.rs:6:7
diff --git a/tests/ui/parser/issues/issue-101477-let.stderr b/tests/ui/parser/issues/issue-101477-let.stderr
index 59e90c8102f..d2671abbdea 100644
--- a/tests/ui/parser/issues/issue-101477-let.stderr
+++ b/tests/ui/parser/issues/issue-101477-let.stderr
@@ -6,9 +6,8 @@ LL |     let x == 2;
    |
 help: try using `=` instead
    |
-LL -     let x == 2;
-LL +     let x = 2;
-   |
+LL |     let x = 2;
+   |           ~
 
 error: aborting due to 1 previous error
 
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/recover/unicode-double-equals-recovery.rs b/tests/ui/parser/recover/unicode-double-equals-recovery.rs
new file mode 100644
index 00000000000..589f0a559bb
--- /dev/null
+++ b/tests/ui/parser/recover/unicode-double-equals-recovery.rs
@@ -0,0 +1,3 @@
+const A: usize ⩵ 2;
+//~^ ERROR unknown start of token: \u{2a75}
+//~| ERROR unexpected `==`
diff --git a/tests/ui/parser/recover/unicode-double-equals-recovery.stderr b/tests/ui/parser/recover/unicode-double-equals-recovery.stderr
new file mode 100644
index 00000000000..6e10dcce04a
--- /dev/null
+++ b/tests/ui/parser/recover/unicode-double-equals-recovery.stderr
@@ -0,0 +1,24 @@
+error: unknown start of token: \u{2a75}
+  --> $DIR/unicode-double-equals-recovery.rs:1:16
+   |
+LL | const A: usize ⩵ 2;
+   |                ^
+   |
+help: Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not
+   |
+LL | const A: usize == 2;
+   |                ~~
+
+error: unexpected `==`
+  --> $DIR/unicode-double-equals-recovery.rs:1:16
+   |
+LL | const A: usize ⩵ 2;
+   |                ^
+   |
+help: try using `=` instead
+   |
+LL | const A: usize = 2;
+   |                ~
+
+error: aborting due to 2 previous errors
+
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/issue-68393-let-pat-assoc-constant.rs b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs
deleted file mode 100644
index 95ead6b5d4a..00000000000
--- a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-pub enum EFoo {
-    A,
-}
-
-pub trait Foo {
-    const X: EFoo;
-}
-
-struct Abc;
-
-impl Foo for Abc {
-    const X: EFoo = EFoo::A;
-}
-
-struct Def;
-impl Foo for Def {
-    const X: EFoo = EFoo::A;
-}
-
-pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
-    //~^ ERROR associated consts cannot be referenced in patterns
-    let A::X = arg;
-    //~^ ERROR associated consts cannot be referenced in patterns
-}
-
-fn main() {}
diff --git a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
deleted file mode 100644
index 62c90b638d7..00000000000
--- a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0158]: associated consts cannot be referenced in patterns
-  --> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9
-   |
-LL |     let A::X = arg;
-   |         ^^^^
-
-error[E0158]: associated consts cannot be referenced in patterns
-  --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40
-   |
-LL | pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
-   |                                        ^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
index 915d07fd08a..8ab6e83641d 100644
--- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -29,7 +29,7 @@ LL | pub use core as reexported_core;
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+   = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
    = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
 help: consider making the `extern crate` item publicly accessible
    |
@@ -40,3 +40,18 @@ error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0365, E0603.
 For more information about an error, try `rustc --explain E0365`.
+Future incompatibility report: Future breakage diagnostic:
+error[E0365]: extern crate `core` is private and cannot be re-exported
+  --> $DIR/pub-reexport-priv-extern-crate.rs:2:9
+   |
+LL | pub use core as reexported_core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
+   = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
+help: consider making the `extern crate` item publicly accessible
+   |
+LL | pub extern crate core;
+   | +++
+
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/resolve/resolve-conflict-import-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr
index e22e636adb6..a8d0efedb6c 100644
--- a/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr
+++ b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr
@@ -8,7 +8,7 @@ LL | use std::slice as std;
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::slice as other_std;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/resolve/resolve-conflict-item-vs-import.stderr b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr
index 3b1b5f1ad00..a8b16009c55 100644
--- a/tests/ui/resolve/resolve-conflict-item-vs-import.stderr
+++ b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr
@@ -11,7 +11,7 @@ LL | fn transmute() {}
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::mem::transmute as other_transmute;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/resolve/resolve-conflict-type-vs-import.stderr b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr
index c5cb4e07862..241e48d0cd5 100644
--- a/tests/ui/resolve/resolve-conflict-type-vs-import.stderr
+++ b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr
@@ -11,7 +11,7 @@ LL | struct Iter;
 help: you can use `as` to change the binding name of the import
    |
 LL | use std::slice::Iter as OtherIter;
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
index c69fe145f77..c01f8934c75 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
@@ -13,7 +13,7 @@ const A: &[B] = &[];
 pub fn main() {
     match &[][..] {
         A => (),
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR must implement `PartialEq`
         _ => (),
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
index 02e2bab4d0a..736e4c30c8a 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
@@ -1,11 +1,8 @@
-error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
+error: to use a constant of type `&[B]` in a pattern, the type must implement `PartialEq`
   --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
    |
 LL |         A => (),
    |         ^
-   |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
index 6d6a336e688..f343013f2b0 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs
@@ -28,13 +28,9 @@ fn main() {
     // Also cover range patterns
     match x {
         NAN..=1.0 => {}, //~ ERROR cannot use NaN in patterns
-        //~^ ERROR lower range bound must be less than or equal to upper
         -1.0..=NAN => {}, //~ ERROR cannot use NaN in patterns
-        //~^ ERROR lower range bound must be less than or equal to upper
         NAN.. => {}, //~ ERROR cannot use NaN in patterns
-        //~^ ERROR lower range bound must be less than or equal to upper
         ..NAN => {}, //~ ERROR cannot use NaN in patterns
-        //~^ ERROR lower range bound must be less than upper
         _ => {},
     };
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
index baca1d75048..44b05ea31e9 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
@@ -34,14 +34,8 @@ LL |         NAN..=1.0 => {},
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:30:9
-   |
-LL |         NAN..=1.0 => {},
-   |         ^^^^^^^^^ lower bound larger than upper bound
-
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:32:16
+  --> $DIR/issue-6804-nan-match.rs:31:16
    |
 LL |         -1.0..=NAN => {},
    |                ^^^
@@ -49,14 +43,8 @@ LL |         -1.0..=NAN => {},
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:32:9
-   |
-LL |         -1.0..=NAN => {},
-   |         ^^^^^^^^^^ lower bound larger than upper bound
-
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:34:9
+  --> $DIR/issue-6804-nan-match.rs:32:9
    |
 LL |         NAN.. => {},
    |         ^^^
@@ -64,14 +52,8 @@ LL |         NAN.. => {},
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/issue-6804-nan-match.rs:34:9
-   |
-LL |         NAN.. => {},
-   |         ^^^^^ lower bound larger than upper bound
-
 error: cannot use NaN in patterns
-  --> $DIR/issue-6804-nan-match.rs:36:11
+  --> $DIR/issue-6804-nan-match.rs:33:11
    |
 LL |         ..NAN => {},
    |           ^^^
@@ -79,13 +61,5 @@ LL |         ..NAN => {},
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
 
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/issue-6804-nan-match.rs:36:9
-   |
-LL |         ..NAN => {},
-   |         ^^^^^
-
-error: aborting due to 11 previous errors
+error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0030, E0579.
-For more information about an error, try `rustc --explain E0030`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr
index 4d543f6a155..7db6a77c77b 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.stderr
@@ -4,20 +4,11 @@ error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#0
 LL | fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] {
    |                                   ^^^^^^^^^^^^^^^^ cannot normalize `process<T>::{constant#0}`
 
-error[E0284]: type annotations needed: cannot satisfy `the constant `T::make(P)` can be evaluated`
-  --> $DIR/const-trait-bounds.rs:18:5
+error[E0284]: type annotations needed: cannot normalize `Struct<T, P>::field::{constant#0}`
+  --> $DIR/const-trait-bounds.rs:20:12
    |
-LL |     [u32; T::make(P)]:,
-   |     ^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `T::make(P)` can be evaluated`
-   |
-note: required by a bound in `Struct`
-  --> $DIR/const-trait-bounds.rs:18:11
-   |
-LL | struct Struct<T: const Trait, const P: usize>
-   |        ------ required by a bound in this struct
-LL | where
-LL |     [u32; T::make(P)]:,
-   |           ^^^^^^^^^^ required by this bound in `Struct`
+LL |     field: [u32; T::make(P)],
+   |            ^^^^^^^^^^^^^^^^^ cannot normalize `Struct<T, P>::field::{constant#0}`
 
 error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#1}`
   --> $DIR/const-trait-bounds.rs:13:5
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/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/self/elision/ignore-non-reference-lifetimes.rs b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs
new file mode 100644
index 00000000000..f7f61b8c810
--- /dev/null
+++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs
@@ -0,0 +1,22 @@
+//@ check-pass
+
+struct Foo<'a>(&'a str);
+
+impl<'b> Foo<'b> {
+    fn a<'a>(self: Self, a: &'a str) -> &str {
+        a
+    }
+    fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
+        a
+    }
+}
+
+struct Foo2<'a>(&'a u32);
+impl<'a> Foo2<'a> {
+    fn foo(self: &Self) -> &u32 { self.0 } // ok
+    fn bar(self: &Foo2<'a>) -> &u32 { self.0 } // ok (do not look into `Foo`)
+    fn baz2(self: Self, arg: &u32) -> &u32 { arg } // use lt from `arg`
+    fn baz3(self: Foo2<'a>, arg: &u32) -> &u32 { arg } // use lt from `arg`
+}
+
+fn main() {}
diff --git a/tests/ui/self/elision/multiple-ref-self-async.rs b/tests/ui/self/elision/multiple-ref-self-async.rs
index fb77f91396c..f63b455901e 100644
--- a/tests/ui/self/elision/multiple-ref-self-async.rs
+++ b/tests/ui/self/elision/multiple-ref-self-async.rs
@@ -1,4 +1,3 @@
-//@ check-pass
 //@ edition:2018
 
 #![feature(arbitrary_self_types)]
@@ -21,22 +20,27 @@ impl Struct {
     // Test using multiple `&Self`:
 
     async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 }
diff --git a/tests/ui/self/elision/multiple-ref-self-async.stderr b/tests/ui/self/elision/multiple-ref-self-async.stderr
new file mode 100644
index 00000000000..e2abc7c1e78
--- /dev/null
+++ b/tests/ui/self/elision/multiple-ref-self-async.stderr
@@ -0,0 +1,63 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self-async.rs:22:74
+   |
+LL |     async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+   |                                           ------------------     ---     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     async fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: &'a u8) -> &'a u8 {
+   |                                    ++++             ++        ++            ++         ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self-async.rs:27:84
+   |
+LL |     async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+   |                                               -----------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     async fn box_wrap_ref_Self_ref_Self<'a>(self: Box<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
+   |                                        ++++                 ++        ++             ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self-async.rs:32:84
+   |
+LL |     async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+   |                                               -----------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     async fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
+   |                                        ++++                 ++        ++             ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self-async.rs:37:93
+   |
+LL |     async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+   |                                                   ----------------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     async fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box<Box<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
+   |                                            ++++                     ++        ++              ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self-async.rs:42:93
+   |
+LL |     async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+   |                                                   ----------------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     async fn box_pin_wrap_ref_Self_ref_Self<'a>(self: Box<Pin<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
+   |                                            ++++                     ++        ++              ++          ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/self/elision/multiple-ref-self.rs b/tests/ui/self/elision/multiple-ref-self.rs
index 01d6bb47c04..dd9b138051d 100644
--- a/tests/ui/self/elision/multiple-ref-self.rs
+++ b/tests/ui/self/elision/multiple-ref-self.rs
@@ -1,5 +1,3 @@
-//@ check-pass
-
 #![feature(arbitrary_self_types)]
 #![allow(non_snake_case)]
 
@@ -20,22 +18,27 @@ impl Struct {
     // Test using multiple `&Self`:
 
     fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 
     fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
         f
     }
 }
diff --git a/tests/ui/self/elision/multiple-ref-self.stderr b/tests/ui/self/elision/multiple-ref-self.stderr
new file mode 100644
index 00000000000..24d74d352e4
--- /dev/null
+++ b/tests/ui/self/elision/multiple-ref-self.stderr
@@ -0,0 +1,63 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self.rs:20:68
+   |
+LL |     fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+   |                                     ------------------     ---     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: &'a u8) -> &'a u8 {
+   |                              ++++             ++        ++            ++         ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self.rs:25:78
+   |
+LL |     fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+   |                                         -----------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn box_wrap_ref_Self_ref_Self<'a>(self: Box<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
+   |                                  ++++                 ++        ++             ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self.rs:30:78
+   |
+LL |     fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+   |                                         -----------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin<Wrap<&'a Self, &'a Self>>, f: &'a u32) -> &'a u32 {
+   |                                  ++++                 ++        ++             ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self.rs:35:87
+   |
+LL |     fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+   |                                             ----------------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box<Box<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
+   |                                      ++++                     ++        ++              ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiple-ref-self.rs:40:87
+   |
+LL |     fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+   |                                             ----------------------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn box_pin_wrap_ref_Self_ref_Self<'a>(self: Box<Pin<Wrap<&'a Self, &'a Self>>>, f: &'a u32) -> &'a u32 {
+   |                                      ++++                     ++        ++              ++          ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/self/elision/no-shadow-pin-self.rs b/tests/ui/self/elision/no-shadow-pin-self.rs
new file mode 100644
index 00000000000..e390b869ca7
--- /dev/null
+++ b/tests/ui/self/elision/no-shadow-pin-self.rs
@@ -0,0 +1,17 @@
+use std::pin::Pin;
+trait Trait {
+    fn method<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 {
+        f
+    }
+}
+
+impl<P> Trait for Pin<P> {
+    // This should not hide `&Self`, which would cause this to compile.
+    fn method(self: Pin<&Self>, f: &u32) -> &u32 {
+        //~^ ERROR `impl` item signature doesn't match `trait`
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/self/elision/no-shadow-pin-self.stderr b/tests/ui/self/elision/no-shadow-pin-self.stderr
new file mode 100644
index 00000000000..23485e9de79
--- /dev/null
+++ b/tests/ui/self/elision/no-shadow-pin-self.stderr
@@ -0,0 +1,32 @@
+error: `impl` item signature doesn't match `trait` item signature
+  --> $DIR/no-shadow-pin-self.rs:10:5
+   |
+LL |     fn method<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 {
+   |     ------------------------------------------------------ expected `fn(Pin<&'1 Pin<P>>, &'a u32) -> &'a u32`
+...
+LL |     fn method(self: Pin<&Self>, f: &u32) -> &u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(Pin<&'1 Pin<P>>, &'2 u32) -> &'1 u32`
+   |
+   = note: expected signature `fn(Pin<&'1 Pin<P>>, &'a u32) -> &'a u32`
+              found signature `fn(Pin<&'1 Pin<P>>, &'2 u32) -> &'1 u32`
+   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+
+error: lifetime may not live long enough
+  --> $DIR/no-shadow-pin-self.rs:12:9
+   |
+LL |     fn method(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                         -          - let's call the lifetime of this reference `'1`
+   |                         |
+   |                         let's call the lifetime of this reference `'2`
+LL |
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn method<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 {
+   |              ++++                       ++          ++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/self/elision/ref-assoc-async.rs b/tests/ui/self/elision/ref-assoc-async.rs
index 2af4f13a41b..25deb25253d 100644
--- a/tests/ui/self/elision/ref-assoc-async.rs
+++ b/tests/ui/self/elision/ref-assoc-async.rs
@@ -1,5 +1,4 @@
 //@ edition:2018
-//@ check-pass
 
 #![allow(non_snake_case)]
 
@@ -18,22 +17,27 @@ impl Trait for Struct {
 impl Struct {
     async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/tests/ui/self/elision/ref-assoc-async.stderr b/tests/ui/self/elision/ref-assoc-async.stderr
new file mode 100644
index 00000000000..cf54a86b45f
--- /dev/null
+++ b/tests/ui/self/elision/ref-assoc-async.stderr
@@ -0,0 +1,77 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc-async.rs:19:9
+   |
+LL |     async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
+   |                                  -                                 - let's call the lifetime of this reference `'1`
+   |                                  |
+   |                                  let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn ref_AssocType<'a>(self: &'a <Struct as Trait>::AssocType, f: &'a u32) -> &u32 {
+   |                           ++++        ++                                   ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc-async.rs:24:9
+   |
+LL |     async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+   |                                          -                                  - let's call the lifetime of this reference `'1`
+   |                                          |
+   |                                          let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_ref_AssocType<'a>(self: Box<&'a <Struct as Trait>::AssocType>, f: &'a u32) -> &u32 {
+   |                               ++++            ++                                    ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc-async.rs:29:9
+   |
+LL |     async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+   |                                          -                                  - let's call the lifetime of this reference `'1`
+   |                                          |
+   |                                          let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn pin_ref_AssocType<'a>(self: Pin<&'a <Struct as Trait>::AssocType>, f: &'a u32) -> &u32 {
+   |                               ++++            ++                                    ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc-async.rs:34:9
+   |
+LL |     async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+   |                                                  -                                   - let's call the lifetime of this reference `'1`
+   |                                                  |
+   |                                                  let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_box_ref_AssocType<'a>(self: Box<Box<&'a <Struct as Trait>::AssocType>>, f: &'a u32) -> &u32 {
+   |                                   ++++                ++                                     ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc-async.rs:39:9
+   |
+LL |     async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+   |                                                  -                                   - let's call the lifetime of this reference `'1`
+   |                                                  |
+   |                                                  let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     async fn box_pin_ref_AssocType<'a>(self: Box<Pin<&'a <Struct as Trait>::AssocType>>, f: &'a u32) -> &u32 {
+   |                                   ++++                ++                                     ++
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/self/elision/ref-assoc.rs b/tests/ui/self/elision/ref-assoc.rs
index 8dc78d31d39..01d2556df62 100644
--- a/tests/ui/self/elision/ref-assoc.rs
+++ b/tests/ui/self/elision/ref-assoc.rs
@@ -1,5 +1,3 @@
-//@ check-pass
-
 #![allow(non_snake_case)]
 
 use std::pin::Pin;
@@ -17,22 +15,27 @@ impl Trait for Struct {
 impl Struct {
     fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 
     fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
         f
+        //~^ ERROR lifetime may not live long enough
     }
 }
 
diff --git a/tests/ui/self/elision/ref-assoc.stderr b/tests/ui/self/elision/ref-assoc.stderr
new file mode 100644
index 00000000000..7c8a1de95ae
--- /dev/null
+++ b/tests/ui/self/elision/ref-assoc.stderr
@@ -0,0 +1,77 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc.rs:17:9
+   |
+LL |     fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
+   |                            -                                 - let's call the lifetime of this reference `'1`
+   |                            |
+   |                            let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_AssocType<'a>(self: &<Struct as Trait>::AssocType, f: &'a u32) -> &'a u32 {
+   |                     ++++                                          ++          ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc.rs:22:9
+   |
+LL |     fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+   |                                    -                                  - let's call the lifetime of this reference `'1`
+   |                                    |
+   |                                    let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_AssocType<'a>(self: Box<&<Struct as Trait>::AssocType>, f: &'a u32) -> &'a u32 {
+   |                         ++++                                               ++          ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc.rs:27:9
+   |
+LL |     fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+   |                                    -                                  - let's call the lifetime of this reference `'1`
+   |                                    |
+   |                                    let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_AssocType<'a>(self: Pin<&<Struct as Trait>::AssocType>, f: &'a u32) -> &'a u32 {
+   |                         ++++                                               ++          ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc.rs:32:9
+   |
+LL |     fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+   |                                            -                                   - let's call the lifetime of this reference `'1`
+   |                                            |
+   |                                            let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_AssocType<'a>(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &'a u32) -> &'a u32 {
+   |                             ++++                                                    ++          ++
+
+error: lifetime may not live long enough
+  --> $DIR/ref-assoc.rs:37:9
+   |
+LL |     fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+   |                                            -                                   - let's call the lifetime of this reference `'1`
+   |                                            |
+   |                                            let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_AssocType<'a>(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &'a u32) -> &'a u32 {
+   |                             ++++                                                    ++          ++
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/self/elision/ref-self-multi.rs b/tests/ui/self/elision/ref-self-multi.rs
new file mode 100644
index 00000000000..ed431a9c852
--- /dev/null
+++ b/tests/ui/self/elision/ref-self-multi.rs
@@ -0,0 +1,29 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+#![allow(unused)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+struct Struct { }
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    fn ref_box_ref_Self(self: &Box<&Self>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
+        f
+    }
+
+    fn ref_wrap_ref_Self(self: &Wrap<&Self, u32>, f: &u32) -> &u32 {
+        //~^ ERROR missing lifetime specifier
+        f
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/self/elision/ref-self-multi.stderr b/tests/ui/self/elision/ref-self-multi.stderr
new file mode 100644
index 00000000000..7e0451aa0d5
--- /dev/null
+++ b/tests/ui/self/elision/ref-self-multi.stderr
@@ -0,0 +1,27 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/ref-self-multi.rs:18:56
+   |
+LL |     fn ref_box_ref_Self(self: &Box<&Self>, f: &u32) -> &u32 {
+   |                               -----------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn ref_box_ref_Self<'a>(self: &'a Box<&'a Self>, f: &'a u32) -> &'a u32 {
+   |                        ++++        ++      ++            ++          ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/ref-self-multi.rs:23:63
+   |
+LL |     fn ref_wrap_ref_Self(self: &Wrap<&Self, u32>, f: &u32) -> &u32 {
+   |                                -----------------     ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `self`'s 2 lifetimes or `f`
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn ref_wrap_ref_Self<'a>(self: &'a Wrap<&'a Self, u32>, f: &'a u32) -> &'a u32 {
+   |                         ++++        ++       ++                 ++          ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/self/elision/ref-self.fixed b/tests/ui/self/elision/ref-self.fixed
index 8bf5a0bb223..784ccb9efe2 100644
--- a/tests/ui/self/elision/ref-self.fixed
+++ b/tests/ui/self/elision/ref-self.fixed
@@ -1,4 +1,6 @@
 //@ run-rustfix
+//@ edition:2018
+
 #![feature(arbitrary_self_types)]
 #![allow(non_snake_case, dead_code)]
 
@@ -56,6 +58,11 @@ impl Struct {
         f
         //~^ ERROR lifetime may not live long enough
     }
+
+    fn ref_box_Self<'a>(self: &Box<Self>, f: &'a u32) -> &'a u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/self/elision/ref-self.rs b/tests/ui/self/elision/ref-self.rs
index 4b4b8aa5b51..dbe441879cc 100644
--- a/tests/ui/self/elision/ref-self.rs
+++ b/tests/ui/self/elision/ref-self.rs
@@ -1,4 +1,6 @@
 //@ run-rustfix
+//@ edition:2018
+
 #![feature(arbitrary_self_types)]
 #![allow(non_snake_case, dead_code)]
 
@@ -56,6 +58,11 @@ impl Struct {
         f
         //~^ ERROR lifetime may not live long enough
     }
+
+    fn ref_box_Self(self: &Box<Self>, f: &u32) -> &u32 {
+        f
+        //~^ ERROR lifetime may not live long enough
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/self/elision/ref-self.stderr b/tests/ui/self/elision/ref-self.stderr
index c4ec8c55a00..64e7bfc1bb0 100644
--- a/tests/ui/self/elision/ref-self.stderr
+++ b/tests/ui/self/elision/ref-self.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:24:9
+  --> $DIR/ref-self.rs:26:9
    |
 LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                 -         - let's call the lifetime of this reference `'1`
@@ -14,7 +14,7 @@ LL |     fn ref_self<'a>(&self, f: &'a u32) -> &'a u32 {
    |                ++++            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:31:9
+  --> $DIR/ref-self.rs:33:9
    |
 LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                       -         - let's call the lifetime of this reference `'1`
@@ -29,7 +29,7 @@ LL |     fn ref_Self<'a>(self: &Self, f: &'a u32) -> &'a u32 {
    |                ++++                  ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:36:9
+  --> $DIR/ref-self.rs:38:9
    |
 LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -44,7 +44,7 @@ LL |     fn box_ref_Self<'a>(self: Box<&Self>, f: &'a u32) -> &'a u32 {
    |                    ++++                       ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:41:9
+  --> $DIR/ref-self.rs:43:9
    |
 LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                               -          - let's call the lifetime of this reference `'1`
@@ -59,7 +59,7 @@ LL |     fn pin_ref_Self<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 {
    |                    ++++                       ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:46:9
+  --> $DIR/ref-self.rs:48:9
    |
 LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -74,7 +74,7 @@ LL |     fn box_box_ref_Self<'a>(self: Box<Box<&Self>>, f: &'a u32) -> &'a u32 {
    |                        ++++                            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:51:9
+  --> $DIR/ref-self.rs:53:9
    |
 LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                       -           - let's call the lifetime of this reference `'1`
@@ -89,7 +89,7 @@ LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&Self>>, f: &'a u32) -> &'a u32 {
    |                        ++++                            ++          ++
 
 error: lifetime may not live long enough
-  --> $DIR/ref-self.rs:56:9
+  --> $DIR/ref-self.rs:58:9
    |
 LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                      -                - let's call the lifetime of this reference `'1`
@@ -103,5 +103,20 @@ help: consider introducing a named lifetime parameter and update trait if needed
 LL |     fn wrap_ref_Self_Self<'a>(self: Wrap<&Self, Self>, f: &'a u8) -> &'a u8 {
    |                          ++++                              ++         ++
 
-error: aborting due to 7 previous errors
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:63:9
+   |
+LL |     fn ref_box_Self(self: &Box<Self>, f: &u32) -> &u32 {
+   |                           -              - let's call the lifetime of this reference `'1`
+   |                           |
+   |                           let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_box_Self<'a>(self: &Box<Self>, f: &'a u32) -> &'a u32 {
+   |                    ++++                       ++          ++
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
index 89c67719b5a..b581cdd0be2 100644
--- a/tests/ui/span/issue-34264.stderr
+++ b/tests/ui/span/issue-34264.stderr
@@ -54,7 +54,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
 LL |     foo(Some(42), 2, "");
-   |     ^^^              -- unexpected argument of type `&'static str`
+   |     ^^^              -- unexpected argument #3 of type `&'static str`
    |
 note: function defined here
   --> $DIR/issue-34264.rs:1:4
@@ -85,7 +85,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
 LL |     bar(1, 2, 3);
-   |     ^^^       - unexpected argument of type `{integer}`
+   |     ^^^       - unexpected argument #3 of type `{integer}`
    |
 note: function defined here
   --> $DIR/issue-34264.rs:3:4
diff --git a/tests/ui/span/missing-unit-argument.stderr b/tests/ui/span/missing-unit-argument.stderr
index ff89f775334..79980f48ab6 100644
--- a/tests/ui/span/missing-unit-argument.stderr
+++ b/tests/ui/span/missing-unit-argument.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:11:33
    |
 LL |     let _: Result<(), String> = Ok();
-   |                                 ^^-- an argument of type `()` is missing
+   |                                 ^^-- argument #1 of type `()` is missing
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
@@ -31,7 +31,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing-unit-argument.rs:13:5
    |
 LL |     foo(());
-   |     ^^^---- an argument of type `()` is missing
+   |     ^^^---- argument #2 of type `()` is missing
    |
 note: function defined here
   --> $DIR/missing-unit-argument.rs:1:4
@@ -47,7 +47,7 @@ error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:14:5
    |
 LL |     bar();
-   |     ^^^-- an argument of type `()` is missing
+   |     ^^^-- argument #1 of type `()` is missing
    |
 note: function defined here
   --> $DIR/missing-unit-argument.rs:2:4
@@ -63,7 +63,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
    |
 LL |     S.baz();
-   |       ^^^-- an argument of type `()` is missing
+   |       ^^^-- argument #1 of type `()` is missing
    |
 note: method defined here
   --> $DIR/missing-unit-argument.rs:6:8
@@ -79,7 +79,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
    |
 LL |     S.generic::<()>();
-   |       ^^^^^^^^^^^^^-- an argument of type `()` is missing
+   |       ^^^^^^^^^^^^^-- argument #1 of type `()` is missing
    |
 note: method defined here
   --> $DIR/missing-unit-argument.rs:7:8
diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs
index 59a015da84e..fb962ad24bf 100644
--- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs
+++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs
@@ -14,6 +14,5 @@ struct Wrapper<const C: <i32 as Trait>::Type> {}
 
 impl<const C: usize> Wrapper<C> {}
 //~^ ERROR the constant `C` is not of type `<i32 as Trait>::Type`
-//~^^ ERROR mismatched types
 
 fn main() {}
diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr
index 71d4277275f..7094ee8c67c 100644
--- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr
+++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr
@@ -20,17 +20,5 @@ note: required by a const generic parameter in `Wrapper`
 LL | struct Wrapper<const C: <i32 as Trait>::Type> {}
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper`
 
-error[E0308]: mismatched types
-  --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30
-   |
-LL | impl<const C: usize> Wrapper<C> {}
-   |                              ^ expected associated type, found `usize`
-   |
-   = note: expected associated type `<i32 as Trait>::Type`
-                         found type `usize`
-   = help: consider constraining the associated type `<i32 as Trait>::Type` to `usize`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
index f89a463bc58..a0ee7714417 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
@@ -6,7 +6,6 @@
 struct S<const L: usize>;
 
 impl<const N: i32> Copy for S<N> {}
-//~^ ERROR: mismatched types
 impl<const M: usize> Copy for S<M> {}
 //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
 
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
index 1dac58e1f69..2953bc95917 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
@@ -1,19 +1,11 @@
 error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
-  --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
+  --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
    |
 LL | impl<const N: i32> Copy for S<N> {}
    | -------------------------------- first implementation here
-LL |
 LL | impl<const M: usize> Copy for S<M> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
 
-error[E0308]: mismatched types
-  --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31
-   |
-LL | impl<const N: i32> Copy for S<N> {}
-   |                               ^ expected `usize`, found `i32`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0119, E0308.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr
index 9ea34290e36..9fdfc00dfcd 100644
--- a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr
+++ b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr
@@ -11,7 +11,7 @@ LL |     let _x = &X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     let _x = addr_of!(X);
-   |              ~~~~~~~~~~~
+   |              ~~~~~~~~~ +
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/reference-to-mut-static-safe.rs:9:15
diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr
index c57b418d7b2..b3e0c84d1d8 100644
--- a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr
+++ b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr
@@ -8,7 +8,7 @@ LL |     let _x = &X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     let _x = addr_of!(X);
-   |              ~~~~~~~~~~~
+   |              ~~~~~~~~~ +
 
 error[E0133]: use of mutable static is unsafe and requires unsafe block
   --> $DIR/reference-to-mut-static-safe.rs:9:15
diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr
index b24943cf593..ca9cfbf7ac7 100644
--- a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr
+++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr
@@ -8,7 +8,7 @@ LL |         let _y = &X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~~~
+   |                  ~~~~~~~~~ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static-unsafe-fn.rs:13:22
@@ -20,7 +20,7 @@ LL |         let ref _a = X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let ref _a = addr_of!(X);
-   |                      ~~~~~~~~~~~
+   |                      +++++++++ +
 
 error[E0796]: creating a mutable reference to a mutable static
   --> $DIR/reference-to-mut-static-unsafe-fn.rs:16:26
@@ -32,7 +32,7 @@ LL |         let ref mut _a = X;
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         let ref mut _a = addr_of_mut!(X);
-   |                          ~~~~~~~~~~~~~~~
+   |                          +++++++++++++ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:25
@@ -44,7 +44,7 @@ LL |         let (_b, _c) = (&X, &mut Y);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (addr_of!(X), &mut Y);
-   |                         ~~~~~~~~~~~
+   |                         ~~~~~~~~~ +
 
 error[E0796]: creating a mutable reference to a mutable static
   --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:29
@@ -56,7 +56,7 @@ LL |         let (_b, _c) = (&X, &mut Y);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (&X, addr_of_mut!(Y));
-   |                             ~~~~~~~~~~~~~~~
+   |                             ~~~~~~~~~~~~~ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static-unsafe-fn.rs:23:13
@@ -68,7 +68,7 @@ LL |         foo(&X);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~~~
+   |             ~~~~~~~~~ +
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/static/reference-to-mut-static.e2021.stderr b/tests/ui/static/reference-to-mut-static.e2021.stderr
index f477e5ac6c5..667d7602f34 100644
--- a/tests/ui/static/reference-to-mut-static.e2021.stderr
+++ b/tests/ui/static/reference-to-mut-static.e2021.stderr
@@ -15,7 +15,7 @@ LL | #![deny(static_mut_refs)]
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~~~
+   |                  ~~~~~~~~~ +
 
 error: creating a mutable reference to mutable static is discouraged
   --> $DIR/reference-to-mut-static.rs:20:18
@@ -29,7 +29,7 @@ LL |         let _y = &mut X;
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         let _y = addr_of_mut!(X);
-   |                  ~~~~~~~~~~~~~~~
+   |                  ~~~~~~~~~~~~~ +
 
 error: creating a shared reference to mutable static is discouraged
   --> $DIR/reference-to-mut-static.rs:28:22
@@ -43,7 +43,7 @@ LL |         let ref _a = X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let ref _a = addr_of!(X);
-   |                      ~~~~~~~~~~~
+   |                      +++++++++ +
 
 error: creating a shared reference to mutable static is discouraged
   --> $DIR/reference-to-mut-static.rs:32:25
@@ -57,7 +57,7 @@ LL |         let (_b, _c) = (&X, &Y);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (addr_of!(X), &Y);
-   |                         ~~~~~~~~~~~
+   |                         ~~~~~~~~~ +
 
 error: creating a shared reference to mutable static is discouraged
   --> $DIR/reference-to-mut-static.rs:32:29
@@ -71,7 +71,7 @@ LL |         let (_b, _c) = (&X, &Y);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (&X, addr_of!(Y));
-   |                             ~~~~~~~~~~~
+   |                             ~~~~~~~~~ +
 
 error: creating a shared reference to mutable static is discouraged
   --> $DIR/reference-to-mut-static.rs:38:13
@@ -85,7 +85,7 @@ LL |         foo(&X);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~~~
+   |             ~~~~~~~~~ +
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/static/reference-to-mut-static.e2024.stderr b/tests/ui/static/reference-to-mut-static.e2024.stderr
index b18e214e84f..e77f4355466 100644
--- a/tests/ui/static/reference-to-mut-static.e2024.stderr
+++ b/tests/ui/static/reference-to-mut-static.e2024.stderr
@@ -8,7 +8,7 @@ LL |         let _y = &X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~~~
+   |                  ~~~~~~~~~ +
 
 error[E0796]: creating a mutable reference to a mutable static
   --> $DIR/reference-to-mut-static.rs:20:18
@@ -20,7 +20,7 @@ LL |         let _y = &mut X;
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |         let _y = addr_of_mut!(X);
-   |                  ~~~~~~~~~~~~~~~
+   |                  ~~~~~~~~~~~~~ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static.rs:28:22
@@ -32,7 +32,7 @@ LL |         let ref _a = X;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let ref _a = addr_of!(X);
-   |                      ~~~~~~~~~~~
+   |                      +++++++++ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static.rs:32:25
@@ -44,7 +44,7 @@ LL |         let (_b, _c) = (&X, &Y);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (addr_of!(X), &Y);
-   |                         ~~~~~~~~~~~
+   |                         ~~~~~~~~~ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static.rs:32:29
@@ -56,7 +56,7 @@ LL |         let (_b, _c) = (&X, &Y);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         let (_b, _c) = (&X, addr_of!(Y));
-   |                             ~~~~~~~~~~~
+   |                             ~~~~~~~~~ +
 
 error[E0796]: creating a shared reference to a mutable static
   --> $DIR/reference-to-mut-static.rs:38:13
@@ -68,7 +68,7 @@ LL |         foo(&X);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~~~
+   |             ~~~~~~~~~ +
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/static/safe-extern-statics-mut.stderr b/tests/ui/static/safe-extern-statics-mut.stderr
index 9a4b651405f..7705a897e27 100644
--- a/tests/ui/static/safe-extern-statics-mut.stderr
+++ b/tests/ui/static/safe-extern-statics-mut.stderr
@@ -11,7 +11,7 @@ LL |     let rb = &B;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     let rb = addr_of!(B);
-   |              ~~~~~~~~~~~
+   |              ~~~~~~~~~ +
 
 warning: creating a shared reference to mutable static is discouraged
   --> $DIR/safe-extern-statics-mut.rs:15:15
@@ -25,7 +25,7 @@ LL |     let xrb = &XB;
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     let xrb = addr_of!(XB);
-   |               ~~~~~~~~~~~~
+   |               ~~~~~~~~~  +
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/safe-extern-statics-mut.rs:11:13
diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr
index c31793f3d8f..6035eef5b71 100644
--- a/tests/ui/statics/issue-15261.stderr
+++ b/tests/ui/statics/issue-15261.stderr
@@ -11,7 +11,7 @@ LL | static n: &'static usize = unsafe { &n_mut };
 help: use `addr_of!` instead to create a raw pointer
    |
 LL | static n: &'static usize = unsafe { addr_of!(n_mut) };
-   |                                     ~~~~~~~~~~~~~~~
+   |                                     ~~~~~~~~~     +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr
index d381328c071..9751f754332 100644
--- a/tests/ui/statics/static-mut-xc.stderr
+++ b/tests/ui/statics/static-mut-xc.stderr
@@ -11,7 +11,7 @@ LL |     static_bound(&static_mut_xc::a);
 help: use `addr_of!` instead to create a raw pointer
    |
 LL |     static_bound(addr_of!(static_mut_xc::a));
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                  ~~~~~~~~~                +
 
 warning: creating a mutable reference to mutable static is discouraged
   --> $DIR/static-mut-xc.rs:30:22
@@ -25,7 +25,7 @@ LL |     static_bound_set(&mut static_mut_xc::a);
 help: use `addr_of_mut!` instead to create a raw pointer
    |
 LL |     static_bound_set(addr_of_mut!(static_mut_xc::a));
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ~~~~~~~~~~~~~                +
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr
index cd285c6c2a4..a7a1a1610af 100644
--- a/tests/ui/statics/static-recursive.stderr
+++ b/tests/ui/statics/static-recursive.stderr
@@ -11,7 +11,7 @@ LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
 help: use `addr_of!` instead to create a raw pointer
    |
 LL | static mut S: *const u8 = unsafe { addr_of!(S) as *const *const u8 as *const u8 };
-   |                                    ~~~~~~~~~~~
+   |                                    ~~~~~~~~~ +
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr
index a7a612a8a9e..b27f769ba34 100644
--- a/tests/ui/stats/hir-stats.stderr
+++ b/tests/ui/stats/hir-stats.stderr
@@ -123,15 +123,15 @@ hir-stats Lifetime                  24 ( 0.3%)             1            24
 hir-stats Mod                       32 ( 0.4%)             1            32
 hir-stats ExprField                 40 ( 0.4%)             1            40
 hir-stats TraitItemRef              56 ( 0.6%)             2            28
+hir-stats GenericArg                64 ( 0.7%)             4            16
+hir-stats - Type                      16 ( 0.2%)             1
+hir-stats - Lifetime                  48 ( 0.5%)             3
 hir-stats Local                     64 ( 0.7%)             1            64
 hir-stats Param                     64 ( 0.7%)             2            32
 hir-stats Body                      72 ( 0.8%)             3            24
 hir-stats InlineAsm                 72 ( 0.8%)             1            72
 hir-stats ImplItemRef               72 ( 0.8%)             2            36
 hir-stats Arm                       80 ( 0.9%)             2            40
-hir-stats GenericArg                96 ( 1.1%)             4            24
-hir-stats - Type                      24 ( 0.3%)             1
-hir-stats - Lifetime                  72 ( 0.8%)             3
 hir-stats FieldDef                  96 ( 1.1%)             2            48
 hir-stats Stmt                      96 ( 1.1%)             3            32
 hir-stats - Let                       32 ( 0.4%)             1
@@ -155,8 +155,8 @@ hir-stats Generics                 560 ( 6.2%)            10            56
 hir-stats Ty                       720 ( 8.0%)            15            48
 hir-stats - Ptr                       48 ( 0.5%)             1
 hir-stats - Ref                       48 ( 0.5%)             1
-hir-stats - Path                     624 ( 6.9%)            13
-hir-stats Expr                     768 ( 8.5%)            12            64
+hir-stats - Path                     624 ( 7.0%)            13
+hir-stats Expr                     768 ( 8.6%)            12            64
 hir-stats - Path                      64 ( 0.7%)             1
 hir-stats - Struct                    64 ( 0.7%)             1
 hir-stats - Match                     64 ( 0.7%)             1
@@ -174,5 +174,5 @@ hir-stats - Use                      352 ( 3.9%)             4
 hir-stats Path                   1_240 (13.8%)            31            40
 hir-stats PathSegment            1_920 (21.4%)            40            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  8_992
+hir-stats Total                  8_960
 hir-stats
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
index 510b99bb5af..1051a16b40d 100644
--- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:6:34
    |
 LL |     let _: Option<(i32, bool)> = Some(1, 2);
-   |                                  ^^^^    - unexpected argument of type `{integer}`
+   |                                  ^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:6:39
@@ -30,7 +30,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
    |
 LL |     int_bool(1, 2);
-   |     ^^^^^^^^    - unexpected argument of type `{integer}`
+   |     ^^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:8:14
@@ -54,7 +54,7 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:11:28
    |
 LL |     let _: Option<(i8,)> = Some();
-   |                            ^^^^-- an argument of type `(i8,)` is missing
+   |                            ^^^^-- argument #1 of type `(i8,)` is missing
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
diff --git a/tests/ui/suggestions/args-instead-of-tuple.stderr b/tests/ui/suggestions/args-instead-of-tuple.stderr
index 0bdf10b0d63..3ca560f93eb 100644
--- a/tests/ui/suggestions/args-instead-of-tuple.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple.stderr
@@ -28,7 +28,7 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple.rs:11:25
    |
 LL |     let _: Option<()> = Some();
-   |                         ^^^^-- an argument of type `()` is missing
+   |                         ^^^^-- argument #1 of type `()` is missing
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
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/issue-109396.stderr b/tests/ui/suggestions/issue-109396.stderr
index d4956872a39..5419e8240c5 100644
--- a/tests/ui/suggestions/issue-109396.stderr
+++ b/tests/ui/suggestions/issue-109396.stderr
@@ -11,14 +11,14 @@ LL |         let mut mutex = std::mem::zeroed(
    |                         ^^^^^^^^^^^^^^^^
 LL |
 LL |             file.as_raw_fd(),
-   |             ---------------- unexpected argument
+   |             ---------------- unexpected argument #1
 LL |
 LL |             0,
-   |             - unexpected argument of type `{integer}`
+   |             - unexpected argument #2 of type `{integer}`
 LL |             0,
-   |             - unexpected argument of type `{integer}`
+   |             - unexpected argument #3 of type `{integer}`
 LL |             0,
-   |             - unexpected argument of type `{integer}`
+   |             - unexpected argument #4 of type `{integer}`
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr
index 52444cd4c45..d9cbbe37d46 100644
--- a/tests/ui/suggestions/issue-109854.stderr
+++ b/tests/ui/suggestions/issue-109854.stderr
@@ -7,9 +7,9 @@ LL |       String::with_capacity(
 LL | /     r#"
 LL | | pub(crate) struct Person<T: Clone> {}
 LL | | "#,
-   | |__- unexpected argument of type `&'static str`
+   | |__- unexpected argument #2 of type `&'static str`
 LL |        r#""#,
-   |        ----- unexpected argument of type `&'static str`
+   |        ----- unexpected argument #3 of type `&'static str`
    |
 note: expected `usize`, found fn item
   --> $DIR/issue-109854.rs:4:5
diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr
index b3616041c4c..af77ddd35e3 100644
--- a/tests/ui/suggestions/issue-85347.stderr
+++ b/tests/ui/suggestions/issue-85347.stderr
@@ -22,8 +22,9 @@ LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    |
 help: consider removing this associated item binding
    |
-LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
-   |                                             ~~~~~~~~~~~~~~~
+LL -     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+LL +     type Bar<'a>: Deref<Target = <Self>::Bar>;
+   |
 
 error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/issue-85347.rs:3:42
@@ -51,8 +52,9 @@ LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider removing this associated item binding
    |
-LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
-   |                                             ~~~~~~~~~~~~~~~
+LL -     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+LL +     type Bar<'a>: Deref<Target = <Self>::Bar>;
+   |
 
 error: aborting due to 4 previous errors
 
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/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs
index c2c3d6d547d..f3485d9c1fa 100644
--- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs
+++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs
@@ -10,7 +10,6 @@
 //@ ignore-wasm no panic or subprocess support
 //@ ignore-emscripten no panic or subprocess support
 //@ ignore-sgx no subprocess support
-//@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#127539)
 
 #![cfg(test)]
 
diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr
index 4c94518d4d1..16001b3eecd 100644
--- a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr
+++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr
@@ -1,9 +1,9 @@
-thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:35:5:
+thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:34:5:
 assertion `left == right` failed
   left: 2
  right: 4
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:29:5:
+thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:28:5:
 assertion `left == right` failed
   left: 2
  right: 4
diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs
index 0c44acaffd7..84740161a70 100644
--- a/tests/ui/test-attrs/test-panic-abort.rs
+++ b/tests/ui/test-attrs/test-panic-abort.rs
@@ -10,7 +10,6 @@
 //@ ignore-wasm no panic or subprocess support
 //@ ignore-emscripten no panic or subprocess support
 //@ ignore-sgx no subprocess support
-//@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#127539)
 
 #![cfg(test)]
 #![feature(test)]
diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout
index 25105f38fcf..f5d14e77da9 100644
--- a/tests/ui/test-attrs/test-panic-abort.run.stdout
+++ b/tests/ui/test-attrs/test-panic-abort.run.stdout
@@ -17,7 +17,7 @@ hello, world
 testing123
 ---- it_fails stderr ----
 testing321
-thread 'main' panicked at $DIR/test-panic-abort.rs:40:5:
+thread 'main' panicked at $DIR/test-panic-abort.rs:39:5:
 assertion `left == right` failed
   left: 2
  right: 5
diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs
index 89b2da4452a..7338642beef 100644
--- a/tests/ui/traits/issue-105231.rs
+++ b/tests/ui/traits/issue-105231.rs
@@ -1,9 +1,9 @@
 //~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
 struct A<T>(B<T>);
 //~^ ERROR recursive types `A` and `B` have infinite size
-//~| ERROR `T` is never used
+//~| ERROR `T` is only used recursively
 struct B<T>(A<A<T>>);
-//~^ ERROR `T` is never used
+//~^ ERROR `T` is only used recursively
 trait Foo {}
 impl<T> Foo for T where T: Send {}
 impl Foo for B<u8> {}
diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr
index 6467a438375..d3014a79ad6 100644
--- a/tests/ui/traits/issue-105231.stderr
+++ b/tests/ui/traits/issue-105231.stderr
@@ -15,23 +15,27 @@ LL |
 LL ~ struct B<T>(Box<A<A<T>>>);
    |
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/issue-105231.rs:2:10
+error: type parameter `T` is only used recursively
+  --> $DIR/issue-105231.rs:2:15
    |
 LL | struct A<T>(B<T>);
-   |          ^ unused type parameter
+   |          -    ^
+   |          |
+   |          type parameter must be used non-recursively in the definition
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+   = 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/issue-105231.rs:5:10
+error: type parameter `T` is only used recursively
+  --> $DIR/issue-105231.rs:5:17
    |
 LL | struct B<T>(A<A<T>>);
-   |          ^ unused type parameter
+   |          -      ^
+   |          |
+   |          type parameter must be used non-recursively in the definition
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+   = note: all type parameters must be used in a non-recursive way in order to constrain their variance
 
 error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
    |
@@ -44,5 +48,5 @@ LL | struct B<T>(A<A<T>>);
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0072, E0275, E0392.
+Some errors have detailed explanations: E0072, E0275.
 For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs
deleted file mode 100644
index bbae67f0bad..00000000000
--- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
-
-fn b()
-where
-    for<const C: usize> [(); C]: Copy,
-    //~^ ERROR cannot capture late-bound const parameter in constant
-{
-}
-
-fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr
deleted file mode 100644
index 4e0441c1c7d..00000000000
--- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/capture-late-ct-in-anon.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: cannot capture late-bound const parameter in constant
-  --> $DIR/capture-late-ct-in-anon.rs:6:30
-   |
-LL |     for<const C: usize> [(); C]: Copy,
-   |         --------------       ^
-   |         |
-   |         parameter defined here
-
-error: aborting due to 1 previous error; 1 warning emitted
-
diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs
index 0695d7d409f..20bd7917e53 100644
--- a/tests/ui/transmutability/issue-101739-1.rs
+++ b/tests/ui/transmutability/issue-101739-1.rs
@@ -7,7 +7,6 @@ mod assert {
     where
         Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
         //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
-        //~| ERROR: mismatched types
     {
     }
 }
diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr
index 6f79bf7b424..ba18a980f4d 100644
--- a/tests/ui/transmutability/issue-101739-1.stderr
+++ b/tests/ui/transmutability/issue-101739-1.stderr
@@ -13,13 +13,6 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
 note: required by a const generic parameter in `BikeshedIntrinsicFrom`
   --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
 
-error[E0308]: mismatched types
-  --> $DIR/issue-101739-1.rs:8:41
-   |
-LL |         Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
-   |                                         ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0412.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs
index 1c0bd29d707..8b36bf3dcb1 100644
--- a/tests/ui/transmutability/issue-101739-2.rs
+++ b/tests/ui/transmutability/issue-101739-2.rs
@@ -16,7 +16,7 @@ mod assert {
     where
         Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied
             Src,
-            ASSUME_ALIGNMENT, //~ ERROR: mismatched types
+            ASSUME_ALIGNMENT,
             ASSUME_LIFETIMES,
             ASSUME_VALIDITY,
             ASSUME_VISIBILITY,
diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr
index 38912696c18..519a374dc22 100644
--- a/tests/ui/transmutability/issue-101739-2.stderr
+++ b/tests/ui/transmutability/issue-101739-2.stderr
@@ -9,13 +9,6 @@ LL | |             ASSUME_VALIDITY,
 LL | |             ASSUME_VISIBILITY,
    | |_____________________________- help: remove these generic arguments
 
-error[E0308]: mismatched types
-  --> $DIR/issue-101739-2.rs:19:13
-   |
-LL |             ASSUME_ALIGNMENT,
-   |             ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0107, E0308.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr
index ce21751f39d..78212ed1e76 100644
--- a/tests/ui/tuple/wrong_argument_ice-3.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-3.stderr
@@ -2,7 +2,7 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
-   |                ^^^^            ------------- unexpected argument of type `Vec<&Process>`
+   |                ^^^^            ------------- unexpected argument #2 of type `Vec<&Process>`
    |
 note: expected `(Vec<String>, Vec<Process>)`, found `Vec<String>`
   --> $DIR/wrong_argument_ice-3.rs:9:21
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index db75a520c65..371f5b10988 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
    |
 LL |     <E>::V();
-   |     ^^^^^^-- an argument of type `u8` is missing
+   |     ^^^^^^-- argument #1 of type `u8` is missing
    |
 note: tuple variant defined here
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
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/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr
index 224ff6e7404..630e82d254e 100644
--- a/tests/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr
@@ -11,7 +11,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |            ^^^^^^^^^^^^^^^^^^     -- unexpected argument of type `{integer}`
+   |            ^^^^^^^^^^^^^^^^^^     -- unexpected argument #2 of type `{integer}`
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
diff --git a/tests/ui/type/type-check/point-at-inference-4.rs b/tests/ui/type/type-check/point-at-inference-4.rs
index 3deb234c275..5745b738532 100644
--- a/tests/ui/type/type-check/point-at-inference-4.rs
+++ b/tests/ui/type/type-check/point-at-inference-4.rs
@@ -13,7 +13,7 @@ fn main() {
     //~^ ERROR this method takes 2 arguments but 1 argument was supplied
     //~| NOTE this argument has type `i32`...
     //~| NOTE ... which causes `s` to have type `S<i32, _>`
-    //~| NOTE an argument is missing
+    //~| NOTE argument #2 is missing
     //~| HELP provide the argument
     //~| HELP change the type of the numeric literal from `i32` to `u32`
     let t: S<u32, _> = s;
diff --git a/tests/ui/type/type-check/point-at-inference-4.stderr b/tests/ui/type/type-check/point-at-inference-4.stderr
index 5f7bb8b9367..a953ca70ea2 100644
--- a/tests/ui/type/type-check/point-at-inference-4.stderr
+++ b/tests/ui/type/type-check/point-at-inference-4.stderr
@@ -2,7 +2,7 @@ error[E0061]: this method takes 2 arguments but 1 argument was supplied
   --> $DIR/point-at-inference-4.rs:12:7
    |
 LL |     s.infer(0i32);
-   |       ^^^^^------ an argument is missing
+   |       ^^^^^------ argument #2 is missing
    |
 note: method defined here
   --> $DIR/point-at-inference-4.rs:4:8
diff --git a/tests/ui/typeck/cyclic_type_ice.stderr b/tests/ui/typeck/cyclic_type_ice.stderr
index bfff6830fc5..36715b4ee5d 100644
--- a/tests/ui/typeck/cyclic_type_ice.stderr
+++ b/tests/ui/typeck/cyclic_type_ice.stderr
@@ -13,7 +13,7 @@ error[E0057]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/cyclic_type_ice.rs:3:5
    |
 LL |     f(f);
-   |     ^--- an argument is missing
+   |     ^--- argument #2 is missing
    |
 note: closure defined here
   --> $DIR/cyclic_type_ice.rs:2:13
diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
index 193544ebd3f..9fc249198d0 100644
--- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
+++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs
@@ -5,7 +5,7 @@
 
 
 trait Trait {
-    fn func<const N: u32>() -> [ (); N ]; //~ ERROR mismatched types
+    fn func<const N: u32>() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize`
 }
 
 struct S {}
diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
index 16aaf0615ed..bff926a2081 100644
--- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
+++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr
@@ -4,11 +4,11 @@ error[E0308]: mismatched types
 LL |     fn func<const N: u32>() -> [ (); { () }] {
    |                                        ^^ expected `usize`, found `()`
 
-error[E0308]: mismatched types
-  --> $DIR/const-in-impl-fn-return-type.rs:8:38
+error: the constant `N` is not of type `usize`
+  --> $DIR/const-in-impl-fn-return-type.rs:8:32
    |
 LL |     fn func<const N: u32>() -> [ (); N ];
-   |                                      ^ expected `usize`, found `u32`
+   |                                ^^^^^^^^^ expected `usize`, found `u32`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr
index 4bab2959651..d4e0dcb50ae 100644
--- a/tests/ui/typeck/remove-extra-argument.stderr
+++ b/tests/ui/typeck/remove-extra-argument.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/remove-extra-argument.rs:6:5
    |
 LL |     l(vec![], vec![])
-   |     ^         ------ unexpected argument of type `Vec<_>`
+   |     ^         ------ unexpected argument #2 of type `Vec<_>`
    |
 note: function defined here
   --> $DIR/remove-extra-argument.rs:3:4
diff --git a/tests/ui/typeck/struct-enum-wrong-args.stderr b/tests/ui/typeck/struct-enum-wrong-args.stderr
index d005eca841e..e58d162901e 100644
--- a/tests/ui/typeck/struct-enum-wrong-args.stderr
+++ b/tests/ui/typeck/struct-enum-wrong-args.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:6:13
    |
 LL |     let _ = Some(3, 2);
-   |             ^^^^    - unexpected argument of type `{integer}`
+   |             ^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
@@ -16,9 +16,9 @@ error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:7:13
    |
 LL |     let _ = Ok(3, 6, 2);
-   |             ^^    -  - unexpected argument of type `{integer}`
+   |             ^^    -  - unexpected argument #3 of type `{integer}`
    |                   |
-   |                   unexpected argument of type `{integer}`
+   |                   unexpected argument #2 of type `{integer}`
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
@@ -32,7 +32,7 @@ error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:8:13
    |
 LL |     let _ = Ok();
-   |             ^^-- an argument is missing
+   |             ^^-- argument #1 is missing
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
@@ -45,7 +45,7 @@ error[E0061]: this struct takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:9:13
    |
 LL |     let _ = Wrapper();
-   |             ^^^^^^^-- an argument of type `i32` is missing
+   |             ^^^^^^^-- argument #1 of type `i32` is missing
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
@@ -61,7 +61,7 @@ error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
    |
 LL |     let _ = Wrapper(5, 2);
-   |             ^^^^^^^    - unexpected argument of type `{integer}`
+   |             ^^^^^^^    - unexpected argument #2 of type `{integer}`
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
@@ -94,7 +94,7 @@ error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/struct-enum-wrong-args.rs:12:13
    |
 LL |     let _ = DoubleWrapper(5);
-   |             ^^^^^^^^^^^^^--- an argument of type `i32` is missing
+   |             ^^^^^^^^^^^^^--- argument #2 of type `i32` is missing
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
@@ -110,7 +110,7 @@ error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
    |
 LL |     let _ = DoubleWrapper(5, 2, 7);
-   |             ^^^^^^^^^^^^^       - unexpected argument of type `{integer}`
+   |             ^^^^^^^^^^^^^       - unexpected argument #3 of type `{integer}`
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
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/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs
index d1114064364..ef3c41ca556 100644
--- a/tests/ui/variance/variance-unused-type-param.rs
+++ b/tests/ui/variance/variance-unused-type-param.rs
@@ -11,11 +11,14 @@ enum SomeEnum<A> { Nothing }
 
 // Here T might *appear* used, but in fact it isn't.
 enum ListCell<T> {
-//~^ ERROR parameter `T` is never used
     Cons(Box<ListCell<T>>),
+    //~^ ERROR parameter `T` is only used recursively
     Nil
 }
 
+struct SelfTyAlias<T>(Box<Self>);
+//~^ ERROR parameter `T` is only used recursively
+
 struct WithBounds<T: Sized> {}
 //~^ ERROR parameter `T` is never used
 
@@ -25,4 +28,9 @@ struct WithWhereBounds<T> where T: Sized {}
 struct WithOutlivesBounds<T: 'static> {}
 //~^ ERROR parameter `T` is never used
 
+struct DoubleNothing<T> {
+//~^ ERROR parameter `T` is never used
+    s: SomeStruct<T>,
+}
+
 fn main() {}
diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr
index 3011b7bd18f..c747532e628 100644
--- a/tests/ui/variance/variance-unused-type-param.stderr
+++ b/tests/ui/variance/variance-unused-type-param.stderr
@@ -16,17 +16,30 @@ LL | enum SomeEnum<A> { Nothing }
    = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData`
    = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/variance-unused-type-param.rs:13:15
+error: type parameter `T` is only used recursively
+  --> $DIR/variance-unused-type-param.rs:14:23
    |
 LL | enum ListCell<T> {
-   |               ^ unused type parameter
+   |               - type parameter must be used non-recursively in the definition
+LL |     Cons(Box<ListCell<T>>),
+   |                       ^
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+   = note: all type parameters must be used in a non-recursive way in order to constrain their variance
+
+error: type parameter `T` is only used recursively
+  --> $DIR/variance-unused-type-param.rs:19:27
+   |
+LL | struct SelfTyAlias<T>(Box<Self>);
+   |                    -      ^^^^
+   |                    |
+   |                    type parameter must be used non-recursively in the definition
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = 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/variance-unused-type-param.rs:19:19
+  --> $DIR/variance-unused-type-param.rs:22:19
    |
 LL | struct WithBounds<T: Sized> {}
    |                   ^ unused type parameter
@@ -34,7 +47,7 @@ LL | struct WithBounds<T: Sized> {}
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/variance-unused-type-param.rs:22:24
+  --> $DIR/variance-unused-type-param.rs:25:24
    |
 LL | struct WithWhereBounds<T> where T: Sized {}
    |                        ^ unused type parameter
@@ -42,13 +55,25 @@ LL | struct WithWhereBounds<T> where T: Sized {}
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/variance-unused-type-param.rs:25:27
+  --> $DIR/variance-unused-type-param.rs:28:27
    |
 LL | struct WithOutlivesBounds<T: 'static> {}
    |                           ^ unused type parameter
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
 
-error: aborting due to 6 previous errors
+error[E0392]: type parameter `T` is never used
+  --> $DIR/variance-unused-type-param.rs:31:22
+   |
+LL | struct DoubleNothing<T> {
+   |                      ^ unused type parameter
+LL |
+LL |     s: SomeStruct<T>,
+   |                   - `T` is named here, but is likely unused in the containing type
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/variants/variant-namespacing.stderr b/tests/ui/variants/variant-namespacing.stderr
index 9e91ff7178d..2a2491b81f9 100644
--- a/tests/ui/variants/variant-namespacing.stderr
+++ b/tests/ui/variants/variant-namespacing.stderr
@@ -11,7 +11,7 @@ LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use variant_namespacing::XE::{XStruct as OtherXStruct, XTuple, XUnit};
-   |                                   ~~~~~~~~~~~~~~~~~~~~~~~
+   |                                           +++++++++++++++
 
 error[E0255]: the name `XTuple` is defined multiple times
   --> $DIR/variant-namespacing.rs:24:44
@@ -26,7 +26,7 @@ LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use variant_namespacing::XE::{XStruct, XTuple as OtherXTuple, XUnit};
-   |                                            ~~~~~~~~~~~~~~~~~~~~~
+   |                                                   ++++++++++++++
 
 error[E0255]: the name `XUnit` is defined multiple times
   --> $DIR/variant-namespacing.rs:24:52
@@ -41,7 +41,7 @@ LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit as OtherXUnit};
-   |                                                    ~~~~~~~~~~~~~~~~~~~
+   |                                                          +++++++++++++
 
 error[E0255]: the name `Struct` is defined multiple times
   --> $DIR/variant-namespacing.rs:28:13
@@ -56,7 +56,7 @@ LL | pub use E::{Struct, Tuple, Unit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use E::{Struct as OtherStruct, Tuple, Unit};
-   |             ~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++
 
 error[E0255]: the name `Tuple` is defined multiple times
   --> $DIR/variant-namespacing.rs:28:21
@@ -71,7 +71,7 @@ LL | pub use E::{Struct, Tuple, Unit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use E::{Struct, Tuple as OtherTuple, Unit};
-   |                     ~~~~~~~~~~~~~~~~~~~
+   |                           +++++++++++++
 
 error[E0255]: the name `Unit` is defined multiple times
   --> $DIR/variant-namespacing.rs:28:28
@@ -86,7 +86,7 @@ LL | pub use E::{Struct, Tuple, Unit};
 help: you can use `as` to change the binding name of the import
    |
 LL | pub use E::{Struct, Tuple, Unit as OtherUnit};
-   |                            ~~~~~~~~~~~~~~~~~
+   |                                 ++++++++++++
 
 error: aborting due to 6 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index d47d54d45c0..5335cf4e4bf 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"]
+users_on_vacation = ["jyn514", "jhpratt", "oli-obk"]
 
 [assign.adhoc_groups]
 compiler-team = [
@@ -928,6 +928,7 @@ compiler-team-contributors = [
     "@fee1-dead",
     "@jieyouxu",
     "@BoxyUwU",
+    "@chenyukang",
 ]
 compiler = [
     "compiler-team",
@@ -976,6 +977,7 @@ diagnostics = [
     "@estebank",
     "@oli-obk",
     "@TaKO8Ki",
+    "@chenyukang",
 ]
 parser = [
     "@compiler-errors",
@@ -989,6 +991,7 @@ lexer = [
     "@nnethercote",
     "@petrochenkov",
     "@estebank",
+    "@chenyukang",
 ]
 arena = [
     "@nnethercote",