about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-04-02 22:22:18 +0000
committerGitHub <noreply@github.com>2025-04-02 22:22:18 +0000
commit5103bdeb29d7aa4d7ad4d811893c76baa8a98ab7 (patch)
treec989d04f4bcd32bcd93ed62208af68e1dbe36b6d
parent4858c3fe7d1a9a7484db4998199f6deb1e05185a (diff)
parente435ba32d85057070dba3f07fa8afd96799a0cfb (diff)
Merge pull request #4245 from RalfJung/rustup
Rustup
-rw-r--r--.gitattributes1
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.gitmodules2
-rw-r--r--Cargo.lock842
-rw-r--r--RELEASES.md134
-rw-r--r--bootstrap.example.toml9
-rw-r--r--compiler/rustc_abi/src/lib.rs3
-rw-r--r--compiler/rustc_ast/src/ast.rs117
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs144
-rw-r--r--compiler/rustc_ast/src/token.rs97
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs62
-rw-r--r--compiler/rustc_ast/src/visit.rs151
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl3
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs66
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs466
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs89
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs7
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs391
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs10
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs162
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs1
-rw-r--r--compiler/rustc_attr_data_structures/src/lib.rs11
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/rustc.rs19
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs2
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs26
-rw-r--r--compiler/rustc_borrowck/src/nll.rs27
-rw-r--r--compiler/rustc_borrowck/src/opaque_types.rs55
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs37
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs188
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/define_opaque.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs17
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/edition_panic.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs40
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs63
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs46
-rw-r--r--compiler/rustc_codegen_cranelift/.cirrus.yml41
-rw-r--r--compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md18
-rw-r--r--compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml13
-rw-r--r--compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js162
-rw-r--r--compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json571
-rw-r--r--compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json11
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml12
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml43
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml6
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json33
-rw-r--r--compiler/rustc_codegen_cranelift/.zed/settings.json25
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock87
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml24
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs49
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt2
-rw-r--r--compiler/rustc_codegen_cranelift/docs/usage.md11
-rw-r--r--compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch (renamed from compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch)12
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch48
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch105
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch26
-rw-r--r--compiler/rustc_codegen_cranelift/patches/coretests-lock.toml35
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/rustfmt.toml4
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs14
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/filter_profile.rs2
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/rustup.sh2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh23
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh58
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs18
-rw-r--r--compiler/rustc_codegen_cranelift/src/config.rs34
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/types.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs225
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs48
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs123
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs26
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs1
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs30
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs214
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs44
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs182
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs11
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl21
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs154
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple/tests.rs68
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs117
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs23
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs24
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs12
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs43
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs2
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs2
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs2
-rw-r--r--compiler/rustc_driver_impl/messages.ftl2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs69
-rw-r--r--compiler/rustc_driver_impl/src/session_diagnostics.rs6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0092.md12
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0093.md10
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0211.md10
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0511.md10
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0789.md2
-rw-r--r--compiler/rustc_errors/src/snippet.rs6
-rw-r--r--compiler/rustc_expand/src/base.rs22
-rw-r--r--compiler/rustc_expand/src/build.rs29
-rw-r--r--compiler/rustc_expand/src/config.rs24
-rw-r--r--compiler/rustc_expand/src/expand.rs127
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs35
-rw-r--r--compiler/rustc_expand/src/placeholders.rs19
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs26
-rw-r--r--compiler/rustc_feature/src/removed.rs3
-rw-r--r--compiler/rustc_feature/src/unstable.rs7
-rw-r--r--compiler/rustc_fs_util/src/lib.rs32
-rw-r--r--compiler/rustc_hir/src/def.rs2
-rw-r--r--compiler/rustc_hir/src/definitions.rs15
-rw-r--r--compiler/rustc_hir/src/hir.rs137
-rw-r--r--compiler/rustc_hir/src/hir/tests.rs1
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/always_applicable.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs299
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs40
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs68
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs156
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs40
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs57
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs11
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/work_product.rs7
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs10
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs12
-rw-r--r--compiler/rustc_interface/messages.ftl9
-rw-r--r--compiler/rustc_interface/src/errors.rs20
-rw-r--r--compiler/rustc_interface/src/passes.rs95
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_interface/src/util.rs35
-rw-r--r--compiler/rustc_lint/messages.ftl25
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/early.rs4
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs128
-rw-r--r--compiler/rustc_lint/src/levels.rs13
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs31
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs13
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs6
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs22
-rw-r--r--compiler/rustc_lint/src/ptr_nulls.rs128
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs44
-rw-r--r--compiler/rustc_lint/src/types.rs8
-rw-r--r--compiler/rustc_lint/src/utils.rs55
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs46
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp13
-rw-r--r--compiler/rustc_metadata/messages.ftl21
-rw-r--r--compiler/rustc_metadata/src/creader.rs127
-rw-r--r--compiler/rustc_metadata/src/errors.rs45
-rw-r--r--compiler/rustc_metadata/src/fs.rs26
-rw-r--r--compiler/rustc_metadata/src/locator.rs67
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs21
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs103
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs10
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs10
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs9
-rw-r--r--compiler/rustc_middle/src/hir/map.rs65
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs14
-rw-r--r--compiler/rustc_middle/src/hir/place.rs10
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs2
-rw-r--r--compiler/rustc_middle/src/middle/region.rs41
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs28
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs76
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs112
-rw-r--r--compiler/rustc_middle/src/query/erase.rs9
-rw-r--r--compiler/rustc_middle/src/query/keys.rs14
-rw-r--r--compiler/rustc_middle/src/query/mod.rs25
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs2
-rw-r--r--compiler/rustc_middle/src/thir.rs6
-rw-r--r--compiler/rustc_middle/src/traits/select.rs8
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs8
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs20
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs89
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs48
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/region.rs6
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs2
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs17
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs7
-rw-r--r--compiler/rustc_middle/src/ty/util.rs46
-rw-r--r--compiler/rustc_middle/src/util/bug.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_constant.rs27
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_place.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/match_pair.rs3
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs74
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs117
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/util.rs8
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs39
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs31
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs38
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs10
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mappings.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs21
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs152
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs123
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs1
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs57
-rw-r--r--compiler/rustc_monomorphize/messages.ftl9
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs14
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs10
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs119
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs16
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs29
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl8
-rw-r--r--compiler/rustc_parse/src/errors.rs39
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs57
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs311
-rw-r--r--compiler/rustc_parse/src/parser/item.rs328
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs80
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs16
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs11
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs19
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs6
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs9
-rw-r--r--compiler/rustc_parse_format/Cargo.toml4
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/messages.ftl8
-rw-r--r--compiler/rustc_passes/src/check_attr.rs61
-rw-r--r--compiler/rustc_passes/src/dead.rs6
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs4
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs29
-rw-r--r--compiler/rustc_passes/src/lang_items.rs28
-rw-r--r--compiler/rustc_passes/src/stability.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs40
-rw-r--r--compiler/rustc_query_impl/src/lib.rs11
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs110
-rw-r--r--compiler/rustc_query_system/Cargo.toml5
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs395
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs7
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs55
-rw-r--r--compiler/rustc_query_system/src/ich/mod.rs2
-rw-r--r--compiler/rustc_query_system/src/query/config.rs5
-rw-r--r--compiler/rustc_query_system/src/query/job.rs189
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs104
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs134
-rw-r--r--compiler/rustc_resolve/Cargo.toml1
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs160
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs7
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs85
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs29
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs4
-rw-r--r--compiler/rustc_resolve/src/ident.rs1
-rw-r--r--compiler/rustc_resolve/src/imports.rs10
-rw-r--r--compiler/rustc_resolve/src/late.rs239
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs181
-rw-r--r--compiler/rustc_resolve/src/lib.rs24
-rw-r--r--compiler/rustc_resolve/src/macros.rs54
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs8
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs1
-rw-r--r--compiler/rustc_session/src/config.rs10
-rw-r--r--compiler/rustc_session/src/filesearch.rs122
-rw-r--r--compiler/rustc_session/src/options.rs62
-rw-r--r--compiler/rustc_session/src/output.rs2
-rw-r--r--compiler/rustc_session/src/session.rs8
-rw-r--r--compiler/rustc_session/src/utils.rs11
-rw-r--r--compiler/rustc_span/src/edit_distance.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs309
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs81
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs5
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs1
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs2
-rw-r--r--compiler/rustc_target/src/callconv/wasm.rs3
-rw-r--r--compiler/rustc_target/src/spec/json.rs8
-rw-r--r--compiler/rustc_target/src/spec/mod.rs10
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs2
-rw-r--r--compiler/rustc_target/src/target_features.rs71
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs6
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs39
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs30
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs10
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs29
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs56
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs32
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs54
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs38
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs8
-rw-r--r--compiler/rustc_type_ir/src/flags.rs16
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs1
-rw-r--r--compiler/rustc_type_ir/src/interner.rs1
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/visit.rs4
-rw-r--r--compiler/stable_mir/src/mir.rs2
-rw-r--r--compiler/stable_mir/src/mir/body.rs19
-rw-r--r--compiler/stable_mir/src/mir/visit.rs744
-rw-r--r--library/Cargo.lock43
-rw-r--r--library/Cargo.toml3
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/boxed.rs12
-rw-r--r--library/alloc/src/sync.rs412
-rw-r--r--library/alloc/src/vec/mod.rs8
-rw-r--r--library/alloctests/tests/arc.rs28
-rw-r--r--library/core/src/cell.rs10
-rw-r--r--library/core/src/cmp.rs134
-rw-r--r--library/core/src/ffi/primitives.rs28
-rw-r--r--library/core/src/fmt/float.rs6
-rw-r--r--library/core/src/fmt/mod.rs394
-rw-r--r--library/core/src/fmt/rt.rs15
-rw-r--r--library/core/src/internal_macros.rs77
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/iter/adapters/flatten.rs55
-rw-r--r--library/core/src/iter/sources/repeat_n.rs59
-rw-r--r--library/core/src/iter/traits/accum.rs4
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/macros/mod.rs2
-rw-r--r--library/core/src/net/ip_addr.rs2
-rw-r--r--library/core/src/num/f32.rs23
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--library/core/src/primitive_docs.rs8
-rw-r--r--library/core/src/ptr/const_ptr.rs3
-rw-r--r--library/core/src/slice/sort/select.rs8
-rw-r--r--library/core/src/slice/sort/stable/mod.rs16
-rw-r--r--library/core/src/slice/sort/unstable/mod.rs9
-rw-r--r--library/core/src/slice/sort/unstable/quicksort.rs9
-rw-r--r--library/core/src/sync/atomic.rs3
-rw-r--r--library/core/src/tuple.rs24
-rw-r--r--library/coretests/tests/fmt/mod.rs20
-rw-r--r--library/coretests/tests/lib.rs10
-rw-r--r--library/coretests/tests/net/ip_addr.rs2
-rw-r--r--library/coretests/tests/num/int_macros.rs697
-rw-r--r--library/coretests/tests/num/uint_macros.rs503
-rw-r--r--library/coretests/tests/pin_macro.rs28
-rw-r--r--library/proc_macro/src/bridge/mod.rs4
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/fs.rs34
-rw-r--r--library/std/src/fs/tests.rs17
-rw-r--r--library/std/src/io/mod.rs8
-rw-r--r--library/std/src/io/stdio.rs63
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/net/tcp/tests.rs8
-rw-r--r--library/std/src/os/fd/owned.rs9
-rw-r--r--library/std/src/os/fd/raw.rs9
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/sync/mod.rs2
-rw-r--r--library/std/src/sys/fs/mod.rs101
-rw-r--r--library/std/src/sys/fs/uefi.rs108
-rw-r--r--library/std/src/sys/fs/unix.rs195
-rw-r--r--library/std/src/sys/fs/windows.rs35
-rw-r--r--library/std/src/sys/mod.rs1
-rw-r--r--library/std/src/sys/net/connection/xous/tcpstream.rs2
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs2
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs2
-rw-r--r--library/std/src/sys/pal/solid/mod.rs2
-rw-r--r--library/std/src/sys/pal/teeos/mod.rs2
-rw-r--r--library/std/src/sys/pal/trusty/mod.rs2
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs86
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs11
-rw-r--r--library/std/src/sys/pal/unix/fd.rs52
-rw-r--r--library/std/src/sys/pal/unix/fuchsia.rs (renamed from library/std/src/sys/pal/unix/process/zircon.rs)0
-rw-r--r--library/std/src/sys/pal/unix/kernel_copy.rs16
-rw-r--r--library/std/src/sys/pal/unix/mod.rs5
-rw-r--r--library/std/src/sys/pal/unix/os.rs8
-rw-r--r--library/std/src/sys/pal/unix/process/mod.rs27
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs117
-rw-r--r--library/std/src/sys/pal/unix/thread.rs18
-rw-r--r--library/std/src/sys/pal/unix/time.rs7
-rw-r--r--library/std/src/sys/pal/unix/weak.rs40
-rw-r--r--library/std/src/sys/pal/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/pal/wasi/mod.rs2
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs2
-rw-r--r--library/std/src/sys/pal/wasip2/mod.rs2
-rw-r--r--library/std/src/sys/pal/wasm/atomics/thread.rs2
-rw-r--r--library/std/src/sys/pal/wasm/mod.rs2
-rw-r--r--library/std/src/sys/pal/windows/args.rs2
-rw-r--r--library/std/src/sys/pal/windows/mod.rs9
-rw-r--r--library/std/src/sys/pal/windows/pipe.rs28
-rw-r--r--library/std/src/sys/pal/xous/mod.rs2
-rw-r--r--library/std/src/sys/pal/zkvm/mod.rs2
-rw-r--r--library/std/src/sys/process/mod.rs19
-rw-r--r--library/std/src/sys/process/uefi.rs (renamed from library/std/src/sys/pal/uefi/process.rs)10
-rw-r--r--library/std/src/sys/process/unix/common.rs (renamed from library/std/src/sys/pal/unix/process/process_common.rs)2
-rw-r--r--library/std/src/sys/process/unix/common/tests.rs (renamed from library/std/src/sys/pal/unix/process/process_common/tests.rs)0
-rw-r--r--library/std/src/sys/process/unix/fuchsia.rs (renamed from library/std/src/sys/pal/unix/process/process_fuchsia.rs)14
-rw-r--r--library/std/src/sys/process/unix/mod.rs23
-rw-r--r--library/std/src/sys/process/unix/unix.rs (renamed from library/std/src/sys/pal/unix/process/process_unix.rs)60
-rw-r--r--library/std/src/sys/process/unix/unix/tests.rs (renamed from library/std/src/sys/pal/unix/process/process_unix/tests.rs)0
-rw-r--r--library/std/src/sys/process/unix/unsupported.rs (renamed from library/std/src/sys/pal/unix/process/process_unsupported.rs)4
-rw-r--r--library/std/src/sys/process/unix/unsupported/wait_status.rs (renamed from library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs)7
-rw-r--r--library/std/src/sys/process/unix/unsupported/wait_status/tests.rs (renamed from library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs)2
-rw-r--r--library/std/src/sys/process/unix/vxworks.rs (renamed from library/std/src/sys/pal/unix/process/process_vxworks.rs)6
-rw-r--r--library/std/src/sys/process/unsupported.rs (renamed from library/std/src/sys/pal/unsupported/process.rs)0
-rw-r--r--library/std/src/sys/process/windows.rs (renamed from library/std/src/sys/pal/windows/process.rs)25
-rw-r--r--library/std/src/sys/process/windows/tests.rs (renamed from library/std/src/sys/pal/windows/process/tests.rs)0
-rw-r--r--library/std/src/sys/random/linux.rs8
-rw-r--r--library/std/src/sys/random/trusty.rs2
-rw-r--r--library/std/src/sys/stdio/sgx.rs12
-rw-r--r--library/std/src/sys/stdio/solid.rs59
-rw-r--r--library/std/src/sys/stdio/teeos.rs53
-rw-r--r--library/std/src/sys/stdio/unix.rs12
-rw-r--r--library/std/src/sys/stdio/unsupported.rs71
-rw-r--r--library/std/src/sys/stdio/xous.rs27
-rw-r--r--library/std/src/thread/spawnhook.rs23
-rw-r--r--library/std/src/thread/tests.rs5
-rw-r--r--library/std/tests/sync/mutex.rs10
-rw-r--r--library/std/tests/sync/once.rs4
-rw-r--r--library/std/tests/sync/once_lock.rs6
-rw-r--r--library/std/tests/sync/rwlock.rs16
-rw-r--r--rustfmt.toml1
-rw-r--r--src/bootstrap/Cargo.lock8
-rw-r--r--src/bootstrap/Cargo.toml6
-rw-r--r--src/bootstrap/bootstrap.py27
-rwxr-xr-xsrc/bootstrap/configure.py5
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/src/bin/main.rs80
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs56
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs216
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs3
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs107
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs32
-rw-r--r--src/bootstrap/src/core/builder/tests.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs156
-rw-r--r--src/bootstrap/src/core/config/tests.rs22
-rw-r--r--src/bootstrap/src/lib.rs66
-rw-r--r--src/bootstrap/src/utils/cc_detect/tests.rs2
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs27
-rw-r--r--src/bootstrap/src/utils/helpers.rs17
-rw-r--r--src/bootstrap/src/utils/metrics.rs22
-rw-r--r--src/bootstrap/src/utils/proc_macro_deps.rs15
-rw-r--r--src/bootstrap/src/utils/tarball.rs28
-rw-r--r--src/build_helper/src/git.rs13
-rw-r--r--src/build_helper/src/metrics.rs74
-rw-r--r--src/ci/citool/Cargo.lock7
-rw-r--r--src/ci/citool/Cargo.toml1
-rw-r--r--src/ci/citool/src/analysis.rs219
-rw-r--r--src/ci/citool/src/main.rs51
-rw-r--r--src/ci/citool/src/metrics.rs20
-rw-r--r--src/ci/citool/src/utils.rs1
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh3
-rwxr-xr-xsrc/ci/docker/run.sh2
m---------src/doc/book0
m---------src/doc/reference0
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ui.md41
-rw-r--r--src/doc/rustc/src/SUMMARY.md35
-rw-r--r--src/doc/rustc/src/command-line-arguments.md53
-rw-r--r--src/doc/rustc/src/command-line-arguments/print-options.md212
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/apple-darwin.md3
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios-macabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md3
-rw-r--r--src/doc/rustc/src/platform-support/apple-tvos.md3
-rw-r--r--src/doc/rustc/src/platform-support/apple-visionos.md3
-rw-r--r--src/doc/rustc/src/platform-support/apple-watchos.md3
-rw-r--r--src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md28
-rw-r--r--src/doc/rustc/src/platform-support/netbsd.md2
-rw-r--r--src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md52
-rw-r--r--src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md3
-rw-r--r--src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/embed-metadata.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md23
-rw-r--r--src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md27
-rw-r--r--src/doc/unstable-book/src/language-features/inline-const-pat.md22
-rw-r--r--src/doc/unstable-book/src/library-features/c-variadic.md26
-rw-r--r--src/etc/installer/msi/rust.wxs57
-rw-r--r--src/etc/test-float-parse/Cargo.toml2
-rw-r--r--src/etc/test-float-parse/src/gen_/exhaustive.rs (renamed from src/etc/test-float-parse/src/gen/exhaustive.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/exponents.rs (renamed from src/etc/test-float-parse/src/gen/exponents.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/fuzz.rs (renamed from src/etc/test-float-parse/src/gen/fuzz.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/integers.rs (renamed from src/etc/test-float-parse/src/gen/integers.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/long_fractions.rs (renamed from src/etc/test-float-parse/src/gen/long_fractions.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/many_digits.rs (renamed from src/etc/test-float-parse/src/gen/many_digits.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/sparse.rs (renamed from src/etc/test-float-parse/src/gen/sparse.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/spot_checks.rs (renamed from src/etc/test-float-parse/src/gen/spot_checks.rs)0
-rw-r--r--src/etc/test-float-parse/src/gen_/subnorm.rs (renamed from src/etc/test-float-parse/src/gen/subnorm.rs)0
-rw-r--r--src/etc/test-float-parse/src/lib.rs38
-rw-r--r--src/etc/test-float-parse/src/ui.rs2
m---------src/gcc0
-rw-r--r--src/librustdoc/clean/auto_trait.rs8
-rw-r--r--src/librustdoc/clean/blanket_impl.rs8
-rw-r--r--src/librustdoc/clean/cfg.rs14
-rw-r--r--src/librustdoc/clean/inline.rs26
-rw-r--r--src/librustdoc/clean/mod.rs13
-rw-r--r--src/librustdoc/clean/types.rs140
-rw-r--r--src/librustdoc/doctest/make.rs548
-rw-r--r--src/librustdoc/doctest/rust.rs4
-rw-r--r--src/librustdoc/doctest/tests.rs78
-rw-r--r--src/librustdoc/formats/cache.rs3
-rw-r--r--src/librustdoc/html/markdown.rs83
-rw-r--r--src/librustdoc/html/render/mod.rs16
-rw-r--r--src/librustdoc/html/render/sidebar.rs67
-rw-r--r--src/librustdoc/html/render/span_map.rs2
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts43
-rw-r--r--src/librustdoc/html/static/js/search.js165
-rw-r--r--src/librustdoc/html/static/js/src-script.js28
-rw-r--r--src/librustdoc/html/static/js/storage.js44
-rw-r--r--src/librustdoc/json/conversions.rs2
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs6
-rw-r--r--src/librustdoc/scrape_examples.rs3
-rw-r--r--src/rustdoc-json-types/lib.rs22
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cfg_not_test.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/duplicate_mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_line_after.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_with_brackets.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/partial_pub_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs101
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1782.rs2
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed66
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs66
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr136
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed79
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs79
-rw-r--r--src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr136
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed1
-rw-r--r--src/tools/clippy/tests/ui/rename.rs1
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr30
-rw-r--r--src/tools/compiletest/src/errors.rs61
-rw-r--r--src/tools/compiletest/src/header.rs45
-rw-r--r--src/tools/compiletest/src/header/tests.rs7
-rw-r--r--src/tools/compiletest/src/json.rs88
-rw-r--r--src/tools/compiletest/src/lib.rs32
-rw-r--r--src/tools/compiletest/src/runtest.rs4
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs2
-rw-r--r--src/tools/jsondocck/Cargo.toml2
-rw-r--r--src/tools/jsondocck/src/cache.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs2
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs14
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/run-make-support/src/run.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs4
-rw-r--r--src/tools/rustbook/Cargo.lock404
-rw-r--r--src/tools/rustbook/Cargo.toml2
-rw-r--r--src/tools/rustdoc-js/tester.js2
-rw-r--r--src/tools/rustfmt/src/closures.rs1
-rw-r--r--src/tools/rustfmt/src/expr.rs2
-rw-r--r--src/tools/rustfmt/src/items.rs102
-rw-r--r--src/tools/rustfmt/src/macros.rs35
-rw-r--r--src/tools/rustfmt/src/modules.rs10
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs2
-rw-r--r--src/tools/rustfmt/src/patterns.rs4
-rw-r--r--src/tools/rustfmt/src/reorder.rs17
-rw-r--r--src/tools/rustfmt/src/types.rs2
-rw-r--r--src/tools/rustfmt/src/visitor.rs82
-rw-r--r--src/tools/rustfmt/tests/source/pattern.rs2
-rw-r--r--src/tools/rustfmt/tests/target/pattern.rs2
-rw-r--r--src/tools/suggest-tests/src/main.rs6
-rw-r--r--src/tools/tidy/src/deps.rs10
-rw-r--r--src/tools/tidy/src/issues.txt5
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--src/tools/tidy/src/unstable_book.rs29
-rw-r--r--src/version2
-rw-r--r--tests/assembly/cstring-merging.rs27
-rw-r--r--tests/assembly/powerpc64-struct-abi.rs2
-rw-r--r--tests/assembly/s390x-vector-abi.rs4
-rw-r--r--tests/assembly/x86_64-cmp.rs46
-rw-r--r--tests/codegen/asm/s390x-clobbers.rs2
-rw-r--r--tests/codegen/assign-desugar-debuginfo.rs18
-rw-r--r--tests/codegen/cast-target-abi.rs2
-rw-r--r--tests/codegen/cffi/ffi-out-of-bounds-loads.rs2
-rw-r--r--tests/codegen/comparison-operators-2-tuple.rs1
-rw-r--r--tests/codegen/const-array.rs4
-rw-r--r--tests/codegen/debug-vtable.rs2
-rw-r--r--tests/codegen/external-no-mangle-statics.rs32
-rw-r--r--tests/codegen/integer-cmp.rs35
-rw-r--r--tests/codegen/intrinsics/three_way_compare.rs27
-rw-r--r--tests/codegen/link_section.rs2
-rw-r--r--tests/codegen/remap_path_prefix/main.rs2
-rw-r--r--tests/codegen/slice-is-ascii.rs2
-rw-r--r--tests/codegen/slice-last-elements-optimization.rs37
-rw-r--r--tests/codegen/uninit-consts.rs6
-rw-r--r--tests/codegen/uninit-repeat-in-aggregate.rs21
-rw-r--r--tests/coverage-run-rustdoc/doctest.coverage16
-rw-r--r--tests/coverage/abort.cov-map4
-rw-r--r--tests/coverage/assert-ne.cov-map4
-rw-r--r--tests/coverage/assert-ne.coverage2
-rw-r--r--tests/coverage/assert-ne.rs2
-rw-r--r--tests/coverage/assert_not.cov-map10
-rw-r--r--tests/coverage/async_block.cov-map8
-rw-r--r--tests/coverage/async_block.coverage2
-rw-r--r--tests/coverage/async_closure.cov-map22
-rw-r--r--tests/coverage/async_closure.coverage6
-rw-r--r--tests/coverage/attr/off-on-sandwich.cov-map12
-rw-r--r--tests/coverage/bad_counter_ids.cov-map16
-rw-r--r--tests/coverage/branch/guard.cov-map4
-rw-r--r--tests/coverage/branch/if-let.cov-map4
-rw-r--r--tests/coverage/branch/if.cov-map18
-rw-r--r--tests/coverage/branch/lazy-boolean.cov-map20
-rw-r--r--tests/coverage/branch/let-else.cov-map6
-rw-r--r--tests/coverage/branch/match-arms.cov-map34
-rw-r--r--tests/coverage/branch/match-trivial.cov-map8
-rw-r--r--tests/coverage/branch/while.cov-map16
-rw-r--r--tests/coverage/closure.cov-map12
-rw-r--r--tests/coverage/closure.coverage22
-rw-r--r--tests/coverage/closure_macro.cov-map6
-rw-r--r--tests/coverage/closure_macro_async.cov-map6
-rw-r--r--tests/coverage/condition/conditions.cov-map10
-rw-r--r--tests/coverage/coroutine.cov-map8
-rw-r--r--tests/coverage/holes.cov-map22
-rw-r--r--tests/coverage/holes.coverage20
-rw-r--r--tests/coverage/inline-dead.cov-map4
-rw-r--r--tests/coverage/inline.cov-map4
-rw-r--r--tests/coverage/issue-83601.cov-map6
-rw-r--r--tests/coverage/issue-84561.cov-map34
-rw-r--r--tests/coverage/issue-84561.coverage42
-rw-r--r--tests/coverage/loop-break.cov-map4
-rw-r--r--tests/coverage/loops_branches.cov-map12
-rw-r--r--tests/coverage/macro_name_span.cov-map4
-rw-r--r--tests/coverage/mcdc/non_control_flow.cov-map10
-rw-r--r--tests/coverage/no_cov_crate.cov-map8
-rw-r--r--tests/coverage/panic_unwind.cov-map4
-rw-r--r--tests/coverage/sort_groups.cov-map4
-rw-r--r--tests/coverage/try_error_result.cov-map50
-rw-r--r--tests/coverage/try_error_result.coverage2
-rw-r--r--tests/coverage/unicode.cov-map6
-rw-r--r--tests/coverage/unicode.coverage2
-rw-r--r--tests/coverage/unreachable.cov-map12
-rw-r--r--tests/coverage/yield.cov-map10
-rw-r--r--tests/crashes/122904.rs12
-rw-r--r--tests/crashes/134334.rs9
-rw-r--r--tests/crashes/134335.rs12
-rw-r--r--tests/incremental/define-opaques.rs19
-rw-r--r--tests/incremental/delayed_span_bug.rs4
-rw-r--r--tests/incremental/env/env_macro.rs18
-rw-r--r--tests/incremental/env/option_env_macro.rs18
-rw-r--r--tests/incremental/user-written-closure-synthetic-closure-conflict.rs15
-rw-r--r--tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir (renamed from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir)4
-rw-r--r--tests/mir-opt/async_closure_fake_read_for_by_move.rs2
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir (renamed from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir)4
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir (renamed from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir)4
-rw-r--r--tests/mir-opt/async_closure_shims.rs4
-rw-r--r--tests/mir-opt/coroutine_drop_cleanup.rs2
-rw-r--r--tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff8
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff49
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff49
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff49
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff49
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.rs39
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir48
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir48
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir44
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir44
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir70
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.rs24
-rw-r--r--tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir70
-rw-r--r--tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir70
-rw-r--r--tests/mir-opt/pre-codegen/tuple_ord.rs16
-rw-r--r--tests/pretty/autodiff_forward.pp6
-rw-r--r--tests/pretty/autodiff_forward.rs2
-rw-r--r--tests/pretty/autodiff_reverse.pp2
-rw-r--r--tests/pretty/autodiff_reverse.rs2
-rw-r--r--tests/pretty/hir-lifetimes.pp96
-rw-r--r--tests/pretty/hir-lifetimes.rs91
-rw-r--r--tests/pretty/hir-struct-expr.pp28
-rw-r--r--tests/pretty/hir-struct-expr.rs24
-rw-r--r--tests/pretty/stmt_expr_attributes.rs5
-rw-r--r--tests/pretty/tests-are-sorted.pp3
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs4
-rw-r--r--tests/run-make/doctests-keep-binaries/rmake.rs2
-rw-r--r--tests/run-make/embed-metadata/dep1.rs1
-rw-r--r--tests/run-make/embed-metadata/foo.rs5
-rw-r--r--tests/run-make/embed-metadata/rmake.rs86
-rw-r--r--tests/run-make/issue-107495-archive-permissions/rmake.rs4
-rw-r--r--tests/run-make/print-crate-root-lint-levels/lib.rs5
-rw-r--r--tests/run-make/print-crate-root-lint-levels/rmake.rs118
-rw-r--r--tests/run-make/rustc-help/help-v.stdout2
-rw-r--r--tests/run-make/rustc-help/help.stdout2
-rw-r--r--tests/run-make/rustdoc-error-lines/rmake.rs6
-rw-r--r--tests/run-make/symbols-all-mangled/rmake.rs16
-rw-r--r--tests/run-make/target-cpu-native/rmake.rs2
-rw-r--r--tests/rustdoc-json/assoc_items.rs24
-rw-r--r--tests/rustdoc-json/assoc_type.rs8
-rw-r--r--tests/rustdoc-json/attrs/automatically_derived.rs13
-rw-r--r--tests/rustdoc-json/attrs/deprecated.rs32
-rw-r--r--tests/rustdoc-json/attrs/export_name_2021.rs2
-rw-r--r--tests/rustdoc-json/attrs/export_name_2024.rs2
-rw-r--r--tests/rustdoc-json/attrs/must_use.rs4
-rw-r--r--tests/rustdoc-json/attrs/no_mangle_2021.rs2
-rw-r--r--tests/rustdoc-json/attrs/no_mangle_2024.rs2
-rw-r--r--tests/rustdoc-json/attrs/non_exhaustive.rs6
-rw-r--r--tests/rustdoc-json/attrs/repr_align.rs2
-rw-r--r--tests/rustdoc-json/attrs/repr_c.rs6
-rw-r--r--tests/rustdoc-json/attrs/repr_combination.rs23
-rw-r--r--tests/rustdoc-json/attrs/repr_int_enum.rs6
-rw-r--r--tests/rustdoc-json/attrs/repr_packed.rs8
-rw-r--r--tests/rustdoc-json/attrs/repr_transparent.rs29
-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/extern_safe.rs8
-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-in-assoc-type.rs18
-rw-r--r--tests/rustdoc-json/impl-trait-precise-capturing.rs6
-rw-r--r--tests/rustdoc-json/impls/auto.rs6
-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.rs12
-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/impls/pub_for_hidden_private.rs2
-rw-r--r--tests/rustdoc-json/impls/trait-for-dyn-trait.rs14
-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.rs38
-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/path_name.rs42
-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/pub_mod_in_private_mod.rs2
-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.rs16
-rw-r--r--tests/rustdoc-json/reexport/simple_public.rs18
-rw-r--r--tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs2
-rw-r--r--tests/rustdoc-json/return-type-notation.rs4
-rw-r--r--tests/rustdoc-json/return_private.rs8
-rw-r--r--tests/rustdoc-json/statics/extern.rs36
-rw-r--r--tests/rustdoc-json/statics/statics.rs16
-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_dyn_compatible.rs12
-rw-r--r--tests/rustdoc-json/traits/private_supertrait.rs8
-rw-r--r--tests/rustdoc-json/traits/self.rs30
-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/coverage/html.rs2
-rw-r--r--tests/rustdoc-ui/deprecated-attrs.rs4
-rw-r--r--tests/rustdoc-ui/doc-cfg-check-cfg.rs16
-rw-r--r--tests/rustdoc-ui/doc-cfg-unstable.rs10
-rw-r--r--tests/rustdoc-ui/doc-cfg-unstable.stderr23
-rw-r--r--tests/rustdoc-ui/doctest-output.rs2
-rw-r--r--tests/rustdoc-ui/doctest/display-output.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/extern-crate.rs23
-rw-r--r--tests/rustdoc-ui/doctest/extern-crate.stdout6
-rw-r--r--tests/rustdoc-ui/doctest/per-target-ignores.rs14
-rw-r--r--tests/rustdoc-ui/doctest/per-target-ignores.stdout6
-rw-r--r--tests/rustdoc-ui/extract-doctests.stdout2
-rw-r--r--tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs2
-rw-r--r--tests/rustdoc-ui/include-str-bare-urls.rs2
-rw-r--r--tests/rustdoc-ui/lints/check.rs2
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout4
-rw-r--r--tests/rustdoc-ui/remap-path-prefix-lint.rs2
-rw-r--r--tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs2
-rw-r--r--tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs2
-rw-r--r--tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs2
-rw-r--r--tests/rustdoc-ui/use_both_out_dir_and_output_options.rs2
-rw-r--r--tests/rustdoc/deref/deref-methods-24686-target.rs27
-rw-r--r--tests/rustdoc/playground.rs2
-rw-r--r--tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs16
-rw-r--r--tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr15
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs1
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_visitor.rs81
-rw-r--r--tests/ui/abi/compatibility.rs1
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.rs1
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.stderr44
-rw-r--r--tests/ui/abi/simd-abi-checks-s390x.rs2
-rw-r--r--tests/ui/asm/inline-syntax.rs5
-rw-r--r--tests/ui/asm/naked-functions-target-feature.rs21
-rw-r--r--tests/ui/asm/naked-functions.rs7
-rw-r--r--tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr (renamed from tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr)4
-rw-r--r--tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs7
-rw-r--r--tests/ui/associated-types/bound-lifetime-constrained.ok.stderr8
-rw-r--r--tests/ui/associated-types/bound-lifetime-constrained.rs5
-rw-r--r--tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr8
-rw-r--r--tests/ui/associated-types/bound-lifetime-in-binding-only.rs5
-rw-r--r--tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr8
-rw-r--r--tests/ui/associated-types/bound-lifetime-in-return-only.rs5
-rw-r--r--tests/ui/associated-types/issue-59324.stderr26
-rw-r--r--tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs28
-rw-r--r--tests/ui/attributes/crate-name-empty.rs5
-rw-r--r--tests/ui/attributes/crate-name-empty.stderr8
-rw-r--r--tests/ui/attributes/dont-dup-expr-attrs.rs133
-rw-r--r--tests/ui/attributes/inner-attr-metavar.rs14
-rw-r--r--tests/ui/attributes/nonterminal-expansion.rs4
-rw-r--r--tests/ui/attributes/nonterminal-expansion.stderr11
-rw-r--r--tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs3
-rw-r--r--tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr6
-rw-r--r--tests/ui/borrowck/mut-borrow-outside-loop.rs4
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs36
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr48
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs36
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr43
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs41
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr140
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-wrap.rs32
-rw-r--r--tests/ui/cfg/disallowed-cli-cfgs.rs2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr2
-rw-r--r--tests/ui/check-cfg/invalid-arguments.rs2
-rw-r--r--tests/ui/check-cfg/target_feature.stderr49
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/closures/upvar-or-pattern-issue-138958.rs11
-rw-r--r--tests/ui/codegen/duplicated-path-in-error.rs2
-rw-r--r--tests/ui/codegen/empty-static-libs-issue-108825.rs16
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs23
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs25
-rw-r--r--tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs25
-rw-r--r--tests/ui/codemap_tests/issue-11715.rs3
-rw-r--r--tests/ui/codemap_tests/issue-11715.stderr2
-rw-r--r--tests/ui/coercion/struct-coerce-vec-to-slice.rs20
-rw-r--r--tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs16
-rw-r--r--tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs3
-rw-r--r--tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr16
-rw-r--r--tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs3
-rw-r--r--tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr8
-rw-r--r--tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.rs41
-rw-r--r--tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.stderr23
-rw-r--r--tests/ui/consts/assoc-const-elided-lifetime.stderr2
-rw-r--r--tests/ui/consts/async-block.rs5
-rw-r--r--tests/ui/consts/async-block.with_feature.stderr8
-rw-r--r--tests/ui/consts/const-eval/const_fn_ptr.rs2
-rw-r--r--tests/ui/consts/const-eval/const_fn_ptr_fail.rs2
-rw-r--r--tests/ui/consts/const-eval/const_fn_ptr_fail2.rs2
-rw-r--r--tests/ui/consts/const-eval/issue-85155.rs3
-rw-r--r--tests/ui/consts/const_in_pattern/arrays-and-slices.rs53
-rw-r--r--tests/ui/consts/const_in_pattern/arrays-and-slices.stderr84
-rw-r--r--tests/ui/consts/invalid-inline-const-in-match-arm.rs9
-rw-r--r--tests/ui/consts/invalid-inline-const-in-match-arm.stderr18
-rw-r--r--tests/ui/consts/miri_unleashed/abi-mismatch.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/assoc_const.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/box.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/inline_asm.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/mutable_references.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/non_const_fn.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/ptr_arith.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/static-no-inner-mut.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/tls.rs2
-rw-r--r--tests/ui/consts/static-default-lifetime/elided-lifetime.rs2
-rw-r--r--tests/ui/consts/static-default-lifetime/elided-lifetime.stderr20
-rw-r--r--tests/ui/consts/static-default-lifetime/static-trait-impl.rs15
-rw-r--r--tests/ui/consts/static-default-lifetime/static-trait-impl.stderr24
-rw-r--r--tests/ui/consts/too_generic_eval_ice.current.stderr (renamed from tests/ui/consts/too_generic_eval_ice.stderr)8
-rw-r--r--tests/ui/consts/too_generic_eval_ice.next.stderr9
-rw-r--r--tests/ui/consts/too_generic_eval_ice.rs13
-rw-r--r--tests/ui/coverage-attr/name-value.stderr34
-rw-r--r--tests/ui/coverage-attr/word-only.stderr30
-rw-r--r--tests/ui/custom_test_frameworks/full.rs15
-rw-r--r--tests/ui/dep-graph/dep-graph-dump.rs2
-rw-r--r--tests/ui/deprecation/deprecated_ar.rs2
-rw-r--r--tests/ui/deprecation/deprecated_inline_threshold.rs6
-rw-r--r--tests/ui/deprecation/deprecated_no_stack_check_opt.rs2
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.rs10
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr10
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.rs5
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.stderr14
-rw-r--r--tests/ui/did_you_mean/recursion_limit_deref.rs3
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.rs2
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.rs2
-rw-r--r--tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs2
-rw-r--r--tests/ui/errors/wrong-target-spec.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr20
-rw-r--r--tests/ui/feature-gates/feature-gate-inline_const_pat.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-inline_const_pat.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-link-arg-attribute.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-movrs_target_feature.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs26
-rw-r--r--tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr111
-rw-r--r--tests/ui/fmt/fmt_debug/invalid.rs2
-rw-r--r--tests/ui/fn/bad-turbofish-hints-issue-121901.rs8
-rw-r--r--tests/ui/fn/bad-turbofish-hints-issue-121901.stderr25
-rw-r--r--tests/ui/fn/trait-fn-generic-mismatch.rs12
-rw-r--r--tests/ui/fn/trait-fn-generic-mismatch.stderr32
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions0.rs5
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.rs2
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.stderr19
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.rs22
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.stderr43
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions3.rs19
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions3.stderr13
-rw-r--r--tests/ui/impl-trait/define-via-const.rs12
-rw-r--r--tests/ui/impl-trait/define-via-extern.rs16
-rw-r--r--tests/ui/impl-trait/define-via-extern.stderr14
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs3
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr18
-rw-r--r--tests/ui/impl-trait/impl_trait_projections.rs5
-rw-r--r--tests/ui/impl-trait/impl_trait_projections.stderr10
-rw-r--r--tests/ui/impl-trait/in-trait/dump.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/refine-captures.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/refine-captures.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/variance.rs2
-rw-r--r--tests/ui/impl-trait/inside-item-nested-in-anon-const.rs25
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.stderr23
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr4
-rw-r--r--tests/ui/impl-trait/precise-capturing/redundant.rs1
-rw-r--r--tests/ui/impl-trait/precise-capturing/redundant.stderr10
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr4
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr4
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit.stderr6
-rw-r--r--tests/ui/impl-trait/precise-capturing/self-capture.rs2
-rw-r--r--tests/ui/imports/glob-resolve1.stderr5
-rw-r--r--tests/ui/imports/issue-4366-2.stderr5
-rw-r--r--tests/ui/imports/issue-4366.stderr5
-rw-r--r--tests/ui/imports/show-private-items-issue-138626.rs19
-rw-r--r--tests/ui/imports/show-private-items-issue-138626.stderr20
-rw-r--r--tests/ui/infinite/infinite-autoderef.stderr4
-rw-r--r--tests/ui/infinite/infinite-struct.rs2
-rw-r--r--tests/ui/inline-const/collect-scopes-in-pat.rs16
-rw-r--r--tests/ui/inline-const/const-block-pat-liveness.rs18
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.rs28
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.stderr15
-rw-r--r--tests/ui/inline-const/const-match-pat-inference.rs11
-rw-r--r--tests/ui/inline-const/const-match-pat-lifetime-err.rs47
-rw-r--r--tests/ui/inline-const/const-match-pat-lifetime-err.stderr28
-rw-r--r--tests/ui/inline-const/const-match-pat-lifetime.rs34
-rw-r--r--tests/ui/inline-const/const-match-pat-range.rs38
-rw-r--r--tests/ui/inline-const/const-match-pat.rs20
-rw-r--r--tests/ui/inline-const/in-pat-recovery.rs11
-rw-r--r--tests/ui/inline-const/in-pat-recovery.stderr10
-rw-r--r--tests/ui/inline-const/pat-match-fndef.rs12
-rw-r--r--tests/ui/inline-const/pat-match-fndef.stderr8
-rw-r--r--tests/ui/inline-const/pat-unsafe-err.rs22
-rw-r--r--tests/ui/inline-const/pat-unsafe-err.stderr19
-rw-r--r--tests/ui/inline-const/pat-unsafe.rs29
-rw-r--r--tests/ui/inline-const/pat-unsafe.stderr20
-rw-r--r--tests/ui/instrument-coverage/bad-value.rs3
-rw-r--r--tests/ui/instrument-coverage/coverage-options.rs2
-rw-r--r--tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs4
-rw-r--r--tests/ui/invalid-compile-flags/invalid-llvm-passes.rs2
-rw-r--r--tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs3
-rw-r--r--tests/ui/invalid-compile-flags/print-without-arg.stderr2
-rw-r--r--tests/ui/invalid-compile-flags/print.rs2
-rw-r--r--tests/ui/invalid-compile-flags/print.stderr2
-rw-r--r--tests/ui/invalid-module-declaration/invalid-module-declaration.rs2
-rw-r--r--tests/ui/issues/issue-28777.rs22
-rw-r--r--tests/ui/issues/issue-31260.rs15
-rw-r--r--tests/ui/issues/issue-9382.rs37
-rw-r--r--tests/ui/lang-items/lang-item-generic-requirements.rs2
-rw-r--r--tests/ui/layout/reprc-power-alignment.rs26
-rw-r--r--tests/ui/link-native-libs/modifiers-bad.rs5
-rw-r--r--tests/ui/link-native-libs/modifiers-override-2.rs2
-rw-r--r--tests/ui/link-native-libs/msvc-non-utf8-output.rs2
-rw-r--r--tests/ui/linkage-attr/link-self-contained-consistency.rs3
-rw-r--r--tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs2
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs2
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs2
-rw-r--r--tests/ui/lint/dead-code/anon-const-in-pat.rs44
-rw-r--r--tests/ui/lint/expansion-time.rs2
-rw-r--r--tests/ui/lint/inert-attr-macro.rs7
-rw-r--r--tests/ui/lint/inert-attr-macro.stderr14
-rw-r--r--tests/ui/lint/inline-exported.rs30
-rw-r--r--tests/ui/lint/inline-exported.stderr31
-rw-r--r--tests/ui/lint/invalid_null_args.rs136
-rw-r--r--tests/ui/lint/invalid_null_args.stderr330
-rw-r--r--tests/ui/lint/linker-warning.stderr2
-rw-r--r--tests/ui/lint/lint-unexported-no-mangle.rs7
-rw-r--r--tests/ui/lint/unused/lint-unused-imports-self-single.fixed29
-rw-r--r--tests/ui/lint/unused/lint-unused-imports-self-single.rs30
-rw-r--r--tests/ui/lint/unused/lint-unused-imports-self-single.stderr44
-rw-r--r--tests/ui/lint/wasm_c_abi_transition.rs41
-rw-r--r--tests/ui/lint/wasm_c_abi_transition.stderr85
-rw-r--r--tests/ui/lto/lto-and-no-bitcode-in-rlib.rs2
-rw-r--r--tests/ui/macros/include-single-expr.rs4
-rw-r--r--tests/ui/macros/nonterminal-matching.rs4
-rw-r--r--tests/ui/macros/nonterminal-matching.stderr4
-rw-r--r--tests/ui/match/issue-112438.rs10
-rw-r--r--tests/ui/match/validate-range-endpoints.rs3
-rw-r--r--tests/ui/match/validate-range-endpoints.stderr28
-rw-r--r--tests/ui/mir-dataflow/inits-1.rs2
-rw-r--r--tests/ui/mir-dataflow/liveness-enum.rs2
-rw-r--r--tests/ui/mir-dataflow/liveness-projection.rs2
-rw-r--r--tests/ui/mir-dataflow/liveness-ptr.rs2
-rw-r--r--tests/ui/mir-dataflow/uninits-1.rs2
-rw-r--r--tests/ui/mir-dataflow/uninits-2.rs2
-rw-r--r--tests/ui/mir/enable_passes_validation.rs3
-rw-r--r--tests/ui/mir/inline-causes-trimmed-paths.rs36
-rw-r--r--tests/ui/mir/issue-75053.rs5
-rw-r--r--tests/ui/mir/issue-75053.stderr8
-rw-r--r--tests/ui/mir/var_debug_ref.rs24
-rw-r--r--tests/ui/missing/missing-allocator.rs2
-rw-r--r--tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs2
-rw-r--r--tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs2
-rw-r--r--tests/ui/occurs-check-2.rs2
-rw-r--r--tests/ui/occurs-check-2.stderr6
-rw-r--r--tests/ui/occurs-check-3.stderr4
-rw-r--r--tests/ui/occurs-check.stderr4
-rw-r--r--tests/ui/panic-handler/panic-handler-wrong-location.rs2
-rw-r--r--tests/ui/parser/attribute/attr-bad-meta-4.rs2
-rw-r--r--tests/ui/parser/attribute/attr-bad-meta-4.stderr24
-rw-r--r--tests/ui/parser/closure-return-syntax.rs16
-rw-r--r--tests/ui/parser/closure-return-syntax.stderr34
-rw-r--r--tests/ui/parser/extern-abi-from-mac-literal-frag.rs4
-rw-r--r--tests/ui/parser/float-field-interpolated.rs8
-rw-r--r--tests/ui/parser/float-field-interpolated.stderr8
-rw-r--r--tests/ui/parser/issues/issue-103451.rs2
-rw-r--r--tests/ui/parser/issues/issue-10636-2.rs2
-rw-r--r--tests/ui/parser/issues/issue-111692.rs32
-rw-r--r--tests/ui/parser/issues/issue-111692.stderr46
-rw-r--r--tests/ui/parser/issues/issue-24375.stderr4
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs3
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr2
-rw-r--r--tests/ui/parser/issues/issue-62524.rs3
-rw-r--r--tests/ui/parser/issues/issue-62524.stderr2
-rw-r--r--tests/ui/parser/issues/issue-62554.rs3
-rw-r--r--tests/ui/parser/issues/issue-62554.stderr2
-rw-r--r--tests/ui/parser/issues/issue-62894.rs2
-rw-r--r--tests/ui/parser/issues/issue-62973.rs4
-rw-r--r--tests/ui/parser/issues/issue-62973.stderr6
-rw-r--r--tests/ui/parser/issues/issue-63116.rs3
-rw-r--r--tests/ui/parser/issues/issue-63116.stderr4
-rw-r--r--tests/ui/parser/issues/issue-63135.rs3
-rw-r--r--tests/ui/parser/issues/issue-63135.stderr2
-rw-r--r--tests/ui/parser/issues/issue-81804.rs5
-rw-r--r--tests/ui/parser/issues/issue-81804.stderr4
-rw-r--r--tests/ui/parser/issues/issue-81827.rs7
-rw-r--r--tests/ui/parser/issues/issue-81827.stderr4
-rw-r--r--tests/ui/parser/issues/issue-84104.rs2
-rw-r--r--tests/ui/parser/issues/issue-84148-2.rs2
-rw-r--r--tests/ui/parser/issues/issue-88770.rs3
-rw-r--r--tests/ui/parser/issues/issue-88770.stderr2
-rw-r--r--tests/ui/parser/issues/issue-94340.rs3
-rw-r--r--tests/ui/parser/macro/trait-non-item-macros.rs2
-rw-r--r--tests/ui/parser/macro/trait-non-item-macros.stderr2
-rw-r--r--tests/ui/parser/mbe_missing_right_paren.rs2
-rw-r--r--tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs13
-rw-r--r--tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr13
-rw-r--r--tests/ui/parser/missing_right_paren.rs3
-rw-r--r--tests/ui/parser/missing_right_paren.stderr2
-rw-r--r--tests/ui/parser/operator-precedence-braces-exprs.rs28
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.stderr116
-rw-r--r--tests/ui/parser/recover/recover-pat-issues.stderr24
-rw-r--r--tests/ui/parser/recover/recover-pat-lets.stderr8
-rw-r--r--tests/ui/parser/recover/recover-pat-ranges.stderr24
-rw-r--r--tests/ui/parser/recover/recover-pat-wildcards.stderr4
-rw-r--r--tests/ui/parser/struct-literal-in-for.rs17
-rw-r--r--tests/ui/parser/struct-literal-in-for.stderr31
-rw-r--r--tests/ui/parser/struct-literal-in-if.rs22
-rw-r--r--tests/ui/parser/struct-literal-in-if.stderr34
-rw-r--r--tests/ui/parser/struct-literal-in-match-discriminant.rs13
-rw-r--r--tests/ui/parser/struct-literal-in-match-discriminant.stderr18
-rw-r--r--tests/ui/parser/struct-literal-in-while.rs22
-rw-r--r--tests/ui/parser/struct-literal-in-while.stderr34
-rw-r--r--tests/ui/parser/struct-literal-restrictions-in-lamda.rs17
-rw-r--r--tests/ui/parser/struct-literal-restrictions-in-lamda.stderr37
-rw-r--r--tests/ui/parser/struct-literal-variant-in-if.rs25
-rw-r--r--tests/ui/parser/struct-literal-variant-in-if.stderr76
-rw-r--r--tests/ui/parser/struct-literals-in-invalid-places.rs92
-rw-r--r--tests/ui/parser/struct-literals-in-invalid-places.stderr234
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.rs9
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.stderr80
-rw-r--r--tests/ui/parser/unbalanced-doublequote.rs4
-rw-r--r--tests/ui/parser/unbalanced-doublequote.stderr2
-rw-r--r--tests/ui/parser/unclosed-delimiter-in-dep.rs2
-rw-r--r--tests/ui/parser/use-unclosed-brace.rs2
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-flags.rs3
-rw-r--r--tests/ui/pattern/non-structural-match-types.rs31
-rw-r--r--tests/ui/pattern/non-structural-match-types.stderr46
-rw-r--r--tests/ui/pin-macro/pin_move.rs26
-rw-r--r--tests/ui/pin-macro/pin_move.stderr38
-rw-r--r--tests/ui/precondition-checks/copy-nonoverlapping.rs2
-rw-r--r--tests/ui/precondition-checks/copy.rs2
-rw-r--r--tests/ui/precondition-checks/read_volatile.rs2
-rw-r--r--tests/ui/precondition-checks/replace.rs2
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts-mut.rs2
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts.rs2
-rw-r--r--tests/ui/precondition-checks/swap-nonoverlapping.rs2
-rw-r--r--tests/ui/precondition-checks/write_volatile.rs2
-rw-r--r--tests/ui/precondition-checks/zero-size-null.rs2
-rw-r--r--tests/ui/print-request/invalid-target.rs2
-rw-r--r--tests/ui/print-request/print-lints-help.rs7
-rw-r--r--tests/ui/print-request/print-lints-help.stderr (renamed from tests/ui/rustc-print-info-issue-138612.stderr)2
-rw-r--r--tests/ui/print-request/stability.rs8
-rw-r--r--tests/ui/print-request/supported-crate-types.linux.stdout7
-rw-r--r--tests/ui/print-request/supported-crate-types.musl.stdout5
-rw-r--r--tests/ui/print-request/supported-crate-types.rs20
-rw-r--r--tests/ui/print-request/supported-crate-types.wasm.stdout5
-rw-r--r--tests/ui/privacy/privacy-ns1.stderr24
-rw-r--r--tests/ui/privacy/privacy-ns2.stderr24
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.rs7
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.stderr22
-rw-r--r--tests/ui/privacy/where-pub-type-impls-priv-trait.rs1
-rw-r--r--tests/ui/privacy/where-pub-type-impls-priv-trait.stderr20
-rw-r--r--tests/ui/proc-macro/cfg-attr-trace.rs10
-rw-r--r--tests/ui/proc-macro/cfg-attr-trace.stdout40
-rw-r--r--tests/ui/proc-macro/inner-attr-non-inline-mod.rs5
-rw-r--r--tests/ui/proc-macro/inner-attr-non-inline-mod.stderr4
-rw-r--r--tests/ui/proc-macro/inner-attr-non-inline-mod.stdout30
-rw-r--r--tests/ui/proc-macro/macro-rules-derive-cfg.stdout129
-rw-r--r--tests/ui/proc-macro/no-macro-use-attr.rs5
-rw-r--r--tests/ui/proc-macro/no-macro-use-attr.stderr8
-rw-r--r--tests/ui/proc-macro/nonterminal-token-hygiene.stdout20
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.rs2
-rw-r--r--tests/ui/resolve/auxiliary/macro_helpers.rs16
-rw-r--r--tests/ui/resolve/issue-21221-1.stderr11
-rw-r--r--tests/ui/resolve/parse-error-resolve.rs2
-rw-r--r--tests/ui/resolve/prelude-order.rs89
-rw-r--r--tests/ui/resolve/prelude-order.stderr47
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs6
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs2
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs2
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr264
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr274
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr196
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs4
-rw-r--r--tests/ui/rmeta/no_optitimized_mir.rs2
-rw-r--r--tests/ui/rmeta/no_optitimized_mir.stderr2
-rw-r--r--tests/ui/runtime/on-broken-pipe/default.rs2
-rw-r--r--tests/ui/runtime/on-broken-pipe/no-flag-arg.rs2
-rw-r--r--tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs2
-rw-r--r--tests/ui/rustc-env/min-stack-banana.rs3
-rw-r--r--tests/ui/rustc-error.rs6
-rw-r--r--tests/ui/rustc-error.stderr8
-rw-r--r--tests/ui/rustc-print-info-issue-138612.rs2
-rw-r--r--tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs2
-rw-r--r--tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs2
-rw-r--r--tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs3
-rw-r--r--tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs2
-rw-r--r--tests/ui/sanitizer/cfi/requires-lto.rs2
-rw-r--r--tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs2
-rw-r--r--tests/ui/sanitizer/crt-static.rs2
-rw-r--r--tests/ui/sanitizer/split-lto-unit-requires-lto.rs2
-rw-r--r--tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs26
-rw-r--r--tests/ui/simd/empty-simd-vector-in-operand.rs15
-rw-r--r--tests/ui/simd/empty-simd-vector-in-operand.stderr15
-rw-r--r--tests/ui/sized/dont-incompletely-prefer-built-in.rs21
-rw-r--r--tests/ui/span/range-2.rs4
-rw-r--r--tests/ui/span/regionck-unboxed-closure-lifetimes.rs3
-rw-r--r--tests/ui/span/regionck-unboxed-closure-lifetimes.stderr2
-rw-r--r--tests/ui/stable-mir-print/async-closure.stdout2
-rw-r--r--tests/ui/stack-protector/warn-stack-protector-unsupported.rs4
-rw-r--r--tests/ui/stats/input-stats.stderr84
-rw-r--r--tests/ui/std/channel-stack-overflow-issue-102246.rs20
-rw-r--r--tests/ui/structs/struct-construct-with-call-issue-138931.rs25
-rw-r--r--tests/ui/structs/struct-construct-with-call-issue-138931.stderr58
-rw-r--r--tests/ui/suggestions/attribute-typos.rs4
-rw-r--r--tests/ui/suggestions/attribute-typos.stderr10
-rw-r--r--tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs17
-rw-r--r--tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr21
-rw-r--r--tests/ui/symbol-mangling-version/bad-value.rs4
-rw-r--r--tests/ui/symbol-mangling-version/unstable.rs3
-rw-r--r--tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs2
-rw-r--r--tests/ui/target-feature/invalid-attribute.stderr12
-rw-r--r--tests/ui/target-feature/missing-plusminus-2.rs2
-rw-r--r--tests/ui/target-feature/missing-plusminus.rs2
-rw-r--r--tests/ui/target-feature/similar-feature-suggestion.rs2
-rw-r--r--tests/ui/target-feature/tied-features-cli.rs4
-rw-r--r--tests/ui/target-feature/tied-features-no-implication-1.rs2
-rw-r--r--tests/ui/target-feature/unstable-feature.rs2
-rw-r--r--tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs7
-rw-r--r--tests/ui/target_modifiers/defaults_check.error.stderr4
-rw-r--r--tests/ui/target_modifiers/incompatible_regparm.rs2
-rw-r--r--tests/ui/target_modifiers/no_value_bool.error.stderr13
-rw-r--r--tests/ui/target_modifiers/no_value_bool.error_explicit.stderr13
-rw-r--r--tests/ui/target_modifiers/no_value_bool.rs22
-rw-r--r--tests/ui/thread-local/spawn-hook-atexit.rs24
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.rs7
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.stderr2
-rw-r--r--tests/ui/traits/const-traits/feature-gate.gated.stderr8
-rw-r--r--tests/ui/traits/const-traits/feature-gate.rs5
-rw-r--r--tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr9
-rw-r--r--tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr9
-rw-r--r--tests/ui/traits/incomplete-infer-via-sized-wc.rs19
-rw-r--r--tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs28
-rw-r--r--tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr27
-rw-r--r--tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr25
-rw-r--r--tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs26
-rw-r--r--tests/ui/traits/mutual-recursion-issue-75860.stderr2
-rw-r--r--tests/ui/traits/next-solver/well-formed-in-relate.rs21
-rw-r--r--tests/ui/traits/next-solver/well-formed-in-relate.stderr27
-rw-r--r--tests/ui/traits/object/suggestion-trait-object-issue-139174.rs24
-rw-r--r--tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr40
-rw-r--r--tests/ui/treat-err-as-bug/span_delayed_bug.rs2
-rw-r--r--tests/ui/treat-err-as-bug/span_delayed_bug.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs18
-rw-r--r--tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr30
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.stderr51
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53096.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53096.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60407.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60407.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr57
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr11
-rw-r--r--tests/ui/type/pattern_types/const_block.rs10
-rw-r--r--tests/ui/type/pattern_types/literals.rs3
-rw-r--r--tests/ui/type/pattern_types/range_patterns.rs4
-rw-r--r--tests/ui/type/pattern_types/validity.rs2
-rw-r--r--tests/ui/type/pattern_types/validity.stderr26
-rw-r--r--tests/ui/unpretty/avoid-crash.rs2
-rw-r--r--tests/ui/unresolved/unresolved-import.rs2
-rw-r--r--tests/ui/unresolved/unresolved-import.stderr10
-rw-r--r--tests/ui/unsafe/const_pat_in_layout_restricted.rs23
-rw-r--r--tests/ui/variance/variance-uniquearc.rs27
-rw-r--r--tests/ui/variance/variance-uniquearc.stderr15
-rw-r--r--tests/ui/variance/variance-uniquerc.rs2
-rw-r--r--triagebot.toml60
1470 files changed, 21634 insertions, 16076 deletions
diff --git a/.gitattributes b/.gitattributes
index d29c15fe712..8700d5d6dcf 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,6 +5,7 @@
 *.h rust
 *.rs rust diff=rust
 *.fixed linguist-language=Rust
+*.pp linguist-language=Rust
 *.mir linguist-language=Rust
 src/etc/installer/gfx/* binary
 src/vendor/** -text
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 25397006ee2..51dd0f81ed1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -69,6 +69,8 @@ jobs:
     env:
       CI_JOB_NAME: ${{ matrix.name }}
       CI_JOB_DOC_URL: ${{ matrix.doc_url }}
+      GITHUB_WORKFLOW_RUN_ID: ${{ github.run_id }}
+      GITHUB_REPOSITORY: ${{ github.repository }}
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
       HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
diff --git a/.gitmodules b/.gitmodules
index 97a0c0c54cf..d09d81ccadc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -45,7 +45,7 @@
 	shallow = true
 [submodule "src/tools/enzyme"]
 	path = src/tools/enzyme
-	url = https://github.com/EnzymeAD/Enzyme.git
+	url = https://github.com/rust-lang/Enzyme.git
 	shallow = true
 [submodule "src/gcc"]
 	path = src/gcc
diff --git a/Cargo.lock b/Cargo.lock
index 90e035e8010..96526f7e9e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -35,18 +35,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "ahash"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
-dependencies = [
- "cfg-if",
- "once_cell",
- "version_check",
- "zerocopy 0.7.35",
-]
-
-[[package]]
 name = "aho-corasick"
 version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,9 +158,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.95"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
 dependencies = [
  "backtrace",
 ]
@@ -227,9 +215,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 
 [[package]]
 name = "basic-toml"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8"
+checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
 dependencies = [
  "serde",
 ]
@@ -245,15 +233,15 @@ dependencies = [
 
 [[package]]
 name = "bitflags"
-version = "2.8.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
 
 [[package]]
 name = "blake3"
-version = "1.5.5"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e"
+checksum = "34a796731680be7931955498a16a10b2270c7762963d5d570fdbfe02dcbf314f"
 dependencies = [
  "arrayref",
  "arrayvec",
@@ -320,9 +308,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.16.0"
+version = "3.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 
 [[package]]
 name = "bytecount"
@@ -331,16 +319,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
 
 [[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
 name = "bytes"
-version = "1.9.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
 
 [[package]]
 name = "camino"
@@ -358,7 +340,7 @@ dependencies = [
  "cargo_metadata 0.18.1",
  "directories",
  "rustc-build-sysroot",
- "rustc_tools_util 0.4.0",
+ "rustc_tools_util 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version",
  "serde",
  "serde_json",
@@ -389,16 +371,16 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.19.1"
+version = "0.19.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924"
+checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
 dependencies = [
  "camino",
  "cargo-platform",
  "semver",
  "serde",
  "serde_json",
- "thiserror 2.0.11",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -428,22 +410,22 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
 name = "chrono"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
+checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
  "num-traits",
  "serde",
- "windows-targets 0.52.6",
+ "windows-link",
 ]
 
 [[package]]
 name = "chrono-tz"
-version = "0.10.1"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c6ac4f2c0bf0f44e9161aec9675e1050aa4a530663c4a9e37e108fa948bca9f"
+checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
 dependencies = [
  "chrono",
  "chrono-tz-build",
@@ -452,9 +434,9 @@ dependencies = [
 
 [[package]]
 name = "chrono-tz-build"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7"
+checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
 dependencies = [
  "parse-zoneinfo",
  "phf_codegen",
@@ -472,9 +454,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.26"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
+checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -492,9 +474,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.26"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
+checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
 dependencies = [
  "anstream",
  "anstyle",
@@ -504,14 +486,14 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.24"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -542,7 +524,7 @@ dependencies = [
  "rustc_tools_util 0.4.2",
  "serde",
  "serde_json",
- "syn 2.0.96",
+ "syn 2.0.100",
  "tempfile",
  "termize",
  "tokio",
@@ -652,7 +634,7 @@ dependencies = [
  "nom",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -719,9 +701,9 @@ dependencies = [
 
 [[package]]
 name = "console"
-version = "0.15.10"
+version = "0.15.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
+checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
 dependencies = [
  "encode_unicode",
  "libc",
@@ -756,9 +738,9 @@ dependencies = [
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
 dependencies = [
  "libc",
 ]
@@ -843,9 +825,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.78+curl-8.11.0"
+version = "0.4.80+curl-8.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf"
+checksum = "55f7df2eac63200c3ab25bde3b2268ef2ee56af3d238e76d61f01c3c49bff734"
 dependencies = [
  "cc",
  "libc",
@@ -858,9 +840,9 @@ dependencies = [
 
 [[package]]
 name = "darling"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
 dependencies = [
  "darling_core",
  "darling_macro",
@@ -868,27 +850,27 @@ dependencies = [
 
 [[package]]
 name = "darling_core"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
 dependencies = [
  "fnv",
  "ident_case",
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "darling_macro"
-version = "0.20.10"
+version = "0.20.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -910,9 +892,9 @@ dependencies = [
 
 [[package]]
 name = "deranged"
-version = "0.3.11"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
 dependencies = [
  "powerfmt",
 ]
@@ -925,7 +907,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -946,7 +928,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -956,7 +938,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
 dependencies = [
  "derive_builder_core",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -968,7 +950,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1046,26 +1028,26 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "dissimilar"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
+checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
 
 [[package]]
 name = "either"
-version = "1.13.0"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
 
 [[package]]
 name = "elsa"
-version = "1.11.0"
+version = "1.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2343daaeabe09879d4ea058bb4f1e63da3fc07dadc6634e01bda1b3d6a9d9d2b"
+checksum = "9abf33c656a7256451ebb7d0082c5a471820c31269e49d807c538c252352186e"
 dependencies = [
  "stable_deref_trait",
 ]
@@ -1097,22 +1079,22 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.11.6"
+version = "0.11.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
+checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697"
 dependencies = [
  "anstream",
  "anstyle",
  "env_filter",
- "humantime",
+ "jiff",
  "log",
 ]
 
 [[package]]
 name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
 name = "errno"
@@ -1181,12 +1163,12 @@ dependencies = [
 
 [[package]]
 name = "flate2"
-version = "1.0.35"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
+checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
 dependencies = [
  "crc32fast",
- "miniz_oxide 0.8.3",
+ "miniz_oxide 0.8.5",
 ]
 
 [[package]]
@@ -1231,9 +1213,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "foldhash"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
 
 [[package]]
 name = "form_urlencoded"
@@ -1325,7 +1307,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1409,14 +1391,14 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi 0.13.3+wasi-0.2.2",
- "windows-targets 0.52.6",
+ "r-efi",
+ "wasi 0.14.2+wasi-0.2.4",
 ]
 
 [[package]]
@@ -1427,17 +1409,6 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
 name = "gimli"
-version = "0.30.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9"
-dependencies = [
- "fallible-iterator",
- "indexmap",
- "stable_deref_trait",
-]
-
-[[package]]
-name = "gimli"
 version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
@@ -1455,9 +1426,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
 
 [[package]]
 name = "globset"
-version = "0.4.15"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19"
+checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -1477,21 +1448,12 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-dependencies = [
- "ahash",
- "allocator-api2",
-]
-
-[[package]]
-name = "hashbrown"
 version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 dependencies = [
  "allocator-api2",
+ "equivalent",
  "foldhash",
  "serde",
 ]
@@ -1548,9 +1510,9 @@ dependencies = [
 
 [[package]]
 name = "html5ever"
-version = "0.29.2"
+version = "0.29.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b958f80f0fde8601dc6c08685adc743eecaa046181cebd5a57551468dfc2ddc"
+checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c"
 dependencies = [
  "log",
  "mac",
@@ -1569,22 +1531,23 @@ dependencies = [
 
 [[package]]
 name = "humantime"
-version = "2.1.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.61"
+version = "0.1.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
  "iana-time-zone-haiku",
  "js-sys",
+ "log",
  "wasm-bindgen",
- "windows-core 0.52.0",
+ "windows-core 0.61.0",
 ]
 
 [[package]]
@@ -1624,9 +1587,9 @@ dependencies = [
 
 [[package]]
 name = "icu_list_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1825170d2c6679cb20dbd96a589d034e49f698aed9a2ef4fafc9a0101ed298f"
+checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120"
 
 [[package]]
 name = "icu_locid"
@@ -1657,9 +1620,9 @@ dependencies = [
 
 [[package]]
 name = "icu_locid_transform_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
 
 [[package]]
 name = "icu_normalizer"
@@ -1681,9 +1644,9 @@ dependencies = [
 
 [[package]]
 name = "icu_normalizer_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
 
 [[package]]
 name = "icu_properties"
@@ -1702,9 +1665,9 @@ dependencies = [
 
 [[package]]
 name = "icu_properties_data"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
 
 [[package]]
 name = "icu_provider"
@@ -1744,7 +1707,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -1810,20 +1773,20 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
 
 [[package]]
 name = "indexmap"
-version = "2.7.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
 dependencies = [
  "equivalent",
- "hashbrown 0.15.2",
+ "hashbrown",
  "serde",
 ]
 
 [[package]]
 name = "indicatif"
-version = "0.17.9"
+version = "0.17.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281"
+checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"
 dependencies = [
  "console",
  "number_prefix",
@@ -1840,9 +1803,9 @@ checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
 
 [[package]]
 name = "inout"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
 dependencies = [
  "generic-array",
 ]
@@ -1896,16 +1859,41 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.14"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "jiff"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
 
 [[package]]
 name = "jobserver"
-version = "0.1.32"
+version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
 dependencies = [
+ "getrandom 0.3.2",
  "libc",
 ]
 
@@ -1925,7 +1913,7 @@ version = "0.1.0"
 dependencies = [
  "fs-err",
  "getopts",
- "jsonpath_lib",
+ "jsonpath-rust",
  "regex",
  "serde_json",
  "shlex",
@@ -1945,14 +1933,16 @@ dependencies = [
 ]
 
 [[package]]
-name = "jsonpath_lib"
-version = "0.3.0"
+name = "jsonpath-rust"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f"
+checksum = "9b0231bb404a6cd6c8f0ab41b907049063a089fc02aa7636cc5cd9a4d87364c9"
 dependencies = [
- "log",
- "serde",
+ "pest",
+ "pest_derive",
+ "regex",
  "serde_json",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -1968,6 +1958,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
 
 [[package]]
+name = "leb128fmt"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
 name = "levenshtein"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1975,15 +1971,15 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
 
 [[package]]
 name = "lexopt"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401"
+checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7"
 
 [[package]]
 name = "libc"
-version = "0.2.169"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 
 [[package]]
 name = "libdbus-sys"
@@ -2043,9 +2039,9 @@ dependencies = [
 
 [[package]]
 name = "libz-sys"
-version = "1.1.21"
+version = "1.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa"
+checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d"
 dependencies = [
  "cc",
  "libc",
@@ -2072,15 +2068,15 @@ dependencies = [
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.15"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
 
 [[package]]
 name = "litemap"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
 
 [[package]]
 name = "lld-wrapper"
@@ -2109,9 +2105,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.25"
+version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 
 [[package]]
 name = "lzma-sys"
@@ -2132,9 +2128,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
 [[package]]
 name = "markup5ever"
-version = "0.15.0"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a7b81dfb91586d0677086d40a6d755070e0799b71bb897485bac408dfd5c69"
+checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
 dependencies = [
  "log",
  "phf",
@@ -2152,7 +2148,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -2256,9 +2252,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.3"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
 dependencies = [
  "adler2",
 ]
@@ -2281,7 +2277,7 @@ dependencies = [
  "chrono-tz",
  "colored",
  "directories",
- "getrandom 0.3.1",
+ "getrandom 0.3.2",
  "libc",
  "libffi",
  "libloading",
@@ -2468,11 +2464,11 @@ checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "crc32fast",
  "flate2",
- "hashbrown 0.15.2",
+ "hashbrown",
  "indexmap",
  "memchr",
  "ruzstd",
- "wasmparser 0.222.0",
+ "wasmparser 0.222.1",
 ]
 
 [[package]]
@@ -2486,9 +2482,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.21.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
 
 [[package]]
 name = "opener"
@@ -2504,15 +2500,15 @@ dependencies = [
 
 [[package]]
 name = "openssl-probe"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.104"
+version = "0.9.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
+checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
 dependencies = [
  "cc",
  "libc",
@@ -2646,6 +2642,51 @@ dependencies = [
 ]
 
 [[package]]
+name = "pest"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
+dependencies = [
+ "memchr",
+ "thiserror 2.0.12",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
 name = "phf"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2697,9 +2738,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.31"
+version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
 
 [[package]]
 name = "polonius-engine"
@@ -2714,9 +2755,18 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "1.10.0"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
 
 [[package]]
 name = "powerfmt"
@@ -2726,11 +2776,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.20"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
 dependencies = [
- "zerocopy 0.7.35",
+ "zerocopy",
 ]
 
 [[package]]
@@ -2757,9 +2807,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.93"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
 dependencies = [
  "unicode-ident",
 ]
@@ -2816,14 +2866,20 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 
 [[package]]
 name = "quote"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
+[[package]]
 name = "rand"
 version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2841,8 +2897,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
 dependencies = [
  "rand_chacha 0.9.0",
- "rand_core 0.9.0",
- "zerocopy 0.8.14",
+ "rand_core 0.9.3",
+ "zerocopy",
 ]
 
 [[package]]
@@ -2862,7 +2918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
 dependencies = [
  "ppv-lite86",
- "rand_core 0.9.0",
+ "rand_core 0.9.3",
 ]
 
 [[package]]
@@ -2876,12 +2932,11 @@ dependencies = [
 
 [[package]]
 name = "rand_core"
-version = "0.9.0"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
 dependencies = [
- "getrandom 0.3.1",
- "zerocopy 0.8.14",
+ "getrandom 0.3.2",
 ]
 
 [[package]]
@@ -2890,7 +2945,7 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41"
 dependencies = [
- "rand_core 0.9.0",
+ "rand_core 0.9.3",
 ]
 
 [[package]]
@@ -2915,9 +2970,9 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.8"
+version = "0.5.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
+checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
 dependencies = [
  "bitflags",
 ]
@@ -3035,7 +3090,7 @@ dependencies = [
  "rinja_parser",
  "rustc-hash 2.1.1",
  "serde",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3062,7 +3117,7 @@ dependencies = [
  "regex",
  "serde_json",
  "similar",
- "wasmparser 0.219.1",
+ "wasmparser 0.219.2",
 ]
 
 [[package]]
@@ -3132,9 +3187,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-stable-hash"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2febf9acc5ee5e99d1ad0afcdbccc02d87aa3f857a1f01f825b80eacf8edfcd1"
+checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08"
 
 [[package]]
 name = "rustc-std-workspace-alloc"
@@ -3366,7 +3421,7 @@ name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
  "bitflags",
- "gimli 0.30.0",
+ "gimli 0.31.1",
  "itertools",
  "libc",
  "measureme 12.0.1",
@@ -3442,7 +3497,7 @@ dependencies = [
  "thin-vec",
  "thorin-dwp",
  "tracing",
- "wasm-encoder 0.219.1",
+ "wasm-encoder 0.219.2",
  "windows 0.59.0",
 ]
 
@@ -3480,7 +3535,7 @@ dependencies = [
  "either",
  "elsa",
  "ena",
- "hashbrown 0.15.2",
+ "hashbrown",
  "indexmap",
  "jobserver",
  "libc",
@@ -3667,7 +3722,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "unic-langid",
 ]
 
@@ -3810,7 +3865,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -3957,7 +4012,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "synstructure",
 ]
 
@@ -4259,6 +4314,7 @@ dependencies = [
 name = "rustc_query_system"
 version = "0.0.0"
 dependencies = [
+ "hashbrown",
  "parking_lot",
  "rustc-rayon-core",
  "rustc_abi",
@@ -4284,6 +4340,7 @@ name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
  "bitflags",
+ "itertools",
  "pulldown-cmark 0.11.3",
  "rustc_arena",
  "rustc_ast",
@@ -4436,13 +4493,13 @@ dependencies = [
 
 [[package]]
 name = "rustc_tools_util"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3316159ab19e19d1065ecc49278e87f767a9dae9fae80348d2b4d4fa4ae02d4d"
+version = "0.4.2"
 
 [[package]]
 name = "rustc_tools_util"
 version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3b75158011a63889ba12084cf1224baad7bcad50f6ee7c842f772b74aa148ed"
 
 [[package]]
 name = "rustc_trait_selection"
@@ -4544,7 +4601,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "synstructure",
 ]
 
@@ -4634,7 +4691,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -4668,9 +4725,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.43"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
+checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
 dependencies = [
  "bitflags",
  "errno",
@@ -4681,9 +4738,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
+checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
 
 [[package]]
 name = "ruzstd"
@@ -4696,9 +4753,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.18"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "same-file"
@@ -4747,40 +4804,39 @@ checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe"
 
 [[package]]
 name = "semver"
-version = "1.0.24"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.135"
+version = "1.0.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
 dependencies = [
- "indexmap",
  "itoa",
  "memchr",
  "ryu",
@@ -4841,9 +4897,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
 [[package]]
 name = "similar"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
+checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
 
 [[package]]
 name = "siphasher"
@@ -4862,15 +4918,15 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.13.2"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
 
 [[package]]
 name = "socket2"
-version = "0.5.8"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
+checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -4940,9 +4996,9 @@ dependencies = [
 
 [[package]]
 name = "stacker"
-version = "0.1.18"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d08feb8f695b465baed819b03c128dc23f57a694510ab1f06c77f763975685e"
+checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9"
 dependencies = [
  "cc",
  "cfg-if",
@@ -4959,9 +5015,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
 name = "string_cache"
-version = "0.8.8"
+version = "0.8.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe"
+checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
 dependencies = [
  "new_debug_unreachable",
  "parking_lot",
@@ -5028,9 +5084,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.96"
+version = "2.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5045,7 +5101,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5071,9 +5127,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.43"
+version = "0.4.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
+checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
 dependencies = [
  "filetime",
  "libc",
@@ -5082,13 +5138,12 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.15.0"
+version = "3.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
+checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
 dependencies = [
- "cfg-if",
  "fastrand",
- "getrandom 0.2.15",
+ "getrandom 0.3.2",
  "once_cell",
  "rustix",
  "windows-sys 0.59.0",
@@ -5148,9 +5203,9 @@ dependencies = [
 
 [[package]]
 name = "thin-vec"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b"
+checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
 
 [[package]]
 name = "thiserror"
@@ -5163,11 +5218,11 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "2.0.11"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
 dependencies = [
- "thiserror-impl 2.0.11",
+ "thiserror-impl 2.0.12",
 ]
 
 [[package]]
@@ -5178,28 +5233,28 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.11"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "thorin-dwp"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "813ba76597db32dc4f6992fd8bf8f394715b88d352fd97401da67dab6283b4c6"
+checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1"
 dependencies = [
- "gimli 0.30.0",
- "hashbrown 0.14.5",
+ "gimli 0.31.1",
+ "hashbrown",
  "object 0.36.7",
  "tracing",
 ]
@@ -5228,7 +5283,7 @@ name = "tidy"
 version = "0.1.0"
 dependencies = [
  "build_helper",
- "cargo_metadata 0.19.1",
+ "cargo_metadata 0.19.2",
  "fluent-syntax",
  "ignore",
  "miropt-test-tools",
@@ -5258,9 +5313,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.37"
+version = "0.3.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
+checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
 dependencies = [
  "deranged",
  "itoa",
@@ -5273,15 +5328,15 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.2"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
 
 [[package]]
 name = "time-macros"
-version = "0.2.19"
+version = "0.2.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
+checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
 dependencies = [
  "num-conv",
  "time-core",
@@ -5299,9 +5354,9 @@ dependencies = [
 
 [[package]]
 name = "tinyvec"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
+checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
 dependencies = [
  "tinyvec_macros",
 ]
@@ -5314,9 +5369,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.43.0"
+version = "1.44.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
+checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
 dependencies = [
  "backtrace",
  "bytes",
@@ -5386,7 +5441,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -5473,9 +5528,9 @@ dependencies = [
 
 [[package]]
 name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 
 [[package]]
 name = "ucd-parse"
@@ -5487,6 +5542,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "ucd-trie"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
+
+[[package]]
 name = "ui_test"
 version = "0.29.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5551,7 +5612,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "unic-langid-impl",
 ]
 
@@ -5563,9 +5624,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.14"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-normalization"
@@ -5689,11 +5750,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "uuid"
-version = "1.12.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
+checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
 dependencies = [
- "getrandom 0.2.15",
+ "getrandom 0.3.2",
 ]
 
 [[package]]
@@ -5732,9 +5793,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasi"
-version = "0.13.3+wasi-0.2.2"
+version = "0.14.2+wasi-0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
 dependencies = [
  "wit-bindgen-rt",
 ]
@@ -5767,7 +5828,7 @@ dependencies = [
  "log",
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "wasm-bindgen-shared",
 ]
 
@@ -5789,7 +5850,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -5815,7 +5876,7 @@ dependencies = [
  "libc",
  "tempfile",
  "wasi-preview1-component-adapter-provider",
- "wasmparser 0.223.0",
+ "wasmparser 0.223.1",
  "wat",
  "windows-sys 0.59.0",
  "winsplit",
@@ -5832,29 +5893,39 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.219.1"
+version = "0.219.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54"
+checksum = "8aa79bcd666a043b58f5fa62b221b0b914dd901e6f620e8ab7371057a797f3e1"
 dependencies = [
  "leb128",
- "wasmparser 0.219.1",
+ "wasmparser 0.219.2",
 ]
 
 [[package]]
 name = "wasm-encoder"
-version = "0.223.0"
+version = "0.223.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e636076193fa68103e937ac951b5f2f587624097017d764b8984d9c0f149464"
+checksum = "7a0a96fdeaee8fbeb4bd917fb8157d48c0d61c3b1f4ee4c363c8e8d68b2f4fe8"
 dependencies = [
  "leb128",
- "wasmparser 0.223.0",
+ "wasmparser 0.223.1",
+]
+
+[[package]]
+name = "wasm-encoder"
+version = "0.228.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05d30290541f2d4242a162bbda76b8f2d8b1ac59eab3568ed6f2327d52c9b2c4"
+dependencies = [
+ "leb128fmt",
+ "wasmparser 0.228.0",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.223.0"
+version = "0.223.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c730c3379d3d20e5a0245b0724b924483e853588ca8fba547c1e21f19e7d735"
+checksum = "e2e7e37883181704d96b89dbd8f1291be13694c71cd0663aebb94b46d235a377"
 dependencies = [
  "anyhow",
  "indexmap",
@@ -5863,15 +5934,15 @@ dependencies = [
  "serde_json",
  "spdx",
  "url",
- "wasm-encoder 0.223.0",
- "wasmparser 0.223.0",
+ "wasm-encoder 0.223.1",
+ "wasmparser 0.223.1",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.219.1"
+version = "0.219.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5"
+checksum = "5220ee4c6ffcc0cb9d7c47398052203bc902c8ef3985b0c8134118440c0b2921"
 dependencies = [
  "bitflags",
  "indexmap",
@@ -5879,44 +5950,55 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.222.0"
+version = "0.222.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4adf50fde1b1a49c1add6a80d47aea500c88db70551805853aa8b88f3ea27ab5"
+checksum = "fa210fd1788e6b37a1d1930f3389c48e1d6ebd1a013d34fa4b7f9e3e3bf03146"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.223.0"
+version = "0.223.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5a99faceb1a5a84dd6084ec4bfa4b2ab153b5793b43fd8f58b89232634afc35"
+checksum = "664b980991ed9a8c834eb528a8979ab1109edcf52dc05dd5751e2cc3fb31035d"
 dependencies = [
  "bitflags",
- "hashbrown 0.15.2",
+ "hashbrown",
  "indexmap",
  "semver",
  "serde",
 ]
 
 [[package]]
+name = "wasmparser"
+version = "0.228.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3"
+dependencies = [
+ "bitflags",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
 name = "wast"
-version = "223.0.0"
+version = "228.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59b2ba8a2ff9f06194b7be9524f92e45e70149f4dacc0d0c7ad92b59ac875e4"
+checksum = "9e5aae124478cb51439f6587f074a3a5e835afd22751c59a87b2e2a882727c97"
 dependencies = [
  "bumpalo",
- "leb128",
+ "leb128fmt",
  "memchr",
  "unicode-width 0.2.0",
- "wasm-encoder 0.223.0",
+ "wasm-encoder 0.228.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.223.0"
+version = "1.228.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "662786915c427e4918ff01eabb3c4756d4d947cd8f635761526b4cc9da2eaaad"
+checksum = "7ec29c89a8d055df988de7236483bf569988ac3d6905899f6af5ef920f9385ad"
 dependencies = [
  "wast",
 ]
@@ -5993,15 +6075,6 @@ dependencies = [
 
 [[package]]
 name = "windows-core"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-core"
 version = "0.57.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
@@ -6019,13 +6092,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
 dependencies = [
  "windows-implement 0.59.0",
- "windows-interface 0.59.0",
- "windows-result 0.3.0",
- "windows-strings",
+ "windows-interface 0.59.1",
+ "windows-result 0.3.2",
+ "windows-strings 0.3.1",
  "windows-targets 0.53.0",
 ]
 
 [[package]]
+name = "windows-core"
+version = "0.61.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
+dependencies = [
+ "windows-implement 0.60.0",
+ "windows-interface 0.59.1",
+ "windows-link",
+ "windows-result 0.3.2",
+ "windows-strings 0.4.0",
+]
+
+[[package]]
 name = "windows-implement"
 version = "0.57.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6033,7 +6119,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -6044,7 +6130,18 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
 ]
 
 [[package]]
@@ -6055,21 +6152,27 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "windows-interface"
-version = "0.59.0"
+version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
+name = "windows-link"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+
+[[package]]
 name = "windows-result"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6080,20 +6183,29 @@ dependencies = [
 
 [[package]]
 name = "windows-result"
-version = "0.3.0"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
 dependencies = [
- "windows-targets 0.53.0",
+ "windows-link",
 ]
 
 [[package]]
 name = "windows-strings"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491"
+checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
 dependencies = [
- "windows-targets 0.53.0",
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
+dependencies = [
+ "windows-link",
 ]
 
 [[package]]
@@ -6325,18 +6437,18 @@ checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956"
 
 [[package]]
 name = "wit-bindgen-rt"
-version = "0.33.0"
+version = "0.39.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "wit-component"
-version = "0.223.0"
+version = "0.223.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c10ed2aeee4c8ec5715875f62f4a3de3608d6987165c116810d8c2908aa9d93b"
+checksum = "3fc2fcc52a79f6f010a89c867e53e06d4227f86c58984add3e37f32b8e7af5f0"
 dependencies = [
  "anyhow",
  "bitflags",
@@ -6345,17 +6457,17 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.223.0",
+ "wasm-encoder 0.223.1",
  "wasm-metadata",
- "wasmparser 0.223.0",
+ "wasmparser 0.223.1",
  "wit-parser",
 ]
 
 [[package]]
 name = "wit-parser"
-version = "0.223.0"
+version = "0.223.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92772f4dcacb804b275981eea1d920b12b377993b53307f1e33d87404e080281"
+checksum = "263fde17f1fbe55a413f16eb59094bf751795c6da469a05c3d45ea6c77df6b40"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -6366,7 +6478,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.223.0",
+ "wasmparser 0.223.1",
 ]
 
 [[package]]
@@ -6387,12 +6499,11 @@ version = "0.1.1"
 
 [[package]]
 name = "xattr"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909"
+checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e"
 dependencies = [
  "libc",
- "linux-raw-sys",
  "rustix",
 ]
 
@@ -6434,69 +6545,48 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "synstructure",
 ]
 
 [[package]]
 name = "zerocopy"
-version = "0.7.35"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
 dependencies = [
- "byteorder",
- "zerocopy-derive 0.7.35",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.8.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468"
-dependencies = [
- "zerocopy-derive 0.8.14",
+ "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.35"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
 
 [[package]]
 name = "zerofrom"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
  "synstructure",
 ]
 
@@ -6519,5 +6609,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.96",
+ "syn 2.0.100",
 ]
diff --git a/RELEASES.md b/RELEASES.md
index 381b9ebc952..0948eb85192 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,137 @@
+Version 1.86.0 (2025-04-03)
+==========================
+
+<a id="1.86.0-Language"></a>
+
+Language
+--------
+- [Stabilize upcasting trait objects to supertraits.](https://github.com/rust-lang/rust/pull/134367)
+- [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090)
+- [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397)
+- Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604)
+- [More pointers are now detected as definitely not-null based on their alignment in const eval.](https://github.com/rust-lang/rust/pull/133700)
+- [Empty `repr()` attribute applied to invalid items are now correctly rejected.](https://github.com/rust-lang/rust/pull/133925)
+- [Inner attributes `#![test]` and `#![rustfmt::skip]` are no longer accepted in more places than intended.](https://github.com/rust-lang/rust/pull/134276)
+
+<a id="1.86.0-Compiler"></a>
+
+Compiler
+--------
+- [Debug-assert that raw pointers are non-null on access.](https://github.com/rust-lang/rust/pull/134424)
+- [Change `-O` to mean `-C opt-level=3` instead of `-C opt-level=2` to match Cargo's defaults.](https://github.com/rust-lang/rust/pull/135439)
+- [Fix emission of `overflowing_literals` under certain macro environments.](https://github.com/rust-lang/rust/pull/136393)
+
+<a id="1.86.0-Platform-Support"></a>
+
+Platform Support
+----------------
+- [Replace `i686-unknown-redox` target with `i586-unknown-redox`.](https://github.com/rust-lang/rust/pull/136698)
+- [Increase baseline CPU of `i686-unknown-hurd-gnu` to Pentium 4.](https://github.com/rust-lang/rust/pull/136700)
+- New tier 3 targets:
+  - [`{aarch64-unknown,x86_64-pc}-nto-qnx710_iosock`](https://github.com/rust-lang/rust/pull/133631).
+    For supporting Neutrino QNX 7.1 with `io-socket` network stack.
+  - [`{aarch64-unknown,x86_64-pc}-nto-qnx800`](https://github.com/rust-lang/rust/pull/133631).
+    For supporting Neutrino QNX 8.0 (`no_std`-only).
+  - [`{x86_64,i686}-win7-windows-gnu`](https://github.com/rust-lang/rust/pull/134609).
+    Intended for backwards compatibility with Windows 7. `{x86_64,i686}-win7-windows-msvc` are the Windows MSVC counterparts that already exist as Tier 3 targets.
+  - [`amdgcn-amd-amdhsa`](https://github.com/rust-lang/rust/pull/134740).
+  - [`x86_64-pc-cygwin`](https://github.com/rust-lang/rust/pull/134999).
+  - [`{mips,mipsel}-mti-none-elf`](https://github.com/rust-lang/rust/pull/135074).
+    Initial bare-metal support.
+  - [`m68k-unknown-none-elf`](https://github.com/rust-lang/rust/pull/135085).
+  - [`armv7a-nuttx-{eabi,eabihf}`, `aarch64-unknown-nuttx`, and `thumbv7a-nuttx-{eabi,eabihf}`](https://github.com/rust-lang/rust/pull/135757).
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.86.0-Libraries"></a>
+
+Libraries
+---------
+- The type of `FromBytesWithNulError` in `CStr::from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>` was [changed from an opaque struct to an enum](https://github.com/rust-lang/rust/pull/134143), allowing users to examine why the conversion failed.
+- [Remove `RustcDecodable` and `RustcEncodable`.](https://github.com/rust-lang/rust/pull/134272)
+- [Deprecate libtest's `--logfile` option.](https://github.com/rust-lang/rust/pull/134283)
+- [On recent versions of Windows, `std::fs::remove_file` will now remove read-only files.](https://github.com/rust-lang/rust/pull/134679)
+
+<a id="1.86.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down)
+- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up)
+- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut)
+- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut)
+- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html)
+- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut)
+- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut)
+- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones)
+- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if)
+- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait)
+- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force)
+- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait)
+
+These APIs are now stable in const contexts:
+
+- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut)
+- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position)
+- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary)
+- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at)
+- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked)
+- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut)
+- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked)
+
+<a id="1.86.0-Cargo"></a>
+
+Cargo
+-----
+- [When merging, replace rather than combine configuration keys that refer to a program path and its arguments.](https://github.com/rust-lang/cargo/pull/15066/)
+- [Error if both `--package` and `--workspace` are passed but the requested package is missing.](https://github.com/rust-lang/cargo/pull/15071/) This was previously silently ignored, which was considered a bug since missing packages should be reported.
+- [Deprecate the token argument in `cargo login` to avoid shell history leaks.](https://github.com/rust-lang/cargo/pull/15057/)
+- [Simplify the implementation of `SourceID` comparisons.](https://github.com/rust-lang/cargo/pull/14980/) This may potentially change behavior if the canonicalized URL compares differently in alternative registries.
+
+<a id="1.86.0-Rustdoc"></a>
+
+Rustdoc
+-----
+- [Add a sans-serif font setting.](https://github.com/rust-lang/rust/pull/133636)
+
+<a id="1.86.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+- [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951)
+  Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail.
+- [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300)
+- [The future incompatibility lint `cenum_impl_drop_cast` has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`.
+- [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037)
+  To compile for pre-SSE2 32-bit x86, use a "i586" target instead.
+
+<a id="1.86.0-Internal-Changes"></a>
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807)
+  The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster.
+
+
+Version 1.85.1 (2025-03-18)
+==========================
+
+<a id="1.85.1"></a>
+
+- [Fix the doctest-merging feature of the 2024 Edition.](https://github.com/rust-lang/rust/pull/137899/)
+- [Relax some `target_feature` checks when generating docs.](https://github.com/rust-lang/rust/pull/137632/)
+- [Fix errors in `std::fs::rename` on Windows 10, version 1607.](https://github.com/rust-lang/rust/pull/137528/)
+- [Downgrade bootstrap `cc` to fix custom targets.](https://github.com/rust-lang/rust/pull/137460/)
+- [Skip submodule updates when building Rust from a source tarball.](https://github.com/rust-lang/rust/pull/137338/)
+
 Version 1.85.0 (2025-02-20)
 ==========================
 
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 294d9780716..2a98821f225 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -1,7 +1,7 @@
 # Sample TOML configuration file for building Rust.
 #
 # To configure bootstrap, run `./configure` or `./x.py setup`.
-# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-configtoml for more information.
+# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-bootstraptoml for more information.
 #
 # All options are commented out by default in this file, and they're commented
 # out with their default values. The build system by default looks for
@@ -28,8 +28,9 @@
 #  - A new option
 #  - A change in the default values
 #
-# If `change-id` does not match the version that is currently running,
-# `x.py` will inform you about the changes made on bootstrap.
+# If the change-id does not match the version currently in use, x.py will 
+# display the changes made to the bootstrap.
+# To suppress these warnings, you can set change-id = "ignore".
 #change-id = <latest change id in src/bootstrap/src/utils/change_tracker.rs>
 
 # =============================================================================
@@ -446,7 +447,7 @@
 # a specific version.
 #ccache = false
 
-# List of paths to exclude from the build and test processes. 
+# List of paths to exclude from the build and test processes.
 # For example, exclude = ["tests/ui", "src/tools/tidy"].
 #exclude = []
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 3f28dc7a1ef..843d5ca61dd 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1462,7 +1462,8 @@ impl BackendRepr {
         !self.is_unsized()
     }
 
-    /// Returns `true` if this is a single signed integer scalar
+    /// Returns `true` if this is a single signed integer scalar.
+    /// Sanity check: panics if this is not a scalar type (see PR #70189).
     #[inline]
     pub fn is_signed(&self) -> bool {
         match self {
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 5b7545b3396..33c20602dfd 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -545,14 +545,6 @@ pub struct Block {
     pub rules: BlockCheckMode,
     pub span: Span,
     pub tokens: Option<LazyAttrTokenStream>,
-    /// The following *isn't* a parse error, but will cause multiple errors in following stages.
-    /// ```compile_fail
-    /// let x = {
-    ///     foo: var
-    /// };
-    /// ```
-    /// #34255
-    pub could_be_bare_literal: bool,
 }
 
 /// A match pattern.
@@ -3311,9 +3303,6 @@ pub struct Item<K = ItemKind> {
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
-    /// The name of the item.
-    /// It might be a dummy name in case of anonymous items.
-    pub ident: Ident,
 
     pub kind: K,
 
@@ -3335,23 +3324,23 @@ impl Item {
 
     pub fn opt_generics(&self) -> Option<&Generics> {
         match &self.kind {
-            ItemKind::ExternCrate(_)
+            ItemKind::ExternCrate(..)
             | ItemKind::Use(_)
-            | ItemKind::Mod(_, _)
+            | ItemKind::Mod(..)
             | ItemKind::ForeignMod(_)
             | ItemKind::GlobalAsm(_)
             | ItemKind::MacCall(_)
             | ItemKind::Delegation(_)
             | ItemKind::DelegationMac(_)
-            | ItemKind::MacroDef(_) => None,
+            | ItemKind::MacroDef(..) => None,
             ItemKind::Static(_) => None,
             ItemKind::Const(i) => Some(&i.generics),
             ItemKind::Fn(i) => Some(&i.generics),
             ItemKind::TyAlias(i) => Some(&i.generics),
-            ItemKind::TraitAlias(generics, _)
-            | ItemKind::Enum(_, generics)
-            | ItemKind::Struct(_, generics)
-            | ItemKind::Union(_, generics) => Some(&generics),
+            ItemKind::TraitAlias(_, generics, _)
+            | ItemKind::Enum(_, _, generics)
+            | ItemKind::Struct(_, _, generics)
+            | ItemKind::Union(_, _, generics) => Some(&generics),
             ItemKind::Trait(i) => Some(&i.generics),
             ItemKind::Impl(i) => Some(&i.generics),
         }
@@ -3428,6 +3417,7 @@ impl Default for FnHeader {
 pub struct Trait {
     pub safety: Safety,
     pub is_auto: IsAuto,
+    pub ident: Ident,
     pub generics: Generics,
     pub bounds: GenericBounds,
     pub items: ThinVec<P<AssocItem>>,
@@ -3473,6 +3463,7 @@ pub struct TyAliasWhereClauses {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct TyAlias {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub where_clauses: TyAliasWhereClauses,
     pub bounds: GenericBounds,
@@ -3501,6 +3492,7 @@ pub struct FnContract {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Fn {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub sig: FnSig,
     pub contract: Option<P<FnContract>>,
@@ -3514,6 +3506,7 @@ pub struct Delegation {
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
     pub path: Path,
+    pub ident: Ident,
     pub rename: Option<Ident>,
     pub body: Option<P<Block>>,
     /// The item was expanded from a glob delegation item.
@@ -3531,18 +3524,22 @@ pub struct DelegationMac {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StaticItem {
+    pub ident: Ident,
     pub ty: P<Ty>,
     pub safety: Safety,
     pub mutability: Mutability,
     pub expr: Option<P<Expr>>,
+    pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ConstItem {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub ty: P<Ty>,
     pub expr: Option<P<Expr>>,
+    pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
 }
 
 // Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
@@ -3551,7 +3548,7 @@ pub enum ItemKind {
     /// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
     ///
     /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
-    ExternCrate(Option<Symbol>),
+    ExternCrate(Option<Symbol>, Ident),
     /// A use declaration item (`use`).
     ///
     /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
@@ -3573,7 +3570,7 @@ pub enum ItemKind {
     /// E.g., `mod foo;` or `mod foo { .. }`.
     /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not
     /// semantically by Rust.
-    Mod(Safety, ModKind),
+    Mod(Safety, Ident, ModKind),
     /// An external module (`extern`).
     ///
     /// E.g., `extern {}` or `extern "C" {}`.
@@ -3587,15 +3584,15 @@ pub enum ItemKind {
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
-    Enum(EnumDef, Generics),
+    Enum(Ident, EnumDef, Generics),
     /// A struct definition (`struct`).
     ///
     /// E.g., `struct Foo<A> { x: A }`.
-    Struct(VariantData, Generics),
+    Struct(Ident, VariantData, Generics),
     /// A union definition (`union`).
     ///
     /// E.g., `union Foo<A, B> { x: A, y: B }`.
-    Union(VariantData, Generics),
+    Union(Ident, VariantData, Generics),
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
@@ -3603,7 +3600,7 @@ pub enum ItemKind {
     /// Trait alias.
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
-    TraitAlias(Generics, GenericBounds),
+    TraitAlias(Ident, Generics, GenericBounds),
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
@@ -3614,7 +3611,7 @@ pub enum ItemKind {
     MacCall(P<MacCall>),
 
     /// A macro definition.
-    MacroDef(MacroDef),
+    MacroDef(Ident, MacroDef),
 
     /// A single delegation item (`reuse`).
     ///
@@ -3626,6 +3623,31 @@ pub enum ItemKind {
 }
 
 impl ItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            ItemKind::ExternCrate(_, ident)
+            | ItemKind::Static(box StaticItem { ident, .. })
+            | ItemKind::Const(box ConstItem { ident, .. })
+            | ItemKind::Fn(box Fn { ident, .. })
+            | ItemKind::Mod(_, ident, _)
+            | ItemKind::TyAlias(box TyAlias { ident, .. })
+            | ItemKind::Enum(ident, ..)
+            | ItemKind::Struct(ident, ..)
+            | ItemKind::Union(ident, ..)
+            | ItemKind::Trait(box Trait { ident, .. })
+            | ItemKind::TraitAlias(ident, ..)
+            | ItemKind::MacroDef(ident, _)
+            | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+            ItemKind::Use(_)
+            | ItemKind::ForeignMod(_)
+            | ItemKind::GlobalAsm(_)
+            | ItemKind::Impl(_)
+            | ItemKind::MacCall(_)
+            | ItemKind::DelegationMac(_) => None,
+        }
+    }
+
     /// "a" or "an"
     pub fn article(&self) -> &'static str {
         use ItemKind::*;
@@ -3666,11 +3688,11 @@ impl ItemKind {
             Self::Fn(box Fn { generics, .. })
             | Self::TyAlias(box TyAlias { generics, .. })
             | Self::Const(box ConstItem { generics, .. })
-            | Self::Enum(_, generics)
-            | Self::Struct(_, generics)
-            | Self::Union(_, generics)
+            | Self::Enum(_, _, generics)
+            | Self::Struct(_, _, generics)
+            | Self::Union(_, _, generics)
             | Self::Trait(box Trait { generics, .. })
-            | Self::TraitAlias(generics, _)
+            | Self::TraitAlias(_, generics, _)
             | Self::Impl(box Impl { generics, .. }) => Some(generics),
             _ => None,
         }
@@ -3706,6 +3728,17 @@ pub enum AssocItemKind {
 }
 
 impl AssocItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            AssocItemKind::Const(box ConstItem { ident, .. })
+            | AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Type(box TyAlias { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None,
+        }
+    }
+
     pub fn defaultness(&self) -> Defaultness {
         match *self {
             Self::Const(box ConstItem { defaultness, .. })
@@ -3752,14 +3785,26 @@ impl TryFrom<ItemKind> for AssocItemKind {
 pub enum ForeignItemKind {
     /// A foreign static item (`static FOO: u8`).
     Static(Box<StaticItem>),
-    /// An foreign function.
+    /// A foreign function.
     Fn(Box<Fn>),
-    /// An foreign type.
+    /// A foreign type.
     TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
     MacCall(P<MacCall>),
 }
 
+impl ForeignItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            ForeignItemKind::Static(box StaticItem { ident, .. })
+            | ForeignItemKind::Fn(box Fn { ident, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => Some(ident),
+
+            ForeignItemKind::MacCall(_) => None,
+        }
+    }
+}
+
 impl From<ForeignItemKind> for ItemKind {
     fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
         match foreign_item_kind {
@@ -3796,21 +3841,21 @@ mod size_asserts {
 
     use super::*;
     // tidy-alphabetical-start
-    static_assert_size!(AssocItem, 88);
+    static_assert_size!(AssocItem, 80);
     static_assert_size!(AssocItemKind, 16);
     static_assert_size!(Attribute, 32);
     static_assert_size!(Block, 32);
     static_assert_size!(Expr, 72);
     static_assert_size!(ExprKind, 40);
-    static_assert_size!(Fn, 176);
-    static_assert_size!(ForeignItem, 88);
+    static_assert_size!(Fn, 184);
+    static_assert_size!(ForeignItem, 80);
     static_assert_size!(ForeignItemKind, 16);
     static_assert_size!(GenericArg, 24);
     static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 40);
     static_assert_size!(Impl, 136);
-    static_assert_size!(Item, 136);
-    static_assert_size!(ItemKind, 64);
+    static_assert_size!(Item, 144);
+    static_assert_size!(ItemKind, 80);
     static_assert_size!(LitKind, 24);
     static_assert_size!(Local, 80);
     static_assert_size!(MetaItemLit, 40);
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 849cc650e9d..c9e2e9911ef 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -209,13 +209,11 @@ impl HasTokens for Attribute {
 impl HasTokens for Nonterminal {
     fn tokens(&self) -> Option<&LazyAttrTokenStream> {
         match self {
-            Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(),
             Nonterminal::NtBlock(block) => block.tokens(),
         }
     }
     fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
         match self {
-            Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
         }
     }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 4edd0864300..f7d13acdfc4 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -41,7 +41,6 @@ pub trait WalkItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
@@ -900,8 +899,6 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
 fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
     match nt {
         token::NtBlock(block) => vis.visit_block(block),
-        token::NtExpr(expr) => vis.visit_expr(expr),
-        token::NtLiteral(expr) => vis.visit_expr(expr),
     }
 }
 
@@ -963,10 +960,10 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     match kind {
         FnKind::Fn(
             _ctxt,
-            _ident,
             _vis,
             Fn {
                 defaultness,
+                ident,
                 generics,
                 contract,
                 body,
@@ -974,8 +971,9 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
                 define_opaque,
             },
         ) => {
-            // Identifier and visibility are visited as a part of the item.
+            // Visibility is visited as a part of the item.
             visit_defaultness(vis, defaultness);
+            vis.visit_ident(ident);
             vis.visit_fn_header(header);
             vis.visit_generics(generics);
             vis.visit_fn_decl(decl);
@@ -987,10 +985,7 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
             }
             vis.visit_span(span);
 
-            for (id, path) in define_opaque.iter_mut().flatten() {
-                vis.visit_id(id);
-                vis.visit_path(path)
-            }
+            walk_define_opaques(vis, define_opaque);
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
             vis.visit_closure_binder(binder);
@@ -1225,7 +1220,7 @@ fn walk_mt<T: MutVisitor>(vis: &mut T, MutTy { ty, mutbl: _ }: &mut MutTy) {
 }
 
 pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut P<Block>) {
-    let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
+    let Block { id, stmts, rules: _, span, tokens } = block.deref_mut();
     vis.visit_id(id);
     stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
     visit_lazy_tts(vis, tokens);
@@ -1236,12 +1231,11 @@ pub fn walk_item_kind<K: WalkItemKind>(
     kind: &mut K,
     span: Span,
     id: NodeId,
-    ident: &mut Ident,
     visibility: &mut Visibility,
     ctxt: K::Ctxt,
     vis: &mut impl MutVisitor,
 ) {
-    kind.walk(span, id, ident, visibility, ctxt, vis)
+    kind.walk(span, id, visibility, ctxt, vis)
 }
 
 impl WalkItemKind for ItemKind {
@@ -1250,26 +1244,35 @@ impl WalkItemKind for ItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         _ctxt: Self::Ctxt,
         vis: &mut impl MutVisitor,
     ) {
         match self {
-            ItemKind::ExternCrate(_orig_name) => {}
+            ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
             ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-            ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
+            ItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                safety: _,
+                mutability: _,
+                expr,
+                define_opaque,
+            }) => {
+                vis.visit_ident(ident);
                 vis.visit_ty(ty);
                 visit_opt(expr, |expr| vis.visit_expr(expr));
+                walk_define_opaques(vis, define_opaque);
             }
             ItemKind::Const(item) => {
-                visit_const_item(item, vis);
+                walk_const_item(vis, item);
             }
             ItemKind::Fn(func) => {
-                vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
+                vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id);
             }
-            ItemKind::Mod(safety, mod_kind) => {
+            ItemKind::Mod(safety, ident, mod_kind) => {
                 visit_safety(vis, safety);
+                vis.visit_ident(ident);
                 match mod_kind {
                     ModKind::Loaded(
                         items,
@@ -1286,18 +1289,29 @@ impl WalkItemKind for ItemKind {
             }
             ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
             ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
-            ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => {
+            ItemKind::TyAlias(box TyAlias {
+                defaultness,
+                ident,
+                generics,
+                where_clauses,
+                bounds,
+                ty,
+            }) => {
                 visit_defaultness(vis, defaultness);
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| vis.visit_ty(ty));
                 walk_ty_alias_where_clauses(vis, where_clauses);
             }
-            ItemKind::Enum(EnumDef { variants }, generics) => {
+            ItemKind::Enum(ident, EnumDef { variants }, generics) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
             }
-            ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
+            ItemKind::Struct(ident, variant_data, generics)
+            | ItemKind::Union(ident, variant_data, generics) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 vis.visit_variant_data(variant_data);
             }
@@ -1318,24 +1332,32 @@ impl WalkItemKind for ItemKind {
                 visit_polarity(vis, polarity);
                 visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
                 vis.visit_ty(self_ty);
-                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Impl));
+                items.flat_map_in_place(|item| {
+                    vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
+                });
             }
-            ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
+            ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
                 visit_safety(vis, safety);
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
                 items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
             }
-            ItemKind::TraitAlias(generics, bounds) => {
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
             }
             ItemKind::MacCall(m) => vis.visit_mac_call(m),
-            ItemKind::MacroDef(def) => vis.visit_macro_def(def),
+            ItemKind::MacroDef(ident, def) => {
+                vis.visit_ident(ident);
+                vis.visit_macro_def(def)
+            }
             ItemKind::Delegation(box Delegation {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
@@ -1343,6 +1365,7 @@ impl WalkItemKind for ItemKind {
                 vis.visit_id(id);
                 vis.visit_qself(qself);
                 vis.visit_path(path);
+                vis.visit_ident(ident);
                 if let Some(rename) = rename {
                     vis.visit_ident(rename);
                 }
@@ -1375,30 +1398,27 @@ impl WalkItemKind for AssocItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
     ) {
         match self {
             AssocItemKind::Const(item) => {
-                visit_const_item(item, visitor);
+                walk_const_item(visitor, item);
             }
             AssocItemKind::Fn(func) => {
-                visitor.visit_fn(
-                    FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func),
-                    span,
-                    id,
-                );
+                visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id);
             }
             AssocItemKind::Type(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_ident(ident);
                 visitor.visit_generics(generics);
                 visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1409,6 +1429,7 @@ impl WalkItemKind for AssocItemKind {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
@@ -1416,6 +1437,7 @@ impl WalkItemKind for AssocItemKind {
                 visitor.visit_id(id);
                 visitor.visit_qself(qself);
                 visitor.visit_path(path);
+                visitor.visit_ident(ident);
                 if let Some(rename) = rename {
                     visitor.visit_ident(rename);
                 }
@@ -1442,14 +1464,14 @@ impl WalkItemKind for AssocItemKind {
     }
 }
 
-fn visit_const_item<T: MutVisitor>(
-    ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
-    visitor: &mut T,
-) {
-    visit_defaultness(visitor, defaultness);
-    visitor.visit_generics(generics);
-    visitor.visit_ty(ty);
-    visit_opt(expr, |expr| visitor.visit_expr(expr));
+fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
+    let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
+    visit_defaultness(vis, defaultness);
+    vis.visit_ident(ident);
+    vis.visit_generics(generics);
+    vis.visit_ty(ty);
+    visit_opt(expr, |expr| vis.visit_expr(expr));
+    walk_define_opaques(vis, define_opaque);
 }
 
 fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
@@ -1482,12 +1504,11 @@ fn walk_item_ctxt<K: WalkItemKind>(
     item: &mut P<Item<K>>,
     ctxt: K::Ctxt,
 ) {
-    let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
+    let Item { attrs, id, kind, vis, span, tokens } = item.deref_mut();
     visitor.visit_id(id);
     visit_attrs(visitor, attrs);
     visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
-    kind.walk(*span, *id, ident, vis, ctxt, visitor);
+    kind.walk(*span, *id, vis, ctxt, visitor);
     visit_lazy_tts(visitor, tokens);
     visitor.visit_span(span);
 }
@@ -1520,31 +1541,37 @@ impl WalkItemKind for ForeignItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
     ) {
         match self {
-            ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
+            ForeignItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                mutability: _,
+                expr,
+                safety: _,
+                define_opaque,
+            }) => {
+                visitor.visit_ident(ident);
                 visitor.visit_ty(ty);
                 visit_opt(expr, |expr| visitor.visit_expr(expr));
+                walk_define_opaques(visitor, define_opaque);
             }
             ForeignItemKind::Fn(func) => {
-                visitor.visit_fn(
-                    FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func),
-                    span,
-                    id,
-                );
+                visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id);
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_ident(ident);
                 visitor.visit_generics(generics);
                 visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1929,6 +1956,18 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
     }
 }
 
+fn walk_define_opaques<T: MutVisitor>(
+    vis: &mut T,
+    define_opaque: &mut Option<ThinVec<(NodeId, Path)>>,
+) {
+    if let Some(define_opaque) = define_opaque {
+        for (id, path) in define_opaque {
+            vis.visit_id(id);
+            vis.visit_path(path)
+        }
+    }
+}
+
 /// Some value for the AST node that is valid but possibly meaningless. Similar
 /// to `Default` but not intended for wide use. The value will never be used
 /// meaningfully, it exists just to support unwinding in `visit_clobber` in the
@@ -1960,8 +1999,7 @@ impl DummyAstNode for Item {
                 span: Default::default(),
                 tokens: Default::default(),
             },
-            ident: Ident::dummy(),
-            kind: ItemKind::ExternCrate(None),
+            kind: ItemKind::ExternCrate(None, Ident::dummy()),
             tokens: Default::default(),
         }
     }
@@ -2028,7 +2066,7 @@ impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNo
 #[derive(Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn),
+    Fn(FnCtxt, &'a mut Visibility, &'a mut Fn),
 
     /// E.g., `|x, y| body`.
     Closure(
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index f7cd63aaaf8..d57a369eebf 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -198,16 +198,17 @@ impl Lit {
         }
     }
 
-    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` excluding unary negation.
+    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
+    /// `Parser::eat_token_lit` (excluding unary negation).
     pub fn from_token(token: &Token) -> Option<Lit> {
         match token.uninterpolate().kind {
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
             Literal(token_lit) => Some(token_lit),
-            Interpolated(ref nt)
-                if let NtExpr(expr) | NtLiteral(expr) = &**nt
-                    && let ast::ExprKind::Lit(token_lit) = expr.kind =>
-            {
-                Some(token_lit)
+            OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
+                MetaVarKind::Literal | MetaVarKind::Expr { .. },
+            ))) => {
+                // Unreachable with the current test suite.
+                panic!("from_token metavar");
             }
             _ => None,
         }
@@ -447,8 +448,9 @@ pub enum TokenKind {
 
     /// Identifier token.
     /// Do not forget about `NtIdent` when you want to match on identifiers.
-    /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
-    /// treat regular and interpolated identifiers in the same way.
+    /// It's recommended to use `Token::{ident,uninterpolate}` and
+    /// `Parser::token_uninterpolated_span` to treat regular and interpolated
+    /// identifiers in the same way.
     Ident(Symbol, IdentIsRaw),
     /// This identifier (and its span) is the identifier passed to the
     /// declarative macro. The span in the surrounding `Token` is the span of
@@ -457,8 +459,9 @@ pub enum TokenKind {
 
     /// Lifetime identifier token.
     /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
-    /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
-    /// treat regular and interpolated lifetime identifiers in the same way.
+    /// It's recommended to use `Token::{ident,uninterpolate}` and
+    /// `Parser::token_uninterpolated_span` to treat regular and interpolated
+    /// identifiers in the same way.
     Lifetime(Symbol, IdentIsRaw),
     /// This identifier (and its span) is the lifetime passed to the
     /// declarative macro. The span in the surrounding `Token` is the span of
@@ -584,20 +587,6 @@ impl Token {
         Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span)
     }
 
-    /// For interpolated tokens, returns a span of the fragment to which the interpolated
-    /// token refers. For all other tokens this is just a regular span.
-    /// It is particularly important to use this for identifiers and lifetimes
-    /// for which spans affect name resolution and edition checks.
-    /// Note that keywords are also identifiers, so they should use this
-    /// if they keep spans or perform edition checks.
-    pub fn uninterpolated_span(&self) -> Span {
-        match self.kind {
-            NtIdent(ident, _) | NtLifetime(ident, _) => ident.span,
-            Interpolated(ref nt) => nt.use_span(),
-            _ => self.span,
-        }
-    }
-
     pub fn is_range_separator(&self) -> bool {
         [DotDot, DotDotDot, DotDotEq].contains(&self.kind)
     }
@@ -642,12 +631,7 @@ impl Token {
             PathSep                           | // global path
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
-            Interpolated(ref nt) =>
-                matches!(&**nt,
-                    NtBlock(..)   |
-                    NtExpr(..)    |
-                    NtLiteral(..)
-                ),
+            Interpolated(ref nt) => matches!(&**nt, NtBlock(..)),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Block |
                 MetaVarKind::Expr { .. } |
@@ -677,11 +661,6 @@ impl Token {
             Lt |                                 // path (UFCS constant)
             Shl => true,                         // path (double UFCS)
             Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern
-            Interpolated(nt) =>
-                matches!(&**nt,
-                    | NtExpr(..)
-                    | NtLiteral(..)
-                ),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Expr { .. } |
                 MetaVarKind::Literal |
@@ -724,7 +703,7 @@ impl Token {
         match self.kind {
             OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true,
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
-            Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
+            Interpolated(ref nt) => matches!(&**nt, NtBlock(..)),
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
                 MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal,
             ))) => true,
@@ -768,22 +747,12 @@ impl Token {
     ///
     /// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
     ///
-    /// Keep this in sync with and `Lit::from_token`, excluding unary negation.
+    /// Keep this in sync with `Lit::from_token` and `Parser::eat_token_lit`
+    /// (excluding unary negation).
     pub fn can_begin_literal_maybe_minus(&self) -> bool {
         match self.uninterpolate().kind {
             Literal(..) | Minus => true,
             Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
-            Interpolated(ref nt) => match &**nt {
-                NtLiteral(_) => true,
-                NtExpr(e) => match &e.kind {
-                    ast::ExprKind::Lit(_) => true,
-                    ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
-                        matches!(&e.kind, ast::ExprKind::Lit(_))
-                    }
-                    _ => false,
-                },
-                _ => false,
-            },
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind {
                 MetaVarKind::Literal => true,
                 MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => {
@@ -798,14 +767,6 @@ impl Token {
     pub fn can_begin_string_literal(&self) -> bool {
         match self.uninterpolate().kind {
             Literal(..) => true,
-            Interpolated(ref nt) => match &**nt {
-                NtLiteral(_) => true,
-                NtExpr(e) => match &e.kind {
-                    ast::ExprKind::Lit(_) => true,
-                    _ => false,
-                },
-                _ => false,
-            },
             OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind {
                 MetaVarKind::Literal => true,
                 MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal,
@@ -869,12 +830,17 @@ impl Token {
 
     /// 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 {
+    pub fn is_metavar_expr(&self) -> bool {
         #[allow(irrefutable_let_patterns)] // FIXME: temporary
         if let Interpolated(nt) = &self.kind
-            && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt
+            && let NtBlock(_) = &**nt
         {
             true
+        } else if matches!(
+            self.is_metavar_seq(),
+            Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path)
+        ) {
+            true
         } else {
             matches!(self.is_metavar_seq(), Some(MetaVarKind::Path))
         }
@@ -882,6 +848,7 @@ impl Token {
 
     /// Is the token an interpolated block (`$b:block`)?
     pub fn is_whole_block(&self) -> bool {
+        #[allow(irrefutable_let_patterns)] // FIXME: temporary
         if let Interpolated(nt) = &self.kind
             && let NtBlock(..) = &**nt
         {
@@ -928,11 +895,6 @@ impl Token {
         self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
     }
 
-    /// Don't use this unless you're doing something very loose and heuristic-y.
-    pub fn is_any_keyword(&self) -> bool {
-        self.is_non_raw_ident_where(Ident::is_any_keyword)
-    }
-
     /// Returns true for reserved identifiers used internally for elided lifetimes,
     /// unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special_ident(&self) -> bool {
@@ -1105,8 +1067,6 @@ pub enum NtExprKind {
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
     NtBlock(P<ast::Block>),
-    NtExpr(P<ast::Expr>),
-    NtLiteral(P<ast::Expr>),
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
@@ -1196,15 +1156,12 @@ impl Nonterminal {
     pub fn use_span(&self) -> Span {
         match self {
             NtBlock(block) => block.span,
-            NtExpr(expr) | NtLiteral(expr) => expr.span,
         }
     }
 
     pub fn descr(&self) -> &'static str {
         match self {
             NtBlock(..) => "block",
-            NtExpr(..) => "expression",
-            NtLiteral(..) => "literal",
         }
     }
 }
@@ -1223,8 +1180,6 @@ impl fmt::Debug for Nonterminal {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             NtBlock(..) => f.pad("NtBlock(..)"),
-            NtExpr(..) => f.pad("NtExpr(..)"),
-            NtLiteral(..) => f.pad("NtLiteral(..)"),
         }
     }
 }
@@ -1247,7 +1202,7 @@ mod size_asserts {
     // tidy-alphabetical-start
     static_assert_size!(Lit, 12);
     static_assert_size!(LitKind, 2);
-    static_assert_size!(Nonterminal, 16);
+    static_assert_size!(Nonterminal, 8);
     static_assert_size!(Token, 24);
     static_assert_size!(TokenKind, 16);
     // tidy-alphabetical-end
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index bdd244be6d1..fb331e74aeb 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -233,35 +233,52 @@ fn attrs_and_tokens_to_token_trees(
 
     // Insert inner attribute tokens.
     if !inner_attrs.is_empty() {
-        let mut found = false;
-        // Check the last two trees (to account for a trailing semi)
-        for tree in res.iter_mut().rev().take(2) {
-            if let TokenTree::Delimited(span, spacing, delim, delim_tokens) = tree {
-                // Inner attributes are only supported on extern blocks, functions,
-                // impls, and modules. All of these have their inner attributes
-                // placed at the beginning of the rightmost outermost braced group:
-                // e.g. fn foo() { #![my_attr] }
-                //
-                // Therefore, we can insert them back into the right location
-                // without needing to do any extra position tracking.
-                //
-                // Note: Outline modules are an exception - they can
-                // have attributes like `#![my_attr]` at the start of a file.
-                // Support for custom attributes in this position is not
-                // properly implemented - we always synthesize fake tokens,
-                // so we never reach this code.
+        let found = insert_inner_attrs(inner_attrs, res);
+        assert!(found, "Failed to find trailing delimited group in: {res:?}");
+    }
+
+    // Inner attributes are only supported on blocks, functions, impls, and
+    // modules. All of these have their inner attributes placed at the
+    // beginning of the rightmost outermost braced group:
+    // e.g. `fn foo() { #![my_attr] }`. (Note: the braces may be within
+    // invisible delimiters.)
+    //
+    // Therefore, we can insert them back into the right location without
+    // needing to do any extra position tracking.
+    //
+    // Note: Outline modules are an exception - they can have attributes like
+    // `#![my_attr]` at the start of a file. Support for custom attributes in
+    // this position is not properly implemented - we always synthesize fake
+    // tokens, so we never reach this code.
+    fn insert_inner_attrs(inner_attrs: &[Attribute], tts: &mut Vec<TokenTree>) -> bool {
+        for tree in tts.iter_mut().rev() {
+            if let TokenTree::Delimited(span, spacing, Delimiter::Brace, stream) = tree {
+                // Found it: the rightmost, outermost braced group.
                 let mut tts = vec![];
                 for inner_attr in inner_attrs {
                     tts.extend(inner_attr.token_trees());
                 }
-                tts.extend(delim_tokens.0.iter().cloned());
+                tts.extend(stream.0.iter().cloned());
                 let stream = TokenStream::new(tts);
-                *tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
-                found = true;
-                break;
+                *tree = TokenTree::Delimited(*span, *spacing, Delimiter::Brace, stream);
+                return true;
+            } else if let TokenTree::Delimited(span, spacing, Delimiter::Invisible(src), stream) =
+                tree
+            {
+                // Recurse inside invisible delimiters.
+                let mut vec: Vec<_> = stream.iter().cloned().collect();
+                if insert_inner_attrs(inner_attrs, &mut vec) {
+                    *tree = TokenTree::Delimited(
+                        *span,
+                        *spacing,
+                        Delimiter::Invisible(*src),
+                        TokenStream::new(vec),
+                    );
+                    return true;
+                }
             }
         }
-        assert!(found, "Failed to find trailing delimited group in: {res:?}");
+        false
     }
 }
 
@@ -462,7 +479,6 @@ impl TokenStream {
     pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
         match nt {
             Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
-            Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
         }
     }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ce8d6df75af..1ef92ff8898 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -16,6 +16,7 @@
 pub use rustc_ast_ir::visit::VisitorResult;
 pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
 use rustc_span::{Ident, Span};
+use thin_vec::ThinVec;
 
 use crate::ast::*;
 use crate::ptr::P;
@@ -23,7 +24,7 @@ use crate::ptr::P;
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AssocCtxt {
     Trait,
-    Impl,
+    Impl { of_trait: bool },
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
@@ -65,7 +66,7 @@ impl BoundKind {
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn),
+    Fn(FnCtxt, &'a Visibility, &'a Fn),
 
     /// E.g., `|x, y| body`.
     Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
@@ -74,21 +75,21 @@ pub enum FnKind<'a> {
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header),
+            FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header),
             FnKind::Closure(..) => None,
         }
     }
 
     pub fn ident(&self) -> Option<&Ident> {
         match self {
-            FnKind::Fn(_, ident, ..) => Some(ident),
+            FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
             _ => None,
         }
     }
 
     pub fn decl(&self) -> &'a FnDecl {
         match self {
-            FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl,
+            FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl,
             FnKind::Closure(_, _, decl, _) => decl,
         }
     }
@@ -117,7 +118,6 @@ pub trait WalkItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         visibility: &'a Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut V,
@@ -363,49 +363,72 @@ impl WalkItemKind for ItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut V,
     ) -> V::Result {
         match self {
-            ItemKind::ExternCrate(_rename) => {}
+            ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)),
             ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
-            ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
+            ItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                safety: _,
+                mutability: _,
+                expr,
+                define_opaque,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
+                try_visit!(walk_define_opaques(visitor, define_opaque));
             }
-            ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
+            ItemKind::Const(box ConstItem {
+                defaultness: _,
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
+                try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             ItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Free, vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
-            ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _inline, _inner_span, _) => {
-                    walk_list!(visitor, visit_item, items);
+            ItemKind::Mod(_unsafety, ident, mod_kind) => {
+                try_visit!(visitor.visit_ident(ident));
+                match mod_kind {
+                    ModKind::Loaded(items, _inline, _inner_span, _) => {
+                        walk_list!(visitor, visit_item, items);
+                    }
+                    ModKind::Unloaded => {}
                 }
-                ModKind::Unloaded => {}
-            },
+            }
             ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
                 walk_list!(visitor, visit_foreign_item, items);
             }
             ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
             ItemKind::TyAlias(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
             }
-            ItemKind::Enum(enum_definition, generics) => {
+            ItemKind::Enum(ident, enum_definition, generics) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_enum_def(enum_definition));
             }
@@ -422,34 +445,54 @@ impl WalkItemKind for ItemKind {
                 try_visit!(visitor.visit_generics(generics));
                 visit_opt!(visitor, visit_trait_ref, of_trait);
                 try_visit!(visitor.visit_ty(self_ty));
-                walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
+                walk_list!(
+                    visitor,
+                    visit_assoc_item,
+                    items,
+                    AssocCtxt::Impl { of_trait: of_trait.is_some() }
+                );
             }
-            ItemKind::Struct(struct_definition, generics)
-            | ItemKind::Union(struct_definition, generics) => {
+            ItemKind::Struct(ident, struct_definition, generics)
+            | ItemKind::Union(ident, struct_definition, generics) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_variant_data(struct_definition));
             }
-            ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => {
+            ItemKind::Trait(box Trait {
+                safety: _,
+                is_auto: _,
+                ident,
+                generics,
+                bounds,
+                items,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
                 walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
             }
-            ItemKind::TraitAlias(generics, bounds) => {
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             }
             ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-            ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)),
+            ItemKind::MacroDef(ident, ts) => {
+                try_visit!(visitor.visit_ident(ident));
+                try_visit!(visitor.visit_mac_def(ts, id))
+            }
             ItemKind::Delegation(box Delegation {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
             }) => {
                 try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
+                try_visit!(visitor.visit_ident(ident));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
@@ -723,27 +766,37 @@ impl WalkItemKind for ForeignItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut V,
     ) -> V::Result {
         match self {
-            ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
+            ForeignItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                mutability: _,
+                expr,
+                safety: _,
+                define_opaque,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
+                try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             ForeignItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
@@ -890,10 +943,10 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
     match kind {
         FnKind::Fn(
             _ctxt,
-            _ident,
             _vis,
             Fn {
                 defaultness: _,
+                ident,
                 sig: FnSig { header, decl, span: _ },
                 generics,
                 contract,
@@ -901,15 +954,14 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
                 define_opaque,
             },
         ) => {
-            // Identifier and visibility are visited as a part of the item.
+            // Visibility is visited as a part of the item.
+            try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_fn_header(header));
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(decl));
             visit_opt!(visitor, visit_contract, contract);
             visit_opt!(visitor, visit_block, body);
-            for (id, path) in define_opaque.iter().flatten() {
-                try_visit!(visitor.visit_path(path, *id))
-            }
+            try_visit!(walk_define_opaques(visitor, define_opaque));
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
             try_visit!(visitor.visit_closure_binder(binder));
@@ -927,29 +979,39 @@ impl WalkItemKind for AssocItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut V,
     ) -> V::Result {
         match self {
-            AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
+            AssocItemKind::Const(box ConstItem {
+                defaultness: _,
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
+                try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             AssocItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             AssocItemKind::Type(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
                 try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_ident(ident));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
             }
@@ -960,12 +1022,14 @@ impl WalkItemKind for AssocItemKind {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
             }) => {
                 try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
+                try_visit!(visitor.visit_ident(ident));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
@@ -1007,11 +1071,10 @@ fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
     item: &'a Item<K>,
     ctxt: K::Ctxt,
 ) -> V::Result {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
+    let Item { id, span, vis, attrs, kind, tokens: _ } = item;
     walk_list!(visitor, visit_attribute, attrs);
     try_visit!(visitor.visit_vis(vis));
-    try_visit!(visitor.visit_ident(ident));
-    try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor));
+    try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
     V::Result::output()
 }
 
@@ -1035,7 +1098,7 @@ pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef)
 }
 
 pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
-    let Block { stmts, id: _, rules: _, span: _, tokens: _, could_be_bare_literal: _ } = block;
+    let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block;
     walk_list!(visitor, visit_stmt, stmts);
     V::Result::output()
 }
@@ -1337,3 +1400,15 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
     }
     V::Result::output()
 }
+
+fn walk_define_opaques<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
+) -> V::Result {
+    if let Some(define_opaque) = define_opaque {
+        for (id, path) in define_opaque {
+            try_visit!(visitor.visit_path(path, *id));
+        }
+    }
+    V::Result::output()
+}
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 65e5b530bbe..5ef76fb64aa 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -141,9 +141,6 @@ ast_lowering_never_pattern_with_guard =
 
 ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
 
-ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-    .note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-
 ast_lowering_previously_used_here = previously used here
 
 ast_lowering_register1 = register `{$reg1_name}`
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index efc1fa05c5f..9899ee03a51 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -56,13 +56,20 @@ use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
 pub(crate) struct DelegationResults<'hir> {
     pub body_id: hir::BodyId,
     pub sig: hir::FnSig<'hir>,
+    pub ident: Ident,
     pub generics: &'hir hir::Generics<'hir>,
 }
 
 impl<'hir> LoweringContext<'_, 'hir> {
     /// Defines whether the delegatee is an associated function whose first parameter is `self`.
-    pub(crate) fn delegatee_is_method(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool {
-        let sig_id = self.get_delegation_sig_id(item_id, path_id, span);
+    pub(crate) fn delegatee_is_method(
+        &self,
+        item_id: NodeId,
+        path_id: NodeId,
+        span: Span,
+        is_in_trait_impl: bool,
+    ) -> bool {
+        let sig_id = self.get_delegation_sig_id(item_id, path_id, span, is_in_trait_impl);
         let Ok(sig_id) = sig_id else {
             return false;
         };
@@ -88,18 +95,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
         &mut self,
         delegation: &Delegation,
         item_id: NodeId,
+        is_in_trait_impl: bool,
     ) -> DelegationResults<'hir> {
         let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
-        let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
+        let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
         match sig_id {
             Ok(sig_id) => {
                 let (param_count, c_variadic) = self.param_count(sig_id);
                 let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
                 let sig = self.lower_delegation_sig(sig_id, decl, span);
                 let body_id = self.lower_delegation_body(delegation, param_count, span);
-
+                let ident = self.lower_ident(delegation.ident);
                 let generics = self.lower_delegation_generics(span);
-                DelegationResults { body_id, sig, generics }
+                DelegationResults { body_id, sig, ident, generics }
             }
             Err(err) => self.generate_delegation_error(err, span),
         }
@@ -110,8 +118,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         item_id: NodeId,
         path_id: NodeId,
         span: Span,
+        is_in_trait_impl: bool,
     ) -> Result<DefId, ErrorGuaranteed> {
-        let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
+        let sig_id = if is_in_trait_impl { item_id } else { path_id };
         self.get_resolution_id(sig_id, span)
     }
 
@@ -397,8 +406,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let header = self.generate_header_error();
         let sig = hir::FnSig { decl, header, span };
 
+        let ident = Ident::dummy();
         let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
-        DelegationResults { generics, body_id, sig }
+        DelegationResults { ident, generics, body_id, sig }
     }
 
     fn generate_header_error(&self) -> hir::FnHeader {
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index ceeb5dffbea..576fa9731e9 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -445,14 +445,6 @@ pub(crate) struct NoPreciseCapturesOnApit {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_no_precise_captures_on_rpitit)]
-#[note]
-pub(crate) struct NoPreciseCapturesOnRpitit {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(ast_lowering_yield_in_closure)]
 pub(crate) struct YieldInClosure {
     #[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 7f3d060bb8a..52291fdfb30 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -2150,11 +2150,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.expr_uint(sp, ast::UintTy::U16, value as u128)
     }
 
-    pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
-        let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
-        self.expr(sp, hir::ExprKind::Lit(lit))
-    }
-
     pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
         let lit = self
             .arena
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index faa47274f96..0de0319c667 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -323,14 +323,12 @@ fn make_count<'hir>(
 /// Generates
 ///
 /// ```text
-///     <core::fmt::rt::Placeholder::new(
-///         …usize, // position
-///         '…', // fill
-///         <core::fmt::rt::Alignment>::…, // alignment
-///         …u32, // flags
-///         <core::fmt::rt::Count::…>, // width
-///         <core::fmt::rt::Count::…>, // precision
-///     )
+///     <core::fmt::rt::Placeholder {
+///         position: …usize,
+///         flags: …u32,
+///         precision: <core::fmt::rt::Count::…>,
+///         width: <core::fmt::rt::Count::…>,
+///     }
 /// ```
 fn make_format_spec<'hir>(
     ctx: &mut LoweringContext<'_, 'hir>,
@@ -361,34 +359,36 @@ fn make_format_spec<'hir>(
         zero_pad,
         debug_hex,
     } = &placeholder.format_options;
-    let fill = ctx.expr_char(sp, fill.unwrap_or(' '));
-    let align = ctx.expr_lang_item_type_relative(
-        sp,
-        hir::LangItem::FormatAlignment,
-        match alignment {
-            Some(FormatAlignment::Left) => sym::Left,
-            Some(FormatAlignment::Right) => sym::Right,
-            Some(FormatAlignment::Center) => sym::Center,
-            None => sym::Unknown,
-        },
-    );
-    // This needs to match `Flag` in library/core/src/fmt/rt.rs.
-    let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
-        | ((sign == Some(FormatSign::Minus)) as u32) << 1
-        | (alternate as u32) << 2
-        | (zero_pad as u32) << 3
-        | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4
-        | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5;
+    let fill = fill.unwrap_or(' ');
+    // These need to match the constants in library/core/src/fmt/rt.rs.
+    let align = match alignment {
+        Some(FormatAlignment::Left) => 0,
+        Some(FormatAlignment::Right) => 1,
+        Some(FormatAlignment::Center) => 2,
+        None => 3,
+    };
+    // This needs to match the constants in library/core/src/fmt/rt.rs.
+    let flags: u32 = fill as u32
+        | ((sign == Some(FormatSign::Plus)) as u32) << 21
+        | ((sign == Some(FormatSign::Minus)) as u32) << 22
+        | (alternate as u32) << 23
+        | (zero_pad as u32) << 24
+        | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25
+        | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26
+        | (width.is_some() as u32) << 27
+        | (precision.is_some() as u32) << 28
+        | align << 29
+        | 1 << 31; // Highest bit always set.
     let flags = ctx.expr_u32(sp, flags);
     let precision = make_count(ctx, sp, precision, argmap);
     let width = make_count(ctx, sp, width, argmap);
-    let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
-        sp,
-        hir::LangItem::FormatPlaceholder,
-        sym::new,
-    ));
-    let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]);
-    ctx.expr_call_mut(sp, format_placeholder_new, args)
+    let position = ctx.expr_field(Ident::new(sym::position, sp), ctx.arena.alloc(position), sp);
+    let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp);
+    let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp);
+    let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp);
+    let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp));
+    let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]);
+    ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None))
 }
 
 fn expand_format_args<'hir>(
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index bd011d59aaa..28f596ac092 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -5,9 +5,8 @@ use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
-use rustc_hir::{self as hir, HirId, PredicateOrigin};
+use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin};
 use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
@@ -104,14 +103,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
     }
 
     fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
-        let def_id = self.resolver.node_id_to_def_id[&item.id];
-        let parent_id = self.tcx.local_parent(def_id);
-        let parent_hir = self.lower_node(parent_id).unwrap();
-        self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir))
+        self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
     }
 
     fn lower_foreign_item(&mut self, item: &ForeignItem) {
-        debug_assert_ne!(item.ident.name, kw::Empty);
         self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
     }
 }
@@ -132,8 +127,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
-        let mut node_ids =
-            smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
+        let mut node_ids = smallvec![hir::ItemId { owner_id: self.owner_id(i.id) }];
         if let ItemKind::Use(use_tree) = &i.kind {
             self.lower_item_id_use_tree(use_tree, &mut node_ids);
         }
@@ -144,9 +138,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         match &tree.kind {
             UseTreeKind::Nested { items, .. } => {
                 for &(ref nested, id) in items {
-                    vec.push(hir::ItemId {
-                        owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
-                    });
+                    vec.push(hir::ItemId { owner_id: self.owner_id(id) });
                     self.lower_item_id_use_tree(nested, vec);
                 }
             }
@@ -158,7 +150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let vis_span = self.lower_span(i.vis.span);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
-        let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind);
+        let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);
         let item = hir::Item {
             owner_id: hir_id.expect_owner(),
             kind,
@@ -173,34 +165,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         id: NodeId,
         hir_id: hir::HirId,
-        ident: Ident,
         attrs: &'hir [hir::Attribute],
         vis_span: Span,
         i: &ItemKind,
     ) -> hir::ItemKind<'hir> {
         match i {
-            ItemKind::ExternCrate(orig_name) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::ExternCrate(orig_name, ident) => {
+                let ident = self.lower_ident(*ident);
                 hir::ItemKind::ExternCrate(*orig_name, ident)
             }
             ItemKind::Use(use_tree) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 // Start with an empty prefix.
                 let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
 
                 self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
             }
-            ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Static(box ast::StaticItem {
+                ident,
+                ty: t,
+                safety: _,
+                mutability: m,
+                expr: e,
+                define_opaque,
+            }) => {
+                let ident = self.lower_ident(*ident);
                 let (ty, body_id) =
                     self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
+                self.lower_define_opaque(hir_id, define_opaque);
                 hir::ItemKind::Static(ident, ty, *m, body_id)
             }
-            ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Const(box ast::ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, (ty, body_id)) = self.lower_generics(
                     generics,
                     id,
@@ -209,17 +211,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
                     },
                 );
+                self.lower_define_opaque(hir_id, &define_opaque);
                 hir::ItemKind::Const(ident, ty, generics, body_id)
             }
             ItemKind::Fn(box Fn {
                 sig: FnSig { decl, header, span: fn_sig_span },
+                ident,
                 generics,
                 body,
                 contract,
                 define_opaque,
                 ..
             }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
                 self.with_new_scopes(*fn_sig_span, |this| {
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
@@ -246,8 +249,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
                         span: this.lower_span(*fn_sig_span),
                     };
-                    this.lower_define_opaque(hir_id, &define_opaque);
-                    let ident = this.lower_ident(ident);
+                    this.lower_define_opaque(hir_id, define_opaque);
+                    let ident = this.lower_ident(*ident);
                     hir::ItemKind::Fn {
                         ident,
                         sig,
@@ -257,9 +260,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 })
             }
-            ItemKind::Mod(_, mod_kind) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Mod(_, ident, mod_kind) => {
+                let ident = self.lower_ident(*ident);
                 match mod_kind {
                     ModKind::Loaded(items, _, spans, _) => {
                         hir::ItemKind::Mod(ident, self.lower_mod(items, spans))
@@ -267,24 +269,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
                 }
             }
-            ItemKind::ForeignMod(fm) => {
-                debug_assert_eq!(ident.name, kw::Empty);
-                hir::ItemKind::ForeignMod {
-                    abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
-                    items: self
-                        .arena
-                        .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
-                }
-            }
+            ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
+                abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
+                items: self
+                    .arena
+                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+            },
             ItemKind::GlobalAsm(asm) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 let asm = self.lower_inline_asm(span, asm);
                 let fake_body =
                     self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
                 hir::ItemKind::GlobalAsm { asm, fake_body }
             }
-            ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
+            ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -293,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 //
                 // type Foo = Foo1
                 // opaque type Foo1: Trait
-                let ident = self.lower_ident(ident);
+                let ident = self.lower_ident(*ident);
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let (generics, ty) = self.lower_generics(
@@ -321,9 +318,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TyAlias(ident, ty, generics)
             }
-            ItemKind::Enum(enum_definition, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Enum(ident, enum_definition, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, variants) = self.lower_generics(
                     generics,
                     id,
@@ -336,9 +332,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics)
             }
-            ItemKind::Struct(struct_def, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Struct(ident, struct_def, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, struct_def) = self.lower_generics(
                     generics,
                     id,
@@ -347,9 +342,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Struct(ident, struct_def, generics)
             }
-            ItemKind::Union(vdata, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Union(ident, vdata, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, vdata) = self.lower_generics(
                     generics,
                     id,
@@ -368,7 +362,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self_ty: ty,
                 items: impl_items,
             }) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
                 //
@@ -408,10 +401,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         (trait_ref, lowered_ty)
                     });
 
-                self.is_in_trait_impl = trait_ref.is_some();
-                let new_impl_items = self
-                    .arena
-                    .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
+                let new_impl_items = self.arena.alloc_from_iter(
+                    impl_items
+                        .iter()
+                        .map(|item| self.lower_impl_item_ref(item, trait_ref.is_some())),
+                );
 
                 // `defaultness.has_value()` is never called for an `impl`, always `true` in order
                 // to not cause an assertion failure inside the `lower_defaultness` function.
@@ -433,9 +427,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     items: new_impl_items,
                 }))
             }
-            ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, (safety, items, bounds)) = self.lower_generics(
                     generics,
                     id,
@@ -454,9 +447,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
             }
-            ItemKind::TraitAlias(generics, bounds) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, bounds) = self.lower_generics(
                     generics,
                     id,
@@ -470,9 +462,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TraitAlias(ident, generics, bounds)
             }
-            ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
+                let ident = self.lower_ident(*ident);
                 let body = P(self.lower_delim_args(body));
                 let def_id = self.local_def_id(id);
                 let def_kind = self.tcx.def_kind(def_id);
@@ -486,11 +477,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 hir::ItemKind::Macro(ident, macro_def, macro_kind)
             }
             ItemKind::Delegation(box delegation) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
-                let delegation_results = self.lower_delegation(delegation, id);
+                let delegation_results = self.lower_delegation(delegation, id, false);
                 hir::ItemKind::Fn {
-                    ident,
+                    ident: delegation_results.ident,
                     sig: delegation_results.sig,
                     generics: delegation_results.generics,
                     body: delegation_results.body_id,
@@ -585,7 +574,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 // Add all the nested `PathListItem`s to the HIR.
                 for &(ref use_tree, id) in trees {
-                    let new_hir_id = self.local_def_id(id);
+                    let owner_id = self.owner_id(id);
 
                     // Each `use` import is an item and thus are owners of the
                     // names in the path. Up to this point the nested import is
@@ -602,7 +591,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         }
 
                         let item = hir::Item {
-                            owner_id: hir::OwnerId { def_id: new_hir_id },
+                            owner_id,
                             kind,
                             vis_span,
                             span: this.lower_span(use_tree.span),
@@ -631,29 +620,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn lower_assoc_item(
-        &mut self,
-        item: &AssocItem,
-        ctxt: AssocCtxt,
-        parent_hir: &'hir hir::OwnerInfo<'hir>,
-    ) -> hir::OwnerNode<'hir> {
-        let parent_item = parent_hir.node().expect_item();
-        match parent_item.kind {
-            hir::ItemKind::Impl(impl_) => {
-                self.is_in_trait_impl = impl_.of_trait.is_some();
-            }
-            hir::ItemKind::Trait(..) => {}
-            kind => {
-                span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
-            }
-        }
-
+    fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> hir::OwnerNode<'hir> {
         // Evaluate with the lifetimes in `params` in-scope.
         // This is used to track which lifetimes have already been defined,
         // and which need to be replicated when lowering an async fn.
         match ctxt {
             AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
-            AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
+            AssocCtxt::Impl { of_trait } => {
+                hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait))
+            }
         }
     }
 
@@ -661,47 +636,64 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let owner_id = hir_id.expect_owner();
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
-        let item = hir::ForeignItem {
-            owner_id,
-            ident: self.lower_ident(i.ident),
-            kind: match &i.kind {
-                ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
-                    let fdec = &sig.decl;
-                    let itctx = ImplTraitContext::Universal;
-                    let (generics, (decl, fn_args)) =
-                        self.lower_generics(generics, i.id, itctx, |this| {
-                            (
-                                // Disallow `impl Trait` in foreign items.
-                                this.lower_fn_decl(
-                                    fdec,
-                                    i.id,
-                                    sig.span,
-                                    FnDeclKind::ExternFn,
-                                    None,
-                                ),
-                                this.lower_fn_params_to_names(fdec),
-                            )
-                        });
+        let (ident, kind) = match &i.kind {
+            ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => {
+                let fdec = &sig.decl;
+                let itctx = ImplTraitContext::Universal;
+                let (generics, (decl, fn_args)) =
+                    self.lower_generics(generics, i.id, itctx, |this| {
+                        (
+                            // Disallow `impl Trait` in foreign items.
+                            this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None),
+                            this.lower_fn_params_to_names(fdec),
+                        )
+                    });
 
-                    // Unmarked safety in unsafe block defaults to unsafe.
-                    let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
+                // Unmarked safety in unsafe block defaults to unsafe.
+                let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
 
+                if define_opaque.is_some() {
+                    self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
+                }
+
+                (
+                    ident,
                     hir::ForeignItemKind::Fn(
                         hir::FnSig { header, decl, span: self.lower_span(sig.span) },
                         fn_args,
                         generics,
-                    )
-                }
-                ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
-                    let ty = self
-                        .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
-                    let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
+                    ),
+                )
+            }
+            ForeignItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                mutability,
+                expr: _,
+                safety,
+                define_opaque,
+            }) => {
+                let ty =
+                    self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
+                let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
 
-                    hir::ForeignItemKind::Static(ty, *mutability, safety)
+                // njn: where for this?
+                if define_opaque.is_some() {
+                    self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
                 }
-                ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
-                ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
-            },
+
+                (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))
+            }
+            ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => {
+                (ident, hir::ForeignItemKind::Type)
+            }
+            ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
+        };
+
+        let item = hir::ForeignItem {
+            owner_id,
+            ident: self.lower_ident(*ident),
+            kind,
             vis_span: self.lower_span(i.vis.span),
             span: self.lower_span(i.span),
         };
@@ -710,8 +702,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
         hir::ForeignItemRef {
-            id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
-            ident: self.lower_ident(i.ident),
+            id: hir::ForeignItemId { owner_id: self.owner_id(i.id) },
+            // `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind
+            // without an identifier and it cannot reach here.
+            ident: self.lower_ident(i.kind.ident().unwrap()),
             span: self.lower_span(i.span),
         }
     }
@@ -798,13 +792,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
-        debug_assert_ne!(i.ident.name, kw::Empty);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
         let trait_item_def_id = hir_id.expect_owner();
 
-        let (generics, kind, has_default) = match &i.kind {
-            AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
+        let (ident, generics, kind, has_default) = match &i.kind {
+            AssocItemKind::Const(box ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => {
                 let (generics, kind) = self.lower_generics(
                     generics,
                     i.id,
@@ -817,9 +817,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::TraitItemKind::Const(ty, body)
                     },
                 );
-                (generics, kind, expr.is_some())
+
+                if define_opaque.is_some() {
+                    if expr.is_some() {
+                        self.lower_define_opaque(hir_id, &define_opaque);
+                    } else {
+                        self.dcx().span_err(
+                            i.span,
+                            "only trait consts with default bodies can define opaque types",
+                        );
+                    }
+                }
+
+                (*ident, generics, kind, expr.is_some())
             }
-            AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
+            AssocItemKind::Fn(box Fn {
+                sig, ident, generics, body: None, define_opaque, ..
+            }) => {
                 // FIXME(contracts): Deny contract here since it won't apply to
                 // any impl method or callees.
                 let names = self.lower_fn_params_to_names(&sig.decl);
@@ -837,10 +851,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         "only trait methods with default bodies can define opaque types",
                     );
                 }
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
+                (
+                    *ident,
+                    generics,
+                    hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)),
+                    false,
+                )
             }
             AssocItemKind::Fn(box Fn {
                 sig,
+                ident,
                 generics,
                 body: Some(body),
                 contract,
@@ -866,9 +886,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     attrs,
                 );
                 self.lower_define_opaque(hir_id, &define_opaque);
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
+                (
+                    *ident,
+                    generics,
+                    hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
+                    true,
+                )
             }
-            AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
+            AssocItemKind::Type(box TyAlias {
+                ident, generics, where_clauses, bounds, ty, ..
+            }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 let (generics, kind) = self.lower_generics(
@@ -891,15 +918,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         )
                     },
                 );
-                (generics, kind, ty.is_some())
+                (*ident, generics, kind, ty.is_some())
             }
             AssocItemKind::Delegation(box delegation) => {
-                let delegation_results = self.lower_delegation(delegation, i.id);
+                let delegation_results = self.lower_delegation(delegation, i.id, false);
                 let item_kind = hir::TraitItemKind::Fn(
                     delegation_results.sig,
                     hir::TraitFn::Provided(delegation_results.body_id),
                 );
-                (delegation_results.generics, item_kind, true)
+                (delegation.ident, delegation_results.generics, item_kind, true)
             }
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 panic!("macros should have been expanded by now")
@@ -908,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let item = hir::TraitItem {
             owner_id: trait_item_def_id,
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             generics,
             kind,
             span: self.lower_span(i.span),
@@ -918,23 +945,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
-        let kind = match &i.kind {
-            AssocItemKind::Const(..) => hir::AssocItemKind::Const,
-            AssocItemKind::Type(..) => hir::AssocItemKind::Type,
-            AssocItemKind::Fn(box Fn { sig, .. }) => {
-                hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
+        let (ident, kind) = match &i.kind {
+            AssocItemKind::Const(box ConstItem { ident, .. }) => {
+                (*ident, hir::AssocItemKind::Const)
             }
-            AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
-                has_self: self.delegatee_is_method(i.id, delegation.id, i.span),
-            },
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type),
+            AssocItemKind::Fn(box Fn { ident, sig, .. }) => {
+                (*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() })
+            }
+            AssocItemKind::Delegation(box delegation) => (
+                delegation.ident,
+                hir::AssocItemKind::Fn {
+                    has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
+                },
+            ),
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 panic!("macros should have been expanded by now")
             }
         };
-        let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
+        let id = hir::TraitItemId { owner_id: self.owner_id(i.id) };
         hir::TraitItemRef {
             id,
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             span: self.lower_span(i.span),
             kind,
         }
@@ -945,28 +977,49 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.expr(span, hir::ExprKind::Err(guar))
     }
 
-    fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
-        debug_assert_ne!(i.ident.name, kw::Empty);
+    fn lower_impl_item(
+        &mut self,
+        i: &AssocItem,
+        is_in_trait_impl: bool,
+    ) -> &'hir hir::ImplItem<'hir> {
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
 
-        let (generics, kind) = match &i.kind {
-            AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
+        let (ident, (generics, kind)) = match &i.kind {
+            AssocItemKind::Const(box ConstItem {
+                ident,
                 generics,
-                i.id,
-                ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
-                |this| {
-                    let ty =
-                        this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
-                    let body = this.lower_const_body(i.span, expr.as_deref());
-
-                    hir::ImplItemKind::Const(ty, body)
-                },
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => (
+                *ident,
+                self.lower_generics(
+                    generics,
+                    i.id,
+                    ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
+                    |this| {
+                        let ty = this
+                            .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
+                        let body = this.lower_const_body(i.span, expr.as_deref());
+                        this.lower_define_opaque(hir_id, &define_opaque);
+                        hir::ImplItemKind::Const(ty, body)
+                    },
+                ),
             ),
-            AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
+            AssocItemKind::Fn(box Fn {
+                sig,
+                ident,
+                generics,
+                body,
+                contract,
+                define_opaque,
+                ..
+            }) => {
                 let body_id = self.lower_maybe_coroutine_body(
                     sig.span,
                     i.span,
@@ -981,50 +1034,56 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     generics,
                     sig,
                     i.id,
-                    if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
+                    if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
                     sig.header.coroutine_kind,
                     attrs,
                 );
                 self.lower_define_opaque(hir_id, &define_opaque);
 
-                (generics, hir::ImplItemKind::Fn(sig, body_id))
+                (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))
             }
-            AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
+            AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
-                self.lower_generics(
-                    &generics,
-                    i.id,
-                    ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
-                    |this| match ty {
-                        None => {
-                            let guar = this.dcx().span_delayed_bug(
-                                i.span,
-                                "expected to lower associated type, but it was missing",
-                            );
-                            let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
-                            hir::ImplItemKind::Type(ty)
-                        }
-                        Some(ty) => {
-                            let ty = this.lower_ty(
-                                ty,
-                                ImplTraitContext::OpaqueTy {
-                                    origin: hir::OpaqueTyOrigin::TyAlias {
-                                        parent: this.local_def_id(i.id),
-                                        in_assoc_ty: true,
+                (
+                    *ident,
+                    self.lower_generics(
+                        &generics,
+                        i.id,
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
+                        |this| match ty {
+                            None => {
+                                let guar = this.dcx().span_delayed_bug(
+                                    i.span,
+                                    "expected to lower associated type, but it was missing",
+                                );
+                                let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
+                                hir::ImplItemKind::Type(ty)
+                            }
+                            Some(ty) => {
+                                let ty = this.lower_ty(
+                                    ty,
+                                    ImplTraitContext::OpaqueTy {
+                                        origin: hir::OpaqueTyOrigin::TyAlias {
+                                            parent: this.local_def_id(i.id),
+                                            in_assoc_ty: true,
+                                        },
                                     },
-                                },
-                            );
-                            hir::ImplItemKind::Type(ty)
-                        }
-                    },
+                                );
+                                hir::ImplItemKind::Type(ty)
+                            }
+                        },
+                    ),
                 )
             }
             AssocItemKind::Delegation(box delegation) => {
-                let delegation_results = self.lower_delegation(delegation, i.id);
+                let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl);
                 (
-                    delegation_results.generics,
-                    hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+                    delegation.ident,
+                    (
+                        delegation_results.generics,
+                        hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+                    ),
                 )
             }
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
@@ -1034,7 +1093,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let item = hir::ImplItem {
             owner_id: hir_id.expect_owner(),
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             generics,
             kind,
             vis_span: self.lower_span(i.vis.span),
@@ -1044,10 +1103,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.arena.alloc(item)
     }
 
-    fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
+    fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef {
         hir::ImplItemRef {
-            id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
-            ident: self.lower_ident(i.ident),
+            id: hir::ImplItemId { owner_id: self.owner_id(i.id) },
+            // `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only
+            // assoc item kinds without an identifier and they cannot reach here.
+            ident: self.lower_ident(i.kind.ident().unwrap()),
             span: self.lower_span(i.span),
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
@@ -1056,7 +1117,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
                 AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
-                    has_self: self.delegatee_is_method(i.id, delegation.id, i.span),
+                    has_self: self.delegatee_is_method(
+                        i.id,
+                        delegation.id,
+                        i.span,
+                        is_in_trait_impl,
+                    ),
                 },
                 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                     panic!("macros should have been expanded by now")
@@ -1724,8 +1790,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return;
         };
         let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
-            let res = self.resolver.get_partial_res(*id).unwrap();
-            let Some(did) = res.expect_full_res().opt_def_id() else {
+            let res = self.resolver.get_partial_res(*id);
+            let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else {
                 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
                 return None;
             };
@@ -1798,7 +1864,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             GenericParamKind::Lifetime => {
                 let lt_id = self.next_node_id();
-                let lifetime = self.new_named_lifetime(id, lt_id, ident);
+                let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
                 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
                     lifetime,
                     bounds,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index e08850da4a7..d5d6dcd8d63 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -55,7 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
 use rustc_hir::{
-    self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
+    self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName,
+    TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -121,7 +122,6 @@ struct LoweringContext<'a, 'hir> {
     catch_scope: Option<HirId>,
     loop_scope: Option<HirId>,
     is_in_loop_condition: bool,
-    is_in_trait_impl: bool,
     is_in_dyn_type: bool,
 
     current_hir_id_owner: hir::OwnerId,
@@ -173,7 +173,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             catch_scope: None,
             loop_scope: None,
             is_in_loop_condition: false,
-            is_in_trait_impl: false,
             is_in_dyn_type: false,
             coroutine_kind: None,
             task_context: None,
@@ -536,6 +535,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
     }
 
+    /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`.
+    fn owner_id(&self, node: NodeId) -> hir::OwnerId {
+        hir::OwnerId { def_id: self.local_def_id(node) }
+    }
+
     /// Freshen the `LoweringContext` and ready it to lower a nested item.
     /// The lowered item is registered into `self.children`.
     ///
@@ -547,7 +551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         owner: NodeId,
         f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
     ) {
-        let def_id = self.local_def_id(owner);
+        let owner_id = self.owner_id(owner);
 
         let current_attrs = std::mem::take(&mut self.attrs);
         let current_bodies = std::mem::take(&mut self.bodies);
@@ -558,8 +562,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         #[cfg(debug_assertions)]
         let current_node_id_to_local_id = std::mem::take(&mut self.node_id_to_local_id);
         let current_trait_map = std::mem::take(&mut self.trait_map);
-        let current_owner =
-            std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
+        let current_owner = std::mem::replace(&mut self.current_hir_id_owner, owner_id);
         let current_local_counter =
             std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
         let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
@@ -577,7 +580,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let item = f(self);
-        debug_assert_eq!(def_id, item.def_id().def_id);
+        debug_assert_eq!(owner_id, item.def_id());
         // `f` should have consumed all the elements in these vectors when constructing `item`.
         debug_assert!(self.impl_trait_defs.is_empty());
         debug_assert!(self.impl_trait_bounds.is_empty());
@@ -598,8 +601,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.impl_trait_defs = current_impl_trait_defs;
         self.impl_trait_bounds = current_impl_trait_bounds;
 
-        debug_assert!(!self.children.iter().any(|(id, _)| id == &def_id));
-        self.children.push((def_id, hir::MaybeOwner::Owner(info)));
+        debug_assert!(!self.children.iter().any(|(id, _)| id == &owner_id.def_id));
+        self.children.push((owner_id.def_id, hir::MaybeOwner::Owner(info)));
     }
 
     fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
@@ -621,7 +624,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         // Don't hash unless necessary, because it's expensive.
         let (opt_hash_including_bodies, attrs_hash) =
-            self.tcx.hash_owner_nodes(node, &bodies, &attrs);
+            self.tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque);
         let num_nodes = self.item_local_id_counter.as_usize();
         let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
         let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
@@ -1438,28 +1441,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // frequently opened issues show.
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
-        // Feature gate for RPITIT + use<..>
-        match origin {
-            rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
-                if !self.tcx.features().precise_capturing_in_traits()
-                    && let Some(span) = bounds.iter().find_map(|bound| match *bound {
-                        ast::GenericBound::Use(_, span) => Some(span),
-                        _ => None,
-                    })
-                {
-                    let mut diag =
-                        self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span });
-                    add_feature_diagnostics(
-                        &mut diag,
-                        self.tcx.sess,
-                        sym::precise_capturing_in_traits,
-                    );
-                    diag.emit();
-                }
-            }
-            _ => {}
-        }
-
         self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
             this.lower_param_bounds(bounds, itctx)
         })
@@ -1775,7 +1756,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
-        self.new_named_lifetime(l.id, l.id, l.ident)
+        self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
+    }
+
+    fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
+        self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1784,28 +1769,43 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         id: NodeId,
         new_id: NodeId,
         ident: Ident,
+        is_anon_in_path: IsAnonInPath,
     ) -> &'hir hir::Lifetime {
+        debug_assert_ne!(ident.name, kw::Empty);
         let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
         let res = match res {
             LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
             LifetimeRes::Fresh { param, .. } => {
+                debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
                 let param = self.local_def_id(param);
                 hir::LifetimeName::Param(param)
             }
-            LifetimeRes::Infer => hir::LifetimeName::Infer,
-            LifetimeRes::Static { .. } => hir::LifetimeName::Static,
+            LifetimeRes::Infer => {
+                debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+                hir::LifetimeName::Infer
+            }
+            LifetimeRes::Static { .. } => {
+                debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
+                hir::LifetimeName::Static
+            }
             LifetimeRes::Error => hir::LifetimeName::Error,
             LifetimeRes::ElidedAnchor { .. } => {
                 panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span);
             }
         };
 
+        #[cfg(debug_assertions)]
+        if is_anon_in_path == IsAnonInPath::Yes {
+            debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
+        }
+
         debug!(?res);
-        self.arena.alloc(hir::Lifetime {
-            hir_id: self.lower_node_id(new_id),
-            ident: self.lower_ident(ident),
+        self.arena.alloc(hir::Lifetime::new(
+            self.lower_node_id(new_id),
+            self.lower_ident(ident),
             res,
-        })
+            is_anon_in_path,
+        ))
     }
 
     fn lower_generic_params_mut(
@@ -2389,11 +2389,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// when the bound is written, even if it is written with `'_` like in
     /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
     fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
-        let r = hir::Lifetime {
-            hir_id: self.next_id(),
-            ident: Ident::new(kw::Empty, self.lower_span(span)),
-            res: hir::LifetimeName::ImplicitObjectLifetimeDefault,
-        };
+        let r = hir::Lifetime::new(
+            self.next_id(),
+            Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
+            hir::LifetimeName::ImplicitObjectLifetimeDefault,
+            IsAnonInPath::No,
+        );
         debug!("elided_dyn_bound: r={:?}", r);
         self.arena.alloc(r)
     }
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index d00c797755f..c464c159c34 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
 use rustc_session::parse::add_feature_diagnostics;
-use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
@@ -450,10 +450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             0,
             (start.as_u32()..end.as_u32()).map(|i| {
                 let id = NodeId::from_u32(i);
-                let l = self.lower_lifetime(&Lifetime {
-                    id,
-                    ident: Ident::new(kw::Empty, elided_lifetime_span),
-                });
+                let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
                 GenericArg::Lifetime(l)
             }),
         );
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 75839e86b8d..9916de8b7b1 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -47,14 +47,14 @@ enum SelfSemantic {
 }
 
 enum TraitOrTraitImpl {
-    Trait { span: Span, constness: Option<Span> },
-    TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: Span },
+    Trait { span: Span, constness_span: Option<Span> },
+    TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
 }
 
 impl TraitOrTraitImpl {
     fn constness(&self) -> Option<Span> {
         match self {
-            Self::Trait { constness: Some(span), .. }
+            Self::Trait { constness_span: Some(span), .. }
             | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
             _ => None,
         }
@@ -66,7 +66,7 @@ struct AstValidator<'a> {
     features: &'a Features,
 
     /// The span of the `extern` in an `extern { ... }` block, if any.
-    extern_mod: Option<Span>,
+    extern_mod_span: Option<Span>,
 
     outer_trait_or_trait_impl: Option<TraitOrTraitImpl>,
 
@@ -75,7 +75,7 @@ struct AstValidator<'a> {
     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
     /// Nested `impl Trait` _is_ allowed in associated type position,
     /// e.g., `impl Iterator<Item = impl Debug>`.
-    outer_impl_trait: Option<Span>,
+    outer_impl_trait_span: Option<Span>,
 
     disallow_tilde_const: Option<TildeConstReason>,
 
@@ -96,17 +96,22 @@ impl<'a> AstValidator<'a> {
             trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
                 constness,
                 polarity,
-                trait_ref: trait_ref.path.span,
+                trait_ref_span: trait_ref.path.span,
             }),
         );
         f(self);
         self.outer_trait_or_trait_impl = old;
     }
 
-    fn with_in_trait(&mut self, span: Span, constness: Option<Span>, f: impl FnOnce(&mut Self)) {
+    fn with_in_trait(
+        &mut self,
+        span: Span,
+        constness_span: Option<Span>,
+        f: impl FnOnce(&mut Self),
+    ) {
         let old = mem::replace(
             &mut self.outer_trait_or_trait_impl,
-            Some(TraitOrTraitImpl::Trait { span, constness }),
+            Some(TraitOrTraitImpl::Trait { span, constness_span }),
         );
         f(self);
         self.outer_trait_or_trait_impl = old;
@@ -170,10 +175,10 @@ impl<'a> AstValidator<'a> {
         Err(errors::WhereClauseBeforeTypeAlias { span, sugg })
     }
 
-    fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.outer_impl_trait, outer);
+    fn with_impl_trait(&mut self, outer_span: Option<Span>, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.outer_impl_trait_span, outer_span);
         f(self);
-        self.outer_impl_trait = old;
+        self.outer_impl_trait_span = old;
     }
 
     // Mirrors `visit::walk_ty`, but tracks relevant state.
@@ -258,21 +263,22 @@ impl<'a> AstValidator<'a> {
             && let TraitOrTraitImpl::TraitImpl {
                 constness: Const::No,
                 polarity: ImplPolarity::Positive,
-                trait_ref,
+                trait_ref_span,
                 ..
             } = parent
         {
-            Some(trait_ref.shrink_to_lo())
+            Some(trait_ref_span.shrink_to_lo())
         } else {
             None
         };
 
-        let make_trait_const_sugg =
-            if const_trait_impl && let TraitOrTraitImpl::Trait { span, constness: None } = parent {
-                Some(span.shrink_to_lo())
-            } else {
-                None
-            };
+        let make_trait_const_sugg = if const_trait_impl
+            && let TraitOrTraitImpl::Trait { span, constness_span: None } = parent
+        {
+            Some(span.shrink_to_lo())
+        } else {
+            None
+        };
 
         let parent_constness = parent.constness();
         self.dcx().emit_err(errors::TraitFnConst {
@@ -334,8 +340,7 @@ impl<'a> AstValidator<'a> {
             .filter(|attr| {
                 let arr = [
                     sym::allow,
-                    sym::cfg,
-                    sym::cfg_attr,
+                    sym::cfg_trace,
                     sym::cfg_attr_trace,
                     sym::deny,
                     sym::expect,
@@ -449,13 +454,13 @@ impl<'a> AstValidator<'a> {
         check_where_clause(where_clauses.after);
     }
 
-    fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
-        let Some(body) = body else {
+    fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body_span: Option<Span>) {
+        let Some(body_span) = body_span else {
             return;
         };
         self.dcx().emit_err(errors::BodyInExtern {
             span: ident.span,
-            body,
+            body: body_span,
             block: self.current_extern_span(),
             kind,
         });
@@ -474,7 +479,7 @@ impl<'a> AstValidator<'a> {
     }
 
     fn current_extern_span(&self) -> Span {
-        self.sess.source_map().guess_head_span(self.extern_mod.unwrap())
+        self.sess.source_map().guess_head_span(self.extern_mod_span.unwrap())
     }
 
     /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
@@ -584,9 +589,10 @@ impl<'a> AstValidator<'a> {
         self.dcx().emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
     }
 
-    fn deny_generic_params(&self, generics: &Generics, ident: Span) {
+    fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
         if !generics.params.is_empty() {
-            self.dcx().emit_err(errors::AutoTraitGeneric { span: generics.span, ident });
+            self.dcx()
+                .emit_err(errors::AutoTraitGeneric { span: generics.span, ident: ident_span });
         }
     }
 
@@ -606,11 +612,11 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn deny_items(&self, trait_items: &[P<AssocItem>], ident: Span) {
+    fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
         if !trait_items.is_empty() {
-            let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
+            let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
             let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
-            self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident });
+            self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident: ident_span });
         }
     }
 
@@ -695,7 +701,7 @@ impl<'a> AstValidator<'a> {
                 }
             }
             TyKind::ImplTrait(_, bounds) => {
-                if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
+                if let Some(outer_impl_trait_sp) = self.outer_impl_trait_span {
                     self.dcx().emit_err(errors::NestedImplTrait {
                         span: ty.span,
                         outer: outer_impl_trait_sp,
@@ -728,6 +734,19 @@ impl<'a> AstValidator<'a> {
             )
         }
     }
+
+    // Used within `visit_item` for item kinds where we don't call `visit::walk_item`.
+    fn visit_attrs_vis(&mut self, attrs: &'a AttrVec, vis: &'a Visibility) {
+        walk_list!(self, visit_attribute, attrs);
+        self.visit_vis(vis);
+    }
+
+    // Used within `visit_item` for item kinds where we don't call `visit::walk_item`.
+    fn visit_attrs_vis_ident(&mut self, attrs: &'a AttrVec, vis: &'a Visibility, ident: &'a Ident) {
+        walk_list!(self, visit_attribute, attrs);
+        self.visit_vis(vis);
+        self.visit_ident(ident);
+    }
 }
 
 /// Checks that generic parameters are in the correct order,
@@ -818,8 +837,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.has_proc_macro_decls = true;
         }
 
-        if attr::contains_name(&item.attrs, sym::no_mangle) {
-            self.check_nomangle_item_asciionly(item.ident, item.span);
+        if let Some(ident) = item.kind.ident()
+            && attr::contains_name(&item.attrs, sym::no_mangle)
+        {
+            self.check_nomangle_item_asciionly(ident, item.span);
         }
 
         match &item.kind {
@@ -833,37 +854,33 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self_ty,
                 items,
             }) => {
-                self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
-                    this.visibility_not_permitted(
-                        &item.vis,
-                        errors::VisibilityNotPermittedNote::TraitImpl,
-                    );
-                    if let TyKind::Dummy = self_ty.kind {
-                        // Abort immediately otherwise the `TyKind::Dummy` will reach HIR lowering,
-                        // which isn't allowed. Not a problem for this obscure, obsolete syntax.
-                        this.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span });
-                    }
-                    if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity)
-                    {
-                        this.dcx().emit_err(errors::UnsafeNegativeImpl {
-                            span: sp.to(t.path.span),
-                            negative: sp,
-                            r#unsafe: span,
-                        });
-                    }
+                self.visit_attrs_vis(&item.attrs, &item.vis);
+                self.visibility_not_permitted(
+                    &item.vis,
+                    errors::VisibilityNotPermittedNote::TraitImpl,
+                );
+                if let TyKind::Dummy = self_ty.kind {
+                    // Abort immediately otherwise the `TyKind::Dummy` will reach HIR lowering,
+                    // which isn't allowed. Not a problem for this obscure, obsolete syntax.
+                    self.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span });
+                }
+                if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity) {
+                    self.dcx().emit_err(errors::UnsafeNegativeImpl {
+                        span: sp.to(t.path.span),
+                        negative: sp,
+                        r#unsafe: span,
+                    });
+                }
 
-                    this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
-                    let disallowed = matches!(constness, Const::No)
-                        .then(|| TildeConstReason::TraitImpl { span: item.span });
-                    this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
-                    this.visit_trait_ref(t);
-                    this.visit_ty(self_ty);
+                let disallowed = matches!(constness, Const::No)
+                    .then(|| TildeConstReason::TraitImpl { span: item.span });
+                self.with_tilde_const(disallowed, |this| this.visit_generics(generics));
+                self.visit_trait_ref(t);
+                self.visit_ty(self_ty);
 
-                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
+                self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
+                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true });
                 });
-                walk_list!(self, visit_attribute, &item.attrs);
-                return; // Avoid visiting again.
             }
             ItemKind::Impl(box Impl {
                 safety,
@@ -883,45 +900,49 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     only_trait,
                 };
 
-                self.with_in_trait_impl(None, |this| {
-                    this.visibility_not_permitted(
-                        &item.vis,
-                        errors::VisibilityNotPermittedNote::IndividualImplItems,
-                    );
-                    if let &Safety::Unsafe(span) = safety {
-                        this.dcx().emit_err(errors::InherentImplCannotUnsafe {
-                            span: self_ty.span,
-                            annotation_span: span,
-                            annotation: "unsafe",
-                            self_ty: self_ty.span,
-                        });
-                    }
-                    if let &ImplPolarity::Negative(span) = polarity {
-                        this.dcx().emit_err(error(span, "negative", false));
-                    }
-                    if let &Defaultness::Default(def_span) = defaultness {
-                        this.dcx().emit_err(error(def_span, "`default`", true));
-                    }
-                    if let &Const::Yes(span) = constness {
-                        this.dcx().emit_err(error(span, "`const`", true));
-                    }
+                self.visit_attrs_vis(&item.attrs, &item.vis);
+                self.visibility_not_permitted(
+                    &item.vis,
+                    errors::VisibilityNotPermittedNote::IndividualImplItems,
+                );
+                if let &Safety::Unsafe(span) = safety {
+                    self.dcx().emit_err(errors::InherentImplCannotUnsafe {
+                        span: self_ty.span,
+                        annotation_span: span,
+                        annotation: "unsafe",
+                        self_ty: self_ty.span,
+                    });
+                }
+                if let &ImplPolarity::Negative(span) = polarity {
+                    self.dcx().emit_err(error(span, "negative", false));
+                }
+                if let &Defaultness::Default(def_span) = defaultness {
+                    self.dcx().emit_err(error(def_span, "`default`", true));
+                }
+                if let &Const::Yes(span) = constness {
+                    self.dcx().emit_err(error(span, "`const`", true));
+                }
 
-                    this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
-                    this.with_tilde_const(
-                        Some(TildeConstReason::Impl { span: item.span }),
-                        |this| this.visit_generics(generics),
-                    );
-                    this.visit_ty(self_ty);
-                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
+                self.with_tilde_const(Some(TildeConstReason::Impl { span: item.span }), |this| {
+                    this.visit_generics(generics)
+                });
+                self.visit_ty(self_ty);
+                self.with_in_trait_impl(None, |this| {
+                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false });
                 });
-                walk_list!(self, visit_attribute, &item.attrs);
-                return; // Avoid visiting again.
             }
             ItemKind::Fn(
-                func
-                @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
+                func @ box Fn {
+                    defaultness,
+                    ident,
+                    generics: _,
+                    sig,
+                    contract: _,
+                    body,
+                    define_opaque: _,
+                },
             ) => {
+                self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
                 self.check_defaultness(item.span, *defaultness);
 
                 let is_intrinsic =
@@ -949,45 +970,40 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     });
                 }
 
-                self.visit_vis(&item.vis);
-                self.visit_ident(&item.ident);
-                let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func);
                 self.visit_fn(kind, item.span, item.id);
-                walk_list!(self, visit_attribute, &item.attrs);
-                return; // Avoid visiting again.
             }
             ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
-                self.with_in_extern_mod(*safety, |this| {
-                    let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
-                    this.visibility_not_permitted(
-                        &item.vis,
-                        errors::VisibilityNotPermittedNote::IndividualForeignItems,
-                    );
-
-                    if &Safety::Default == safety {
-                        if item.span.at_least_rust_2024() {
-                            this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
-                        } else {
-                            this.lint_buffer.buffer_lint(
-                                MISSING_UNSAFE_ON_EXTERN,
-                                item.id,
-                                item.span,
-                                BuiltinLintDiag::MissingUnsafeOnExtern {
-                                    suggestion: item.span.shrink_to_lo(),
-                                },
-                            );
-                        }
+                let old_item = mem::replace(&mut self.extern_mod_span, Some(item.span));
+                self.visibility_not_permitted(
+                    &item.vis,
+                    errors::VisibilityNotPermittedNote::IndividualForeignItems,
+                );
+
+                if &Safety::Default == safety {
+                    if item.span.at_least_rust_2024() {
+                        self.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
+                    } else {
+                        self.lint_buffer.buffer_lint(
+                            MISSING_UNSAFE_ON_EXTERN,
+                            item.id,
+                            item.span,
+                            BuiltinLintDiag::MissingUnsafeOnExtern {
+                                suggestion: item.span.shrink_to_lo(),
+                            },
+                        );
                     }
+                }
 
-                    if abi.is_none() {
-                        this.maybe_lint_missing_abi(*extern_span, item.id);
-                    }
+                if abi.is_none() {
+                    self.maybe_lint_missing_abi(*extern_span, item.id);
+                }
+                self.with_in_extern_mod(*safety, |this| {
                     visit::walk_item(this, item);
-                    this.extern_mod = old_item;
                 });
-                return; // Avoid visiting again.
+                self.extern_mod_span = old_item;
             }
-            ItemKind::Enum(def, _) => {
+            ItemKind::Enum(_, def, _) => {
                 for variant in &def.variants {
                     self.visibility_not_permitted(
                         &variant.vis,
@@ -1000,36 +1016,33 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         );
                     }
                 }
+                visit::walk_item(self, item)
             }
-            ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
+            ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
+                self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
                 let is_const_trait =
                     attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
-                self.with_in_trait(item.span, is_const_trait, |this| {
-                    if *is_auto == IsAuto::Yes {
-                        // Auto traits cannot have generics, super traits nor contain items.
-                        this.deny_generic_params(generics, item.ident.span);
-                        this.deny_super_traits(bounds, item.ident.span);
-                        this.deny_where_clause(&generics.where_clause, item.ident.span);
-                        this.deny_items(items, item.ident.span);
-                    }
+                if *is_auto == IsAuto::Yes {
+                    // Auto traits cannot have generics, super traits nor contain items.
+                    self.deny_generic_params(generics, ident.span);
+                    self.deny_super_traits(bounds, ident.span);
+                    self.deny_where_clause(&generics.where_clause, ident.span);
+                    self.deny_items(items, ident.span);
+                }
 
-                    // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
-                    // context for the supertraits.
-                    this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
-                    let disallowed = is_const_trait
-                        .is_none()
-                        .then(|| TildeConstReason::Trait { span: item.span });
-                    this.with_tilde_const(disallowed, |this| {
-                        this.visit_generics(generics);
-                        walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
-                    });
+                // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
+                // context for the supertraits.
+                let disallowed =
+                    is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
+                self.with_tilde_const(disallowed, |this| {
+                    this.visit_generics(generics);
+                    walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
+                });
+                self.with_in_trait(item.span, is_const_trait, |this| {
                     walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
                 });
-                walk_list!(self, visit_attribute, &item.attrs);
-                return; // Avoid visiting again
             }
-            ItemKind::Mod(safety, mod_kind) => {
+            ItemKind::Mod(safety, ident, mod_kind) => {
                 if let &Safety::Unsafe(span) = safety {
                     self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
                 }
@@ -1037,36 +1050,31 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
                     && !attr::contains_name(&item.attrs, sym::path)
                 {
-                    self.check_mod_file_item_asciionly(item.ident);
+                    self.check_mod_file_item_asciionly(*ident);
                 }
+                visit::walk_item(self, item)
             }
-            ItemKind::Struct(vdata, generics) => match vdata {
+            ItemKind::Struct(ident, vdata, generics) => match vdata {
                 VariantData::Struct { fields, .. } => {
-                    self.visit_vis(&item.vis);
-                    self.visit_ident(&item.ident);
+                    self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
                     self.visit_generics(generics);
                     // Permit `Anon{Struct,Union}` as field type.
                     walk_list!(self, visit_struct_field_def, fields);
-                    walk_list!(self, visit_attribute, &item.attrs);
-                    return;
                 }
-                _ => {}
+                _ => visit::walk_item(self, item),
             },
-            ItemKind::Union(vdata, generics) => {
+            ItemKind::Union(ident, vdata, generics) => {
                 if vdata.fields().is_empty() {
                     self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
                 }
                 match vdata {
                     VariantData::Struct { fields, .. } => {
-                        self.visit_vis(&item.vis);
-                        self.visit_ident(&item.ident);
+                        self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
                         self.visit_generics(generics);
                         // Permit `Anon{Struct,Union}` as field type.
                         walk_list!(self, visit_struct_field_def, fields);
-                        walk_list!(self, visit_attribute, &item.attrs);
-                        return;
                     }
-                    _ => {}
+                    _ => visit::walk_item(self, item),
                 }
             }
             ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
@@ -1077,6 +1085,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         replace_span: self.ending_semi_or_hi(item.span),
                     });
                 }
+                visit::walk_item(self, item);
             }
             ItemKind::Static(box StaticItem { expr, safety, .. }) => {
                 self.check_item_safety(item.span, *safety);
@@ -1090,6 +1099,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         replace_span: self.ending_semi_or_hi(item.span),
                     });
                 }
+                visit::walk_item(self, item);
             }
             ItemKind::TyAlias(
                 ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
@@ -1113,23 +1123,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         help: self.sess.is_nightly_build(),
                     });
                 }
+                visit::walk_item(self, item);
             }
-            _ => {}
+            _ => visit::walk_item(self, item),
         }
-
-        visit::walk_item(self, item);
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
-            ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+            ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
                 self.check_defaultness(fi.span, *defaultness);
-                self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
+                self.check_foreign_fn_bodyless(*ident, body.as_deref());
                 self.check_foreign_fn_headerless(sig.header);
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_item_ascii_only(*ident);
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
@@ -1137,15 +1147,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 ..
             }) => {
                 self.check_defaultness(fi.span, *defaultness);
-                self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
+                self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
                 self.check_foreign_ty_genericless(generics, where_clauses);
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_item_ascii_only(*ident);
             }
-            ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => {
+            ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => {
                 self.check_item_safety(fi.span, *safety);
-                self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span));
+                self.check_foreign_item_ascii_only(*ident);
             }
             ForeignItemKind::MacCall(..) => {}
         }
@@ -1354,7 +1364,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         if let FnKind::Fn(
             _,
             _,
-            _,
             Fn {
                 sig: FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. },
                 ..
@@ -1365,7 +1374,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
 
         // Functions without bodies cannot have patterns.
-        if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk {
+        if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
                     if let Some(ident) = ident {
@@ -1399,22 +1408,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .is_some();
 
         let disallowed = (!tilde_const_allowed).then(|| match fk {
-            FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span },
+            FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span },
             FnKind::Closure(..) => TildeConstReason::Closure,
         });
         self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if attr::contains_name(&item.attrs, sym::no_mangle) {
-            self.check_nomangle_item_asciionly(item.ident, item.span);
+        if let Some(ident) = item.kind.ident()
+            && attr::contains_name(&item.attrs, sym::no_mangle)
+        {
+            self.check_nomangle_item_asciionly(ident, item.span);
         }
 
         if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
             self.check_defaultness(item.span, item.kind.defaultness());
         }
 
-        if ctxt == AssocCtxt::Impl {
+        if let AssocCtxt::Impl { .. } = ctxt {
             match &item.kind {
                 AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
                     self.dcx().emit_err(errors::AssocConstWithoutBody {
@@ -1467,8 +1478,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
         }
 
-        if let AssocItemKind::Const(..) = item.kind {
-            self.check_item_named(item.ident, "const");
+        if let AssocItemKind::Const(ci) = &item.kind {
+            self.check_item_named(ci.ident, "const");
         }
 
         let parent_is_const =
@@ -1480,10 +1491,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     || ctxt == AssocCtxt::Trait
                     || matches!(func.sig.header.constness, Const::Yes(_)) =>
             {
-                self.visit_vis(&item.vis);
-                self.visit_ident(&item.ident);
-                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func);
-                walk_list!(self, visit_attribute, &item.attrs);
+                self.visit_attrs_vis_ident(&item.attrs, &item.vis, &func.ident);
+                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func);
                 self.visit_fn(kind, item.span, item.id);
             }
             AssocItemKind::Type(_) => {
@@ -1588,7 +1597,7 @@ fn deny_equality_constraints(
                     generics.where_clause.span
                 } else {
                     let mut span = predicate_span;
-                    let mut prev: Option<Span> = None;
+                    let mut prev_span: Option<Span> = None;
                     let mut preds = generics.where_clause.predicates.iter().peekable();
                     // Find the predicate that shouldn't have been in the where bound list.
                     while let Some(pred) = preds.next() {
@@ -1598,12 +1607,12 @@ fn deny_equality_constraints(
                             if let Some(next) = preds.peek() {
                                 // This is the first predicate, remove the trailing comma as well.
                                 span = span.with_hi(next.span.lo());
-                            } else if let Some(prev) = prev {
+                            } else if let Some(prev_span) = prev_span {
                                 // Remove the previous comma as well.
-                                span = span.with_lo(prev.hi());
+                                span = span.with_lo(prev_span.hi());
                             }
                         }
-                        prev = Some(pred.span);
+                        prev_span = Some(pred.span);
                     }
                     span
                 };
@@ -1678,10 +1687,10 @@ pub fn check_crate(
     let mut validator = AstValidator {
         sess,
         features,
-        extern_mod: None,
+        extern_mod_span: None,
         outer_trait_or_trait_impl: None,
         has_proc_macro_decls: false,
-        outer_impl_trait: None,
+        outer_impl_trait_span: None,
         disallow_tilde_const: Some(TildeConstReason::Item),
         extern_mod_safety: None,
         lint_buffer: lints,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 31ff102c127..ea60e083c4c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -99,6 +99,13 @@ impl<'a> PostExpansionVisitor<'a> {
                 }
                 visit::walk_ty(self, ty);
             }
+
+            fn visit_anon_const(&mut self, _: &ast::AnonConst) -> Self::Result {
+                // We don't walk the anon const because it crosses a conceptual boundary: We're no
+                // longer "inside" the original type.
+                // Brittle: We assume that the callers of `check_impl_trait` will later recurse into
+                // the items found in the AnonConst to look for nested TyAliases.
+            }
         }
         ImplTraitVisitor { vis: self, in_associated_ty }.visit_ty(ty);
     }
@@ -229,7 +236,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate!(&self, trait_alias, i.span, "trait aliases are experimental");
             }
 
-            ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
+            ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate!(&self, decl_macro, i.span, msg);
             }
@@ -483,7 +490,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         half_open_range_patterns_in_slices,
         "half-open range patterns in slices are unstable"
     );
-    gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
     gate_all!(associated_const_equality, "associated const equality is incomplete");
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
     gate_all!(dyn_star, "`dyn*` trait objects are experimental");
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index cdb18179449..3dbfc191f8f 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -593,7 +593,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
-        if attr.has_name(sym::cfg_attr_trace) {
+        if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) {
             // It's not a valid identifier, so avoid printing it
             // to keep the printed code reasonably parse-able.
             return false;
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 6236f8ecfb5..653bd77cc4d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -28,36 +28,43 @@ impl<'a> State<'a> {
     }
 
     fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
             ast::ForeignItemKind::Fn(func) => {
-                self.print_fn_full(ident, vis, attrs, &*func);
-            }
-            ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
-                self.print_item_const(
-                    ident,
-                    Some(*mutability),
-                    &ast::Generics::default(),
-                    ty,
-                    expr.as_deref(),
-                    vis,
-                    *safety,
-                    ast::Defaultness::Final,
-                )
+                self.print_fn_full(vis, attrs, &*func);
             }
+            ast::ForeignItemKind::Static(box ast::StaticItem {
+                ident,
+                ty,
+                mutability,
+                expr,
+                safety,
+                define_opaque,
+            }) => self.print_item_const(
+                *ident,
+                Some(*mutability),
+                &ast::Generics::default(),
+                ty,
+                expr.as_deref(),
+                vis,
+                *safety,
+                ast::Defaultness::Final,
+                define_opaque.as_deref(),
+            ),
             ast::ForeignItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -86,7 +93,9 @@ impl<'a> State<'a> {
         vis: &ast::Visibility,
         safety: ast::Safety,
         defaultness: ast::Defaultness,
+        define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
     ) {
+        self.print_define_opaques(define_opaque);
         self.head("");
         self.print_visibility(vis);
         self.print_safety(safety);
@@ -155,7 +164,7 @@ impl<'a> State<'a> {
         self.print_outer_attributes(&item.attrs);
         self.ann.pre(self, AnnNode::Item(item));
         match &item.kind {
-            ast::ItemKind::ExternCrate(orig_name) => {
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
                 self.head(visibility_qualified(&item.vis, "extern crate"));
                 if let &Some(orig_name) = orig_name {
                     self.print_name(orig_name);
@@ -163,7 +172,7 @@ impl<'a> State<'a> {
                     self.word("as");
                     self.space();
                 }
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.word(";");
                 self.end(); // end inner head-block
                 self.end(); // end outer head-block
@@ -174,10 +183,17 @@ impl<'a> State<'a> {
                 self.print_use_tree(tree);
                 self.word(";");
             }
-            ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => {
+            ast::ItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                safety,
+                mutability: mutbl,
+                expr: body,
+                define_opaque,
+            }) => {
                 self.print_safety(*safety);
                 self.print_item_const(
-                    item.ident,
+                    *ident,
                     Some(*mutbl),
                     &ast::Generics::default(),
                     ty,
@@ -185,11 +201,19 @@ impl<'a> State<'a> {
                     &item.vis,
                     ast::Safety::Default,
                     ast::Defaultness::Final,
+                    define_opaque.as_deref(),
                 );
             }
-            ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
+            ast::ItemKind::Const(box ast::ConstItem {
+                defaultness,
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+            }) => {
                 self.print_item_const(
-                    item.ident,
+                    *ident,
                     None,
                     generics,
                     ty,
@@ -197,18 +221,19 @@ impl<'a> State<'a> {
                     &item.vis,
                     ast::Safety::Default,
                     *defaultness,
+                    define_opaque.as_deref(),
                 );
             }
             ast::ItemKind::Fn(func) => {
-                self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func);
+                self.print_fn_full(&item.vis, &item.attrs, &*func);
             }
-            ast::ItemKind::Mod(safety, mod_kind) => {
+            ast::ItemKind::Mod(safety, ident, mod_kind) => {
                 self.head(Self::to_string(|s| {
                     s.print_visibility(&item.vis);
                     s.print_safety(*safety);
                     s.word("mod");
                 }));
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
 
                 match mod_kind {
                     ModKind::Loaded(items, ..) => {
@@ -252,13 +277,14 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    item.ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -267,16 +293,16 @@ impl<'a> State<'a> {
                     *defaultness,
                 );
             }
-            ast::ItemKind::Enum(enum_definition, params) => {
-                self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
+            ast::ItemKind::Enum(ident, enum_definition, params) => {
+                self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
             }
-            ast::ItemKind::Struct(struct_def, generics) => {
+            ast::ItemKind::Struct(ident, struct_def, generics) => {
                 self.head(visibility_qualified(&item.vis, "struct"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
+                self.print_struct(struct_def, generics, *ident, item.span, true);
             }
-            ast::ItemKind::Union(struct_def, generics) => {
+            ast::ItemKind::Union(ident, struct_def, generics) => {
                 self.head(visibility_qualified(&item.vis, "union"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
+                self.print_struct(struct_def, generics, *ident, item.span, true);
             }
             ast::ItemKind::Impl(box ast::Impl {
                 safety,
@@ -326,19 +352,19 @@ impl<'a> State<'a> {
                 self.bclose(item.span, empty);
             }
             ast::ItemKind::Trait(box ast::Trait {
-                is_auto,
                 safety,
+                is_auto,
+                ident,
                 generics,
                 bounds,
                 items,
-                ..
             }) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_safety(*safety);
                 self.print_is_auto(*is_auto);
                 self.word_nbsp("trait");
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.print_generic_params(&generics.params);
                 if !bounds.is_empty() {
                     self.word_nbsp(":");
@@ -354,9 +380,9 @@ impl<'a> State<'a> {
                 let empty = item.attrs.is_empty() && items.is_empty();
                 self.bclose(item.span, empty);
             }
-            ast::ItemKind::TraitAlias(generics, bounds) => {
+            ast::ItemKind::TraitAlias(ident, generics, bounds) => {
                 self.head(visibility_qualified(&item.vis, "trait"));
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.print_generic_params(&generics.params);
                 self.nbsp();
                 if !bounds.is_empty() {
@@ -374,8 +400,8 @@ impl<'a> State<'a> {
                     self.word(";");
                 }
             }
-            ast::ItemKind::MacroDef(macro_def) => {
-                self.print_mac_def(macro_def, &item.ident, item.span, |state| {
+            ast::ItemKind::MacroDef(ident, macro_def) => {
+                self.print_mac_def(macro_def, &ident, item.span, |state| {
                     state.print_visibility(&item.vis)
                 });
             }
@@ -528,18 +554,25 @@ impl<'a> State<'a> {
     }
 
     fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
             ast::AssocItemKind::Fn(func) => {
-                self.print_fn_full(ident, vis, attrs, &*func);
+                self.print_fn_full(vis, attrs, &*func);
             }
-            ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
+            ast::AssocItemKind::Const(box ast::ConstItem {
+                defaultness,
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+            }) => {
                 self.print_item_const(
-                    ident,
+                    *ident,
                     None,
                     generics,
                     ty,
@@ -547,17 +580,19 @@ impl<'a> State<'a> {
                     vis,
                     ast::Safety::Default,
                     *defaultness,
+                    define_opaque.as_deref(),
                 );
             }
             ast::AssocItemKind::Type(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -643,29 +678,17 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_fn_full(
-        &mut self,
-        name: Ident,
-        vis: &ast::Visibility,
-        attrs: &[ast::Attribute],
-        func: &ast::Fn,
-    ) {
-        let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
+    fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) {
+        let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque } = func;
 
-        if let Some(define_opaque) = define_opaque {
-            for (_, path) in define_opaque {
-                self.word("define opaques from ");
-                self.print_path(path, false, 0);
-                self.word(",");
-            }
-        }
+        self.print_define_opaques(define_opaque.as_deref());
 
         if body.is_some() {
             self.head("");
         }
         self.print_visibility(vis);
         self.print_defaultness(*defaultness);
-        self.print_fn(&sig.decl, sig.header, Some(name), generics);
+        self.print_fn(&sig.decl, sig.header, Some(*ident), generics);
         if let Some(contract) = &contract {
             self.nbsp();
             self.print_contract(contract);
@@ -678,6 +701,21 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) {
+        if let Some(define_opaque) = define_opaque {
+            self.word("#[define_opaque(");
+            for (i, (_, path)) in define_opaque.iter().enumerate() {
+                if i != 0 {
+                    self.word_space(",");
+                }
+
+                self.print_path(path, false, 0);
+            }
+            self.word(")]");
+        }
+        self.hardbreak_if_not_bol();
+    }
+
     fn print_contract(&mut self, contract: &ast::FnContract) {
         if let Some(pred) = &contract.requires {
             self.word("rustc_requires");
@@ -697,13 +735,13 @@ impl<'a> State<'a> {
         &mut self,
         decl: &ast::FnDecl,
         header: ast::FnHeader,
-        name: Option<Ident>,
+        ident: Option<Ident>,
         generics: &ast::Generics,
     ) {
         self.print_fn_header_info(header);
-        if let Some(name) = name {
+        if let Some(ident) = ident {
             self.nbsp();
-            self.print_ident(name);
+            self.print_ident(ident);
         }
         self.print_generic_params(&generics.params);
         self.print_fn_params_and_ret(decl, false);
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index d2d1285b075..969bce7ae20 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -191,6 +191,7 @@ pub enum AttributeKind {
     },
     MacroTransparency(Transparency),
     Repr(ThinVec<(ReprAttr, Span)>),
+    RustcMacroEdition2021,
     Stability {
         stability: Stability,
         /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute
diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index bbd3308809c..c61b44b273d 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -182,21 +182,18 @@ macro_rules! find_attr {
     }};
 
     ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
-        fn check_attribute_iterator<'a>(_: &'_ impl IntoIterator<Item = &'a rustc_hir::Attribute>) {}
-        check_attribute_iterator(&$attributes_list);
-
-        let find_attribute = |iter| {
+        'done: {
             for i in $attributes_list {
+                let i: &rustc_hir::Attribute = i;
                 match i {
                     rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => {
-                        return Some($e);
+                        break 'done Some($e);
                     }
                     _ => {}
                 }
             }
 
             None
-        };
-        find_attribute($attributes_list)
+        }
     }};
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 6ecd6b4d7db..bac111159db 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -28,6 +28,7 @@ pub(crate) mod cfg;
 pub(crate) mod confusables;
 pub(crate) mod deprecation;
 pub(crate) mod repr;
+pub(crate) mod rustc;
 pub(crate) mod stability;
 pub(crate) mod transparency;
 pub(crate) mod util;
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc.rs b/compiler/rustc_attr_parsing/src/attributes/rustc.rs
new file mode 100644
index 00000000000..bdd3bef2834
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc.rs
@@ -0,0 +1,19 @@
+use rustc_attr_data_structures::AttributeKind;
+use rustc_span::sym;
+
+use super::{AcceptContext, SingleAttributeParser};
+use crate::parser::ArgParser;
+
+pub(crate) struct RustcMacroEdition2021Parser;
+
+// FIXME(jdonszelmann): make these proper diagnostics
+impl SingleAttributeParser for RustcMacroEdition2021Parser {
+    const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_edition_2021];
+
+    fn on_duplicate(_cx: &crate::context::AcceptContext<'_>, _first_span: rustc_span::Span) {}
+
+    fn convert(_cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        assert!(args.no_args());
+        Some(AttributeKind::RustcMacroEdition2021)
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 6d76456e83c..bdad6b50186 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -5,7 +5,7 @@ use rustc_attr_data_structures::{
     StableSince, UnstableReason, VERSION_PLACEHOLDER,
 };
 use rustc_errors::ErrorGuaranteed;
-use rustc_span::{Span, Symbol, kw, sym};
+use rustc_span::{Span, Symbol, sym};
 
 use super::util::parse_version;
 use super::{AcceptMapping, AttributeParser, SingleAttributeParser};
@@ -61,11 +61,7 @@ impl AttributeParser for StabilityParser {
         }),
         (&[sym::rustc_allowed_through_unstable_modules], |this, cx, args| {
             reject_outside_std!(cx);
-            this.allowed_through_unstable_modules =
-                Some(match args.name_value().and_then(|i| i.value_as_str()) {
-                    Some(msg) => msg,
-                    None => kw::Empty,
-                });
+            this.allowed_through_unstable_modules = args.name_value().and_then(|i| i.value_as_str())
         }),
     ];
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 35541bb04bd..a68d4578b40 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -15,6 +15,7 @@ use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInterna
 use crate::attributes::confusables::ConfusablesParser;
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::repr::ReprParser;
+use crate::attributes::rustc::RustcMacroEdition2021Parser;
 use crate::attributes::stability::{
     BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
 };
@@ -76,6 +77,7 @@ attribute_groups!(
         // tidy-alphabetical-start
         Single<ConstStabilityIndirectParser>,
         Single<DeprecationParser>,
+        Single<RustcMacroEdition2021Parser>,
         Single<TransparencyParser>,
         // tidy-alphabetical-end
     ];
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 5a89f7c351c..45cdd232564 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -1,7 +1,7 @@
 //! This file provides API for compiler consumers.
 
 use rustc_hir::def_id::LocalDefId;
-use rustc_index::{IndexSlice, IndexVec};
+use rustc_index::IndexVec;
 use rustc_middle::mir::{Body, Promoted};
 use rustc_middle::ty::TyCtxt;
 
@@ -100,8 +100,5 @@ pub fn get_body_with_borrowck_facts(
     def: LocalDefId,
     options: ConsumerOptions,
 ) -> BodyWithBorrowckFacts<'_> {
-    let (input_body, promoted) = tcx.mir_promoted(def);
-    let input_body: &Body<'_> = &input_body.borrow();
-    let promoted: &IndexSlice<_, _> = &promoted.borrow();
-    *super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
+    *super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 978186f76a1..7cc42260906 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1364,7 +1364,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
         // Try to find predicates on *generic params* that would allow copying `ty`
         let mut suggestion =
-            if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+            if let Some(symbol) = tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                 format!(": {symbol}.clone()")
             } else {
                 ".clone()".to_owned()
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 29cc749877b..0394a42ea9c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -502,7 +502,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 let upvar = &self.upvars[upvar_field.unwrap().index()];
                 let upvar_hir_id = upvar.get_root_variable();
                 let upvar_name = upvar.to_string(tcx);
-                let upvar_span = tcx.hir().span(upvar_hir_id);
+                let upvar_span = tcx.hir_span(upvar_hir_id);
 
                 let place_name = self.describe_any_place(move_place.as_ref());
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 6b11f1a3681..d1d783c22e3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -513,14 +513,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             ty::VarianceDiagInfo::Invariant { ty, param_index } => {
                 let (desc, note) = match ty.kind() {
                     ty::RawPtr(ty, mutbl) => {
-                        assert_eq!(*mutbl, rustc_hir::Mutability::Mut);
+                        assert_eq!(*mutbl, hir::Mutability::Mut);
                         (
                             format!("a mutable pointer to `{}`", ty),
                             "mutable pointers are invariant over their type parameter".to_string(),
                         )
                     }
                     ty::Ref(_, inner_ty, mutbl) => {
-                        assert_eq!(*mutbl, rustc_hir::Mutability::Mut);
+                        assert_eq!(*mutbl, hir::Mutability::Mut);
                         (
                             format!("a mutable reference to `{inner_ty}`"),
                             "mutable references are invariant over their type parameter"
@@ -628,7 +628,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             if let Some(def_hir) = defined_hir {
                 let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
-                let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
+                let upvar_def_span = self.infcx.tcx.hir_span(def_hir);
                 let upvar_span = upvars_map.get(&def_hir).unwrap().span;
                 diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span });
                 diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span });
@@ -887,7 +887,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     // Skip `async` desugaring `impl Future`.
                 }
                 if let TyKind::TraitObject(_, lt) = alias_ty.kind {
-                    if lt.ident.name == kw::Empty {
+                    if lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault {
                         spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
                     } else {
                         spans_suggs.push((lt.ident.span, "'a".to_string()));
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 412aaf70c3f..45f5eaa514b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -291,7 +291,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         match *error_region {
             ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
                 let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id;
-                let span = tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
+                let span = tcx.hir_span_if_local(def_id).unwrap_or(DUMMY_SP);
                 RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
             }),
 
@@ -302,7 +302,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
             ty::ReLateParam(late_param) => match late_param.kind {
                 ty::LateParamRegionKind::Named(region_def_id, name) => {
                     // Get the span to point to, even if we don't use the name.
-                    let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
+                    let span = tcx.hir_span_if_local(region_def_id).unwrap_or(DUMMY_SP);
                     debug!(
                         "bound region named: {:?}, is_named: {:?}",
                         name,
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 693d22abbe6..14ed6a27a7a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -70,7 +70,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}");
 
         let upvar_name = tcx.hir_name(upvar_hir_id);
-        let upvar_span = tcx.hir().span(upvar_hir_id);
+        let upvar_span = tcx.hir_span(upvar_hir_id);
         debug!(
             "get_upvar_name_and_span_for_region: upvar_name={upvar_name:?} upvar_span={upvar_span:?}",
         );
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ed95545dea4..7f0ee28531c 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -73,6 +73,7 @@ mod def_use;
 mod diagnostics;
 mod member_constraints;
 mod nll;
+mod opaque_types;
 mod path_utils;
 mod place_ext;
 mod places_conflict;
@@ -102,11 +103,8 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
-    let (input_body, promoted) = tcx.mir_promoted(def);
-    debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
-
+    let (input_body, _) = tcx.mir_promoted(def);
     let input_body: &Body<'_> = &input_body.borrow();
-
     if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
         debug!("Skipping borrowck because of injected body or tainted body");
         // Let's make up a borrowck result! Fun times!
@@ -119,7 +117,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
         return tcx.arena.alloc(result);
     }
 
-    let borrowck_result = do_mir_borrowck(tcx, input_body, &*promoted.borrow(), None).0;
+    let borrowck_result = do_mir_borrowck(tcx, def, None).0;
     debug!("mir_borrowck done");
 
     tcx.arena.alloc(borrowck_result)
@@ -130,15 +128,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
 /// Use `consumer_options: None` for the default behavior of returning
 /// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
 /// to the given [`ConsumerOptions`].
-#[instrument(skip(tcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
+#[instrument(skip(tcx), level = "debug")]
 fn do_mir_borrowck<'tcx>(
     tcx: TyCtxt<'tcx>,
-    input_body: &Body<'tcx>,
-    input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
+    def: LocalDefId,
     consumer_options: Option<ConsumerOptions>,
 ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
-    let def = input_body.source.def_id().expect_local();
     let infcx = BorrowckInferCtxt::new(tcx, def);
+    let (input_body, promoted) = tcx.mir_promoted(def);
+    let input_body: &Body<'_> = &input_body.borrow();
+    let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
     if let Some(e) = input_body.tainted_by_errors {
         infcx.set_tainted_by_errors(e);
     }
@@ -192,7 +191,7 @@ fn do_mir_borrowck<'tcx>(
     // Compute non-lexical lifetimes.
     let nll::NllOutput {
         regioncx,
-        opaque_type_values,
+        concrete_opaque_types,
         polonius_input,
         polonius_output,
         opt_closure_req,
@@ -222,7 +221,7 @@ fn do_mir_borrowck<'tcx>(
         body,
         &regioncx,
         &opt_closure_req,
-        &opaque_type_values,
+        &concrete_opaque_types,
         diags_buffer,
     );
 
@@ -357,7 +356,7 @@ fn do_mir_borrowck<'tcx>(
     let tainted_by_errors = mbcx.emit_errors();
 
     let result = BorrowCheckResult {
-        concrete_opaque_types: opaque_type_values,
+        concrete_opaque_types: concrete_opaque_types.into_inner(),
         closure_requirements: opt_closure_req,
         used_mut_upvars: mbcx.used_mut_upvars,
         tainted_by_errors,
@@ -498,7 +497,8 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
                 )
             });
 
-            self.inject_new_hidden_type_unchecked(key, hidden_ty);
+            let prev = self.register_hidden_type_in_storage(key, hidden_ty);
+            assert_eq!(prev, None);
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 2031579dfd5..8e7b6f083ac 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -1,13 +1,11 @@
 //! The entry point of the NLL borrow checker.
 
+use std::io;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::str::FromStr;
-use std::{env, io};
 
 use polonius_engine::{Algorithm, Output};
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir::def_id::LocalDefId;
 use rustc_index::IndexSlice;
 use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
 use rustc_middle::mir::{
@@ -15,7 +13,7 @@ use rustc_middle::mir::{
     dump_enabled, dump_mir,
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_mir_dataflow::ResultsCursor;
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
@@ -27,6 +25,7 @@ use tracing::{debug, instrument};
 use crate::borrow_set::BorrowSet;
 use crate::consumers::ConsumerOptions;
 use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
+use crate::opaque_types::ConcreteOpaqueTypes;
 use crate::polonius::PoloniusDiagnosticsContext;
 use crate::polonius::legacy::{
     PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
@@ -40,7 +39,7 @@ use crate::{BorrowckInferCtxt, polonius, renumber};
 /// closure requirements to propagate, and any generated errors.
 pub(crate) struct NllOutput<'tcx> {
     pub regioncx: RegionInferenceContext<'tcx>,
-    pub opaque_type_values: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
+    pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
     pub polonius_input: Option<Box<PoloniusFacts>>,
     pub polonius_output: Option<Box<PoloniusOutput>>,
     pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
@@ -99,6 +98,8 @@ pub(crate) fn compute_regions<'a, 'tcx>(
 
     let location_map = Rc::new(DenseLocationMap::new(body));
 
+    let mut concrete_opaque_types = ConcreteOpaqueTypes::default();
+
     // Run the MIR type-checker.
     let MirTypeckResults {
         constraints,
@@ -116,6 +117,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         flow_inits,
         move_data,
         Rc::clone(&location_map),
+        &mut concrete_opaque_types,
     );
 
     // Create the region inference context, taking ownership of the
@@ -160,9 +162,8 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         }
 
         if polonius_output {
-            let algorithm =
-                env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
-            let algorithm = Algorithm::from_str(&algorithm).unwrap();
+            let algorithm = infcx.tcx.env_var("POLONIUS_ALGORITHM").unwrap_or("Hybrid");
+            let algorithm = Algorithm::from_str(algorithm).unwrap();
             debug!("compute_regions: using polonius algorithm {:?}", algorithm);
             let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis");
             Some(Box::new(Output::compute(polonius_facts, algorithm, false)))
@@ -180,11 +181,11 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         infcx.set_tainted_by_errors(guar);
     }
 
-    let remapped_opaque_tys = regioncx.infer_opaque_types(infcx, opaque_type_values);
+    regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types);
 
     NllOutput {
         regioncx,
-        opaque_type_values: remapped_opaque_tys,
+        concrete_opaque_types,
         polonius_input: polonius_facts.map(Box::new),
         polonius_output,
         opt_closure_req: closure_region_requirements,
@@ -300,7 +301,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
-    opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
+    concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>,
     diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
 ) {
     let tcx = infcx.tcx;
@@ -343,8 +344,8 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
         err
     };
 
-    if !opaque_type_values.is_empty() {
-        err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}"));
+    if !concrete_opaque_types.is_empty() {
+        err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}"));
     }
 
     diagnostics_buffer.buffer_non_error(err);
diff --git a/compiler/rustc_borrowck/src/opaque_types.rs b/compiler/rustc_borrowck/src/opaque_types.rs
new file mode 100644
index 00000000000..5c78814abdd
--- /dev/null
+++ b/compiler/rustc_borrowck/src/opaque_types.rs
@@ -0,0 +1,55 @@
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt};
+
+#[derive(Debug, Default)]
+pub(super) struct ConcreteOpaqueTypes<'tcx> {
+    concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
+}
+
+impl<'tcx> ConcreteOpaqueTypes<'tcx> {
+    pub(super) fn is_empty(&self) -> bool {
+        self.concrete_opaque_types.is_empty()
+    }
+
+    pub(super) fn into_inner(self) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
+        self.concrete_opaque_types
+    }
+
+    /// Insert an opaque type into the list of opaque types defined by this function
+    /// after mapping the hidden type to the generic parameters of the opaque type
+    /// definition.
+    pub(super) fn insert(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        def_id: LocalDefId,
+        hidden_ty: OpaqueHiddenType<'tcx>,
+    ) {
+        // Sometimes two opaque types are the same only after we remap the generic parameters
+        // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
+        // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
+        // only know that once we convert the generic parameters to those of the opaque type.
+        if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) {
+            if prev.ty != hidden_ty.ty {
+                let (Ok(guar) | Err(guar)) =
+                    prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
+                prev.ty = Ty::new_error(tcx, guar);
+            }
+            // Pick a better span if there is one.
+            // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
+            prev.span = prev.span.substitute_dummy(hidden_ty.span);
+        } else {
+            self.concrete_opaque_types.insert(def_id, hidden_ty);
+        }
+    }
+
+    pub(super) fn extend_from_nested_body(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        nested_body: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
+    ) {
+        for (&def_id, &hidden_ty) in nested_body {
+            self.insert(tcx, def_id, hidden_ty);
+        }
+    }
+}
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 04839448596..ca8b9fb4e9d 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -15,6 +15,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::{debug, instrument};
 
 use super::RegionInferenceContext;
+use crate::opaque_types::ConcreteOpaqueTypes;
 use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
 use crate::universal_regions::RegionClassification;
 
@@ -67,8 +68,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         infcx: &InferCtxt<'tcx>,
         opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
-    ) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
-        let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
+        concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
+    ) {
         let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
             FxIndexMap::default();
 
@@ -143,33 +144,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     continue;
                 }
             }
-            // Sometimes two opaque types are the same only after we remap the generic parameters
-            // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
-            // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
-            // only know that once we convert the generic parameters to those of the opaque type.
-            if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
-                if prev.ty != ty {
-                    let guar = ty.error_reported().err().unwrap_or_else(|| {
-                        let (Ok(e) | Err(e)) = prev
-                            .build_mismatch_error(
-                                &OpaqueHiddenType { ty, span: concrete_type.span },
-                                infcx.tcx,
-                            )
-                            .map(|d| d.emit());
-                        e
-                    });
-                    prev.ty = Ty::new_error(infcx.tcx, guar);
-                }
-                // Pick a better span if there is one.
-                // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
-                prev.span = prev.span.substitute_dummy(concrete_type.span);
-            } else {
-                result.insert(
-                    opaque_type_key.def_id,
-                    OpaqueHiddenType { ty, span: concrete_type.span },
-                );
-            }
 
+            concrete_opaque_types.insert(
+                infcx.tcx,
+                opaque_type_key.def_id,
+                OpaqueHiddenType { ty, span: concrete_type.span },
+            );
             // Check that all opaque types have the same region parameters if they have the same
             // non-region parameters. This is necessary because within the new solver we perform
             // various query operations modulo regions, and thus could unsoundly select some impls
@@ -193,7 +173,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 });
             }
         }
-        result
     }
 
     /// Map the regions in the type to named regions. This is similar to what
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0fda3e31690..f6144a25938 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -45,6 +45,7 @@ use crate::borrow_set::BorrowSet;
 use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
 use crate::diagnostics::UniverseInfo;
 use crate::member_constraints::MemberConstraintSet;
+use crate::opaque_types::ConcreteOpaqueTypes;
 use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
 use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
 use crate::region_infer::TypeTest;
@@ -111,6 +112,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     location_map: Rc<DenseLocationMap>,
+    concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -165,6 +167,7 @@ pub(crate) fn type_check<'a, 'tcx>(
         polonius_facts,
         borrow_set,
         constraints: &mut constraints,
+        concrete_opaque_types,
         polonius_liveness,
     };
 
@@ -230,6 +233,7 @@ struct TypeChecker<'a, 'tcx> {
     polonius_facts: &'a mut Option<PoloniusFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
+    concrete_opaque_types: &'a mut ConcreteOpaqueTypes<'tcx>,
     /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints.
     polonius_liveness: Option<PoloniusLivenessContext>,
 }
@@ -2499,7 +2503,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         args: GenericArgsRef<'tcx>,
         locations: Locations,
     ) -> ty::InstantiatedPredicates<'tcx> {
-        if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
+        let closure_borrowck_results = tcx.mir_borrowck(def_id);
+        self.concrete_opaque_types
+            .extend_from_nested_body(tcx, &closure_borrowck_results.concrete_opaque_types);
+
+        if let Some(closure_requirements) = &closure_borrowck_results.closure_requirements {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.universal_regions,
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 1c1b2c88f76..ea406e70666 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -21,15 +21,15 @@ pub(crate) fn expand(
 
     // Allow using `#[alloc_error_handler]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
+    let (item, ident, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
         && let ItemKind::Fn(fn_kind) = &item.kind
     {
-        (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        (item, fn_kind.ident, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
     } else if let Annotatable::Stmt(stmt) = &item
         && let StmtKind::Item(item) = &stmt.kind
         && let ItemKind::Fn(fn_kind) = &item.kind
     {
-        (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        (item, fn_kind.ident, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
     } else {
         ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
         return vec![orig_item];
@@ -39,7 +39,7 @@ pub(crate) fn expand(
     let span = ecx.with_def_site_ctxt(item.span);
 
     // Generate item statements for the allocator methods.
-    let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
+    let stmts = thin_vec![generate_handler(ecx, ident, span, sig_span)];
 
     // Generate anonymous constant serving as container for the allocator methods.
     let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
@@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
     let kind = ItemKind::Fn(Box::new(Fn {
         defaultness: ast::Defaultness::Final,
         sig,
+        ident: Ident::from_str_and_span("__rg_oom", span),
         generics: Generics::default(),
         contract: None,
         body,
@@ -93,6 +94,6 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
 
     let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
 
-    let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
+    let item = cx.item(span, attrs, kind);
     cx.stmt_item(sig_span, item)
 }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index eb5b345e49e..3e8ddb8abd4 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -10,7 +10,7 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_parse::exp;
 use rustc_parse::parser::{ExpKeywordPair, Parser};
 use rustc_session::lint;
-use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw};
+use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw};
 use rustc_target::asm::InlineAsmArch;
 use smallvec::smallvec;
 use {rustc_ast as ast, rustc_parse_format as parse};
@@ -888,7 +888,6 @@ pub(super) fn expand_global_asm<'cx>(
             };
             match mac {
                 Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
-                    ident: Ident::empty(),
                     attrs: ast::AttrVec::new(),
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index a949ab94f3a..ea7248ca539 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -112,7 +112,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
             self.span,
             self.cx.item(
                 self.span,
-                Ident::empty(),
                 thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
                 ItemKind::Use(UseTree {
                     prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index dcd3c1ce8d9..8937d35d53a 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -26,6 +26,16 @@ mod llvm_enzyme {
 
     use crate::errors;
 
+    pub(crate) fn outer_normal_attr(
+        kind: &P<rustc_ast::NormalAttr>,
+        id: rustc_ast::AttrId,
+        span: Span,
+    ) -> rustc_ast::Attribute {
+        let style = rustc_ast::AttrStyle::Outer;
+        let kind = rustc_ast::AttrKind::Normal(kind.clone());
+        rustc_ast::Attribute { kind, id, style, span }
+    }
+
     // If we have a default `()` return type or explicitley `()` return type,
     // then we often can skip doing some work.
     fn has_ret(ty: &FnRetTy) -> bool {
@@ -136,26 +146,26 @@ mod llvm_enzyme {
         }
         let dcx = ecx.sess.dcx();
         // first get the annotable item:
-        let (sig, is_impl): (FnSig, bool) = match &item {
+        let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item {
             Annotatable::Item(iitem) => {
-                let sig = match &iitem.kind {
-                    ItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+                let (ident, sig) = match &iitem.kind {
+                    ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
                     _ => {
                         dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                         return vec![item];
                     }
                 };
-                (sig.clone(), false)
+                (*ident, sig.clone(), false)
             }
-            Annotatable::AssocItem(assoc_item, _) => {
-                let sig = match &assoc_item.kind {
-                    ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+            Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
+                let (ident, sig) = match &assoc_item.kind {
+                    ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
                     _ => {
                         dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                         return vec![item];
                     }
                 };
-                (sig.clone(), true)
+                (*ident, sig.clone(), true)
             }
             _ => {
                 dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@@ -174,11 +184,9 @@ mod llvm_enzyme {
         let has_ret = has_ret(&sig.decl.output);
         let sig_span = ecx.with_call_site_ctxt(sig.span);
 
-        let (vis, primal) = match &item {
-            Annotatable::Item(iitem) => (iitem.vis.clone(), iitem.ident.clone()),
-            Annotatable::AssocItem(assoc_item, _) => {
-                (assoc_item.vis.clone(), assoc_item.ident.clone())
-            }
+        let vis = match &item {
+            Annotatable::Item(iitem) => iitem.vis.clone(),
+            Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(),
             _ => {
                 dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                 return vec![item];
@@ -224,27 +232,15 @@ mod llvm_enzyme {
             .filter(|a| **a == DiffActivity::Active || **a == DiffActivity::ActiveOnly)
             .count() as u32;
         let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span);
-        let new_decl_span = d_sig.span;
         let d_body = gen_enzyme_body(
-            ecx,
-            &x,
-            n_active,
-            &sig,
-            &d_sig,
-            primal,
-            &new_args,
-            span,
-            sig_span,
-            new_decl_span,
-            idents,
-            errored,
+            ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored,
         );
-        let d_ident = first_ident(&meta_item_vec[0]);
 
         // The first element of it is the name of the function to be generated
         let asdf = Box::new(ast::Fn {
             defaultness: ast::Defaultness::Final,
             sig: d_sig,
+            ident: first_ident(&meta_item_vec[0]),
             generics: Generics::default(),
             contract: None,
             body: Some(d_body),
@@ -270,36 +266,39 @@ mod llvm_enzyme {
         };
         let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None });
         let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
-        let attr: ast::Attribute = ast::Attribute {
-            kind: ast::AttrKind::Normal(rustc_ad_attr.clone()),
-            id: new_id,
-            style: ast::AttrStyle::Outer,
-            span,
-        };
+        let attr = outer_normal_attr(&rustc_ad_attr, new_id, span);
         let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
-        let inline_never: ast::Attribute = ast::Attribute {
-            kind: ast::AttrKind::Normal(inline_never_attr),
-            id: new_id,
-            style: ast::AttrStyle::Outer,
-            span,
-        };
+        let inline_never = outer_normal_attr(&inline_never_attr, new_id, span);
+
+        // We're avoid duplicating the attributes `#[rustc_autodiff]` and `#[inline(never)]`.
+        fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool {
+            match (attr, item) {
+                (ast::AttrKind::Normal(a), ast::AttrKind::Normal(b)) => {
+                    let a = &a.item.path;
+                    let b = &b.item.path;
+                    a.segments.len() == b.segments.len()
+                        && a.segments.iter().zip(b.segments.iter()).all(|(a, b)| a.ident == b.ident)
+                }
+                _ => false,
+            }
+        }
 
         // Don't add it multiple times:
         let orig_annotatable: Annotatable = match item {
             Annotatable::Item(ref mut iitem) => {
-                if !iitem.attrs.iter().any(|a| a.id == attr.id) {
+                if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
                     iitem.attrs.push(attr);
                 }
-                if !iitem.attrs.iter().any(|a| a.id == inline_never.id) {
+                if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) {
                     iitem.attrs.push(inline_never.clone());
                 }
                 Annotatable::Item(iitem.clone())
             }
-            Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => {
-                if !assoc_item.attrs.iter().any(|a| a.id == attr.id) {
+            Annotatable::AssocItem(ref mut assoc_item, i @ Impl { of_trait: false }) => {
+                if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
                     assoc_item.attrs.push(attr);
                 }
-                if !assoc_item.attrs.iter().any(|a| a.id == inline_never.id) {
+                if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) {
                     assoc_item.attrs.push(inline_never.clone());
                 }
                 Annotatable::AssocItem(assoc_item.clone(), i)
@@ -314,13 +313,7 @@ mod llvm_enzyme {
             delim: rustc_ast::token::Delimiter::Parenthesis,
             tokens: ts,
         });
-        let d_attr: ast::Attribute = ast::Attribute {
-            kind: ast::AttrKind::Normal(rustc_ad_attr.clone()),
-            id: new_id,
-            style: ast::AttrStyle::Outer,
-            span,
-        };
-
+        let d_attr = outer_normal_attr(&rustc_ad_attr, new_id, span);
         let d_annotatable = if is_impl {
             let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf);
             let d_fn = P(ast::AssocItem {
@@ -328,14 +321,12 @@ mod llvm_enzyme {
                 id: ast::DUMMY_NODE_ID,
                 span,
                 vis,
-                ident: d_ident,
                 kind: assoc_item,
                 tokens: None,
             });
-            Annotatable::AssocItem(d_fn, Impl)
+            Annotatable::AssocItem(d_fn, Impl { of_trait: false })
         } else {
-            let mut d_fn =
-                ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
+            let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
             d_fn.vis = vis;
             Annotatable::Item(d_fn)
         };
@@ -361,30 +352,27 @@ mod llvm_enzyme {
         ty
     }
 
-    /// We only want this function to type-check, since we will replace the body
-    /// later on llvm level. Using `loop {}` does not cover all return types anymore,
-    /// so instead we build something that should pass. We also add a inline_asm
-    /// line, as one more barrier for rustc to prevent inlining of this function.
-    /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see
-    /// <https://github.com/EnzymeAD/rust/issues/173>, so this isn't sufficient.
-    /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate
-    /// this function (which should never happen, since it is only a placeholder).
-    /// Finally, we also add back_box usages of all input arguments, to prevent rustc
-    /// from optimizing any arguments away.
-    fn gen_enzyme_body(
+    // Will generate a body of the type:
+    // ```
+    // {
+    //   unsafe {
+    //   asm!("NOP");
+    //   }
+    //   ::core::hint::black_box(primal(args));
+    //   ::core::hint::black_box((args, ret));
+    //   <This part remains to be done by following function>
+    // }
+    // ```
+    fn init_body_helper(
         ecx: &ExtCtxt<'_>,
-        x: &AutoDiffAttrs,
-        n_active: u32,
-        sig: &ast::FnSig,
-        d_sig: &ast::FnSig,
+        span: Span,
         primal: Ident,
         new_names: &[String],
-        span: Span,
         sig_span: Span,
         new_decl_span: Span,
-        idents: Vec<Ident>,
+        idents: &[Ident],
         errored: bool,
-    ) -> P<ast::Block> {
+    ) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) {
         let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]);
         let noop = ast::InlineAsm {
             asm_macro: ast::AsmMacro::Asm,
@@ -403,7 +391,6 @@ mod llvm_enzyme {
             tokens: None,
             rules: unsf,
             span,
-            could_be_bare_literal: false,
         };
         let unsf_expr = ecx.expr_block(P(unsf_block));
         let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path));
@@ -433,6 +420,51 @@ mod llvm_enzyme {
         }
         body.stmts.push(ecx.stmt_semi(black_box_remaining_args));
 
+        (body, primal_call, black_box_primal_call, blackbox_call_expr)
+    }
+
+    /// We only want this function to type-check, since we will replace the body
+    /// later on llvm level. Using `loop {}` does not cover all return types anymore,
+    /// so instead we manually build something that should pass the type checker.
+    /// We also add a inline_asm line, as one more barrier for rustc to prevent inlining
+    /// or const propagation. inline_asm will also triggers an Enzyme crash if due to another
+    /// bug would ever try to accidentially differentiate this placeholder function body.
+    /// Finally, we also add back_box usages of all input arguments, to prevent rustc
+    /// from optimizing any arguments away.
+    fn gen_enzyme_body(
+        ecx: &ExtCtxt<'_>,
+        x: &AutoDiffAttrs,
+        n_active: u32,
+        sig: &ast::FnSig,
+        d_sig: &ast::FnSig,
+        primal: Ident,
+        new_names: &[String],
+        span: Span,
+        sig_span: Span,
+        idents: Vec<Ident>,
+        errored: bool,
+    ) -> P<ast::Block> {
+        let new_decl_span = d_sig.span;
+
+        // Just adding some default inline-asm and black_box usages to prevent early inlining
+        // and optimizations which alter the function signature.
+        //
+        // The bb_primal_call is the black_box call of the primal function. We keep it around,
+        // since it has the convenient property of returning the type of the primal function,
+        // Remember, we only care to match types here.
+        // No matter which return we pick, we always wrap it into a std::hint::black_box call,
+        // to prevent rustc from propagating it into the caller.
+        let (mut body, primal_call, bb_primal_call, bb_call_expr) = init_body_helper(
+            ecx,
+            span,
+            primal,
+            new_names,
+            sig_span,
+            new_decl_span,
+            &idents,
+            errored,
+        );
+
         if !has_ret(&d_sig.decl.output) {
             // there is no return type that we have to match, () works fine.
             return body;
@@ -444,7 +476,7 @@ mod llvm_enzyme {
 
         if primal_ret && n_active == 0 && x.mode.is_rev() {
             // We only have the primal ret.
-            body.stmts.push(ecx.stmt_expr(black_box_primal_call));
+            body.stmts.push(ecx.stmt_expr(bb_primal_call));
             return body;
         }
 
@@ -536,11 +568,11 @@ mod llvm_enzyme {
                 return body;
             }
             [arg] => {
-                ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![arg.clone()]);
+                ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![arg.clone()]);
             }
             args => {
                 let ret_tuple: P<ast::Expr> = ecx.expr_tuple(span, args.into());
-                ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![ret_tuple]);
+                ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![ret_tuple]);
             }
         }
         assert!(has_ret(&d_sig.decl.output));
@@ -553,7 +585,7 @@ mod llvm_enzyme {
         ecx: &ExtCtxt<'_>,
         span: Span,
         primal: Ident,
-        idents: Vec<Ident>,
+        idents: &[Ident],
     ) -> P<ast::Expr> {
         let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower;
         if has_self {
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 5788966b6e7..b3ba9073118 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -121,18 +121,11 @@ impl CfgEval<'_> {
                     let item = parser.parse_item(ForceCollect::Yes)?.unwrap();
                     Annotatable::Item(self.flat_map_item(item).pop().unwrap())
                 }
-                Annotatable::AssocItem(_, AssocCtxt::Trait) => {
+                Annotatable::AssocItem(_, ctxt) => {
                     let item = parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap();
                     Annotatable::AssocItem(
-                        self.flat_map_assoc_item(item, AssocCtxt::Trait).pop().unwrap(),
-                        AssocCtxt::Trait,
-                    )
-                }
-                Annotatable::AssocItem(_, AssocCtxt::Impl) => {
-                    let item = parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap();
-                    Annotatable::AssocItem(
-                        self.flat_map_assoc_item(item, AssocCtxt::Impl).pop().unwrap(),
-                        AssocCtxt::Impl,
+                        self.flat_map_assoc_item(item, ctxt).pop().unwrap(),
+                        ctxt,
                     )
                 }
                 Annotatable::ForeignItem(_) => {
diff --git a/compiler/rustc_builtin_macros/src/define_opaque.rs b/compiler/rustc_builtin_macros/src/define_opaque.rs
index 9777e772cf2..cd02e81f568 100644
--- a/compiler/rustc_builtin_macros/src/define_opaque.rs
+++ b/compiler/rustc_builtin_macros/src/define_opaque.rs
@@ -11,15 +11,20 @@ pub(crate) fn expand(
     let define_opaque = match &mut item {
         Annotatable::Item(p) => match &mut p.kind {
             ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
+            ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque),
+            ast::ItemKind::Static(si) => Some(&mut si.define_opaque),
             _ => None,
         },
         Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
             ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque),
+            ast::AssocItemKind::Const(ct) => Some(&mut ct.define_opaque),
             _ => None,
         },
         Annotatable::Stmt(s) => match &mut s.kind {
             ast::StmtKind::Item(p) => match &mut p.kind {
                 ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
+                ast::ItemKind::Const(ct) => Some(&mut ct.define_opaque),
+                ast::ItemKind::Static(si) => Some(&mut si.define_opaque),
                 _ => None,
             },
             _ => None,
@@ -47,7 +52,10 @@ pub(crate) fn expand(
                 .collect(),
         );
     } else {
-        ecx.dcx().span_err(meta_item.span, "only functions and methods can define opaque types");
+        ecx.dcx().span_err(
+            meta_item.span,
+            "only functions, statics, and consts can define opaque types",
+        );
     }
 
     vec![item]
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 2653a9f48b9..e259f5b3955 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -103,7 +103,7 @@ impl MultiItemModifier for Expander {
 fn dummy_annotatable() -> Annotatable {
     Annotatable::GenericParam(ast::GenericParam {
         id: ast::DUMMY_NODE_ID,
-        ident: Ident::empty(),
+        ident: Ident::dummy(),
         attrs: Default::default(),
         bounds: Default::default(),
         is_placeholder: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index c3656e8244f..44cf215c662 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone(
     let is_simple;
     match item {
         Annotatable::Item(annitem) => match &annitem.kind {
-            ItemKind::Struct(_, Generics { params, .. })
-            | ItemKind::Enum(_, Generics { params, .. }) => {
+            ItemKind::Struct(_, _, Generics { params, .. })
+            | ItemKind::Enum(_, _, Generics { params, .. }) => {
                 let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let has_derive_copy = cx.resolver.has_derive_copy(container_id);
                 if has_derive_copy
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 7958e037555..aa01da3151e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord(
 
     // Order in which to perform matching
     let discr_then_data = if let Annotatable::Item(item) = item
-        && let ItemKind::Enum(def, _) = &item.kind
+        && let ItemKind::Enum(_, def, _) = &item.kind
     {
         let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
         match dataful.iter().filter(|&&b| b).count() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 46b79e09780..446d8afeedd 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
     item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
 
     let (name_ident, generics) = if let Annotatable::Item(aitem) = item
-        && let ItemKind::Struct(struct_data, g) = &aitem.kind
+        && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind
     {
         if !matches!(
             struct_data,
@@ -40,7 +40,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
             cx.dcx().emit_err(RequireOneField { span });
             return;
         }
-        (aitem.ident, g)
+        (*ident, g)
     } else {
         cx.dcx().emit_err(RequireTransparent { span });
         return;
@@ -108,7 +108,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
         push(Annotatable::Item(
             cx.item(
                 span,
-                Ident::empty(),
                 attrs.clone(),
                 ast::ItemKind::Impl(Box::new(ast::Impl {
                     safety: ast::Safety::Default,
@@ -153,7 +152,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
         let trait_ref = cx.trait_ref(trait_path);
         let item = cx.item(
             span,
-            Ident::empty(),
             attrs.clone(),
             ast::ItemKind::Impl(Box::new(ast::Impl {
                 safety: ast::Safety::Default,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 03ee59de70e..b9197be4442 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -487,28 +487,28 @@ impl<'a> TraitDef<'a> {
                 );
 
                 let newitem = match &item.kind {
-                    ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
+                    ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def(
                         cx,
                         struct_def,
-                        item.ident,
+                        *ident,
                         generics,
                         from_scratch,
                         is_packed,
                     ),
-                    ast::ItemKind::Enum(enum_def, generics) => {
+                    ast::ItemKind::Enum(ident, enum_def, generics) => {
                         // We ignore `is_packed` here, because `repr(packed)`
                         // enums cause an error later on.
                         //
                         // This can only cause further compilation errors
                         // downstream in blatantly illegal code, so it is fine.
-                        self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
+                        self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch)
                     }
-                    ast::ItemKind::Union(struct_def, generics) => {
+                    ast::ItemKind::Union(ident, struct_def, generics) => {
                         if self.supports_unions {
                             self.expand_struct_def(
                                 cx,
                                 struct_def,
-                                item.ident,
+                                *ident,
                                 generics,
                                 from_scratch,
                                 is_packed,
@@ -596,7 +596,6 @@ impl<'a> TraitDef<'a> {
             P(ast::AssocItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
-                ident,
                 vis: ast::Visibility {
                     span: self.span.shrink_to_lo(),
                     kind: ast::VisibilityKind::Inherited,
@@ -605,6 +604,7 @@ impl<'a> TraitDef<'a> {
                 attrs: ast::AttrVec::new(),
                 kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
                     defaultness: ast::Defaultness::Final,
+                    ident,
                     generics: Generics::default(),
                     where_clauses: ast::TyAliasWhereClauses::default(),
                     bounds: Vec::new(),
@@ -789,7 +789,6 @@ impl<'a> TraitDef<'a> {
 
         cx.item(
             self.span,
-            Ident::empty(),
             attrs,
             ast::ItemKind::Impl(Box::new(ast::Impl {
                 safety: ast::Safety::Default,
@@ -1033,10 +1032,10 @@ impl<'a> MethodDef<'a> {
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
-            ident: method_ident,
             kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
                 defaultness,
                 sig,
+                ident: method_ident,
                 generics: fn_generics,
                 contract: None,
                 body: Some(body_block),
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index c112589b131..50e7b989ed8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -110,7 +110,6 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
         span,
         tokens: None,
-        could_be_bare_literal: false,
     }))
 }
 
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index b39c9861fd6..ccfcc3079eb 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -74,11 +74,11 @@ pub(crate) fn use_panic_2021(mut span: Span) -> bool {
     // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
     loop {
         let expn = span.ctxt().outer_expn_data();
-        if let Some(features) = expn.allow_internal_unstable {
-            if features.iter().any(|&f| f == sym::edition_panic) {
-                span = expn.call_site;
-                continue;
-            }
+        if let Some(features) = expn.allow_internal_unstable
+            && features.contains(&sym::edition_panic)
+        {
+            span = expn.call_site;
+            continue;
         }
         break expn.edition >= Edition::Edition2021;
     }
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 90d79235820..4b1958bce32 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -25,15 +25,15 @@ pub(crate) fn expand(
 
     // Allow using `#[global_allocator]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
-        && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+    let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
+        && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
     {
-        (item, false, ecx.with_def_site_ctxt(ty.span))
+        (item, *ident, false, ecx.with_def_site_ctxt(ty.span))
     } else if let Annotatable::Stmt(stmt) = &item
         && let StmtKind::Item(item) = &stmt.kind
-        && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+        && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
     {
-        (item, true, ecx.with_def_site_ctxt(ty.span))
+        (item, *ident, true, ecx.with_def_site_ctxt(ty.span))
     } else {
         ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
         return vec![orig_item];
@@ -41,7 +41,7 @@ pub(crate) fn expand(
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
-    let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx };
+    let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx };
 
     // Generate item statements for the allocator methods.
     let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
@@ -80,17 +80,13 @@ impl AllocFnFactory<'_, '_> {
         let kind = ItemKind::Fn(Box::new(Fn {
             defaultness: ast::Defaultness::Final,
             sig,
+            ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span),
             generics: Generics::default(),
             contract: None,
             body,
             define_opaque: None,
         }));
-        let item = self.cx.item(
-            self.span,
-            Ident::from_str_and_span(&global_fn_name(method.name), self.span),
-            self.attrs(),
-            kind,
-        );
+        let item = self.cx.item(self.span, self.attrs(), kind);
         self.cx.stmt_item(self.ty_span, item)
     }
 
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index ee6475c8b8e..8862965c053 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -92,7 +92,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
+    fn collect_custom_derive(
+        &mut self,
+        item: &'a ast::Item,
+        function_name: Ident,
+        attr: &'a ast::Attribute,
+    ) {
         let Some((trait_name, proc_attrs)) =
             parse_macro_name_and_helper_attrs(self.dcx, attr, "derive")
         else {
@@ -104,7 +109,7 @@ impl<'a> CollectProcMacros<'a> {
                 id: item.id,
                 span: item.span,
                 trait_name,
-                function_name: item.ident,
+                function_name,
                 attrs: proc_attrs,
             }));
         } else {
@@ -118,12 +123,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
+    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
         if self.in_root && item.vis.kind.is_pub() {
             self.macros.push(ProcMacro::Attr(ProcMacroDef {
                 id: item.id,
                 span: item.span,
-                function_name: item.ident,
+                function_name,
             }));
         } else {
             let msg = if !self.in_root {
@@ -136,12 +141,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
+    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
         if self.in_root && item.vis.kind.is_pub() {
             self.macros.push(ProcMacro::Bang(ProcMacroDef {
                 id: item.id,
                 span: item.span,
-                function_name: item.ident,
+                function_name,
             }));
         } else {
             let msg = if !self.in_root {
@@ -165,12 +170,6 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             }
         }
 
-        // First up, make sure we're checking a bare function. If we're not then
-        // we're just not interested in this item.
-        //
-        // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
-        let is_fn = matches!(item.kind, ast::ItemKind::Fn(..));
-
         let mut found_attr: Option<&'a ast::Attribute> = None;
 
         for attr in &item.attrs {
@@ -214,7 +213,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             return;
         };
 
-        if !is_fn {
+        // Make sure we're checking a bare function. If we're not then we're
+        // just not interested any further in this item.
+        let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind {
+            fn_.ident
+        } else {
             self.dcx
                 .create_err(errors::AttributeOnlyBeUsedOnBareFunctions {
                     span: attr.span,
@@ -222,7 +225,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
                 })
                 .emit();
             return;
-        }
+        };
 
         if self.is_test_crate {
             return;
@@ -238,12 +241,13 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             return;
         }
 
+        // Try to locate a `#[proc_macro_derive]` attribute.
         if attr.has_name(sym::proc_macro_derive) {
-            self.collect_custom_derive(item, attr);
+            self.collect_custom_derive(item, fn_ident, attr);
         } else if attr.has_name(sym::proc_macro_attribute) {
-            self.collect_attr_proc_macro(item);
+            self.collect_attr_proc_macro(item, fn_ident);
         } else if attr.has_name(sym::proc_macro) {
-            self.collect_bang_proc_macro(item);
+            self.collect_bang_proc_macro(item, fn_ident);
         };
 
         let prev_in_root = mem::replace(&mut self.in_root, false);
@@ -278,7 +282,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
     let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     let proc_macro = Ident::new(sym::proc_macro, span);
-    let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+    let krate = cx.item(span, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, proc_macro));
 
     let bridge = Ident::new(sym::bridge, span);
     let client = Ident::new(sym::client, span);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index ba63b185e09..a1ee53b7ca2 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -43,9 +43,8 @@ pub fn inject(
 
     let item = cx.item(
         span,
-        Ident::new(name, ident_span),
         thin_vec![cx.attr_word(sym::macro_use, span)],
-        ast::ItemKind::ExternCrate(None),
+        ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)),
     );
 
     krate.items.insert(0, item);
@@ -68,7 +67,6 @@ pub fn inject(
     // Inject the relevant crate's prelude.
     let use_item = cx.item(
         span,
-        Ident::empty(),
         thin_vec![cx.attr_word(sym::prelude_import, span)],
         ast::ItemKind::Use(ast::UseTree {
             prefix: cx.path(span, import_path),
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index a05fff2dcd1..1cef4f9514c 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -51,21 +51,28 @@ pub(crate) fn expand_test_case(
             return vec![];
         }
     };
-    item = item.map(|mut item| {
-        let test_path_symbol = Symbol::intern(&item_path(
-            // skip the name of the root module
-            &ecx.current_expansion.module.mod_path[1..],
-            &item.ident,
-        ));
-        item.vis = ast::Visibility {
-            span: item.vis.span,
-            kind: ast::VisibilityKind::Public,
-            tokens: None,
-        };
-        item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
-        item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
-        item
-    });
+
+    // `#[test_case]` is valid on functions, consts, and statics. Only modify
+    // the item in those cases.
+    match &mut item.kind {
+        ast::ItemKind::Fn(box ast::Fn { ident, .. })
+        | ast::ItemKind::Const(box ast::ConstItem { ident, .. })
+        | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => {
+            ident.span = ident.span.with_ctxt(sp.ctxt());
+            let test_path_symbol = Symbol::intern(&item_path(
+                // skip the name of the root module
+                &ecx.current_expansion.module.mod_path[1..],
+                ident,
+            ));
+            item.vis = ast::Visibility {
+                span: item.vis.span,
+                kind: ast::VisibilityKind::Public,
+                tokens: None,
+            };
+            item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
+        }
+        _ => {}
+    }
 
     let ret = if is_stmt {
         Annotatable::Stmt(P(ecx.stmt_item(item.span, item)))
@@ -162,17 +169,17 @@ pub(crate) fn expand_test_or_bench(
     let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
     let attr_sp = cx.with_def_site_ctxt(attr_sp);
 
-    let test_id = Ident::new(sym::test, attr_sp);
+    let test_ident = Ident::new(sym::test, attr_sp);
 
     // creates test::$name
-    let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+    let test_path = |name| cx.path(ret_ty_sp, vec![test_ident, Ident::from_str_and_span(name, sp)]);
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
         cx.path(
             sp,
             vec![
-                test_id,
+                test_ident,
                 Ident::from_str_and_span("ShouldPanic", sp),
                 Ident::from_str_and_span(name, sp),
             ],
@@ -184,7 +191,7 @@ pub(crate) fn expand_test_or_bench(
         cx.path(
             sp,
             vec![
-                test_id,
+                test_ident,
                 Ident::from_str_and_span("TestType", sp),
                 Ident::from_str_and_span(name, sp),
             ],
@@ -223,7 +230,7 @@ pub(crate) fn expand_test_or_bench(
                             // super::$test_fn(b)
                             cx.expr_call(
                                 ret_ty_sp,
-                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                cx.expr_path(cx.path(sp, vec![fn_.ident])),
                                 thin_vec![cx.expr_ident(sp, b)],
                             ),
                         ],
@@ -249,7 +256,7 @@ pub(crate) fn expand_test_or_bench(
                             // $test_fn()
                             cx.expr_call(
                                 ret_ty_sp,
-                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                cx.expr_path(cx.path(sp, vec![fn_.ident])),
                                 ThinVec::new(),
                             ), // )
                         ],
@@ -262,15 +269,14 @@ pub(crate) fn expand_test_or_bench(
     let test_path_symbol = Symbol::intern(&item_path(
         // skip the name of the root module
         &cx.current_expansion.module.mod_path[1..],
-        &item.ident,
+        &fn_.ident,
     ));
 
-    let location_info = get_location_info(cx, &item);
+    let location_info = get_location_info(cx, &fn_);
 
     let mut test_const =
         cx.item(
             sp,
-            Ident::new(item.ident.name, sp),
             thin_vec![
                 // #[cfg(test)]
                 cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
@@ -283,8 +289,10 @@ pub(crate) fn expand_test_or_bench(
             ast::ItemKind::Const(
                 ast::ConstItem {
                     defaultness: ast::Defaultness::Final,
+                    ident: Ident::new(fn_.ident.name, sp),
                     generics: ast::Generics::default(),
                     ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
+                    define_opaque: None,
                     // test::TestDescAndFn {
                     expr: Some(
                         cx.expr_struct(
@@ -379,7 +387,8 @@ pub(crate) fn expand_test_or_bench(
     });
 
     // extern crate test
-    let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+    let test_extern =
+        cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident));
 
     debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
@@ -433,8 +442,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
         .emit();
 }
 
-fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) {
-    let span = item.ident.span;
+fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, usize, usize) {
+    let span = fn_.ident.span;
     let (source_file, lo_line, lo_col, hi_line, hi_col) =
         cx.sess.source_map().span_to_location_info(span);
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 768b459ec5e..56a67b0534d 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -134,7 +134,8 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         if let Some(name) = get_test_name(&item) {
             debug!("this is a test item");
 
-            let test = Test { span: item.span, ident: item.ident, name };
+            // `unwrap` is ok because only functions, consts, and static should reach here.
+            let test = Test { span: item.span, ident: item.kind.ident().unwrap(), name };
             self.tests.push(test);
         }
 
@@ -142,19 +143,12 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         // mods or tests inside of functions will break things
         if let ast::ItemKind::Mod(
             _,
+            _,
             ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
         ) = item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
-            walk_item_kind(
-                &mut item.kind,
-                item.span,
-                item.id,
-                &mut item.ident,
-                &mut item.vis,
-                (),
-                self,
-            );
+            walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), self);
             self.add_test_cases(item.id, span, prev_tests);
         } else {
             // But in those cases, we emit a lint to warn the user of these missing tests.
@@ -181,9 +175,9 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
 }
 
 fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
-    match item.kind {
-        ast::ItemKind::Fn(..) => {
-            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name))
+    match &item.kind {
+        ast::ItemKind::Fn(fn_) => {
+            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name))
         }
         _ => EntryPointType::None,
     }
@@ -295,7 +289,7 @@ fn generate_test_harness(
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let sp = cx.def_site;
     let ecx = &cx.ext_cx;
-    let test_id = Ident::new(sym::test, sp);
+    let test_ident = Ident::new(sym::test, sp);
 
     let runner_name = match cx.panic_strategy {
         PanicStrategy::Unwind => "test_main_static",
@@ -303,10 +297,9 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     };
 
     // test::test_main_static(...)
-    let mut test_runner = cx
-        .test_runner
-        .clone()
-        .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)]));
+    let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| {
+        ecx.path(sp, vec![test_ident, Ident::from_str_and_span(runner_name, sp)])
+    });
 
     test_runner.span = sp;
 
@@ -317,7 +310,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     // extern crate test
     let test_extern_stmt = ecx.stmt_item(
         sp,
-        ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
+        ecx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)),
     );
 
     // #[rustc_main]
@@ -340,23 +333,24 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
     let defaultness = ast::Defaultness::Final;
+
+    // Honor the reexport_test_harness_main attribute
+    let main_ident = match cx.reexport_test_harness_main {
+        Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
+        None => Ident::new(sym::main, sp),
+    };
+
     let main = ast::ItemKind::Fn(Box::new(ast::Fn {
         defaultness,
         sig,
+        ident: main_ident,
         generics: ast::Generics::default(),
         contract: None,
         body: Some(main_body),
         define_opaque: None,
     }));
 
-    // Honor the reexport_test_harness_main attribute
-    let main_id = match cx.reexport_test_harness_main {
-        Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
-        None => Ident::new(sym::main, sp),
-    };
-
     let main = P(ast::Item {
-        ident: main_id,
         attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
         id: ast::DUMMY_NODE_ID,
         kind: main,
diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml
index 1ec99eb3d17..ee5de8b42f4 100644
--- a/compiler/rustc_codegen_cranelift/.cirrus.yml
+++ b/compiler/rustc_codegen_cranelift/.cirrus.yml
@@ -1,20 +1,21 @@
-task:
-  name: freebsd
-  freebsd_instance:
-    image: freebsd-13-2-release-amd64
-  setup_rust_script:
-    - pkg install -y git-tiny binutils
-    - curl https://sh.rustup.rs -sSf --output rustup.sh
-    - sh rustup.sh --default-toolchain none -y --profile=minimal
-  target_cache:
-    folder: build/cg_clif
-  prepare_script:
-    - . $HOME/.cargo/env
-    - ./y.sh prepare
-  test_script:
-    - . $HOME/.cargo/env
-    # Disabling incr comp reduces cache size and incr comp doesn't save as much
-    # on CI anyway.
-    - export CARGO_BUILD_INCREMENTAL=false
-    # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
-    - ./y.sh test --skip-test test.rust-random/rand
+# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed.
+# task:
+#   name: freebsd
+#   freebsd_instance:
+#     image: freebsd-13-2-release-amd64
+#   setup_rust_script:
+#     - pkg install -y git-tiny binutils
+#     - curl https://sh.rustup.rs -sSf --output rustup.sh
+#     - sh rustup.sh --default-toolchain none -y --profile=minimal
+#   target_cache:
+#     folder: build/cg_clif
+#   prepare_script:
+#     - . $HOME/.cargo/env
+#     - ./y.sh prepare
+#   test_script:
+#     - . $HOME/.cargo/env
+#     # Disabling incr comp reduces cache size and incr comp doesn't save as much
+#     # on CI anyway.
+#     - export CARGO_BUILD_INCREMENTAL=false
+#     # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
+#     - ./y.sh test --skip-test test.rust-random/rand
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md b/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
deleted file mode 100644
index c70ba8f4953..00000000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# github-release
-
-An action used to publish GitHub releases for `wasmtime`.
-
-As of the time of this writing there's a few actions floating around which
-perform github releases but they all tend to have their set of drawbacks.
-Additionally nothing handles deleting releases which we need for our rolling
-`dev` release.
-
-To handle all this this action rolls-its-own implementation using the
-actions/toolkit repository and packages published there. These run in a Docker
-container and take various inputs to orchestrate the release from the build.
-
-More comments can be found in `main.js`.
-
-Testing this is really hard. If you want to try though run `npm install` and
-then `node main.js`. You'll have to configure a bunch of env vars though to get
-anything reasonably working.
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml b/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
deleted file mode 100644
index 36e5209f50c..00000000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-name: 'rustc_codegen_cranelift github releases'
-description: 'rustc_codegen_cranelift github releases'
-inputs:
-  token:
-    description: ''
-    required: true
-  files:
-    description: ''
-    required: true
-runs:
-  using: 'node16'
-  main: 'main.js'
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
deleted file mode 100644
index 1eb2b7f23b2..00000000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-const core = require('@actions/core');
-const path = require("path");
-const fs = require("fs");
-const github = require('@actions/github');
-const glob = require('glob');
-
-function sleep(milliseconds) {
-  return new Promise(resolve => setTimeout(resolve, milliseconds))
-}
-
-async function runOnce() {
-  // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*`
-  const files = core.getInput('files');
-  const token = core.getInput('token');
-  const slug = process.env.GITHUB_REPOSITORY;
-  const owner = slug.split('/')[0];
-  const repo = slug.split('/')[1];
-  const sha = process.env.GITHUB_SHA;
-  let name = 'dev';
-  if (process.env.GITHUB_REF.startsWith('refs/tags/v')) {
-    name = process.env.GITHUB_REF.substring(10);
-  }
-
-  core.info(`files: ${files}`);
-  core.info(`name: ${name}`);
-  core.info(`token: ${token}`);
-
-  const octokit = github.getOctokit(token);
-
-  // For the `dev` release we may need to update the tag to point to the new
-  // commit on this branch. All other names should already have tags associated
-  // with them.
-  if (name == 'dev') {
-    let tag = null;
-    try {
-      tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
-      core.info(`found existing tag`);
-      console.log("tag: ", JSON.stringify(tag.data, null, 2));
-    } catch (e) {
-      // ignore if this tag doesn't exist
-      core.info(`no existing tag found`);
-    }
-
-    if (tag === null || tag.data.object.sha !== sha) {
-      core.info(`updating existing tag or creating new one`);
-
-      try {
-        core.info(`updating dev tag`);
-        await octokit.rest.git.updateRef({
-          owner,
-          repo,
-          ref: 'tags/dev',
-          sha,
-          force: true,
-        });
-      } catch (e) {
-        console.log("ERROR: ", JSON.stringify(e.response, null, 2));
-        core.info(`creating dev tag`);
-        try {
-          await octokit.rest.git.createRef({
-            owner,
-            repo,
-            ref: 'refs/tags/dev',
-            sha,
-          });
-        } catch (e) {
-          // we might race with others, so assume someone else has created the
-          // tag by this point.
-          console.log("failed to create tag: ", JSON.stringify(e.response, null, 2));
-        }
-      }
-
-      console.log("double-checking tag is correct");
-      tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name });
-      if (tag.data.object.sha !== sha) {
-        console.log("tag: ", JSON.stringify(tag.data, null, 2));
-        throw new Error("tag didn't work");
-      }
-    } else {
-      core.info(`existing tag works`);
-    }
-  }
-
-  // Delete a previous release
-  try {
-    core.info(`fetching release`);
-    let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name });
-    console.log("found release: ", JSON.stringify(release.data, null, 2));
-    await octokit.rest.repos.deleteRelease({
-      owner,
-      repo,
-      release_id: release.data.id,
-    });
-    console.log("deleted release");
-  } catch (e) {
-    console.log("ERROR: ", JSON.stringify(e, null, 2));
-  }
-
-  console.log("creating a release");
-  let release = await octokit.rest.repos.createRelease({
-    owner,
-    repo,
-    tag_name: name,
-    prerelease: name === 'dev',
-  });
-
-  // Delete all assets from a previous run
-  for (const asset of release.data.assets) {
-    console.log(`deleting prior asset ${asset.id}`);
-    await octokit.rest.repos.deleteReleaseAsset({
-      owner,
-      repo,
-      asset_id: asset.id,
-    });
-  }
-
-  // Upload all the relevant assets for this release as just general blobs.
-  for (const file of glob.sync(files)) {
-    const size = fs.statSync(file).size;
-    const name = path.basename(file);
-    core.info(`upload ${file}`);
-    await octokit.rest.repos.uploadReleaseAsset({
-      data: fs.createReadStream(file),
-      headers: { 'content-length': size, 'content-type': 'application/octet-stream' },
-      name,
-      url: release.data.upload_url,
-    });
-  }
-}
-
-async function run() {
-  const retries = 10;
-  for (let i = 0; i < retries; i++) {
-    try {
-      await runOnce();
-      break;
-    } catch (e) {
-      if (i === retries - 1)
-        throw e;
-      logError(e);
-      console.log("RETRYING after 10s");
-      await sleep(10000)
-    }
-  }
-}
-
-function logError(e) {
-  console.log("ERROR: ", e.message);
-  try {
-    console.log(JSON.stringify(e, null, 2));
-  } catch (e) {
-    // ignore json errors for now
-  }
-  console.log(e.stack);
-}
-
-run().catch(err => {
-  logError(err);
-  core.setFailed(err.message);
-});
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
deleted file mode 100644
index dd3b2a048f0..00000000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json
+++ /dev/null
@@ -1,571 +0,0 @@
-{
-  "name": "rustc_codegen_cranelift-github-release",
-  "version": "0.0.0",
-  "lockfileVersion": 2,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "rustc_codegen_cranelift-github-release",
-      "version": "0.0.0",
-      "dependencies": {
-        "@actions/core": "^1.9.1",
-        "@actions/github": "^5.1.0",
-        "glob": "^7.1.5"
-      }
-    },
-    "node_modules/@actions/core": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
-      "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
-      "dependencies": {
-        "@actions/http-client": "^2.0.1",
-        "uuid": "^8.3.2"
-      }
-    },
-    "node_modules/@actions/github": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
-      "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
-      "dependencies": {
-        "@actions/http-client": "^2.0.1",
-        "@octokit/core": "^3.6.0",
-        "@octokit/plugin-paginate-rest": "^2.17.0",
-        "@octokit/plugin-rest-endpoint-methods": "^5.13.0"
-      }
-    },
-    "node_modules/@actions/http-client": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
-      "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
-      "dependencies": {
-        "tunnel": "^0.0.6"
-      }
-    },
-    "node_modules/@octokit/auth-token": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
-      "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
-      "dependencies": {
-        "@octokit/types": "^6.0.3"
-      }
-    },
-    "node_modules/@octokit/core": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
-      "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
-      "dependencies": {
-        "@octokit/auth-token": "^2.4.4",
-        "@octokit/graphql": "^4.5.8",
-        "@octokit/request": "^5.6.3",
-        "@octokit/request-error": "^2.0.5",
-        "@octokit/types": "^6.0.3",
-        "before-after-hook": "^2.2.0",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "node_modules/@octokit/endpoint": {
-      "version": "6.0.12",
-      "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
-      "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
-      "dependencies": {
-        "@octokit/types": "^6.0.3",
-        "is-plain-object": "^5.0.0",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "node_modules/@octokit/graphql": {
-      "version": "4.8.0",
-      "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
-      "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
-      "dependencies": {
-        "@octokit/request": "^5.6.0",
-        "@octokit/types": "^6.0.3",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "node_modules/@octokit/openapi-types": {
-      "version": "12.11.0",
-      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
-      "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
-    },
-    "node_modules/@octokit/plugin-paginate-rest": {
-      "version": "2.21.3",
-      "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
-      "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
-      "dependencies": {
-        "@octokit/types": "^6.40.0"
-      },
-      "peerDependencies": {
-        "@octokit/core": ">=2"
-      }
-    },
-    "node_modules/@octokit/plugin-rest-endpoint-methods": {
-      "version": "5.16.2",
-      "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
-      "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
-      "dependencies": {
-        "@octokit/types": "^6.39.0",
-        "deprecation": "^2.3.1"
-      },
-      "peerDependencies": {
-        "@octokit/core": ">=3"
-      }
-    },
-    "node_modules/@octokit/request": {
-      "version": "5.6.3",
-      "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
-      "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
-      "dependencies": {
-        "@octokit/endpoint": "^6.0.1",
-        "@octokit/request-error": "^2.1.0",
-        "@octokit/types": "^6.16.1",
-        "is-plain-object": "^5.0.0",
-        "node-fetch": "^2.6.7",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "node_modules/@octokit/request-error": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
-      "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
-      "dependencies": {
-        "@octokit/types": "^6.0.3",
-        "deprecation": "^2.0.0",
-        "once": "^1.4.0"
-      }
-    },
-    "node_modules/@octokit/types": {
-      "version": "6.41.0",
-      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
-      "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
-      "dependencies": {
-        "@octokit/openapi-types": "^12.11.0"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-    },
-    "node_modules/before-after-hook": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
-      "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
-    },
-    "node_modules/deprecation": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
-      "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
-    },
-    "node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "node_modules/is-plain-object": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
-      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/node-fetch": {
-      "version": "2.6.7",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-      "dependencies": {
-        "whatwg-url": "^5.0.0"
-      },
-      "engines": {
-        "node": "4.x || >=6.0.0"
-      },
-      "peerDependencies": {
-        "encoding": "^0.1.0"
-      },
-      "peerDependenciesMeta": {
-        "encoding": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
-    },
-    "node_modules/tunnel": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
-      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
-      "engines": {
-        "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
-      }
-    },
-    "node_modules/universal-user-agent": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
-      "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
-    },
-    "node_modules/uuid": {
-      "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
-    },
-    "node_modules/whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
-      "dependencies": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
-    }
-  },
-  "dependencies": {
-    "@actions/core": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
-      "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
-      "requires": {
-        "@actions/http-client": "^2.0.1",
-        "uuid": "^8.3.2"
-      }
-    },
-    "@actions/github": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
-      "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
-      "requires": {
-        "@actions/http-client": "^2.0.1",
-        "@octokit/core": "^3.6.0",
-        "@octokit/plugin-paginate-rest": "^2.17.0",
-        "@octokit/plugin-rest-endpoint-methods": "^5.13.0"
-      }
-    },
-    "@actions/http-client": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
-      "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
-      "requires": {
-        "tunnel": "^0.0.6"
-      }
-    },
-    "@octokit/auth-token": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
-      "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
-      "requires": {
-        "@octokit/types": "^6.0.3"
-      }
-    },
-    "@octokit/core": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
-      "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
-      "requires": {
-        "@octokit/auth-token": "^2.4.4",
-        "@octokit/graphql": "^4.5.8",
-        "@octokit/request": "^5.6.3",
-        "@octokit/request-error": "^2.0.5",
-        "@octokit/types": "^6.0.3",
-        "before-after-hook": "^2.2.0",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "@octokit/endpoint": {
-      "version": "6.0.12",
-      "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
-      "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
-      "requires": {
-        "@octokit/types": "^6.0.3",
-        "is-plain-object": "^5.0.0",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "@octokit/graphql": {
-      "version": "4.8.0",
-      "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
-      "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
-      "requires": {
-        "@octokit/request": "^5.6.0",
-        "@octokit/types": "^6.0.3",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "@octokit/openapi-types": {
-      "version": "12.11.0",
-      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
-      "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
-    },
-    "@octokit/plugin-paginate-rest": {
-      "version": "2.21.3",
-      "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
-      "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
-      "requires": {
-        "@octokit/types": "^6.40.0"
-      }
-    },
-    "@octokit/plugin-rest-endpoint-methods": {
-      "version": "5.16.2",
-      "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
-      "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
-      "requires": {
-        "@octokit/types": "^6.39.0",
-        "deprecation": "^2.3.1"
-      }
-    },
-    "@octokit/request": {
-      "version": "5.6.3",
-      "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
-      "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
-      "requires": {
-        "@octokit/endpoint": "^6.0.1",
-        "@octokit/request-error": "^2.1.0",
-        "@octokit/types": "^6.16.1",
-        "is-plain-object": "^5.0.0",
-        "node-fetch": "^2.6.7",
-        "universal-user-agent": "^6.0.0"
-      }
-    },
-    "@octokit/request-error": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
-      "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
-      "requires": {
-        "@octokit/types": "^6.0.3",
-        "deprecation": "^2.0.0",
-        "once": "^1.4.0"
-      }
-    },
-    "@octokit/types": {
-      "version": "6.41.0",
-      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
-      "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
-      "requires": {
-        "@octokit/openapi-types": "^12.11.0"
-      }
-    },
-    "balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-    },
-    "before-after-hook": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
-      "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
-    },
-    "deprecation": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
-      "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
-    },
-    "glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "requires": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      }
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "is-plain-object": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
-      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
-    },
-    "minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "node-fetch": {
-      "version": "2.6.7",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-      "requires": {
-        "whatwg-url": "^5.0.0"
-      }
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
-    },
-    "tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
-    },
-    "tunnel": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
-      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
-    },
-    "universal-user-agent": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
-      "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
-    },
-    "uuid": {
-      "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
-    },
-    "webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
-    },
-    "whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
-      "requires": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
-    }
-  }
-}
diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
deleted file mode 100644
index d9c23f8873e..00000000000
--- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "rustc_codegen_cranelift-github-release",
-  "version": "0.0.0",
-  "license": "Apache-2.0 WITH LLVM-exception",
-  "main": "main.js",
-  "dependencies": {
-    "@actions/core": "^1.9.1",
-    "@actions/github": "^5.1.0",
-    "glob": "^7.1.5"
-  }
-}
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
index 30dc5cb1615..6ad041a796c 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
@@ -25,7 +25,10 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
-          - os: macos-latest
+          - os: ubuntu-24.04-arm
+            env:
+              TARGET_TRIPLE: aarch64-unknown-linux-gnu
+          - os: macos-13
             env:
               TARGET_TRIPLE: x86_64-apple-darwin
           - os: macos-latest
@@ -56,13 +59,6 @@ jobs:
       if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
-    - name: Use x86_64 compiler on macOS
-      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
-      run: rustup set default-host x86_64-apple-darwin
-
-    - name: Prepare dependencies
-      run: ./y.sh prepare
-
     - name: Build
       run: ./y.sh build --sysroot none
 
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index 61a4c1270c9..6fd288d195c 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -53,13 +53,12 @@ jobs:
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
-          - os: macos-latest
-            env:
-              TARGET_TRIPLE: x86_64-apple-darwin
-          - os: ubuntu-latest
+          - os: ubuntu-24.04-arm
             env:
               TARGET_TRIPLE: aarch64-unknown-linux-gnu
-            apt_deps: gcc-aarch64-linux-gnu qemu-user
+          - os: macos-13
+            env:
+              TARGET_TRIPLE: x86_64-apple-darwin
           - os: macos-latest
             env:
               TARGET_TRIPLE: aarch64-apple-darwin
@@ -95,10 +94,6 @@ jobs:
       if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
-    - name: Use x86_64 compiler on macOS
-      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
-      run: rustup set default-host x86_64-apple-darwin
-
     - name: Install toolchain and emulator
       if: matrix.apt_deps != null
       run: |
@@ -170,9 +165,6 @@ jobs:
         sudo apt update
         sudo apt install -y hyperfine
 
-    - name: Prepare dependencies
-      run: ./y.sh prepare
-
     - name: Build
       run: ./y.sh build --sysroot none
 
@@ -192,7 +184,10 @@ jobs:
           - os: ubuntu-22.04
             env:
               TARGET_TRIPLE: x86_64-unknown-linux-gnu
-          - os: macos-latest
+          - os: ubuntu-24.04-arm
+            env:
+              TARGET_TRIPLE: aarch64-unknown-linux-gnu
+          - os: macos-13
             env:
               TARGET_TRIPLE: x86_64-apple-darwin
           - os: macos-latest
@@ -218,13 +213,6 @@ jobs:
       if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
-    - name: Use x86_64 compiler on macOS
-      if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin'
-      run: rustup set default-host x86_64-apple-darwin
-
-    - name: Prepare dependencies
-      run: ./y.sh prepare
-
     - name: Build backend
       run: ./y.sh build --sysroot none
 
@@ -273,12 +261,9 @@ jobs:
           rmdir artifacts/ # verify all artifacts are represented in release/
           ls -R release/
 
-      - run: npm install --production
-        working-directory: .github/actions/github-release
-
-      - name: Publish Release
-        uses: ./.github/actions/github-release
-        with:
-          files: "release/*"
-          token: ${{ github.token }}
-        continue-on-error: true
+      - name: Publish release
+        env:
+          GH_TOKEN: ${{ github.token }}
+        run: |
+          gh release delete --cleanup-tag -y dev || true
+          gh release create --target $GITHUB_SHA --prerelease dev release/*
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index 70c214ce8b1..9253ab96353 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -22,9 +22,6 @@ jobs:
         path: build/cg_clif
         key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }}
 
-    - name: Prepare dependencies
-      run: ./y.sh prepare
-
     - name: Test
       run: ./scripts/test_bootstrap.sh
 
@@ -50,8 +47,5 @@ jobs:
         sudo apt update
         sudo apt install -y ripgrep
 
-    - name: Prepare dependencies
-      run: ./y.sh prepare
-
     - name: Test
       run: ./scripts/test_rustc_tests.sh
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index 491646ce59b..68bd93aea89 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -1,41 +1,40 @@
 {
     "editor.formatOnSave": true,
-
     // in case rustc.source is disabled for performance reasons; disable the errors about this
-    "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
+    "rust-analyzer.diagnostics.disabled": [
+        "unresolved-extern-crate",
+        "unresolved-macro-call"
+    ],
     "rust-analyzer.rustc.source": "discover",
     "rust-analyzer.imports.granularity.enforce": true,
     "rust-analyzer.imports.granularity.group": "module",
     "rust-analyzer.imports.prefix": "crate",
-    "rust-analyzer.cargo.features": ["unstable-features"],
+    "rust-analyzer.cargo.features": [
+        "unstable-features"
+    ],
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
         "./build_system/Cargo.toml",
         {
+            "sysroot_src": "./build/stdlib/library",
             "crates": [
                 {
                     "root_module": "./example/mini_core.rs",
-                    "edition": "2018",
+                    "edition": "2015",
                     "deps": [],
                     "cfg": [],
                 },
                 {
                     "root_module": "./example/mini_core_hello_world.rs",
-                    "edition": "2018",
-                    "deps": [{ "crate": 0, "name": "mini_core" }],
-                    "cfg": [],
-                },
-                {
-                    "root_module": "./example/mod_bench.rs",
-                    "edition": "2018",
-                    "deps": [],
+                    "edition": "2015",
+                    "deps": [
+                        {
+                            "crate": 0,
+                            "name": "mini_core"
+                        }
+                    ],
                     "cfg": [],
                 },
-            ]
-        },
-        {
-            "sysroot_src": "./build/stdlib/library",
-            "crates": [
                 {
                     "root_module": "./example/std_example.rs",
                     "edition": "2015",
diff --git a/compiler/rustc_codegen_cranelift/.zed/settings.json b/compiler/rustc_codegen_cranelift/.zed/settings.json
index e93bed36949..4338a347331 100644
--- a/compiler/rustc_codegen_cranelift/.zed/settings.json
+++ b/compiler/rustc_codegen_cranelift/.zed/settings.json
@@ -5,7 +5,10 @@
       "initialization_options": {
         "diagnostics": {
           // in case rustc.source is disabled for performance reasons; disable the errors about this
-          "disabled": ["unresolved-extern-crate", "unresolved-macro-call"]
+          "disabled": [
+            "unresolved-extern-crate",
+            "unresolved-macro-call"
+          ]
         },
         "rustc": {
           "source": "discover"
@@ -18,22 +21,25 @@
           "prefix": "crate"
         },
         "cargo": {
-          "features": ["unstable-features"]
+          "features": [
+            "unstable-features"
+          ]
         },
         "linkedProjects": [
           "./Cargo.toml",
           "./build_system/Cargo.toml",
           {
+            "sysroot_src": "./build/stdlib/library",
             "crates": [
               {
                 "root_module": "./example/mini_core.rs",
-                "edition": "2018",
+                "edition": "2015",
                 "deps": [],
                 "cfg": []
               },
               {
                 "root_module": "./example/mini_core_hello_world.rs",
-                "edition": "2018",
+                "edition": "2015",
                 "deps": [
                   {
                     "crate": 0,
@@ -43,17 +49,6 @@
                 "cfg": []
               },
               {
-                "root_module": "./example/mod_bench.rs",
-                "edition": "2018",
-                "deps": [],
-                "cfg": []
-              }
-            ]
-          },
-          {
-            "sysroot_src": "./build/stdlib/library",
-            "crates": [
-              {
                 "root_module": "./example/std_example.rs",
                 "edition": "2015",
                 "deps": [],
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index ca66ec5c6e9..e5f1896b923 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -42,27 +42,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "cranelift-assembler-x64"
+version = "0.118.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4"
+dependencies = [
+ "cranelift-assembler-x64-meta",
+]
+
+[[package]]
+name = "cranelift-assembler-x64-meta"
+version = "0.118.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b"
+
+[[package]]
 name = "cranelift-bforest"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e15d04a0ce86cb36ead88ad68cf693ffd6cda47052b9e0ac114bc47fd9cd23c4"
+checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-bitset"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c6e3969a7ce267259ce244b7867c5d3bc9e65b0a87e81039588dfdeaede9f34"
+checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab"
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c22032c4cb42558371cf516bb47f26cdad1819d3475c133e93c49f50ebf304e"
+checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41"
 dependencies = [
  "bumpalo",
+ "cranelift-assembler-x64",
  "cranelift-bforest",
  "cranelift-bitset",
  "cranelift-codegen-meta",
@@ -71,7 +87,7 @@ dependencies = [
  "cranelift-entity",
  "cranelift-isle",
  "gimli",
- "hashbrown 0.14.5",
+ "hashbrown",
  "log",
  "regalloc2",
  "rustc-hash",
@@ -82,42 +98,43 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c904bc71c61b27fc57827f4a1379f29de64fe95653b620a3db77d59655eee0b8"
+checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d"
 dependencies = [
+ "cranelift-assembler-x64",
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40180f5497572f644ce88c255480981ae2ec1d7bb4d8e0c0136a13b87a2f2ceb"
+checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e"
 
 [[package]]
 name = "cranelift-control"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d132c6d0bd8a489563472afc171759da0707804a65ece7ceb15a8c6d7dd5ef"
+checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d0d9618275474fbf679dd018ac6e009acbd6ae6850f6a67be33fb3b00b323"
+checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2"
 dependencies = [
  "cranelift-bitset",
 ]
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fac41e16729107393174b0c9e3730fb072866100e1e64e80a1a963b2e484d57"
+checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -127,15 +144,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ca20d576e5070044d0a72a9effc2deacf4d6aa650403189d8ea50126483944d"
+checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e65c42755a719b09662b00c700daaf76cc35d5ace1f5c002ad404b591ff1978"
+checksum = "17f6682f0b193d6b7873cc8e7ed67e8776a8a26f50eeabf88534e9be618b9a03"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -153,9 +170,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b"
+checksum = "ff19784c6de05116e63e6a34791012bd927b2a4eac56233039c46f1b6a4edac8"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -164,9 +181,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7"
+checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -175,9 +192,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.116.1"
+version = "0.118.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aad5a6d3e379493c3f8b35dc61c93d0bf5f27003bbe20614e0200b0ec372ef52"
+checksum = "685e8661a30d1cb69509f589ac643adeee79c5f63c0da316431b9fad29e6d3b4"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -228,12 +245,6 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-
-[[package]]
-name = "hashbrown"
 version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
@@ -248,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
 dependencies = [
  "equivalent",
- "hashbrown 0.15.2",
+ "hashbrown",
 ]
 
 [[package]]
@@ -295,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "crc32fast",
- "hashbrown 0.15.2",
+ "hashbrown",
  "indexmap",
  "memchr",
 ]
@@ -326,7 +337,7 @@ checksum = "145c1c267e14f20fb0f88aa76a1c5ffec42d592c1d28b3cd9148ae35916158d3"
 dependencies = [
  "allocator-api2",
  "bumpalo",
- "hashbrown 0.15.2",
+ "hashbrown",
  "log",
  "rustc-hash",
  "smallvec",
@@ -425,9 +436,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "29.0.1"
+version = "31.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec5e8552e01692e6c2e5293171704fed8abdec79d1a6995a0870ab190e5747d1"
+checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64"
 dependencies = [
  "anyhow",
  "cfg-if",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 670d6f4eef5..08b60de14c1 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.116.0", default-features = false, features = ["std", "unwind", "all-native-arch"] }
-cranelift-frontend = { version = "0.116.0" }
-cranelift-module = { version = "0.116.0" }
-cranelift-native = { version = "0.116.0" }
-cranelift-jit = { version = "0.116.0", optional = true }
-cranelift-object = { version = "0.116.0" }
+cranelift-codegen = { version = "0.118.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
+cranelift-frontend = { version = "0.118.0" }
+cranelift-module = { version = "0.118.0" }
+cranelift-native = { version = "0.118.0" }
+cranelift-jit = { version = "0.118.0", optional = true }
+cranelift-object = { version = "0.118.0" }
 target-lexicon = "0.13"
 gimli = { version = "0.31", default-features = false, features = ["write"] }
 object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
@@ -24,12 +24,12 @@ smallvec = "1.8.1"
 
 [patch.crates-io]
 # Uncomment to use an unreleased version of cranelift
-#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
-#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" }
+#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
+#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" }
 
 # Uncomment to use local checkout of cranelift
 #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 18a840f8a50..28edb5795ce 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -49,13 +49,13 @@ If you want to build the backend manually, you can download it from GitHub and b
 ```bash
 $ git clone https://github.com/rust-lang/rustc_codegen_cranelift
 $ cd rustc_codegen_cranelift
-$ ./y.sh prepare
 $ ./y.sh build
 ```
 
 To run the test suite replace the last command with:
 
 ```bash
+$ ./y.sh prepare # only needs to be run the first time
 $ ./test.sh
 ```
 
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 11f73bdb61f..ba5cc9a29f5 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -91,6 +91,13 @@ impl GitRepo {
 
     fn verify_checksum(&self, dirs: &Dirs) {
         let download_dir = self.download_dir(dirs);
+        if !download_dir.exists() {
+            eprintln!(
+                "Missing directory {download_dir}: Please run ./y.sh prepare to download.",
+                download_dir = download_dir.display(),
+            );
+            std::process::exit(1);
+        }
         let actual_hash = format!("{:016x}", hash_dir(&download_dir));
         if actual_hash != self.content_hash {
             eprintln!(
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index ea7e94c345a..122b541fa35 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,5 +1,4 @@
 use std::ffi::OsStr;
-use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
 
@@ -126,9 +125,9 @@ static PORTABLE_SIMD_SRC: RelPath = RelPath::build("portable-simd");
 
 static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target");
 
-static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests");
+static SYSROOT_TESTS_SRC: RelPath = RelPath::build("sysroot_tests");
 
-static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target");
+static SYSROOT_TESTS: CargoProject = CargoProject::new(&SYSROOT_TESTS_SRC, "sysroot_tests_target");
 
 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
     TestCase::custom("test.rust-random/rand", &|runner| {
@@ -147,28 +146,24 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
             spawn_and_wait(build_cmd);
         }
     }),
-    TestCase::custom("test.libcore", &|runner| {
+    TestCase::custom("test.sysroot", &|runner| {
         apply_patches(
             &runner.dirs,
-            "coretests",
-            &runner.stdlib_source.join("library/coretests"),
-            &LIBCORE_TESTS_SRC.to_path(&runner.dirs),
+            "sysroot_tests",
+            &runner.stdlib_source.join("library"),
+            &SYSROOT_TESTS_SRC.to_path(&runner.dirs),
         );
 
-        let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml");
-        let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock");
-        fs::copy(source_lockfile, target_lockfile).unwrap();
-
-        LIBCORE_TESTS.clean(&runner.dirs);
+        SYSROOT_TESTS.clean(&runner.dirs);
 
         if runner.is_native {
-            let mut test_cmd = LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs);
-            test_cmd.arg("--").arg("-q");
+            let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs);
+            test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]);
             spawn_and_wait(test_cmd);
         } else {
             eprintln!("Cross-Compiling: Not running tests");
-            let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
-            build_cmd.arg("--tests");
+            let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs);
+            build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]);
             spawn_and_wait(build_cmd);
         }
     }),
@@ -330,10 +325,8 @@ impl<'a> TestRunner<'a> {
         target_compiler.rustflags.extend(rustflags_from_env("RUSTFLAGS"));
         target_compiler.rustdocflags.extend(rustflags_from_env("RUSTDOCFLAGS"));
 
-        let jit_supported = use_unstable_features
-            && is_native
-            && target_compiler.triple.contains("x86_64")
-            && !target_compiler.triple.contains("windows");
+        let jit_supported =
+            use_unstable_features && is_native && !target_compiler.triple.contains("windows");
 
         Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
     }
@@ -374,21 +367,7 @@ impl<'a> TestRunner<'a> {
                 TestCaseCmd::JitBin { source, args } => {
                     let mut jit_cmd = self.rustc_command([
                         "-Zunstable-options",
-                        "-Cllvm-args=mode=jit",
-                        "-Cprefer-dynamic",
-                        source,
-                        "--cfg",
-                        "jit",
-                    ]);
-                    if !args.is_empty() {
-                        jit_cmd.env("CG_CLIF_JIT_ARGS", args);
-                    }
-                    spawn_and_wait(jit_cmd);
-
-                    eprintln!("[JIT-lazy] {testname}");
-                    let mut jit_cmd = self.rustc_command([
-                        "-Zunstable-options",
-                        "-Cllvm-args=mode=jit-lazy",
+                        "-Cllvm-args=jit-mode",
                         "-Cprefer-dynamic",
                         source,
                         "--cfg",
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index f578cbef35e..714414fe8d6 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -35,6 +35,6 @@ aot.raw-dylib
 
 testsuite.extended_sysroot
 test.rust-random/rand
-test.libcore
+test.sysroot
 test.regex
 test.portable-simd
diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md
index 135a51ce392..dbe36109f83 100644
--- a/compiler/rustc_codegen_cranelift/docs/usage.md
+++ b/compiler/rustc_codegen_cranelift/docs/usage.md
@@ -38,14 +38,7 @@ $ $cg_clif_dir/dist/cargo-clif jit
 or
 
 ```bash
-$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
-```
-
-There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
-first called.
-
-```bash
-$ $cg_clif_dir/dist/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs
 ```
 
 ## Shell
@@ -54,7 +47,7 @@ These are a few functions that allow you to easily run rust code from the shell
 
 ```bash
 function jit_naked() {
-    echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic
+    echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic
 }
 
 function jit() {
diff --git a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
index 25bfe542d22..de9a3d550ec 100644
--- a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
+++ b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs
@@ -6,16 +6,25 @@
 #![feature(gen_blocks)]
 
 fn foo() -> impl Iterator<Item = u32> {
-    gen { yield 42; for x in 3..6 { yield x } }
+    gen {
+        yield 42;
+        for x in 3..6 {
+            yield x
+        }
+    }
 }
 
 fn moved() -> impl Iterator<Item = u32> {
     let mut x = "foo".to_string();
     gen move {
         yield 42;
-        if x == "foo" { return }
+        if x == "foo" {
+            return;
+        }
         x.clear();
-        for x in 3..6 { yield x }
+        for x in 3..6 {
+            yield x
+        }
     }
 }
 
@@ -32,5 +41,4 @@ fn main() {
     let mut iter = moved();
     assert_eq!(iter.next(), Some(42));
     assert_eq!(iter.next(), None);
-
 }
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch
index 4a06dc3f7ef..16c8488acdb 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch
@@ -10,20 +10,20 @@ Cranelift doesn't support them yet
  library/core/tests/atomic.rs          |  4 ---
  4 files changed, 4 insertions(+), 50 deletions(-)
 
-diff --git a/tests/lib.rs b/tests/lib.rs
+diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs
 index 1e336bf..35e6f54 100644
---- a/tests/lib.rs
-+++ b/tests/lib.rs
+--- a/coretests/tests/lib.rs
++++ b/coretests/tests/lib.rs
 @@ -2,5 +2,4 @@
  // tidy-alphabetical-start
 -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
  #![cfg_attr(test, feature(cfg_match))]
  #![feature(alloc_layout_extra)]
  #![feature(array_chunks)]
-diff --git a/tests/atomic.rs b/tests/atomic.rs
+diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
 index b735957..ea728b6 100644
---- a/tests/atomic.rs
-+++ b/tests/atomic.rs
+--- a/coretests/tests/atomic.rs
++++ b/coretests/tests/atomic.rs
 @@ -185,10 +185,6 @@ fn atomic_alignment() {
      assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
      #[cfg(target_has_atomic = "64")]
diff --git a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch
deleted file mode 100644
index f5ae66c0eb1..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Fri, 3 Dec 2021 12:16:30 +0100
-Subject: [PATCH] Disable long running tests
-
----
- library/core/tests/slice.rs | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/tests/slice.rs b/tests/slice.rs
-index 8402833..84592e0 100644
---- a/tests/slice.rs
-+++ b/tests/slice.rs
-@@ -1809,6 +1809,7 @@ fn sort_unstable() {
-     }
- }
- 
-+/*
- #[test]
- #[cfg(not(target_arch = "wasm32"))]
- #[cfg_attr(miri, ignore)] // Miri is too slow
-@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
-     v.select_nth_unstable(0);
-     assert!(v == [0xDEADBEEF]);
- }
-+*/
- 
- #[test]
- #[should_panic(expected = "index 0 greater than length of slice")]
-@@ -2462,6 +2462,7 @@ take_tests! {
- #[cfg(not(miri))] // unused in Miri
- const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
- 
-+/*
- // can't be a constant due to const mutability rules
- #[cfg(not(miri))] // unused in Miri
- macro_rules! empty_max_mut {
-@@ -2485,6 +2486,7 @@ take_tests! {
-     (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
-     (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
- }
-+*/
- 
- #[test]
- fn test_slice_from_ptr_range() {
--- 
-2.26.2.7.g19db9cfb68
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch
new file mode 100644
index 00000000000..357b8d306cf
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0028-sysroot_tests-Disable-long-running-tests.patch
@@ -0,0 +1,105 @@
+From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Fri, 3 Dec 2021 12:16:30 +0100
+Subject: [PATCH] Disable long running tests
+
+---
+ library/coretests/tests/slice.rs | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs
+index 8402833..84592e0 100644
+--- a/coretests/tests/slice.rs
++++ b/coretests/tests/slice.rs
+@@ -1809,6 +1809,7 @@ fn sort_unstable() {
+     }
+ }
+ 
++/*
+ #[test]
+ #[cfg(not(target_arch = "wasm32"))]
+ #[cfg_attr(miri, ignore)] // Miri is too slow
+@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
+     v.select_nth_unstable(0);
+     assert!(v == [0xDEADBEEF]);
+ }
++*/
+ 
+ #[test]
+ #[should_panic(expected = "index 0 greater than length of slice")]
+@@ -2462,6 +2462,7 @@ take_tests! {
+ #[cfg(not(miri))] // unused in Miri
+ const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
+ 
++/*
+ // can't be a constant due to const mutability rules
+ #[cfg(not(miri))] // unused in Miri
+ macro_rules! empty_max_mut {
+@@ -2485,6 +2486,7 @@ take_tests! {
+     (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
+     (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
+ }
++*/
+ 
+ #[test]
+ fn test_slice_from_ptr_range() {
+diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs
+index d321f8d..8b2040a 100644
+--- a/alloctests/tests/sort/tests.rs
++++ b/alloctests/tests/sort/tests.rs
+@@ -1,3 +1,5 @@
++#![cfg(any())]
++
+ use std::cell::Cell;
+ use std::cmp::Ordering;
+ use std::fmt::Debug;
+diff --git a/alloctests/tests/str.rs b/alloctests/tests/str.rs
+index 906fa2d..b82fa99 100644
+--- a/alloctests/tests/str.rs
++++ b/alloctests/tests/str.rs
+@@ -2234,7 +2234,7 @@ fn const_str_ptr() {
+     const C: *const u8 = B as *const u8;
+ 
+     // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
+-    #[cfg(not(miri))]
++    #[cfg(any())]
+     {
+         let foo = &A as *const u8;
+         assert_eq!(foo, C);
+diff --git a/alloctests/tests/task.rs b/alloctests/tests/task.rs
+index 390dec1..87df6e6 100644
+--- a/alloctests/tests/task.rs
++++ b/alloctests/tests/task.rs
+@@ -4,7 +4,7 @@ use alloc::task::{LocalWake, Wake};
+ use core::task::{LocalWaker, Waker};
+ 
+ #[test]
+-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
+ fn test_waker_will_wake_clone() {
+     struct NoopWaker;
+ 
+@@ -20,7 +20,7 @@ fn test_waker_will_wake_clone() {
+ }
+ 
+ #[test]
+-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
+ fn test_local_waker_will_wake_clone() {
+     struct NoopWaker;
+ 
+diff --git a/alloctests/tests/vec.rs b/alloctests/tests/vec.rs
+index f430d97..cfbd3cb 100644
+--- a/alloctests/tests/vec.rs
++++ b/alloctests/tests/vec.rs
+@@ -762,6 +762,7 @@ fn test_drain_inclusive_range() {
+ }
+ 
+ #[test]
++#[ignore]
+ fn test_drain_max_vec_size() {
+     let mut v = Vec::<()>::with_capacity(usize::MAX);
+     unsafe {
+-- 
+2.26.2.7.g19db9cfb68
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
deleted file mode 100644
index 754025ff49d..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001
-From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
-Date: Fri, 9 Aug 2024 15:44:51 +0000
-Subject: [PATCH] Disable f16 and f128 in compiler-builtins
-
----
- library/liballoc/Cargo.toml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml
-index 7165c3e48af..968552ad435 100644
---- a/library/alloc/Cargo.toml
-+++ b/library/alloc/Cargo.toml
-@@ -11,7 +11,7 @@ test = { path = "../test" }
- bench = false
- 
- [dependencies]
- core = { path = "../core", public = true }
--compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] }
- 
- [features]
- compiler-builtins-mem = ['compiler_builtins/mem']
--- 
-2.34.1
-
diff --git a/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml b/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml
deleted file mode 100644
index af8f28a193b..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/coretests-lock.toml
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "coretests"
-version = "0.0.0"
-dependencies = [
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-
-[[package]]
-name = "rand_xorshift"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
-dependencies = [
- "rand_core",
-]
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 481903c6afb..ceff15b1180 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2025-02-15"
+channel = "nightly-2025-03-30"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
 profile = "minimal"
diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml
index f31fa9c76ab..35c92663eb9 100644
--- a/compiler/rustc_codegen_cranelift/rustfmt.toml
+++ b/compiler/rustc_codegen_cranelift/rustfmt.toml
@@ -1,7 +1,3 @@
-ignore = [
-    "example/gen_block_iterate.rs", # uses edition 2024
-]
-
 # Matches rustfmt.toml of rustc
 style_edition = "2024"
 use_small_heuristics = "Max"
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
index ebbb6879610..e6c63bf5e65 100644
--- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
@@ -50,19 +50,7 @@ fn main() {
                 .chain([
                     "--".to_string(),
                     "-Zunstable-options".to_string(),
-                    "-Cllvm-args=mode=jit".to_string(),
-                ])
-                .collect()
-        }
-        Some("lazy-jit") => {
-            rustflags.push("-Cprefer-dynamic".to_owned());
-            args.remove(0);
-            IntoIterator::into_iter(["rustc".to_string()])
-                .chain(args)
-                .chain([
-                    "--".to_string(),
-                    "-Zunstable-options".to_string(),
-                    "-Cllvm-args=mode=jit-lazy".to_string(),
+                    "-Cllvm-args=jit-mode".to_string(),
                 ])
                 .collect()
         }
diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
index 0252d5b3340..4595063c032 100755
--- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
@@ -4,7 +4,7 @@
 pushd $(dirname "$0")/../
 RUSTC="$(pwd)/dist/rustc-clif"
 popd
-PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
+PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic $0
 #*/
 
 //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
index 355282911c2..152c243aa6a 100755
--- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
@@ -64,7 +64,7 @@ case $1 in
         cg_clif=$(pwd)
         pushd ../rust
         git fetch origin master
-        git checkout "$RUST_VERS"
+        git -c advice.detachedHead=false checkout "$RUST_VERS"
         "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust
         popd
         git merge sync_from_rust -m "Sync from rust $RUST_VERS"
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 54f6baff4fe..ca6426f2ba9 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -43,8 +43,31 @@ verbose-tests = false
 # disabled bootstrap will crash trying to copy llvm tools for the bootstrap
 # compiler.
 llvm-tools = false
+std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"]
 
 EOF
+
+cat <<EOF | git apply -
+diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
+index cf4ef4ee310..fe78560fcaf 100644
+--- a/src/bootstrap/src/core/config/config.rs
++++ b/src/bootstrap/src/core/config/config.rs
+@@ -3138,13 +3138,6 @@ fn parse_download_ci_llvm(
+                     );
+                 }
+
+-                if b && self.is_running_on_ci {
+-                    // On CI, we must always rebuild LLVM if there were any modifications to it
+-                    panic!(
+-                        "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
+-                    );
+-                }
+-
+                 // If download-ci-llvm=true we also want to check that CI llvm is available
+                 b && llvm::is_ci_llvm_available_for_target(self, asserts)
+             }
+EOF
+
 popd
 
 # Allow the testsuite to use llvm tools
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 55230a0b598..95a4302b5e4 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -27,7 +27,6 @@ done
 git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
 git checkout -- tests/ui/proc-macro/pretty-print-hack/
 git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs
-rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
 
 # missing features
 # ================
@@ -57,7 +56,6 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't
 rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
 rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes
 rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo
-rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported
 
 # requires LTO
 rm -r tests/run-make/cdylib
@@ -120,6 +118,7 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
 rm tests/ui/consts/issue-33537.rs # same
 rm tests/ui/consts/const-mut-refs-crate.rs # same
 rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift
+rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures
 
 # doesn't work due to the way the rustc test suite is invoked.
 # should work when using ./x.py test the way it is intended
@@ -136,7 +135,6 @@ rm -r tests/run-make/incr-add-rust-src-component
 # ============
 rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
 rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
-rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold
 
 # bugs in the test suite
 # ======================
@@ -150,48 +148,8 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same
 rm tests/ui/process/process-panic-after-fork.rs # same
 
 cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist
-cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/
 
-# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by
-# rustdoc-clif
 cat <<EOF | git apply -
-diff --git a/tests/run-make/tools.mk b/tests/run-make/tools.mk
-index ea06b620c4c..b969d0009c6 100644
---- a/tests/run-make/tools.mk
-+++ b/tests/run-make/tools.mk
-@@ -9,7 +9,7 @@ RUSTC_ORIGINAL := \$(RUSTC)
- BARE_RUSTC := \$(HOST_RPATH_ENV) '\$(RUSTC)'
- BARE_RUSTDOC := \$(HOST_RPATH_ENV) '\$(RUSTDOC)'
- RUSTC := \$(BARE_RUSTC) --out-dir \$(TMPDIR) -L \$(TMPDIR) \$(RUSTFLAGS) -Ainternal_features
--RUSTDOC := \$(BARE_RUSTDOC) -L \$(TARGET_RPATH_DIR)
-+RUSTDOC := \$(BARE_RUSTDOC)
- ifdef RUSTC_LINKER
- RUSTC := \$(RUSTC) -Clinker='\$(RUSTC_LINKER)'
- RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)'
-diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
-index 9607ff02f96..b7d97caf9a2 100644
---- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
-+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
-@@ -34,7 +34,6 @@ pub fn bare() -> Self {
-     #[track_caller]
-     pub fn new() -> Self {
-         let mut cmd = setup_common();
--        cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR"));
-         Self { cmd }
-     }
-
-diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
-index e7ae773ffa1d3..04bc2d7787da7 100644
---- a/src/tools/compiletest/src/runtest/run_make.rs
-+++ b/src/tools/compiletest/src/runtest/run_make.rs
-@@ -329,7 +329,6 @@ impl TestCx<'_> {
-             .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
-             .arg("--edition=2021")
-             .arg(&self.testpaths.file.join("rmake.rs"))
--            .arg("-Cprefer-dynamic")
-             // Provide necessary library search paths for rustc.
-             .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
-
 diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs
 index 30387af428c..f7895b12961 100644
 --- a/tests/run-make/linker-warning/rmake.rs
@@ -205,7 +163,19 @@ index 30387af428c..f7895b12961 100644
                  regex::escape(run_make_support::build_root().to_str().unwrap()),
                  "/build-root",
              )
-             .run();
+             .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"")
+diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
+index 073116933bd..c3e4578204d 100644
+--- a/src/tools/compiletest/src/runtest/run_make.rs
++++ b/src/tools/compiletest/src/runtest/run_make.rs
+@@ -109,7 +109,6 @@ pub(super) fn run_rmake_test(&self) {
+             // library or compiler features. Here, we force the stage 0 rustc to consider itself as
+             // a stable-channel compiler via \`RUSTC_BOOTSTRAP=-1\` to prevent *any* unstable
+             // library/compiler usages, even if stage 0 rustc is *actually* a nightly rustc.
+-            .env("RUSTC_BOOTSTRAP", "-1")
+             .arg("-o")
+             .arg(&recipe_bin)
+             // Specify library search paths for \`run_make_support\`.
 EOF
 
 echo "[TEST] rustc test suite"
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 125a9201831..adaa754491e 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>(
                     let to_ty = fx.monomorphize(to_ty);
 
                     fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
-                        ty.builtin_deref(true)
-                            .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
+                        ty.builtin_deref(true).is_some_and(|pointee_ty| {
+                            fx.tcx
+                                .type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized())
+                        })
                     }
 
                     if is_wide_ptr(fx, from_ty) {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 766278d8718..abe2972ba0c 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
         },
         ty::FnPtr(..) => pointer_ty(tcx),
         ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
-            if has_ptr_meta(tcx, *pointee_ty) {
+            if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
                 return None;
             } else {
                 pointer_ty(tcx)
@@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>(
             (clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?)
         }
         ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
-            if has_ptr_meta(tcx, *pointee_ty) {
+            if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
                 (pointer_ty(tcx), pointer_ty(tcx))
             } else {
                 return None;
@@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>(
     })
 }
 
-/// Is a pointer to this type a wide ptr?
-pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) {
-        return false;
-    }
-
-    let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized());
-    match tail.kind() {
-        ty::Foreign(..) => false,
-        ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
-        _ => bug!("unexpected unsized tail: {:?}", tail),
-    }
-}
-
 pub(crate) fn codegen_icmp_imm(
     fx: &mut FunctionCx<'_, '_, '_>,
     intcc: IntCC,
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index d784f6e9d9e..d328b33a704 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -1,21 +1,10 @@
-/// The mode to use for compilation.
-#[derive(Copy, Clone, Debug)]
-pub enum CodegenMode {
-    /// AOT compile the crate. This is the default.
-    Aot,
-    /// JIT compile and execute the crate.
-    Jit,
-    /// JIT compile and execute the crate, but only compile functions the first time they are used.
-    JitLazy,
-}
-
 /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
 #[derive(Clone, Debug)]
 pub struct BackendConfig {
     /// Should the crate be AOT compiled or JIT executed.
     ///
-    /// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`.
-    pub codegen_mode: CodegenMode,
+    /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`.
+    pub jit_mode: bool,
 
     /// When JIT mode is enable pass these arguments to the program.
     ///
@@ -27,7 +16,7 @@ impl BackendConfig {
     /// Parse the configuration passed in using `-Cllvm-args`.
     pub fn from_opts(opts: &[String]) -> Result<Self, String> {
         let mut config = BackendConfig {
-            codegen_mode: CodegenMode::Aot,
+            jit_mode: false,
             jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
                 Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
                 Err(std::env::VarError::NotPresent) => vec![],
@@ -43,20 +32,9 @@ impl BackendConfig {
                 // testing cg_clif.
                 continue;
             }
-            if let Some((name, value)) = opt.split_once('=') {
-                match name {
-                    "mode" => {
-                        config.codegen_mode = match value {
-                            "aot" => CodegenMode::Aot,
-                            "jit" => CodegenMode::Jit,
-                            "jit-lazy" => CodegenMode::JitLazy,
-                            _ => return Err(format!("Unknown codegen mode `{}`", value)),
-                        };
-                    }
-                    _ => return Err(format!("Unknown option `{}`", name)),
-                }
-            } else {
-                return Err(format!("Invalid option `{}`", opt));
+            match &**opt {
+                "jit-mode" => config.jit_mode = true,
+                _ => return Err(format!("Unknown option `{}`", opt)),
             }
         }
 
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
index 017d7784dc0..25b922c8be4 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta};
+use crate::{DebugContext, FullyMonomorphizedLayoutCx};
 
 #[derive(Default)]
 pub(crate) struct TypeDebugContext<'tcx> {
@@ -129,7 +129,7 @@ impl DebugContext {
 
         let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true);
 
-        if !has_ptr_meta(tcx, ptr_type) {
+        if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) {
             let pointer_type_id =
                 self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type);
             let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id);
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index a52b18573b1..444dc441286 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -103,12 +103,14 @@ impl OngoingCodegen {
                             ("o", &module_regular.object.as_ref().unwrap()),
                             ("asm.o", &module_global_asm.object.as_ref().unwrap()),
                         ],
+                        &[],
                     )
                 } else {
                     rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
                         sess,
                         &module_regular.name,
                         &[("o", &module_regular.object.as_ref().unwrap())],
+                        &[],
                     )
                 };
                 if let Some((work_product_id, work_product)) = work_product {
@@ -329,7 +331,7 @@ fn produce_final_output_artifacts(
 }
 
 fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
-    let isa = crate::build_isa(sess);
+    let isa = crate::build_isa(sess, false);
 
     let mut builder =
         ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
@@ -381,6 +383,7 @@ fn emit_cgu(
             bytecode: None,
             assembly: None,
             llvm_ir: None,
+            links_from_incr_cache: Vec::new(),
         }),
         existing_work_product: None,
     })
@@ -437,6 +440,7 @@ fn emit_module(
         bytecode: None,
         assembly: None,
         llvm_ir: None,
+        links_from_incr_cache: Vec::new(),
     })
 }
 
@@ -460,22 +464,23 @@ fn reuse_workproduct_for_cgu(
             err
         ));
     }
+
     let obj_out_global_asm =
         crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm");
-    let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") {
+    let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") {
         let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o);
         if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm)
         {
             return Err(format!(
                 "unable to copy {} to {}: {}",
-                source_file_regular.display(),
-                obj_out_regular.display(),
+                source_file_global_asm.display(),
+                obj_out_global_asm.display(),
                 err
             ));
         }
-        true
+        Some(source_file_global_asm)
     } else {
-        false
+        None
     };
 
     Ok(ModuleCodegenResult {
@@ -487,8 +492,9 @@ fn reuse_workproduct_for_cgu(
             bytecode: None,
             assembly: None,
             llvm_ir: None,
+            links_from_incr_cache: vec![source_file_regular],
         },
-        module_global_asm: has_global_asm.then(|| CompiledModule {
+        module_global_asm: source_file_global_asm.map(|source_file| CompiledModule {
             name: cgu.name().to_string(),
             kind: ModuleKind::Regular,
             object: Some(obj_out_global_asm),
@@ -496,6 +502,7 @@ fn reuse_workproduct_for_cgu(
             bytecode: None,
             assembly: None,
             llvm_ir: None,
+            links_from_incr_cache: vec![source_file],
         }),
         existing_work_product: Some((cgu.work_product_id(), work_product)),
     })
@@ -637,6 +644,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled
         bytecode: None,
         assembly: None,
         llvm_ir: None,
+        links_from_incr_cache: Vec::new(),
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 57c88f4b0f9..41f8bb9161c 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -1,75 +1,27 @@
 //! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object
 //! files.
 
-use std::cell::RefCell;
 use std::ffi::CString;
 use std::os::raw::{c_char, c_int};
-use std::sync::{Mutex, OnceLock, mpsc};
 
-use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
 use cranelift_jit::{JITBuilder, JITModule};
 use rustc_codegen_ssa::CrateInfo;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_session::Session;
 use rustc_span::sym;
 
+use crate::CodegenCx;
 use crate::debuginfo::TypeDebugContext;
 use crate::prelude::*;
 use crate::unwind_module::UnwindModule;
-use crate::{CodegenCx, CodegenMode};
 
-struct JitState {
-    jit_module: UnwindModule<JITModule>,
-}
-
-thread_local! {
-    static LAZY_JIT_STATE: RefCell<Option<JitState>> = const { RefCell::new(None) };
-}
-
-/// The Sender owned by the rustc thread
-static GLOBAL_MESSAGE_SENDER: OnceLock<Mutex<mpsc::Sender<UnsafeMessage>>> = OnceLock::new();
-
-/// A message that is sent from the jitted runtime to the rustc thread.
-/// Senders are responsible for upholding `Send` semantics.
-enum UnsafeMessage {
-    /// Request that the specified `Instance` be lazily jitted.
-    ///
-    /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
-    /// this message is sent.
-    JitFn {
-        instance_ptr: *const Instance<'static>,
-        trampoline_ptr: *const u8,
-        tx: mpsc::Sender<*const u8>,
-    },
-}
-unsafe impl Send for UnsafeMessage {}
-
-impl UnsafeMessage {
-    /// Send the message.
-    fn send(self) {
-        thread_local! {
-            /// The Sender owned by the local thread
-            static LOCAL_MESSAGE_SENDER: mpsc::Sender<UnsafeMessage> =
-                GLOBAL_MESSAGE_SENDER
-                    .get().unwrap()
-                    .lock().unwrap()
-                    .clone();
-        }
-        LOCAL_MESSAGE_SENDER.with(|sender| {
-            sender.send(self).expect("rustc thread hung up before lazy JIT request was sent")
-        })
-    }
-}
-
-fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) {
+fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
     let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
 
-    let isa = crate::build_isa(tcx.sess);
+    let isa = crate::build_isa(tcx.sess, true);
     let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
-    jit_builder.hotswap(hotswap);
     crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
     jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
-    jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
     let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
 
     let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
@@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>
     (jit_module, cx)
 }
 
-pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<String>) -> ! {
+pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
     if !tcx.sess.opts.output_types.should_codegen() {
         tcx.dcx().fatal("JIT mode doesn't work with `cargo check`");
     }
@@ -88,8 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
         tcx.dcx().fatal("can't jit non-executable crate");
     }
 
-    let (mut jit_module, mut cx) =
-        create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy));
+    let (mut jit_module, mut cx) = create_jit_module(tcx);
     let mut cached_context = Context::new();
 
     let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
@@ -105,21 +56,15 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
         super::predefine_mono_items(tcx, &mut jit_module, &mono_items);
         for (mono_item, _) in mono_items {
             match mono_item {
-                MonoItem::Fn(inst) => match codegen_mode {
-                    CodegenMode::Aot => unreachable!(),
-                    CodegenMode::Jit => {
-                        codegen_and_compile_fn(
-                            tcx,
-                            &mut cx,
-                            &mut cached_context,
-                            &mut jit_module,
-                            inst,
-                        );
-                    }
-                    CodegenMode::JitLazy => {
-                        codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
-                    }
-                },
+                MonoItem::Fn(inst) => {
+                    codegen_and_compile_fn(
+                        tcx,
+                        &mut cx,
+                        &mut cached_context,
+                        &mut jit_module,
+                        inst,
+                    );
+                }
                 MonoItem::Static(def_id) => {
                     crate::constant::codegen_static(tcx, &mut jit_module, def_id);
                 }
@@ -161,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
     let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
     let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
 
-    LAZY_JIT_STATE.with(|lazy_jit_state| {
-        let mut lazy_jit_state = lazy_jit_state.borrow_mut();
-        assert!(lazy_jit_state.is_none());
-        *lazy_jit_state = Some(JitState { jit_module });
-    });
-
     let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
         unsafe { ::std::mem::transmute(finalized_start) };
 
-    let (tx, rx) = mpsc::channel();
-    GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
-
-    // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
-    // (eg to lazily JIT further functions as required)
-    std::thread::spawn(move || {
-        let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
+    let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
 
-        // Push a null pointer as a terminating argument. This is required by POSIX and
-        // useful as some dynamic linkers use it as a marker to jump over.
-        argv.push(std::ptr::null());
+    // Push a null pointer as a terminating argument. This is required by POSIX and
+    // useful as some dynamic linkers use it as a marker to jump over.
+    argv.push(std::ptr::null());
 
-        let ret = f(args.len() as c_int, argv.as_ptr());
-        std::process::exit(ret);
-    });
-
-    // Handle messages
-    loop {
-        match rx.recv().unwrap() {
-            // lazy JIT compilation request - compile requested instance and return pointer to result
-            UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
-                tx.send(jit_fn(instance_ptr, trampoline_ptr))
-                    .expect("jitted runtime hung up before response to lazy JIT request was sent");
-            }
-        }
-    }
+    let ret = f(args.len() as c_int, argv.as_ptr());
+    std::process::exit(ret);
 }
 
 pub(crate) fn codegen_and_compile_fn<'tcx>(
@@ -227,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
     });
 }
 
-extern "C" fn clif_jit_fn(
-    instance_ptr: *const Instance<'static>,
-    trampoline_ptr: *const u8,
-) -> *const u8 {
-    // send the JIT request to the rustc thread, with a channel for the response
-    let (tx, rx) = mpsc::channel();
-    UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send();
-
-    // block on JIT compilation result
-    rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
-}
-
-fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
-    rustc_middle::ty::tls::with(|tcx| {
-        // lift is used to ensure the correct lifetime for instance.
-        let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
-
-        LAZY_JIT_STATE.with(|lazy_jit_state| {
-            let mut lazy_jit_state = lazy_jit_state.borrow_mut();
-            let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
-            let jit_module = &mut lazy_jit_state.jit_module;
-
-            let name = tcx.symbol_name(instance).name;
-            let sig = crate::abi::get_function_sig(
-                tcx,
-                jit_module.target_config().default_call_conv,
-                instance,
-            );
-            let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
-
-            let current_ptr = jit_module.module.read_got_entry(func_id);
-
-            // If the function's GOT entry has already been updated to point at something other
-            // than the shim trampoline, don't re-jit but just return the new pointer instead.
-            // This does not need synchronization as this code is executed only by a sole rustc
-            // thread.
-            if current_ptr != trampoline_ptr {
-                return current_ptr;
-            }
-
-            jit_module.module.prepare_for_function_redefine(func_id).unwrap();
-
-            let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
-            codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
-
-            assert!(cx.global_asm.is_empty());
-            jit_module.finalize_definitions();
-            jit_module.module.get_finalized_function(func_id)
-        })
-    })
-}
-
 fn dep_symbol_lookup_fn(
     sess: &Session,
     crate_info: CrateInfo,
@@ -326,57 +195,3 @@ fn dep_symbol_lookup_fn(
         None
     })
 }
-
-fn codegen_shim<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cached_context: &mut Context,
-    module: &mut UnwindModule<JITModule>,
-    inst: Instance<'tcx>,
-) {
-    let pointer_type = module.target_config().pointer_type();
-
-    let name = tcx.symbol_name(inst).name;
-    let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
-    let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
-
-    let instance_ptr = Box::into_raw(Box::new(inst));
-
-    let jit_fn = module
-        .declare_function(
-            "__clif_jit_fn",
-            Linkage::Import,
-            &Signature {
-                call_conv: module.target_config().default_call_conv,
-                params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
-                returns: vec![AbiParam::new(pointer_type)],
-            },
-        )
-        .unwrap();
-
-    let context = cached_context;
-    context.clear();
-    let trampoline = &mut context.func;
-    trampoline.signature = sig.clone();
-
-    let mut builder_ctx = FunctionBuilderContext::new();
-    let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
-
-    let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
-    let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
-    let sig_ref = trampoline_builder.func.import_signature(sig);
-
-    let entry_block = trampoline_builder.create_block();
-    trampoline_builder.append_block_params_for_function_params(entry_block);
-    let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();
-
-    trampoline_builder.switch_to_block(entry_block);
-    let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
-    let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
-    let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
-    let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
-    let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
-    let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
-    trampoline_builder.ins().return_(&ret_vals);
-
-    module.define_function(func_id, context).unwrap();
-}
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 310b226814d..fbc33a64285 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -612,6 +612,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             generated_asm.push_str(".att_syntax\n");
         }
 
+        if self.arch == InlineAsmArch::AArch64 {
+            for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
+                if feature.name == sym::neon {
+                    continue;
+                }
+                writeln!(generated_asm, ".arch_extension {}", feature.name).unwrap();
+            }
+        }
+
         // The actual inline asm
         for piece in self.template {
             match piece {
@@ -652,6 +661,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
                                         .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
                                         .unwrap(),
                                 },
+                                InlineAsmArch::AArch64 => match reg {
+                                    InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+                                        // rustc emits v0 rather than q0
+                                        reg.emit(
+                                            &mut generated_asm,
+                                            InlineAsmArch::AArch64,
+                                            Some(modifier.unwrap_or('q')),
+                                        )
+                                        .unwrap()
+                                    }
+                                    _ => reg
+                                        .emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier)
+                                        .unwrap(),
+                                },
                                 _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
                             }
                         }
@@ -665,6 +688,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         }
         generated_asm.push('\n');
 
+        if self.arch == InlineAsmArch::AArch64 {
+            for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
+                if feature.name == sym::neon {
+                    continue;
+                }
+                writeln!(generated_asm, ".arch_extension no{}", feature.name).unwrap();
+            }
+        }
+
         if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
             generated_asm.push_str(".intel_syntax noprefix\n");
         }
@@ -809,7 +841,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             }
             InlineAsmArch::AArch64 => {
                 generated_asm.push_str("    str ");
-                reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
+                match reg {
+                    InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+                        // rustc emits v0 rather than q0
+                        reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
+                    }
+                    _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
+                }
                 writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
             }
             InlineAsmArch::RiscV64 => {
@@ -851,7 +889,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             }
             InlineAsmArch::AArch64 => {
                 generated_asm.push_str("    ldr ");
-                reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
+                match reg {
+                    InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
+                        // rustc emits v0 rather than q0
+                        reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
+                    }
+                    _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
+                }
                 writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
             }
             InlineAsmArch::RiscV64 => {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 720a0d8fbf5..eb0dfbb69c3 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
             );
         }
 
+        "llvm.fptosi.sat.v4i32.v4f32" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane)
+            });
+        }
+
         _ => {
             fx.tcx
                 .dcx()
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index 4c59c81296b..387c87d123a 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -1,5 +1,9 @@
 //! Emulate AArch64 LLVM intrinsics
 
+use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_target::asm::*;
+
+use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner};
 use crate::intrinsics::*;
 use crate::prelude::*;
 
@@ -17,7 +21,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
             fx.bcx.ins().fence();
         }
 
-        "llvm.aarch64.neon.ld1x4.v16i8.p0i8" => {
+        "llvm.aarch64.neon.ld1x4.v16i8.p0" => {
             intrinsic_args!(fx, args => (ptr); intrinsic);
 
             let ptr = ptr.load_scalar(fx);
@@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
             });
         }
 
+        "llvm.aarch64.neon.fcvtns.v4i32.v4f32" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            // Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest
+
+            let a_ptr = a.force_stack(fx).0.get_addr(fx);
+            let res_place = CPlace::new_stack_slot(fx, ret.layout());
+            let res_ptr = res_place.to_ptr().get_addr(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String(
+                    "ldr     q0, [x0]
+                     fcvtns  v0.4s, v0.4s
+                     str     q0, [x1]"
+                        .into(),
+                )],
+                &[
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x0,
+                        )),
+                        value: a_ptr,
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x1,
+                        )),
+                        value: res_ptr,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK,
+            );
+            let res = res_place.to_cvalue(fx);
+            ret.write_cvalue_transmute(fx, res);
+        }
+
+        "llvm.aarch64.neon.frecpe.v4f32" => {
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            let a_ptr = a.force_stack(fx).0.get_addr(fx);
+            let res_place = CPlace::new_stack_slot(fx, ret.layout());
+            let res_ptr = res_place.to_ptr().get_addr(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String(
+                    "ldr     q0, [x0]
+                     frecpe  v0.4s, v0.4s
+                     str     q0, [x1]"
+                        .into(),
+                )],
+                &[
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x0,
+                        )),
+                        value: a_ptr,
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x1,
+                        )),
+                        value: res_ptr,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK,
+            );
+            let res = res_place.to_cvalue(fx);
+            ret.write_cvalue_transmute(fx, res);
+        }
+
+        "llvm.aarch64.neon.frecps.v4f32" => {
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            let a_ptr = a.force_stack(fx).0.get_addr(fx);
+            let b_ptr = b.force_stack(fx).0.get_addr(fx);
+            let res_place = CPlace::new_stack_slot(fx, ret.layout());
+            let res_ptr = res_place.to_ptr().get_addr(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String(
+                    "ldr     q0, [x0]
+                     ldr     q1, [x1]
+                     frecps  v0.4s, v0.4s, v1.4s
+                     str     q0, [x2]"
+                        .into(),
+                )],
+                &[
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x0,
+                        )),
+                        value: a_ptr,
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x1,
+                        )),
+                        value: b_ptr,
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
+                            AArch64InlineAsmReg::x2,
+                        )),
+                        value: res_ptr,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK,
+            );
+            let res = res_place.to_cvalue(fx);
+            ret.write_cvalue_transmute(fx, res);
+        }
+
         _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v")
             || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") =>
         {
@@ -134,7 +253,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
             }
             let res = CValue::by_val(
                 fx.bcx.ins().uextend(types::I32, res_val),
-                fx.layout_of(fx.tcx.types.u32),
+                fx.layout_of(fx.tcx.types.i32),
             );
             ret.write_cvalue(fx, res);
         }
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index ab3386a9b4c..e7afaff3b42 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -42,7 +42,6 @@ use std::sync::Arc;
 use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings::{self, Configurable};
 use rustc_codegen_ssa::CodegenResults;
-use rustc_codegen_ssa::back::versioned_llvm_target;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -214,15 +213,14 @@ impl CodegenBackend for CraneliftCodegenBackend {
             BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
                 .unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
         });
-        match config.codegen_mode {
-            CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module),
-            CodegenMode::Jit | CodegenMode::JitLazy => {
-                #[cfg(feature = "jit")]
-                driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args);
-
-                #[cfg(not(feature = "jit"))]
-                tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
-            }
+        if config.jit_mode {
+            #[cfg(feature = "jit")]
+            driver::jit::run_jit(tcx, config.jit_args);
+
+            #[cfg(not(feature = "jit"))]
+            tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
+        } else {
+            driver::aot::run_aot(tcx, metadata, need_metadata_module)
         }
     }
 
@@ -247,21 +245,19 @@ fn enable_verifier(sess: &Session) -> bool {
 }
 
 fn target_triple(sess: &Session) -> target_lexicon::Triple {
-    // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS.
-    // See <https://github.com/bytecodealliance/target-lexicon/pull/113>
-    match versioned_llvm_target(sess).parse() {
+    match sess.target.llvm_target.parse() {
         Ok(triple) => triple,
         Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)),
     }
 }
 
-fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
+fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
     use target_lexicon::BinaryFormat;
 
     let target_triple = crate::target_triple(sess);
 
     let mut flags_builder = settings::builder();
-    flags_builder.enable("is_pic").unwrap();
+    flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap();
     let enable_verifier = if enable_verifier(sess) { "true" } else { "false" };
     flags_builder.set("enable_verifier", enable_verifier).unwrap();
     flags_builder.set("regalloc_checker", enable_verifier).unwrap();
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index f44e2459a78..2a4d1e3ae57 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
     in_lhs: CValue<'tcx>,
     in_rhs: CValue<'tcx>,
 ) -> CValue<'tcx> {
-    let is_thin_ptr =
-        in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
+    let is_thin_ptr = in_lhs
+        .layout()
+        .ty
+        .builtin_deref(true)
+        .map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized()))
+        .unwrap_or(true);
 
     if is_thin_ptr {
         match bin_op {
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index cc739fefcd0..f8a19589fdd 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -746,7 +746,7 @@ impl<'tcx> CPlace<'tcx> {
         };
 
         let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
-        if has_ptr_meta(fx.tcx, field_layout.ty) {
+        if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) {
             CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
         } else {
             CPlace::for_ptr(field_ptr, field_layout)
@@ -832,7 +832,7 @@ impl<'tcx> CPlace<'tcx> {
 
     pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
         let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
-        if has_ptr_meta(fx.tcx, inner_layout.ty) {
+        if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) {
             let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
             CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
         } else {
@@ -845,7 +845,7 @@ impl<'tcx> CPlace<'tcx> {
         fx: &mut FunctionCx<'_, '_, 'tcx>,
         layout: TyAndLayout<'tcx>,
     ) -> CValue<'tcx> {
-        if has_ptr_meta(fx.tcx, self.layout().ty) {
+        if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) {
             let (ptr, extra) = self.to_ptr_unsized();
             CValue::by_val_pair(ptr.get_addr(fx), extra, layout)
         } else {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index c514b7a428b..474475f311f 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc>(
         llvals.push(cx.const_bytes(bytes));
     }
 
+    // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element.
     cx.const_struct(&llvals, true)
 }
 
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index ec1fd4b641a..3185993c207 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@ test = false
 bitflags = "2.4.1"
 # To avoid duplicate dependencies, this should match the version of gimli used
 # by `rustc_codegen_ssa` via its `thorin-dwp` dependency.
-gimli = "0.30"
+gimli = "0.31"
 itertools = "0.12"
 libc = "0.2"
 measureme = "12.0.1"
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 668795191a2..f083cfbd7d3 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -728,7 +728,7 @@ impl ThinBuffer {
         }
     }
 
-    pub unsafe fn from_raw_ptr(ptr: *mut llvm::ThinLTOBuffer) -> ThinBuffer {
+    pub(crate) unsafe fn from_raw_ptr(ptr: *mut llvm::ThinLTOBuffer) -> ThinBuffer {
         let mut ptr = NonNull::new(ptr).unwrap();
         ThinBuffer(unsafe { ptr.as_mut() })
     }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 55d34f5f2ef..297f104d124 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -14,6 +14,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
+use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
@@ -1074,6 +1075,35 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) }
     }
 
+    fn three_way_compare(
+        &mut self,
+        ty: Ty<'tcx>,
+        lhs: Self::Value,
+        rhs: Self::Value,
+    ) -> Option<Self::Value> {
+        // FIXME: See comment on the definition of `three_way_compare`.
+        if crate::llvm_util::get_version() < (20, 0, 0) {
+            return None;
+        }
+
+        let name = match (ty.is_signed(), ty.primitive_size(self.tcx).bits()) {
+            (true, 8) => "llvm.scmp.i8.i8",
+            (true, 16) => "llvm.scmp.i8.i16",
+            (true, 32) => "llvm.scmp.i8.i32",
+            (true, 64) => "llvm.scmp.i8.i64",
+            (true, 128) => "llvm.scmp.i8.i128",
+
+            (false, 8) => "llvm.ucmp.i8.i8",
+            (false, 16) => "llvm.ucmp.i8.i16",
+            (false, 32) => "llvm.ucmp.i8.i32",
+            (false, 64) => "llvm.ucmp.i8.i64",
+            (false, 128) => "llvm.ucmp.i8.i128",
+
+            _ => bug!("three-way compare unsupported for type {ty:?}"),
+        };
+        Some(self.call_intrinsic(name, &[lhs, rhs]))
+    }
+
     /* Miscellaneous instructions */
     fn memcpy(
         &mut self,
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index 71705ecb4d0..7cd4ee539d8 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -28,6 +28,113 @@ fn get_params(fnc: &Value) -> Vec<&Value> {
     }
 }
 
+fn match_args_from_caller_to_enzyme<'ll>(
+    cx: &SimpleCx<'ll>,
+    args: &mut Vec<&'ll llvm::Value>,
+    inputs: &[DiffActivity],
+    outer_args: &[&'ll llvm::Value],
+) {
+    debug!("matching autodiff arguments");
+    // We now handle the issue that Rust level arguments not always match the llvm-ir level
+    // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on
+    // llvm-ir level. The number of activities matches the number of Rust level arguments, so we
+    // need to match those.
+    // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it
+    // using iterators and peek()?
+    let mut outer_pos: usize = 0;
+    let mut activity_pos = 0;
+
+    let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
+    let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
+    let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
+    let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
+
+    while activity_pos < inputs.len() {
+        let diff_activity = inputs[activity_pos as usize];
+        // Duplicated arguments received a shadow argument, into which enzyme will write the
+        // gradient.
+        let (activity, duplicated): (&Metadata, bool) = match diff_activity {
+            DiffActivity::None => panic!("not a valid input activity"),
+            DiffActivity::Const => (enzyme_const, false),
+            DiffActivity::Active => (enzyme_out, false),
+            DiffActivity::ActiveOnly => (enzyme_out, false),
+            DiffActivity::Dual => (enzyme_dup, true),
+            DiffActivity::DualOnly => (enzyme_dupnoneed, true),
+            DiffActivity::Duplicated => (enzyme_dup, true),
+            DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true),
+            DiffActivity::FakeActivitySize => (enzyme_const, false),
+        };
+        let outer_arg = outer_args[outer_pos];
+        args.push(cx.get_metadata_value(activity));
+        args.push(outer_arg);
+        if duplicated {
+            // We know that duplicated args by construction have a following argument,
+            // so this can not be out of bounds.
+            let next_outer_arg = outer_args[outer_pos + 1];
+            let next_outer_ty = cx.val_ty(next_outer_arg);
+            // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since
+            // vectors behind references (&Vec<T>) are already supported. Users can not pass a
+            // Vec by value for reverse mode, so this would only help forward mode autodiff.
+            let slice = {
+                if activity_pos + 1 >= inputs.len() {
+                    // If there is no arg following our ptr, it also can't be a slice,
+                    // since that would lead to a ptr, int pair.
+                    false
+                } else {
+                    let next_activity = inputs[activity_pos + 1];
+                    // We analyze the MIR types and add this dummy activity if we visit a slice.
+                    next_activity == DiffActivity::FakeActivitySize
+                }
+            };
+            if slice {
+                // A duplicated slice will have the following two outer_fn arguments:
+                // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call:
+                // (..., metadata! enzyme_dup, ptr, ptr, int1, ...).
+                // FIXME(ZuseZ4): We will upstream a safety check later which asserts that
+                // int2 >= int1, which means the shadow vector is large enough to store the gradient.
+                assert!(unsafe {
+                    llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer
+                });
+                let next_outer_arg2 = outer_args[outer_pos + 2];
+                let next_outer_ty2 = cx.val_ty(next_outer_arg2);
+                assert!(unsafe {
+                    llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer
+                });
+                let next_outer_arg3 = outer_args[outer_pos + 3];
+                let next_outer_ty3 = cx.val_ty(next_outer_arg3);
+                assert!(unsafe {
+                    llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer
+                });
+                args.push(next_outer_arg2);
+                args.push(cx.get_metadata_value(enzyme_const));
+                args.push(next_outer_arg);
+                outer_pos += 4;
+                activity_pos += 2;
+            } else {
+                // A duplicated pointer will have the following two outer_fn arguments:
+                // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call:
+                // (..., metadata! enzyme_dup, ptr, ptr, ...).
+                if matches!(diff_activity, DiffActivity::Duplicated | DiffActivity::DuplicatedOnly)
+                {
+                    assert!(
+                        unsafe { llvm::LLVMRustGetTypeKind(next_outer_ty) }
+                            == llvm::TypeKind::Pointer
+                    );
+                }
+                // In the case of Dual we don't have assumptions, e.g. f32 would be valid.
+                args.push(next_outer_arg);
+                outer_pos += 2;
+                activity_pos += 1;
+            }
+        } else {
+            // We do not differentiate with resprect to this argument.
+            // We already added the metadata and argument above, so just increase the counters.
+            outer_pos += 1;
+            activity_pos += 1;
+        }
+    }
+}
+
 /// When differentiating `fn_to_diff`, take a `outer_fn` and generate another
 /// function with expected naming and calling conventions[^1] which will be
 /// discovered by the enzyme LLVM pass and its body populated with the differentiated
@@ -43,9 +150,6 @@ fn generate_enzyme_call<'ll>(
     outer_fn: &'ll Value,
     attrs: AutoDiffAttrs,
 ) {
-    let inputs = attrs.input_activity;
-    let output = attrs.ret_activity;
-
     // We have to pick the name depending on whether we want forward or reverse mode autodiff.
     let mut ad_name: String = match attrs.mode {
         DiffMode::Forward => "__enzyme_fwddiff",
@@ -132,111 +236,13 @@ fn generate_enzyme_call<'ll>(
         let mut args = Vec::with_capacity(num_args as usize + 1);
         args.push(fn_to_diff);
 
-        let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
-        let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
-        let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
-        let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
         let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap();
-
-        match output {
-            DiffActivity::Dual => {
-                args.push(cx.get_metadata_value(enzyme_primal_ret));
-            }
-            DiffActivity::Active => {
-                args.push(cx.get_metadata_value(enzyme_primal_ret));
-            }
-            _ => {}
+        if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) {
+            args.push(cx.get_metadata_value(enzyme_primal_ret));
         }
 
-        debug!("matching autodiff arguments");
-        // We now handle the issue that Rust level arguments not always match the llvm-ir level
-        // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on
-        // llvm-ir level. The number of activities matches the number of Rust level arguments, so we
-        // need to match those.
-        // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it
-        // using iterators and peek()?
-        let mut outer_pos: usize = 0;
-        let mut activity_pos = 0;
         let outer_args: Vec<&llvm::Value> = get_params(outer_fn);
-        while activity_pos < inputs.len() {
-            let diff_activity = inputs[activity_pos as usize];
-            // Duplicated arguments received a shadow argument, into which enzyme will write the
-            // gradient.
-            let (activity, duplicated): (&Metadata, bool) = match diff_activity {
-                DiffActivity::None => panic!("not a valid input activity"),
-                DiffActivity::Const => (enzyme_const, false),
-                DiffActivity::Active => (enzyme_out, false),
-                DiffActivity::ActiveOnly => (enzyme_out, false),
-                DiffActivity::Dual => (enzyme_dup, true),
-                DiffActivity::DualOnly => (enzyme_dupnoneed, true),
-                DiffActivity::Duplicated => (enzyme_dup, true),
-                DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true),
-                DiffActivity::FakeActivitySize => (enzyme_const, false),
-            };
-            let outer_arg = outer_args[outer_pos];
-            args.push(cx.get_metadata_value(activity));
-            args.push(outer_arg);
-            if duplicated {
-                // We know that duplicated args by construction have a following argument,
-                // so this can not be out of bounds.
-                let next_outer_arg = outer_args[outer_pos + 1];
-                let next_outer_ty = cx.val_ty(next_outer_arg);
-                // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since
-                // vectors behind references (&Vec<T>) are already supported. Users can not pass a
-                // Vec by value for reverse mode, so this would only help forward mode autodiff.
-                let slice = {
-                    if activity_pos + 1 >= inputs.len() {
-                        // If there is no arg following our ptr, it also can't be a slice,
-                        // since that would lead to a ptr, int pair.
-                        false
-                    } else {
-                        let next_activity = inputs[activity_pos + 1];
-                        // We analyze the MIR types and add this dummy activity if we visit a slice.
-                        next_activity == DiffActivity::FakeActivitySize
-                    }
-                };
-                if slice {
-                    // A duplicated slice will have the following two outer_fn arguments:
-                    // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call:
-                    // (..., metadata! enzyme_dup, ptr, ptr, int1, ...).
-                    // FIXME(ZuseZ4): We will upstream a safety check later which asserts that
-                    // int2 >= int1, which means the shadow vector is large enough to store the gradient.
-                    assert!(llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer);
-                    let next_outer_arg2 = outer_args[outer_pos + 2];
-                    let next_outer_ty2 = cx.val_ty(next_outer_arg2);
-                    assert!(llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer);
-                    let next_outer_arg3 = outer_args[outer_pos + 3];
-                    let next_outer_ty3 = cx.val_ty(next_outer_arg3);
-                    assert!(llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer);
-                    args.push(next_outer_arg2);
-                    args.push(cx.get_metadata_value(enzyme_const));
-                    args.push(next_outer_arg);
-                    outer_pos += 4;
-                    activity_pos += 2;
-                } else {
-                    // A duplicated pointer will have the following two outer_fn arguments:
-                    // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call:
-                    // (..., metadata! enzyme_dup, ptr, ptr, ...).
-                    if matches!(
-                        diff_activity,
-                        DiffActivity::Duplicated | DiffActivity::DuplicatedOnly
-                    ) {
-                        assert!(
-                            llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Pointer
-                        );
-                    }
-                    // In the case of Dual we don't have assumptions, e.g. f32 would be valid.
-                    args.push(next_outer_arg);
-                    outer_pos += 2;
-                    activity_pos += 1;
-                }
-            } else {
-                // We do not differentiate with resprect to this argument.
-                // We already added the metadata and argument above, so just increase the counters.
-                outer_pos += 1;
-                activity_pos += 1;
-            }
-        }
+        match_args_from_caller_to_enzyme(&cx, &mut args, &attrs.input_activity, &outer_args);
 
         let call = builder.call(enzyme_ty, ad_fn, &args, None);
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 62fa2884e0f..7675e75338a 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -129,7 +129,12 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
         append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range);
     }
 
-    cx.const_struct(&llvals, true)
+    // Avoid wrapping in a struct if there is only a single value. This ensures
+    // that LLVM is able to perform the string merging optimization if the constant
+    // is a valid C string. LLVM only considers bare arrays for this optimization,
+    // not arrays wrapped in a struct. LLVM handles this at:
+    // https://github.com/rust-lang/llvm-project/blob/acaea3d2bb8f351b740db7ebce7d7a40b9e21488/llvm/lib/Target/TargetLoweringObjectFile.cpp#L249-L280
+    if let &[data] = &*llvals { data } else { cx.const_struct(&llvals, true) }
 }
 
 fn codegen_static_initializer<'ll, 'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 926445c780b..f7b096ff976 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -1127,6 +1127,18 @@ impl<'ll> CodegenCx<'ll, '_> {
         ifn!("llvm.usub.sat.i64", fn(t_i64, t_i64) -> t_i64);
         ifn!("llvm.usub.sat.i128", fn(t_i128, t_i128) -> t_i128);
 
+        ifn!("llvm.scmp.i8.i8", fn(t_i8, t_i8) -> t_i8);
+        ifn!("llvm.scmp.i8.i16", fn(t_i16, t_i16) -> t_i8);
+        ifn!("llvm.scmp.i8.i32", fn(t_i32, t_i32) -> t_i8);
+        ifn!("llvm.scmp.i8.i64", fn(t_i64, t_i64) -> t_i8);
+        ifn!("llvm.scmp.i8.i128", fn(t_i128, t_i128) -> t_i8);
+
+        ifn!("llvm.ucmp.i8.i8", fn(t_i8, t_i8) -> t_i8);
+        ifn!("llvm.ucmp.i8.i16", fn(t_i16, t_i16) -> t_i8);
+        ifn!("llvm.ucmp.i8.i32", fn(t_i32, t_i32) -> t_i8);
+        ifn!("llvm.ucmp.i8.i64", fn(t_i64, t_i64) -> t_i8);
+        ifn!("llvm.ucmp.i8.i128", fn(t_i128, t_i128) -> t_i8);
+
         ifn!("llvm.lifetime.start.p0i8", fn(t_i64, ptr) -> void);
         ifn!("llvm.lifetime.end.p0i8", fn(t_i64, ptr) -> void);
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index f622646a5d9..425381b0ffa 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -29,7 +29,7 @@ use back::owned_target_machine::OwnedTargetMachine;
 use back::write::{create_informational_target_machine, create_target_machine};
 use context::SimpleCx;
 use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
-pub(crate) use llvm_util::target_features_cfg;
+use llvm_util::target_features_cfg;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@@ -71,9 +71,7 @@ mod debuginfo;
 mod declare;
 mod errors;
 mod intrinsic;
-// FIXME(Zalathar): Fix all the unreachable-pub warnings that would occur if
-// this isn't pub, then make it not pub.
-pub mod llvm;
+mod llvm;
 mod llvm_util;
 mod mono_item;
 mod type_;
diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
index 63b2b15c514..51bcc4d123d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
@@ -5,17 +5,17 @@ use std::{slice, str};
 
 use rustc_fs_util::path_to_c_string;
 
-pub struct ArchiveRO {
+pub(crate) struct ArchiveRO {
     pub raw: &'static mut super::Archive,
 }
 
 unsafe impl Send for ArchiveRO {}
 
-pub struct Iter<'a> {
+pub(crate) struct Iter<'a> {
     raw: &'a mut super::ArchiveIterator<'a>,
 }
 
-pub struct Child<'a> {
+pub(crate) struct Child<'a> {
     pub raw: &'a mut super::ArchiveChild<'a>,
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
index 11043b664f5..0e0f2b0eab0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -3,13 +3,13 @@
 use libc::c_uint;
 use rustc_span::InnerSpan;
 
-pub use self::Diagnostic::*;
-pub use self::OptimizationDiagnosticKind::*;
+pub(crate) use self::Diagnostic::*;
+use self::OptimizationDiagnosticKind::*;
 use super::{DiagnosticInfo, SMDiagnostic};
 use crate::value::Value;
 
 #[derive(Copy, Clone, Debug)]
-pub enum OptimizationDiagnosticKind {
+pub(crate) enum OptimizationDiagnosticKind {
     OptimizationRemark,
     OptimizationMissed,
     OptimizationAnalysis,
@@ -19,9 +19,10 @@ pub enum OptimizationDiagnosticKind {
     OptimizationRemarkOther,
 }
 
-pub struct OptimizationDiagnostic<'ll> {
+pub(crate) struct OptimizationDiagnostic<'ll> {
     pub kind: OptimizationDiagnosticKind,
     pub pass_name: String,
+    #[expect(dead_code)]
     pub function: &'ll Value,
     pub line: c_uint,
     pub column: c_uint,
@@ -73,14 +74,14 @@ impl<'ll> OptimizationDiagnostic<'ll> {
     }
 }
 
-pub struct SrcMgrDiagnostic {
+pub(crate) struct SrcMgrDiagnostic {
     pub level: super::DiagnosticLevel,
     pub message: String,
     pub source: Option<(String, Vec<InnerSpan>)>,
 }
 
 impl SrcMgrDiagnostic {
-    pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
+    pub(crate) unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic {
         // Recover the post-substitution assembly code from LLVM for better
         // diagnostics.
         let mut have_source = false;
@@ -120,7 +121,7 @@ impl SrcMgrDiagnostic {
 }
 
 #[derive(Clone)]
-pub struct InlineAsmDiagnostic {
+pub(crate) struct InlineAsmDiagnostic {
     pub level: super::DiagnosticLevel,
     pub cookie: u64,
     pub message: String,
@@ -158,7 +159,7 @@ impl InlineAsmDiagnostic {
     }
 }
 
-pub enum Diagnostic<'ll> {
+pub(crate) enum Diagnostic<'ll> {
     Optimization(OptimizationDiagnostic<'ll>),
     InlineAsm(InlineAsmDiagnostic),
     PGO(&'ll DiagnosticInfo),
@@ -166,11 +167,12 @@ pub enum Diagnostic<'ll> {
     Unsupported(&'ll DiagnosticInfo),
 
     /// LLVM has other types that we do not wrap here.
+    #[expect(dead_code)]
     UnknownDiagnostic(&'ll DiagnosticInfo),
 }
 
 impl<'ll> Diagnostic<'ll> {
-    pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
+    pub(crate) unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
         use super::DiagnosticKind as Dk;
 
         unsafe {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
index f6b23862907..79e4cc8aa77 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
@@ -31,20 +31,20 @@ unsafe extern "C" {
 
 #[repr(C)]
 #[derive(Copy, Clone, PartialEq)]
-pub enum LLVMRustVerifierFailureAction {
+pub(crate) enum LLVMRustVerifierFailureAction {
     LLVMAbortProcessAction = 0,
     LLVMPrintMessageAction = 1,
     LLVMReturnStatusAction = 2,
 }
 
 #[cfg(llvm_enzyme)]
-pub use self::Enzyme_AD::*;
+pub(crate) use self::Enzyme_AD::*;
 
 #[cfg(llvm_enzyme)]
-pub mod Enzyme_AD {
+pub(crate) mod Enzyme_AD {
     use libc::c_void;
     unsafe extern "C" {
-        pub fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8);
+        pub(crate) fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8);
     }
     unsafe extern "C" {
         static mut EnzymePrintPerf: c_void;
@@ -56,42 +56,42 @@ pub mod Enzyme_AD {
         static mut EnzymeInline: c_void;
         static mut RustTypeRules: c_void;
     }
-    pub fn set_print_perf(print: bool) {
+    pub(crate) fn set_print_perf(print: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintPerf), print as u8);
         }
     }
-    pub fn set_print_activity(print: bool) {
+    pub(crate) fn set_print_activity(print: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintActivity), print as u8);
         }
     }
-    pub fn set_print_type(print: bool) {
+    pub(crate) fn set_print_type(print: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8);
         }
     }
-    pub fn set_print(print: bool) {
+    pub(crate) fn set_print(print: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8);
         }
     }
-    pub fn set_strict_aliasing(strict: bool) {
+    pub(crate) fn set_strict_aliasing(strict: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeStrictAliasing), strict as u8);
         }
     }
-    pub fn set_loose_types(loose: bool) {
+    pub(crate) fn set_loose_types(loose: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(looseTypeAnalysis), loose as u8);
         }
     }
-    pub fn set_inline(val: bool) {
+    pub(crate) fn set_inline(val: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeInline), val as u8);
         }
     }
-    pub fn set_rust_rules(val: bool) {
+    pub(crate) fn set_rust_rules(val: bool) {
         unsafe {
             EnzymeSetCLBool(std::ptr::addr_of_mut!(RustTypeRules), val as u8);
         }
@@ -99,34 +99,34 @@ pub mod Enzyme_AD {
 }
 
 #[cfg(not(llvm_enzyme))]
-pub use self::Fallback_AD::*;
+pub(crate) use self::Fallback_AD::*;
 
 #[cfg(not(llvm_enzyme))]
-pub mod Fallback_AD {
+pub(crate) mod Fallback_AD {
     #![allow(unused_variables)]
 
-    pub fn set_inline(val: bool) {
+    pub(crate) fn set_inline(val: bool) {
         unimplemented!()
     }
-    pub fn set_print_perf(print: bool) {
+    pub(crate) fn set_print_perf(print: bool) {
         unimplemented!()
     }
-    pub fn set_print_activity(print: bool) {
+    pub(crate) fn set_print_activity(print: bool) {
         unimplemented!()
     }
-    pub fn set_print_type(print: bool) {
+    pub(crate) fn set_print_type(print: bool) {
         unimplemented!()
     }
-    pub fn set_print(print: bool) {
+    pub(crate) fn set_print(print: bool) {
         unimplemented!()
     }
-    pub fn set_strict_aliasing(strict: bool) {
+    pub(crate) fn set_strict_aliasing(strict: bool) {
         unimplemented!()
     }
-    pub fn set_loose_types(loose: bool) {
+    pub(crate) fn set_loose_types(loose: bool) {
         unimplemented!()
     }
-    pub fn set_rust_rules(val: bool) {
+    pub(crate) fn set_rust_rules(val: bool) {
         unimplemented!()
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 83efb3ea660..3ce3761944b 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -32,10 +32,10 @@ use crate::llvm;
 
 /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
 /// which has a different ABI from Rust or C++ `bool`.
-pub type Bool = c_int;
+pub(crate) type Bool = c_int;
 
-pub const True: Bool = 1 as Bool;
-pub const False: Bool = 0 as Bool;
+pub(crate) const True: Bool = 1 as Bool;
+pub(crate) const False: Bool = 0 as Bool;
 
 /// Wrapper for a raw enum value returned from LLVM's C APIs.
 ///
@@ -44,7 +44,7 @@ pub const False: Bool = 0 as Bool;
 /// value and returns it. Instead, return this raw wrapper, then convert to the
 /// Rust-side enum explicitly.
 #[repr(transparent)]
-pub struct RawEnum<T> {
+pub(crate) struct RawEnum<T> {
     value: u32,
     /// We don't own or consume a `T`, but we can produce one.
     _rust_side_type: PhantomData<fn() -> T>,
@@ -64,7 +64,7 @@ impl<T: TryFrom<u32>> RawEnum<T> {
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
 #[allow(dead_code)] // Variants constructed by C++.
-pub enum LLVMRustResult {
+pub(crate) enum LLVMRustResult {
     Success,
     Failure,
 }
@@ -83,7 +83,7 @@ pub enum LLVMRustResult {
 /// C++ API.
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum ModuleFlagMergeBehavior {
+pub(crate) enum ModuleFlagMergeBehavior {
     Error = 1,
     Warning = 2,
     Require = 3,
@@ -101,7 +101,7 @@ pub enum ModuleFlagMergeBehavior {
 /// See <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/CallingConv.h>
 #[derive(Copy, Clone, PartialEq, Debug, TryFromU32)]
 #[repr(C)]
-pub enum CallConv {
+pub(crate) enum CallConv {
     CCallConv = 0,
     FastCallConv = 8,
     ColdCallConv = 9,
@@ -126,7 +126,7 @@ pub enum CallConv {
 /// Must match the layout of `LLVMLinkage`.
 #[derive(Copy, Clone, PartialEq, TryFromU32)]
 #[repr(C)]
-pub enum Linkage {
+pub(crate) enum Linkage {
     ExternalLinkage = 0,
     AvailableExternallyLinkage = 1,
     LinkOnceAnyLinkage = 2,
@@ -153,7 +153,7 @@ pub enum Linkage {
 /// Must match the layout of `LLVMVisibility`.
 #[repr(C)]
 #[derive(Copy, Clone, PartialEq, TryFromU32)]
-pub enum Visibility {
+pub(crate) enum Visibility {
     Default = 0,
     Hidden = 1,
     Protected = 2,
@@ -171,8 +171,9 @@ impl Visibility {
 
 /// LLVMUnnamedAddr
 #[repr(C)]
-pub enum UnnamedAddr {
+pub(crate) enum UnnamedAddr {
     No,
+    #[expect(dead_code)]
     Local,
     Global,
 }
@@ -180,7 +181,7 @@ pub enum UnnamedAddr {
 /// LLVMDLLStorageClass
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum DLLStorageClass {
+pub(crate) enum DLLStorageClass {
     #[allow(dead_code)]
     Default = 0,
     DllImport = 1, // Function to be imported from DLL.
@@ -193,7 +194,8 @@ pub enum DLLStorageClass {
 /// though it is not ABI compatible (since it's a C++ enum)
 #[repr(C)]
 #[derive(Copy, Clone, Debug)]
-pub enum AttributeKind {
+#[expect(dead_code, reason = "Some variants are unused, but are kept to match the C++")]
+pub(crate) enum AttributeKind {
     AlwaysInline = 0,
     ByVal = 1,
     Cold = 2,
@@ -241,7 +243,7 @@ pub enum AttributeKind {
 /// LLVMIntPredicate
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum IntPredicate {
+pub(crate) enum IntPredicate {
     IntEQ = 32,
     IntNE = 33,
     IntUGT = 34,
@@ -275,7 +277,7 @@ impl IntPredicate {
 /// LLVMRealPredicate
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum RealPredicate {
+pub(crate) enum RealPredicate {
     RealPredicateFalse = 0,
     RealOEQ = 1,
     RealOGT = 2,
@@ -321,7 +323,8 @@ impl RealPredicate {
 /// LLVMTypeKind
 #[derive(Copy, Clone, PartialEq, Debug)]
 #[repr(C)]
-pub enum TypeKind {
+#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")]
+pub(crate) enum TypeKind {
     Void = 0,
     Half = 1,
     Float = 2,
@@ -373,7 +376,7 @@ impl TypeKind {
 /// LLVMAtomicRmwBinOp
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum AtomicRmwBinOp {
+pub(crate) enum AtomicRmwBinOp {
     AtomicXchg = 0,
     AtomicAdd = 1,
     AtomicSub = 2,
@@ -409,7 +412,7 @@ impl AtomicRmwBinOp {
 /// LLVMAtomicOrdering
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum AtomicOrdering {
+pub(crate) enum AtomicOrdering {
     #[allow(dead_code)]
     NotAtomic = 0,
     Unordered = 1,
@@ -438,7 +441,7 @@ impl AtomicOrdering {
 /// LLVMRustFileType
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum FileType {
+pub(crate) enum FileType {
     AssemblyFile,
     ObjectFile,
 }
@@ -446,7 +449,8 @@ pub enum FileType {
 /// LLVMMetadataType
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum MetadataType {
+#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")]
+pub(crate) enum MetadataType {
     MD_dbg = 0,
     MD_tbaa = 1,
     MD_prof = 2,
@@ -470,7 +474,7 @@ pub enum MetadataType {
 /// LLVMRustAsmDialect
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum AsmDialect {
+pub(crate) enum AsmDialect {
     Att,
     Intel,
 }
@@ -478,7 +482,7 @@ pub enum AsmDialect {
 /// LLVMRustCodeGenOptLevel
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum CodeGenOptLevel {
+pub(crate) enum CodeGenOptLevel {
     None,
     Less,
     Default,
@@ -487,7 +491,7 @@ pub enum CodeGenOptLevel {
 
 /// LLVMRustPassBuilderOptLevel
 #[repr(C)]
-pub enum PassBuilderOptLevel {
+pub(crate) enum PassBuilderOptLevel {
     O0,
     O1,
     O2,
@@ -499,7 +503,7 @@ pub enum PassBuilderOptLevel {
 /// LLVMRustOptStage
 #[derive(PartialEq)]
 #[repr(C)]
-pub enum OptStage {
+pub(crate) enum OptStage {
     PreLinkNoLTO,
     PreLinkThinLTO,
     PreLinkFatLTO,
@@ -509,7 +513,7 @@ pub enum OptStage {
 
 /// LLVMRustSanitizerOptions
 #[repr(C)]
-pub struct SanitizerOptions {
+pub(crate) struct SanitizerOptions {
     pub sanitize_address: bool,
     pub sanitize_address_recover: bool,
     pub sanitize_cfi: bool,
@@ -530,7 +534,7 @@ pub struct SanitizerOptions {
 /// LLVMRustRelocModel
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum RelocModel {
+pub(crate) enum RelocModel {
     Static,
     PIC,
     DynamicNoPic,
@@ -542,7 +546,7 @@ pub enum RelocModel {
 /// LLVMRustFloatABI
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum FloatAbi {
+pub(crate) enum FloatAbi {
     Default,
     Soft,
     Hard,
@@ -551,7 +555,7 @@ pub enum FloatAbi {
 /// LLVMRustCodeModel
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum CodeModel {
+pub(crate) enum CodeModel {
     Tiny,
     Small,
     Kernel,
@@ -564,7 +568,7 @@ pub enum CodeModel {
 #[derive(Copy, Clone)]
 #[repr(C)]
 #[allow(dead_code)] // Variants constructed by C++.
-pub enum DiagnosticKind {
+pub(crate) enum DiagnosticKind {
     Other,
     InlineAsm,
     StackSize,
@@ -587,7 +591,7 @@ pub enum DiagnosticKind {
 #[derive(Copy, Clone)]
 #[repr(C)]
 #[allow(dead_code)] // Variants constructed by C++.
-pub enum DiagnosticLevel {
+pub(crate) enum DiagnosticLevel {
     Error,
     Warning,
     Note,
@@ -597,7 +601,7 @@ pub enum DiagnosticLevel {
 /// LLVMRustArchiveKind
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum ArchiveKind {
+pub(crate) enum ArchiveKind {
     K_GNU,
     K_BSD,
     K_DARWIN,
@@ -607,15 +611,15 @@ pub enum ArchiveKind {
 
 unsafe extern "C" {
     // LLVMRustThinLTOData
-    pub type ThinLTOData;
+    pub(crate) type ThinLTOData;
 
     // LLVMRustThinLTOBuffer
-    pub type ThinLTOBuffer;
+    pub(crate) type ThinLTOBuffer;
 }
 
 /// LLVMRustThinLTOModule
 #[repr(C)]
-pub struct ThinLTOModule {
+pub(crate) struct ThinLTOModule {
     pub identifier: *const c_char,
     pub data: *const u8,
     pub len: usize,
@@ -624,7 +628,8 @@ pub struct ThinLTOModule {
 /// LLVMThreadLocalMode
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum ThreadLocalMode {
+pub(crate) enum ThreadLocalMode {
+    #[expect(dead_code)]
     NotThreadLocal,
     GeneralDynamic,
     LocalDynamic,
@@ -635,7 +640,7 @@ pub enum ThreadLocalMode {
 /// LLVMRustChecksumKind
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum ChecksumKind {
+pub(crate) enum ChecksumKind {
     None,
     MD5,
     SHA1,
@@ -645,7 +650,7 @@ pub enum ChecksumKind {
 /// LLVMRustMemoryEffects
 #[derive(Copy, Clone)]
 #[repr(C)]
-pub enum MemoryEffects {
+pub(crate) enum MemoryEffects {
     None,
     ReadOnly,
     InaccessibleMemOnly,
@@ -654,7 +659,8 @@ pub enum MemoryEffects {
 /// LLVMOpcode
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[repr(C)]
-pub enum Opcode {
+#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")]
+pub(crate) enum Opcode {
     Ret = 1,
     Br = 2,
     Switch = 3,
@@ -735,48 +741,48 @@ struct InvariantOpaque<'a> {
 
 // Opaque pointer types
 unsafe extern "C" {
-    pub type Module;
-    pub type Context;
-    pub type Type;
-    pub type Value;
-    pub type ConstantInt;
-    pub type Attribute;
-    pub type Metadata;
-    pub type BasicBlock;
-    pub type Comdat;
+    pub(crate) type Module;
+    pub(crate) type Context;
+    pub(crate) type Type;
+    pub(crate) type Value;
+    pub(crate) type ConstantInt;
+    pub(crate) type Attribute;
+    pub(crate) type Metadata;
+    pub(crate) type BasicBlock;
+    pub(crate) type Comdat;
 }
 #[repr(C)]
-pub struct Builder<'a>(InvariantOpaque<'a>);
+pub(crate) struct Builder<'a>(InvariantOpaque<'a>);
 #[repr(C)]
-pub struct PassManager<'a>(InvariantOpaque<'a>);
+pub(crate) struct PassManager<'a>(InvariantOpaque<'a>);
 unsafe extern "C" {
     pub type TargetMachine;
-    pub type Archive;
+    pub(crate) type Archive;
 }
 #[repr(C)]
-pub struct ArchiveIterator<'a>(InvariantOpaque<'a>);
+pub(crate) struct ArchiveIterator<'a>(InvariantOpaque<'a>);
 #[repr(C)]
-pub struct ArchiveChild<'a>(InvariantOpaque<'a>);
+pub(crate) struct ArchiveChild<'a>(InvariantOpaque<'a>);
 unsafe extern "C" {
-    pub type Twine;
-    pub type DiagnosticInfo;
-    pub type SMDiagnostic;
+    pub(crate) type Twine;
+    pub(crate) type DiagnosticInfo;
+    pub(crate) type SMDiagnostic;
 }
 #[repr(C)]
-pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
+pub(crate) struct RustArchiveMember<'a>(InvariantOpaque<'a>);
 /// Opaque pointee of `LLVMOperandBundleRef`.
 #[repr(C)]
 pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
 #[repr(C)]
-pub struct Linker<'a>(InvariantOpaque<'a>);
+pub(crate) struct Linker<'a>(InvariantOpaque<'a>);
 
 unsafe extern "C" {
-    pub type DiagnosticHandler;
+    pub(crate) type DiagnosticHandler;
 }
 
-pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
+pub(crate) type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
 
-pub mod debuginfo {
+pub(crate) mod debuginfo {
     use std::ptr;
 
     use bitflags::bitflags;
@@ -793,7 +799,7 @@ pub mod debuginfo {
     /// builder reference typically has a shorter lifetime than the LLVM
     /// session (`'ll`) that it participates in.
     #[repr(C)]
-    pub struct DIBuilder<'ll>(InvariantOpaque<'ll>);
+    pub(crate) struct DIBuilder<'ll>(InvariantOpaque<'ll>);
 
     /// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder
     /// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder`
@@ -822,22 +828,22 @@ pub mod debuginfo {
         }
     }
 
-    pub type DIDescriptor = Metadata;
-    pub type DILocation = Metadata;
-    pub type DIScope = DIDescriptor;
-    pub type DIFile = DIScope;
-    pub type DILexicalBlock = DIScope;
-    pub type DISubprogram = DIScope;
-    pub type DIType = DIDescriptor;
-    pub type DIBasicType = DIType;
-    pub type DIDerivedType = DIType;
-    pub type DICompositeType = DIDerivedType;
-    pub type DIVariable = DIDescriptor;
-    pub type DIGlobalVariableExpression = DIDescriptor;
-    pub type DIArray = DIDescriptor;
-    pub type DISubrange = DIDescriptor;
-    pub type DIEnumerator = DIDescriptor;
-    pub type DITemplateTypeParameter = DIDescriptor;
+    pub(crate) type DIDescriptor = Metadata;
+    pub(crate) type DILocation = Metadata;
+    pub(crate) type DIScope = DIDescriptor;
+    pub(crate) type DIFile = DIScope;
+    pub(crate) type DILexicalBlock = DIScope;
+    pub(crate) type DISubprogram = DIScope;
+    pub(crate) type DIType = DIDescriptor;
+    pub(crate) type DIBasicType = DIType;
+    pub(crate) type DIDerivedType = DIType;
+    pub(crate) type DICompositeType = DIDerivedType;
+    pub(crate) type DIVariable = DIDescriptor;
+    pub(crate) type DIGlobalVariableExpression = DIDescriptor;
+    pub(crate) type DIArray = DIDescriptor;
+    pub(crate) type DISubrange = DIDescriptor;
+    pub(crate) type DIEnumerator = DIDescriptor;
+    pub(crate) type DITemplateTypeParameter = DIDescriptor;
 
     bitflags! {
         /// Must match the layout of `LLVMDIFlags` in the LLVM-C API.
@@ -846,7 +852,7 @@ pub mod debuginfo {
         /// assertions in `RustWrapper.cpp` used by `fromRust(LLVMDIFlags)`.
         #[repr(transparent)]
         #[derive(Clone, Copy, Default)]
-        pub struct DIFlags: u32 {
+        pub(crate) struct DIFlags: u32 {
             const FlagZero                = 0;
             const FlagPrivate             = 1;
             const FlagProtected           = 2;
@@ -886,7 +892,7 @@ pub mod debuginfo {
     bitflags! {
         #[repr(transparent)]
         #[derive(Clone, Copy, Default)]
-        pub struct DISPFlags: u32 {
+        pub(crate) struct DISPFlags: u32 {
             const SPFlagZero              = 0;
             const SPFlagVirtual           = 1;
             const SPFlagPureVirtual       = 2;
@@ -900,7 +906,7 @@ pub mod debuginfo {
     /// LLVMRustDebugEmissionKind
     #[derive(Copy, Clone)]
     #[repr(C)]
-    pub enum DebugEmissionKind {
+    pub(crate) enum DebugEmissionKind {
         NoDebug,
         FullDebug,
         LineTablesOnly,
@@ -932,8 +938,9 @@ pub mod debuginfo {
     /// LLVMRustDebugNameTableKind
     #[derive(Clone, Copy)]
     #[repr(C)]
-    pub enum DebugNameTableKind {
+    pub(crate) enum DebugNameTableKind {
         Default,
+        #[expect(dead_code)]
         Gnu,
         None,
     }
@@ -943,7 +950,7 @@ pub mod debuginfo {
 bitflags! {
     #[repr(transparent)]
     #[derive(Default)]
-    pub struct AllocKindFlags : u64 {
+    pub(crate) struct AllocKindFlags : u64 {
         const Unknown = 0;
         const Alloc = 1;
         const Realloc = 1 << 1;
@@ -966,19 +973,20 @@ bitflags! {
 }
 
 unsafe extern "C" {
-    pub type ModuleBuffer;
+    pub(crate) type ModuleBuffer;
 }
 
-pub type SelfProfileBeforePassCallback =
+pub(crate) type SelfProfileBeforePassCallback =
     unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
-pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
+pub(crate) type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
 
-pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
-pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
+pub(crate) type GetSymbolsCallback =
+    unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
+pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
 
 #[derive(Copy, Clone)]
 #[repr(transparent)]
-pub struct MetadataKindId(c_uint);
+pub(crate) struct MetadataKindId(c_uint);
 
 impl From<MetadataType> for MetadataKindId {
     fn from(value: MetadataType) -> Self {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index a36226b25a2..6ca81c651ed 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -9,18 +9,18 @@ use libc::c_uint;
 use rustc_abi::{Align, Size, WrappingRange};
 use rustc_llvm::RustString;
 
-pub use self::CallConv::*;
-pub use self::CodeGenOptSize::*;
-pub use self::MetadataType::*;
-pub use self::ffi::*;
+pub(crate) use self::CallConv::*;
+pub(crate) use self::CodeGenOptSize::*;
+pub(crate) use self::MetadataType::*;
+pub(crate) use self::ffi::*;
 use crate::common::AsCCharPtr;
 
-pub mod archive_ro;
-pub mod diagnostic;
-pub mod enzyme_ffi;
+pub(crate) mod archive_ro;
+pub(crate) mod diagnostic;
+pub(crate) mod enzyme_ffi;
 mod ffi;
 
-pub use self::enzyme_ffi::*;
+pub(crate) use self::enzyme_ffi::*;
 
 impl LLVMRustResult {
     pub(crate) fn into_result(self) -> Result<(), ()> {
@@ -127,7 +127,7 @@ pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange)
 }
 
 #[derive(Copy, Clone)]
-pub enum AttributePlace {
+pub(crate) enum AttributePlace {
     ReturnValue,
     Argument(u32),
     Function,
@@ -145,7 +145,7 @@ impl AttributePlace {
 
 #[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
-pub enum CodeGenOptSize {
+pub(crate) enum CodeGenOptSize {
     CodeGenOptSizeNone = 0,
     CodeGenOptSizeDefault = 1,
     CodeGenOptSizeAggressive = 2,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 4a166b0872d..4e85286ed55 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -274,7 +274,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")),
         // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single
         // feature called `fast-unaligned-access`. In LLVM 19, it was split back out.
-        ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
+        ("riscv32" | "riscv64", "unaligned-scalar-mem" | "unaligned-vector-mem")
+            if get_version().0 == 18 =>
+        {
             Some(LLVMFeature::new("fast-unaligned-access"))
         }
         // Filter out features that are not supported by the current LLVM version
@@ -298,6 +300,13 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
         ("sparc", "v8plus") if get_version().0 < 19 => None,
         ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
+        // These new `amx` variants and `movrs` were introduced in LLVM20
+        ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
+            if get_version().0 < 20 =>
+        {
+            None
+        }
+        ("x86", "movrs") if get_version().0 < 20 => None,
         (_, s) => Some(LLVMFeature::new(s)),
     }
 }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 0a2f1d5bb67..97eebffd1fe 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -42,7 +42,7 @@ serde_json = "1.0.59"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tempfile = "3.2"
 thin-vec = "0.2.12"
-thorin-dwp = "0.8"
+thorin-dwp = "0.9"
 tracing = "0.1"
 wasm-encoder = "0.219"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 95912b01600..954a6014809 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -10,8 +10,6 @@ codegen_ssa_apple_deployment_target_invalid =
 codegen_ssa_apple_deployment_target_too_low =
     deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}
 
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-
 codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
 
 codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
@@ -391,8 +389,6 @@ codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
 
 codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
 
-codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-
 codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]`
 
 codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
@@ -402,3 +398,20 @@ codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to sp
 codegen_ssa_version_script_write_failure = failed to write version script: {$error}
 
 codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
+
+codegen_ssa_xcrun_command_line_tools_insufficient =
+    when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode
+
+codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error}
+
+codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}"
+
+# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars.
+codegen_ssa_xcrun_no_developer_dir =
+    pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable
+
+codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk
+    .note = {$stderr}
+
+codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk
+    .note = {$stdout}{$stderr}
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index bfa7635a869..2c8b0ec418d 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -1,16 +1,40 @@
 use std::env;
+use std::ffi::OsString;
 use std::fmt::{Display, from_fn};
 use std::num::ParseIntError;
+use std::path::PathBuf;
+use std::process::Command;
 
+use itertools::Itertools;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_session::Session;
 use rustc_target::spec::Target;
+use tracing::debug;
 
-use crate::errors::AppleDeploymentTarget;
+use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning};
+use crate::fluent_generated as fluent;
 
 #[cfg(test)]
 mod tests;
 
+/// The canonical name of the desired SDK for a given target.
+pub(super) fn sdk_name(target: &Target) -> &'static str {
+    match (&*target.os, &*target.abi) {
+        ("macos", "") => "MacOSX",
+        ("ios", "") => "iPhoneOS",
+        ("ios", "sim") => "iPhoneSimulator",
+        // Mac Catalyst uses the macOS SDK
+        ("ios", "macabi") => "MacOSX",
+        ("tvos", "") => "AppleTVOS",
+        ("tvos", "sim") => "AppleTVSimulator",
+        ("visionos", "") => "XROS",
+        ("visionos", "sim") => "XRSimulator",
+        ("watchos", "") => "WatchOS",
+        ("watchos", "sim") => "WatchSimulator",
+        (os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"),
+    }
+}
+
 pub(super) fn macho_platform(target: &Target) -> u32 {
     match (&*target.os, &*target.abi) {
         ("macos", _) => object::macho::PLATFORM_MACOS,
@@ -253,3 +277,131 @@ pub(super) fn add_version_to_llvm_target(
         format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}")
     }
 }
+
+pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
+    let sdk_name = sdk_name(&sess.target);
+
+    match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
+        Ok((path, stderr)) => {
+            // Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
+            if !stderr.is_empty() {
+                sess.dcx().emit_warn(XcrunSdkPathWarning { sdk_name, stderr });
+            }
+            Some(path)
+        }
+        Err(err) => {
+            let mut diag = sess.dcx().create_err(err);
+
+            // Recognize common error cases, and give more Rust-specific error messages for those.
+            if let Some(developer_dir) = xcode_select_developer_dir() {
+                diag.arg("developer_dir", &developer_dir);
+                diag.note(fluent::codegen_ssa_xcrun_found_developer_dir);
+                if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") {
+                    if sdk_name != "MacOSX" {
+                        diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient);
+                    }
+                }
+            } else {
+                diag.help(fluent::codegen_ssa_xcrun_no_developer_dir);
+            }
+
+            diag.emit();
+            None
+        }
+    }
+}
+
+/// Invoke `xcrun --sdk $sdk_name --show-sdk-path` to get the SDK path.
+///
+/// The exact logic that `xcrun` uses is unspecified (see `man xcrun` for a few details), and may
+/// change between macOS and Xcode versions, but it roughly boils down to finding the active
+/// developer directory, and then invoking `xcodebuild -sdk $sdk_name -version` to get the SDK
+/// details.
+///
+/// Finding the developer directory is roughly done by looking at, in order:
+/// - The `DEVELOPER_DIR` environment variable.
+/// - The `/var/db/xcode_select_link` symlink (set by `xcode-select --switch`).
+/// - `/Applications/Xcode.app` (hardcoded fallback path).
+/// - `/Library/Developer/CommandLineTools` (hardcoded fallback path).
+///
+/// Note that `xcrun` caches its result, but with a cold cache this whole operation can be quite
+/// slow, especially so the first time it's run after a reboot.
+fn xcrun_show_sdk_path(
+    sdk_name: &'static str,
+    verbose: bool,
+) -> Result<(PathBuf, String), XcrunError> {
+    let mut cmd = Command::new("xcrun");
+    if verbose {
+        cmd.arg("--verbose");
+    }
+    // The `--sdk` parameter is the same as in xcodebuild, namely either an absolute path to an SDK,
+    // or the (lowercase) canonical name of an SDK.
+    cmd.arg("--sdk");
+    cmd.arg(&sdk_name.to_lowercase());
+    cmd.arg("--show-sdk-path");
+
+    // We do not stream stdout/stderr lines directly to the user, since whether they are warnings or
+    // errors depends on the status code at the end.
+    let output = cmd.output().map_err(|error| XcrunError::FailedInvoking {
+        sdk_name,
+        command_formatted: format!("{cmd:?}"),
+        error,
+    })?;
+
+    // It is fine to do lossy conversion here, non-UTF-8 paths are quite rare on macOS nowadays
+    // (only possible with the HFS+ file system), and we only use it for error messages.
+    let stderr = String::from_utf8_lossy_owned(output.stderr);
+    if !stderr.is_empty() {
+        debug!(stderr, "original xcrun stderr");
+    }
+
+    // Some versions of `xcodebuild` output beefy errors when invoked via `xcrun`,
+    // but these are usually red herrings.
+    let stderr = stderr
+        .lines()
+        .filter(|line| {
+            !line.contains("Writing error result bundle")
+                && !line.contains("Requested but did not find extension point with identifier")
+        })
+        .join("\n");
+
+    if output.status.success() {
+        Ok((stdout_to_path(output.stdout), stderr))
+    } else {
+        // Output both stdout and stderr, since shims of `xcrun` (such as the one provided by
+        // nixpkgs), do not always use stderr for errors.
+        let stdout = String::from_utf8_lossy_owned(output.stdout).trim().to_string();
+        Err(XcrunError::Unsuccessful {
+            sdk_name,
+            command_formatted: format!("{cmd:?}"),
+            stdout,
+            stderr,
+        })
+    }
+}
+
+/// Invoke `xcode-select --print-path`, and return the current developer directory.
+///
+/// NOTE: We don't do any error handling here, this is only used as a canary in diagnostics (`xcrun`
+/// will have already emitted the relevant error information).
+fn xcode_select_developer_dir() -> Option<PathBuf> {
+    let mut cmd = Command::new("xcode-select");
+    cmd.arg("--print-path");
+    let output = cmd.output().ok()?;
+    if !output.status.success() {
+        return None;
+    }
+    Some(stdout_to_path(output.stdout))
+}
+
+fn stdout_to_path(mut stdout: Vec<u8>) -> PathBuf {
+    // Remove trailing newline.
+    if let Some(b'\n') = stdout.last() {
+        let _ = stdout.pop().unwrap();
+    }
+    #[cfg(unix)]
+    let path = <OsString as std::os::unix::ffi::OsStringExt>::from_vec(stdout);
+    #[cfg(not(unix))] // Unimportant, this is only used on macOS
+    let path = OsString::from(String::from_utf8(stdout).unwrap());
+    PathBuf::from(path)
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
index 7ccda5a8190..8df740a4bcf 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs
@@ -1,4 +1,4 @@
-use super::{add_version_to_llvm_target, parse_version};
+use super::*;
 
 #[test]
 fn test_add_version_to_llvm_target() {
@@ -19,3 +19,69 @@ fn test_parse_version() {
     assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6)));
     assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99)));
 }
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")]
+fn lookup_developer_dir() {
+    let _developer_dir = xcode_select_developer_dir().unwrap();
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn lookup_sdk() {
+    let (sdk_path, stderr) = xcrun_show_sdk_path("MacOSX", false).unwrap();
+    // Check that the found SDK is valid.
+    assert!(sdk_path.join("SDKSettings.plist").exists());
+    assert_eq!(stderr, "");
+
+    // Test that the SDK root is a subdir of the developer directory.
+    if let Some(developer_dir) = xcode_select_developer_dir() {
+        // Only run this test if SDKROOT is not set (otherwise xcrun may look up via. that).
+        if std::env::var_os("SDKROOT").is_some() {
+            assert!(sdk_path.starts_with(&developer_dir));
+        }
+    }
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn lookup_sdk_verbose() {
+    let (_, stderr) = xcrun_show_sdk_path("MacOSX", true).unwrap();
+    // Newer xcrun versions should emit something like this:
+    //
+    //     xcrun: note: looking up SDK with 'xcodebuild -sdk macosx -version Path'
+    //     xcrun: note: xcrun_db = '/var/.../xcrun_db'
+    //     xcrun: note: lookup resolved to: '...'
+    //     xcrun: note: database key is: ...
+    //
+    // Or if the value is already cached, something like this:
+    //
+    //     xcrun: note: database key is: ...
+    //     xcrun: note: lookup resolved in '/var/.../xcrun_db' : '...'
+    assert!(
+        stderr.contains("xcrun: note: lookup resolved"),
+        "stderr should contain lookup note: {stderr}",
+    );
+}
+
+#[test]
+#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
+fn try_lookup_invalid_sdk() {
+    // As a proxy for testing all the different ways that `xcrun` can fail,
+    // test the case where an SDK was not found.
+    let err = xcrun_show_sdk_path("invalid", false).unwrap_err();
+    let XcrunError::Unsuccessful { stderr, .. } = err else {
+        panic!("unexpected error kind: {err:?}");
+    };
+    // Either one of (depending on if using Command Line Tools or full Xcode):
+    // xcrun: error: SDK "invalid" cannot be located
+    // xcodebuild: error: SDK "invalid" cannot be located.
+    assert!(
+        stderr.contains(r#"error: SDK "invalid" cannot be located"#),
+        "stderr should contain xcodebuild note: {stderr}",
+    );
+    assert!(
+        stderr.contains("xcrun: error: unable to lookup item 'Path' in SDK 'invalid'"),
+        "stderr should contain xcrun note: {stderr}",
+    );
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 74597f6263d..7d411087241 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -294,7 +294,7 @@ fn link_rlib<'a>(
             let (metadata, metadata_position) = create_wrapper_file(
                 sess,
                 ".rmeta".to_string(),
-                codegen_results.metadata.raw_data(),
+                codegen_results.metadata.stub_or_full(),
             );
             let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
             match metadata_position {
@@ -670,7 +670,7 @@ fn link_natively(
 ) {
     info!("preparing {:?} to {:?}", crate_type, out_filename);
     let (linker_path, flavor) = linker_and_flavor(sess);
-    let self_contained_components = self_contained_components(sess, crate_type);
+    let self_contained_components = self_contained_components(sess, crate_type, &linker_path);
 
     // On AIX, we ship all libraries as .a big_af archive
     // the expected format is lib<name>.a(libname.so) for the actual
@@ -1494,7 +1494,8 @@ fn print_native_static_libs(
                 | NativeLibKind::Unspecified => {
                     let verbatim = lib.verbatim;
                     if sess.target.is_like_msvc {
-                        Some(format!("{}{}", name, if verbatim { "" } else { ".lib" }))
+                        let (prefix, suffix) = sess.staticlib_components(verbatim);
+                        Some(format!("{prefix}{name}{suffix}"))
                     } else if sess.target.linker_flavor.is_gnu() {
                         Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name))
                     } else {
@@ -1559,17 +1560,13 @@ fn print_native_static_libs(
     match out {
         OutFileName::Real(path) => {
             out.overwrite(&lib_args.join(" "), sess);
-            if !lib_args.is_empty() {
-                sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
-            }
+            sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path });
         }
         OutFileName::Stdout => {
-            if !lib_args.is_empty() {
-                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().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(" ")));
         }
     }
 }
@@ -1783,8 +1780,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
 }
 
 // Returns true if linker is located within sysroot
-fn detect_self_contained_mingw(sess: &Session) -> bool {
-    let (linker, _) = linker_and_flavor(sess);
+fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
     // Assume `-C linker=rust-lld` as self-contained mode
     if linker == Path::new("rust-lld") {
         return true;
@@ -1792,7 +1788,7 @@ fn detect_self_contained_mingw(sess: &Session) -> bool {
     let linker_with_extension = if cfg!(windows) && linker.extension().is_none() {
         linker.with_extension("exe")
     } else {
-        linker
+        linker.to_path_buf()
     };
     for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
         let full_path = dir.join(&linker_with_extension);
@@ -1807,7 +1803,11 @@ fn detect_self_contained_mingw(sess: &Session) -> bool {
 /// Various toolchain components used during linking are used from rustc distribution
 /// instead of being found somewhere on the host system.
 /// We only provide such support for a very limited number of targets.
-fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents {
+fn self_contained_components(
+    sess: &Session,
+    crate_type: CrateType,
+    linker: &Path,
+) -> LinkSelfContainedComponents {
     // Turn the backwards compatible bool values for `self_contained` into fully inferred
     // `LinkSelfContainedComponents`.
     let self_contained =
@@ -1836,7 +1836,7 @@ fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfC
                 LinkSelfContainedDefault::InferredForMingw => {
                     sess.host == sess.target
                         && sess.target.vendor != "uwp"
-                        && detect_self_contained_mingw(sess)
+                        && detect_self_contained_mingw(sess, linker)
                 }
             }
         };
@@ -3201,9 +3201,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
 }
 
 fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
-    let arch = &sess.target.arch;
     let os = &sess.target.os;
-    let llvm_target = &sess.target.llvm_target;
     if sess.target.vendor != "apple"
         || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
         || !matches!(flavor, LinkerFlavor::Darwin(..))
@@ -3215,37 +3213,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
         return None;
     }
 
-    let sdk_name = match (arch.as_ref(), os.as_ref()) {
-        ("aarch64", "tvos") if llvm_target.ends_with("-simulator") => "appletvsimulator",
-        ("aarch64", "tvos") => "appletvos",
-        ("x86_64", "tvos") => "appletvsimulator",
-        ("arm", "ios") => "iphoneos",
-        ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
-        ("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator",
-        ("aarch64", "ios") => "iphoneos",
-        ("x86", "ios") => "iphonesimulator",
-        ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
-        ("x86_64", "ios") => "iphonesimulator",
-        ("x86_64", "watchos") => "watchsimulator",
-        ("arm64_32", "watchos") => "watchos",
-        ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator",
-        ("aarch64", "watchos") => "watchos",
-        ("aarch64", "visionos") if llvm_target.ends_with("-simulator") => "xrsimulator",
-        ("aarch64", "visionos") => "xros",
-        ("arm", "watchos") => "watchos",
-        (_, "macos") => "macosx",
-        _ => {
-            sess.dcx().emit_err(errors::UnsupportedArch { arch, os });
-            return None;
-        }
-    };
-    let sdk_root = match get_apple_sdk_root(sdk_name) {
-        Ok(s) => s,
-        Err(e) => {
-            sess.dcx().emit_err(e);
-            return None;
-        }
-    };
+    let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
 
     match flavor {
         LinkerFlavor::Darwin(Cc::Yes, _) => {
@@ -3255,28 +3223,32 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
             // This is admittedly a bit strange, as on most targets
             // `-isysroot` only applies to include header files, but on Apple
             // targets this also applies to libraries and frameworks.
-            cmd.cc_args(&["-isysroot", &sdk_root]);
+            cmd.cc_arg("-isysroot");
+            cmd.cc_arg(&sdk_root);
         }
         LinkerFlavor::Darwin(Cc::No, _) => {
-            cmd.link_args(&["-syslibroot", &sdk_root]);
+            cmd.link_arg("-syslibroot");
+            cmd.link_arg(&sdk_root);
         }
         _ => unreachable!(),
     }
 
-    Some(sdk_root.into())
+    Some(sdk_root)
 }
 
-fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> {
-    // Following what clang does
-    // (https://github.com/llvm/llvm-project/blob/
-    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
-    // to allow the SDK path to be set. (For clang, xcrun sets
-    // SDKROOT; for rustc, the user or build system can set it, or we
-    // can fall back to checking for xcrun on PATH.)
+fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
     if let Ok(sdkroot) = env::var("SDKROOT") {
-        let p = Path::new(&sdkroot);
-        match sdk_name {
-            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
+        let p = PathBuf::from(&sdkroot);
+
+        // Ignore invalid SDKs, similar to what clang does:
+        // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.6/clang/lib/Driver/ToolChains/Darwin.cpp#L2212-L2229
+        //
+        // NOTE: Things are complicated here by the fact that `rustc` can be run by Cargo to compile
+        // build scripts and proc-macros for the host, and thus we need to ignore SDKROOT if it's
+        // clearly set for the wrong platform.
+        //
+        // FIXME(madsmtm): Make this more robust (maybe read `SDKSettings.json` like Clang does?).
+        match &*apple::sdk_name(&sess.target).to_lowercase() {
             "appletvos"
                 if sdkroot.contains("TVSimulator.platform")
                     || sdkroot.contains("MacOSX.platform") => {}
@@ -3303,26 +3275,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
                 if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
             // Ignore `SDKROOT` if it's not a valid path.
             _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
-            _ => return Ok(sdkroot),
+            _ => return Some(p),
         }
     }
-    let res =
-        Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
-            |output| {
-                if output.status.success() {
-                    Ok(String::from_utf8(output.stdout).unwrap())
-                } else {
-                    let error = String::from_utf8(output.stderr);
-                    let error = format!("process exit with error: {}", error.unwrap());
-                    Err(io::Error::new(io::ErrorKind::Other, &error[..]))
-                }
-            },
-        );
 
-    match res {
-        Ok(output) => Ok(output.trim().to_string()),
-        Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }),
-    }
+    apple::get_sdk_root(sess)
 }
 
 /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e2a59c6efb8..bcf18cf57be 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -450,9 +450,10 @@ impl<'a> GccLinker<'a> {
                     // The output filename already contains `dll_suffix` so
                     // the resulting import library will have a name in the
                     // form of libfoo.dll.a
-                    let mut implib_name = OsString::from(&*self.sess.target.staticlib_prefix);
+                    let (prefix, suffix) = self.sess.staticlib_components(false);
+                    let mut implib_name = OsString::from(prefix);
                     implib_name.push(name);
-                    implib_name.push(&*self.sess.target.staticlib_suffix);
+                    implib_name.push(suffix);
                     let mut out_implib = OsString::from("--out-implib=");
                     out_implib.push(out_filename.with_file_name(implib_name));
                     self.link_arg(out_implib);
@@ -958,9 +959,9 @@ impl<'a> Linker for MsvcLinker<'a> {
         if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
             self.link_staticlib_by_path(&path, whole_archive);
         } else {
-            let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
-            let suffix = if verbatim { "" } else { ".lib" };
-            self.link_arg(format!("{prefix}{name}{suffix}"));
+            let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
+            let (prefix, suffix) = self.sess.staticlib_components(verbatim);
+            self.link_arg(format!("{opts}{prefix}{name}{suffix}"));
         }
     }
 
@@ -1782,7 +1783,10 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
     let mut symbols = Vec::new();
     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
     for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
-        if info.level.is_below_threshold(export_threshold) {
+        // Do not export mangled symbols from cdylibs and don't attempt to export compiler-builtins
+        // from any cdylib. The latter doesn't work anyway as we use hidden visibility for
+        // compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
+        if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
             symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
                 tcx, symbol, cnum,
             ));
@@ -1821,7 +1825,9 @@ pub(crate) fn linked_symbols(
 
     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
     for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
-        if info.level.is_below_threshold(export_threshold) || info.used {
+        if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum)
+            || info.used
+        {
             symbols.push((
                 symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
                 info.kind,
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 68b453ff424..ac9ac9bbb31 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -540,8 +540,8 @@ pub fn create_compressed_metadata_file(
     symbol_name: &str,
 ) -> Vec<u8> {
     let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
-    packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap();
-    packed_metadata.extend(metadata.raw_data());
+    packed_metadata.write_all(&(metadata.stub_or_full().len() as u64).to_le_bytes()).unwrap();
+    packed_metadata.extend(metadata.stub_or_full());
 
     let Some(mut file) = create_object_file(sess) else {
         if sess.target.is_like_wasm {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 5c9e72ae0f1..fd06c50eb81 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -95,16 +95,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
                 return None;
             }
 
-            // Functions marked with #[inline] are codegened with "internal"
-            // linkage and are not exported unless marked with an extern
-            // indicator
-            if !Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
-                || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator()
-            {
-                Some(def_id)
-            } else {
-                None
+            if Instance::mono(tcx, def_id.into()).def.requires_inline(tcx) {
+                return None;
             }
+
+            if tcx.cross_crate_inlinable(def_id) { None } else { Some(def_id) }
         })
         .map(|def_id| {
             // We won't link right if this symbol is stripped during LTO.
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 2ec203458a3..ccc0273280f 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -546,9 +546,12 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
         if let Some(path) = &module.bytecode {
             files.push((OutputType::Bitcode.extension(), path.as_path()));
         }
-        if let Some((id, product)) =
-            copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice())
-        {
+        if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir(
+            sess,
+            &module.name,
+            files.as_slice(),
+            &module.links_from_incr_cache,
+        ) {
             work_products.insert(id, product);
         }
     }
@@ -934,7 +937,9 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
 ) -> WorkItemResult<B> {
     let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
 
-    let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
+    let mut links_from_incr_cache = Vec::new();
+
+    let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
         let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path);
         debug!(
             "copying preexisting module `{}` from {:?} to {}",
@@ -943,7 +948,10 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
             output_path.display()
         );
         match link_or_copy(&source_file, &output_path) {
-            Ok(_) => Some(output_path),
+            Ok(_) => {
+                links_from_incr_cache.push(source_file);
+                Some(output_path)
+            }
             Err(error) => {
                 cgcx.create_dcx().handle().emit_err(errors::CopyPathBuf {
                     source_file,
@@ -966,7 +974,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
             load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file)
         });
 
-    let load_from_incr_cache = |perform, output_type: OutputType| {
+    let mut load_from_incr_cache = |perform, output_type: OutputType| {
         if perform {
             let saved_file = module.source.saved_files.get(output_type.extension())?;
             let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name));
@@ -986,6 +994,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
     }
 
     WorkItemResult::Finished(CompiledModule {
+        links_from_incr_cache,
         name: module.name,
         kind: ModuleKind::Regular,
         object,
@@ -2177,7 +2186,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve
     // these, but it currently does not do so.
     let can_have_static_objects =
-        tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib);
+        tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib);
 
     tcx.sess.target.is_like_windows &&
     can_have_static_objects   &&
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 396febcc637..1985b3b7170 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -658,6 +658,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
                 bytecode: None,
                 assembly: None,
                 llvm_ir: None,
+                links_from_incr_cache: Vec::new(),
             }
         })
     });
@@ -1104,11 +1105,12 @@ pub fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) ->
     // know that later). If we are not doing LTO, there is only one optimized
     // version of each module, so we re-use that.
     let dep_node = cgu.codegen_dep_node(tcx);
-    assert!(
-        !tcx.dep_graph.dep_node_exists(&dep_node),
-        "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
-        cgu.name()
-    );
+    tcx.dep_graph.assert_dep_node_not_yet_allocated_in_current_session(&dep_node, || {
+        format!(
+            "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
+            cgu.name()
+        )
+    });
 
     if tcx.try_mark_green(&dep_node) {
         // We can re-use either the pre- or the post-thinlto state. If no LTO is
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index d5972b5c9e6..a85d032f36e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -604,7 +604,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     if let Some((name, _)) = lang_items::extract(attrs)
         && let Some(lang_item) = LangItem::from_name(name)
     {
-        if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) {
+        if WEAK_LANG_ITEMS.contains(&lang_item) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
         }
         if let Some(link_name) = lang_item.link_name() {
@@ -790,16 +790,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
 
     // check for exactly one autodiff attribute on placeholder functions.
     // There should only be one, since we generate a new placeholder per ad macro.
-    // FIXME(ZuseZ4): re-enable this check. Currently we add multiple, which doesn't cause harm but
-    // looks strange e.g. under cargo-expand.
     let attr = match &attrs[..] {
         [] => return None,
         [attr] => attr,
-        // These two attributes are the same and unfortunately duplicated due to a previous bug.
-        [attr, _attr2] => attr,
         _ => {
-            //FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute
-            //branch above.
             span_bug!(attrs[1].span(), "cg_ssa: rustc_autodiff should only exist once per source");
         }
     };
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 0b7cad0c2fd..f52d29baf9d 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -739,13 +739,6 @@ pub enum ExtractBundledLibsError<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_unsupported_arch)]
-pub(crate) struct UnsupportedArch<'a> {
-    pub arch: &'a str,
-    pub os: &'a str,
-}
-
-#[derive(Diagnostic)]
 pub(crate) enum AppleDeploymentTarget {
     #[diag(codegen_ssa_apple_deployment_target_invalid)]
     Invalid { env_var: &'static str, error: ParseIntError },
@@ -754,12 +747,6 @@ pub(crate) enum AppleDeploymentTarget {
 }
 
 #[derive(Diagnostic)]
-pub(crate) enum AppleSdkRootError<'a> {
-    #[diag(codegen_ssa_apple_sdk_error_sdk_path)]
-    SdkPath { sdk_name: &'a str, error: Error },
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_ssa_read_file)]
 pub(crate) struct ReadFileError {
     pub message: std::io::Error,
@@ -1334,3 +1321,26 @@ pub(crate) struct MixedExportNameAndNoMangle {
     #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
     pub removal_span: Span,
 }
+
+#[derive(Diagnostic, Debug)]
+pub(crate) enum XcrunError {
+    #[diag(codegen_ssa_xcrun_failed_invoking)]
+    FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error },
+
+    #[diag(codegen_ssa_xcrun_unsuccessful)]
+    #[note]
+    Unsuccessful {
+        sdk_name: &'static str,
+        command_formatted: String,
+        stdout: String,
+        stderr: String,
+    },
+}
+
+#[derive(Diagnostic, Debug)]
+#[diag(codegen_ssa_xcrun_sdk_path_warning)]
+#[note]
+pub(crate) struct XcrunSdkPathWarning {
+    pub sdk_name: &'static str,
+    pub stderr: String,
+}
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 44b8cc459cf..d26d6edf314 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -13,6 +13,7 @@
 #![feature(let_chains)]
 #![feature(negative_impls)]
 #![feature(rustdoc_internals)]
+#![feature(string_from_utf8_lossy_owned)]
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
@@ -122,6 +123,7 @@ impl<M> ModuleCodegen<M> {
             bytecode,
             assembly,
             llvm_ir,
+            links_from_incr_cache: Vec::new(),
         }
     }
 }
@@ -135,6 +137,7 @@ pub struct CompiledModule {
     pub bytecode: Option<PathBuf>,
     pub assembly: Option<PathBuf>, // --emit=asm
     pub llvm_ir: Option<PathBuf>,  // --emit=llvm-ir, llvm-bc is in bytecode
+    pub links_from_incr_cache: Vec<PathBuf>,
 }
 
 impl CompiledModule {
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index bc9cde1b2a1..3a6b1f8d4ef 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -332,7 +332,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
     // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
     // basically the commit introducing this comment should be reverted
     if let PassMode::Pair { .. } = fn_abi.ret.mode {
-        let _ = WasmCAbi::Legacy;
+        let _ = WasmCAbi::Legacy { with_lint: true };
         span_bug!(
             tcx.def_span(def_id),
             "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
@@ -384,7 +384,7 @@ fn wasm_type<'tcx>(
                 BackendRepr::SimdVector { .. } => "v128",
                 BackendRepr::Memory { .. } => {
                     // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
-                    let _ = WasmCAbi::Legacy;
+                    let _ = WasmCAbi::Legacy { with_lint: true };
                     span_bug!(
                         tcx.def_span(def_id),
                         "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 0fe6a174735..5c14fe5cd10 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -86,13 +86,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             mir::Rvalue::Repeat(ref elem, count) => {
-                let cg_elem = self.codegen_operand(bx, elem);
-
                 // Do not generate the loop for zero-sized elements or empty arrays.
                 if dest.layout.is_zst() {
                     return;
                 }
 
+                // When the element is a const with all bytes uninit, emit a single memset that
+                // writes undef to the entire destination.
+                if let mir::Operand::Constant(const_op) = elem {
+                    let val = self.eval_mir_constant(const_op);
+                    if val.all_bytes_uninit(self.cx.tcx()) {
+                        let size = bx.const_usize(dest.layout.size.bytes());
+                        bx.memset(
+                            dest.val.llval,
+                            bx.const_undef(bx.type_i8()),
+                            size,
+                            dest.val.align,
+                            MemFlags::empty(),
+                        );
+                        return;
+                    }
+                }
+
+                let cg_elem = self.codegen_operand(bx, elem);
+
                 let try_init_all_same = |bx: &mut Bx, v| {
                     let start = dest.val.llval;
                     let size = bx.const_usize(dest.layout.size.bytes());
@@ -988,6 +1005,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::BinOp::Cmp => {
                 use std::cmp::Ordering;
                 assert!(!is_float);
+                if let Some(value) = bx.three_way_compare(lhs_ty, lhs, rhs) {
+                    return value;
+                }
                 let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
                 if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
                     // FIXME: This actually generates tighter assembly, and is a classic trick
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 5f91133d5b4..f66309cf340 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -397,6 +397,18 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
+    /// Returns `-1` if `lhs < rhs`, `0` if `lhs == rhs`, and `1` if `lhs > rhs`.
+    // FIXME: Move the default implementation from `codegen_scalar_binop` into this method and
+    // remove the `Option` return once LLVM 20 is the minimum version.
+    fn three_way_compare(
+        &mut self,
+        _ty: Ty<'tcx>,
+        _lhs: Self::Value,
+        _rhs: Self::Value,
+    ) -> Option<Self::Value> {
+        None
+    }
+
     fn memcpy(
         &mut self,
         dst: Self::Value,
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 3776fb55c2e..34239ae1d15 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -256,7 +256,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
         Err(err) => {
             let did = cid.instance.def_id();
             let global_const_id = cid.display(tcx);
-            let span = tcx.hir().span_if_local(did);
+            let span = tcx.hir_span_if_local(did);
             match err {
                 ValTreeCreationError::NodesOverflow => {
                     let handled =
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 8f286971e63..d077900587e 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -8,8 +8,9 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::{Borrow, Cow};
+use std::cell::Cell;
 use std::collections::VecDeque;
-use std::{fmt, mem, ptr};
+use std::{fmt, ptr};
 
 use rustc_abi::{Align, HasDataLayout, Size};
 use rustc_ast::Mutability;
@@ -131,7 +132,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
     /// This stores whether we are currently doing reads purely for the purpose of validation.
     /// Those reads do not trigger the machine's hooks for memory reads.
     /// Needless to say, this must only be set with great care!
-    validation_in_progress: bool,
+    validation_in_progress: Cell<bool>,
 }
 
 /// A reference to some allocation that was already bounds-checked for the given region
@@ -158,7 +159,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxIndexMap::default(),
             dead_alloc_map: FxIndexMap::default(),
-            validation_in_progress: false,
+            validation_in_progress: Cell::new(false),
         }
     }
 
@@ -715,7 +716,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
         // accesses. That means we cannot rely on the closure above or the `Some` branch below. We
         // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
-        if !self.memory.validation_in_progress {
+        if !self.memory.validation_in_progress.get() {
             if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
                 M::before_alloc_read(self, alloc_id)?;
             }
@@ -723,7 +724,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
-            if !self.memory.validation_in_progress {
+            if !self.memory.validation_in_progress.get() {
                 M::before_memory_read(
                     self.tcx,
                     &self.machine,
@@ -801,7 +802,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
     {
         let tcx = self.tcx;
-        let validation_in_progress = self.memory.validation_in_progress;
+        let validation_in_progress = self.memory.validation_in_progress.get();
 
         let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
         let ptr_and_alloc = Self::check_and_deref_ptr(
@@ -1087,23 +1088,43 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ///
     /// We do this so Miri's allocation access tracking does not show the validation
     /// reads as spurious accesses.
-    pub fn run_for_validation<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
+    pub fn run_for_validation_mut<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
         // This deliberately uses `==` on `bool` to follow the pattern
         // `assert!(val.replace(new) == old)`.
         assert!(
-            mem::replace(&mut self.memory.validation_in_progress, true) == false,
+            self.memory.validation_in_progress.replace(true) == false,
             "`validation_in_progress` was already set"
         );
         let res = f(self);
         assert!(
-            mem::replace(&mut self.memory.validation_in_progress, false) == true,
+            self.memory.validation_in_progress.replace(false) == true,
+            "`validation_in_progress` was unset by someone else"
+        );
+        res
+    }
+
+    /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
+    /// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
+    ///
+    /// We do this so Miri's allocation access tracking does not show the validation
+    /// reads as spurious accesses.
+    pub fn run_for_validation_ref<R>(&self, f: impl FnOnce(&Self) -> R) -> R {
+        // This deliberately uses `==` on `bool` to follow the pattern
+        // `assert!(val.replace(new) == old)`.
+        assert!(
+            self.memory.validation_in_progress.replace(true) == false,
+            "`validation_in_progress` was already set"
+        );
+        let res = f(self);
+        assert!(
+            self.memory.validation_in_progress.replace(false) == true,
             "`validation_in_progress` was unset by someone else"
         );
         res
     }
 
     pub(super) fn validation_in_progress(&self) -> bool {
-        self.memory.validation_in_progress
+        self.memory.validation_in_progress.get()
     }
 }
 
@@ -1375,7 +1396,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         };
         let src_alloc = self.get_alloc_raw(src_alloc_id)?;
         let src_range = alloc_range(src_offset, size);
-        assert!(!self.memory.validation_in_progress, "we can't be copying during validation");
+        assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
         // For the overlapping case, it is crucial that we trigger the read hook
         // before the write hook -- the aliasing model cares about the order.
         M::before_memory_read(
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index eb3f552cd27..fb7ba6d7ef5 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -1322,7 +1322,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
 
         // Run the visitor.
-        self.run_for_validation(|ecx| {
+        self.run_for_validation_mut(|ecx| {
             let reset_padding = reset_provenance_and_padding && {
                 // Check if `val` is actually stored in memory. If not, padding is not even
                 // represented and we need not reset it.
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 49cafcb17a0..5de9413cf15 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -256,7 +256,7 @@ impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
 }
 
 #[inline]
-fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
+pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
     let mut state = FxHasher::default();
     val.hash(&mut state);
     state.finish()
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index ffbe54d6206..3a64c924cc2 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -564,6 +564,8 @@ where
     }
 }
 
+impl_stable_traits_for_trivial_type!(::std::ffi::OsStr);
+
 impl_stable_traits_for_trivial_type!(::std::path::Path);
 impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
 
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index 05e11c4527f..2c6a0291ac2 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,3 +1,5 @@
+driver_impl_cant_emit_mir = could not emit MIR: {$error}
+
 driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
 driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 8ede6e41336..f1dc4bb795e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -20,7 +20,7 @@
 // tidy-alphabetical-end
 
 use std::cmp::max;
-use std::collections::BTreeMap;
+use std::collections::{BTreeMap, BTreeSet};
 use std::ffi::OsString;
 use std::fmt::Write as _;
 use std::fs::{self, File};
@@ -61,7 +61,7 @@ use rustc_session::config::{
 };
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
-use rustc_session::output::collect_crate_types;
+use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target};
 use rustc_session::{EarlyDiagCtxt, Session, config, filesearch};
 use rustc_span::FileName;
 use rustc_target::json::ToJson;
@@ -108,7 +108,7 @@ mod signal_handler {
 }
 
 use crate::session_diagnostics::{
-    RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
+    CantEmitMIR, RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
     RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage,
 };
 
@@ -243,12 +243,17 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
         return;
     }
 
+    let input = make_input(&default_early_dcx, &matches.free);
+    let has_input = input.is_some();
     let (odir, ofile) = make_output(&matches);
+
+    drop(default_early_dcx);
+
     let mut config = interface::Config {
         opts: sopts,
         crate_cfg: matches.opt_strs("cfg"),
         crate_check_cfg: matches.opt_strs("check-cfg"),
-        input: Input::File(PathBuf::new()),
+        input: input.unwrap_or(Input::File(PathBuf::new())),
         output_file: ofile,
         output_dir: odir,
         ice_file,
@@ -265,16 +270,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
         expanded_args: args,
     };
 
-    let has_input = match make_input(&default_early_dcx, &matches.free) {
-        Some(input) => {
-            config.input = input;
-            true // has input: normal compilation
-        }
-        None => false, // no input: we will exit early
-    };
-
-    drop(default_early_dcx);
-
     callbacks.config(&mut config);
 
     let registered_lints = config.register_lints.is_some();
@@ -379,6 +374,12 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
                 return early_exit();
             }
 
+            if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
+                if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
+                    tcx.dcx().emit_fatal(CantEmitMIR { error });
+                }
+            }
+
             Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend))
         });
 
@@ -407,7 +408,7 @@ fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
     }
 }
 
-// Extract output directory and file from matches.
+/// Extract output directory and file from matches.
 fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileName>) {
     let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
     let ofile = matches.opt_str("o").map(|o| match o.as_str() {
@@ -690,6 +691,34 @@ fn print_crate_info(
                 };
                 println_info!("{}", passes::get_crate_name(sess, attrs));
             }
+            CrateRootLintLevels => {
+                let Some(attrs) = attrs.as_ref() else {
+                    // no crate attributes, print out an error and exit
+                    return Compilation::Continue;
+                };
+                let crate_name = passes::get_crate_name(sess, attrs);
+                let lint_store = crate::unerased_lint_store(sess);
+                let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs);
+                let features = rustc_expand::config::features(sess, attrs, crate_name);
+                let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(
+                    sess,
+                    &features,
+                    true,
+                    lint_store,
+                    &registered_tools,
+                    attrs,
+                );
+                for lint in lint_store.get_lints() {
+                    if let Some(feature_symbol) = lint.feature_gate
+                        && !features.enabled(feature_symbol)
+                    {
+                        // lint is unstable and feature gate isn't active, don't print
+                        continue;
+                    }
+                    let level = lint_levels.lint_level(lint).0;
+                    println_info!("{}={}", lint.name_lower(), level.as_str());
+                }
+            }
             Cfg => {
                 let mut cfgs = sess
                     .psess
@@ -789,6 +818,16 @@ fn print_crate_info(
                     sess.dcx().fatal("only Apple targets currently support deployment version info")
                 }
             }
+            SupportedCrateTypes => {
+                let supported_crate_types = CRATE_TYPES
+                    .iter()
+                    .filter(|(_, crate_type)| !invalid_output_for_target(&sess, *crate_type))
+                    .map(|(crate_type_sym, _)| *crate_type_sym)
+                    .collect::<BTreeSet<_>>();
+                for supported_crate_type in supported_crate_types {
+                    println_info!("{}", supported_crate_type.as_str());
+                }
+            }
         }
 
         req.out.overwrite(&crate_info, sess);
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
index e06c56539d1..774221fd396 100644
--- a/compiler/rustc_driver_impl/src/session_diagnostics.rs
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -3,6 +3,12 @@ use std::error::Error;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 
 #[derive(Diagnostic)]
+#[diag(driver_impl_cant_emit_mir)]
+pub struct CantEmitMIR {
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
 #[diag(driver_impl_rlink_unable_to_read)]
 pub(crate) struct RlinkUnableToRead {
     pub err: std::io::Error,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0092.md b/compiler/rustc_error_codes/src/error_codes/E0092.md
index 84ec0656d1a..be459d040c2 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0092.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0092.md
@@ -6,10 +6,9 @@ Erroneous code example:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn atomic_foo(); // error: unrecognized atomic operation
-                     //        function
-}
+#[rustc_intrinsic]
+unsafe fn atomic_foo(); // error: unrecognized atomic operation
+                        //        function
 ```
 
 Please check you didn't make a mistake in the function's name. All intrinsic
@@ -20,7 +19,6 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn atomic_fence_seqcst(); // ok!
-}
+#[rustc_intrinsic]
+unsafe fn atomic_fence_seqcst(); // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0093.md b/compiler/rustc_error_codes/src/error_codes/E0093.md
index 2bda4d74f72..9929a069927 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0093.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0093.md
@@ -6,9 +6,8 @@ Erroneous code example:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn foo(); // error: unrecognized intrinsic function: `foo`
-}
+#[rustc_intrinsic]
+unsafe fn foo(); // error: unrecognized intrinsic function: `foo`
 
 fn main() {
     unsafe {
@@ -25,9 +24,8 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn atomic_fence_seqcst(); // ok!
-}
+#[rustc_intrinsic]
+unsafe fn atomic_fence_seqcst(); // ok!
 
 fn main() {
     unsafe {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md
index 7aa42628549..c702f14d4d6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0211.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0211.md
@@ -7,9 +7,8 @@ used. Erroneous code examples:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn unreachable(); // error: intrinsic has wrong type
-}
+#[rustc_intrinsic]
+unsafe fn unreachable(); // error: intrinsic has wrong type
 
 // or:
 
@@ -43,9 +42,8 @@ For the first code example, please check the function definition. Example:
 #![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    fn unreachable() -> !; // ok!
-}
+#[rustc_intrinsic]
+unsafe fn unreachable() -> !; // ok!
 ```
 
 The second case example is a bit particular: the main function must always
diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md
index 45ff49bdebb..0fb1cfda67d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0511.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0511.md
@@ -5,9 +5,8 @@ Erroneous code example:
 ```compile_fail,E0511
 #![feature(intrinsics)]
 
-extern "rust-intrinsic" {
-    fn simd_add<T>(a: T, b: T) -> T;
-}
+#[rustc_intrinsic]
+unsafe fn simd_add<T>(a: T, b: T) -> T;
 
 fn main() {
     unsafe { simd_add(0, 1); }
@@ -25,9 +24,8 @@ The generic type has to be a SIMD type. Example:
 #[derive(Copy, Clone)]
 struct i32x2([i32; 2]);
 
-extern "rust-intrinsic" {
-    fn simd_add<T>(a: T, b: T) -> T;
-}
+#[rustc_intrinsic]
+unsafe fn simd_add<T>(a: T, b: T) -> T;
 
 unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0789.md b/compiler/rustc_error_codes/src/error_codes/E0789.md
index 2c0018cc799..c7bc6cfde51 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0789.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0789.md
@@ -14,7 +14,7 @@ Erroneous code example:
 
 #![unstable(feature = "foo_module", reason = "...", issue = "123")]
 
-#[rustc_allowed_through_unstable_modules]
+#[rustc_allowed_through_unstable_modules = "deprecation message"]
 // #[stable(feature = "foo", since = "1.0")]
 struct Foo;
 // ^^^ error: `rustc_allowed_through_unstable_modules` attribute must be
diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs
index 8485d7087cf..f09c2ed5534 100644
--- a/compiler/rustc_errors/src/snippet.rs
+++ b/compiler/rustc_errors/src/snippet.rs
@@ -159,11 +159,7 @@ impl Annotation {
     /// Length of this annotation as displayed in the stderr output
     pub(crate) fn len(&self) -> usize {
         // Account for usize underflows
-        if self.end_col.display > self.start_col.display {
-            self.end_col.display - self.start_col.display
-        } else {
-            self.start_col.display - self.end_col.display
-        }
+        self.end_col.display.abs_diff(self.start_col.display)
     }
 
     pub(crate) fn has_label(&self) -> bool {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 1dd152beb47..d14e476ba32 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -153,7 +153,7 @@ impl Annotatable {
 
     pub fn expect_impl_item(self) -> P<ast::AssocItem> {
         match self {
-            Annotatable::AssocItem(i, AssocCtxt::Impl) => i,
+            Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
             _ => panic!("expected Item"),
         }
     }
@@ -403,6 +403,11 @@ pub trait MacResult {
         None
     }
 
+    /// Creates zero or more impl items.
+    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+        None
+    }
+
     /// Creates zero or more trait items.
     fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         None
@@ -516,6 +521,10 @@ impl MacResult for MacEager {
         self.impl_items
     }
 
+    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+        self.impl_items
+    }
+
     fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         self.trait_items
     }
@@ -613,6 +622,10 @@ impl MacResult for DummyResult {
         Some(SmallVec::new())
     }
 
+    fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+        Some(SmallVec::new())
+    }
+
     fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
@@ -1411,12 +1424,11 @@ pub fn parse_macro_name_and_helper_attrs(
 /// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
 fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
-    let name = item.ident.name;
-    if name == sym::ProceduralMasqueradeDummyType
-        && let ast::ItemKind::Enum(enum_def, _) = &item.kind
+    if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind
+        && ident.name == sym::ProceduralMasqueradeDummyType
         && let [variant] = &*enum_def.variants
         && variant.ident.name == sym::Input
-        && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span)
+        && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
         && let Some(c) = real
             .local_path()
             .unwrap_or(Path::new(""))
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index ee7f68cc2f0..f68172c1f67 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -286,7 +286,6 @@ impl<'a> ExtCtxt<'a> {
             rules: BlockCheckMode::Default,
             span,
             tokens: None,
-            could_be_bare_literal: false,
         })
     }
 
@@ -663,15 +662,8 @@ impl<'a> ExtCtxt<'a> {
         P(ast::FnDecl { inputs, output })
     }
 
-    pub fn item(
-        &self,
-        span: Span,
-        name: Ident,
-        attrs: ast::AttrVec,
-        kind: ast::ItemKind,
-    ) -> P<ast::Item> {
+    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
         P(ast::Item {
-            ident: name,
             attrs,
             id: ast::DUMMY_NODE_ID,
             kind,
@@ -688,18 +680,24 @@ impl<'a> ExtCtxt<'a> {
     pub fn item_static(
         &self,
         span: Span,
-        name: Ident,
+        ident: Ident,
         ty: P<ast::Ty>,
         mutability: ast::Mutability,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         self.item(
             span,
-            name,
             AttrVec::new(),
             ast::ItemKind::Static(
-                ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) }
-                    .into(),
+                ast::StaticItem {
+                    ident,
+                    ty,
+                    safety: ast::Safety::Default,
+                    mutability,
+                    expr: Some(expr),
+                    define_opaque: None,
+                }
+                .into(),
             ),
         )
     }
@@ -707,22 +705,23 @@ impl<'a> ExtCtxt<'a> {
     pub fn item_const(
         &self,
         span: Span,
-        name: Ident,
+        ident: Ident,
         ty: P<ast::Ty>,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         let defaultness = ast::Defaultness::Final;
         self.item(
             span,
-            name,
             AttrVec::new(),
             ast::ItemKind::Const(
                 ast::ConstItem {
                     defaultness,
+                    ident,
                     // FIXME(generic_const_items): Pass the generics as a parameter.
                     generics: ast::Generics::default(),
                     ty,
                     expr: Some(expr),
+                    define_opaque: None,
                 }
                 .into(),
             ),
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index ada49eef7b2..bcc2703c39b 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -156,6 +156,19 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec
         .collect()
 }
 
+pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute {
+    match &mut attr.kind {
+        AttrKind::Normal(normal) => {
+            let NormalAttr { item, tokens } = &mut **normal;
+            item.path.segments[0].ident.name = trace_name;
+            // This makes the trace attributes unobservable to token-based proc macros.
+            *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
+        }
+        AttrKind::DocComment(..) => unreachable!(),
+    }
+    attr
+}
+
 #[macro_export]
 macro_rules! configure {
     ($this:ident, $node:ident) => {
@@ -280,16 +293,7 @@ impl<'a> StripUnconfigured<'a> {
 
         // A trace attribute left in AST in place of the original `cfg_attr` attribute.
         // It can later be used by lints or other diagnostics.
-        let mut trace_attr = cfg_attr.clone();
-        match &mut trace_attr.kind {
-            AttrKind::Normal(normal) => {
-                let NormalAttr { item, tokens } = &mut **normal;
-                item.path.segments[0].ident.name = sym::cfg_attr_trace;
-                // This makes the trace attributes unobservable to token-based proc macros.
-                *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
-            }
-            AttrKind::DocComment(..) => unreachable!(),
-        }
+        let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
 
         let Some((cfg_predicate, expanded_attrs)) =
             rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 87f01be26c2..bca846d2ec4 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -33,7 +33,7 @@ use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym};
 use smallvec::SmallVec;
 
 use crate::base::*;
-use crate::config::StripUnconfigured;
+use crate::config::{StripUnconfigured, attr_into_trace};
 use crate::errors::{
     EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
     RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
@@ -188,9 +188,15 @@ ast_fragments! {
     ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
         "impl item";
         many fn flat_map_assoc_item;
-        fn visit_assoc_item(AssocCtxt::Impl);
+        fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
         fn make_impl_items;
     }
+    TraitImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+        "impl item";
+        many fn flat_map_assoc_item;
+        fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
+        fn make_trait_impl_items;
+    }
     ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
         "foreign item";
         many fn flat_map_foreign_item;
@@ -257,6 +263,7 @@ impl AstFragmentKind {
             AstFragmentKind::Items
             | AstFragmentKind::TraitItems
             | AstFragmentKind::ImplItems
+            | AstFragmentKind::TraitImplItems
             | AstFragmentKind::ForeignItems
             | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
             AstFragmentKind::Arms
@@ -306,6 +313,9 @@ impl AstFragmentKind {
             AstFragmentKind::ImplItems => {
                 AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
             }
+            AstFragmentKind::TraitImplItems => {
+                AstFragment::TraitImplItems(items.map(Annotatable::expect_impl_item).collect())
+            }
             AstFragmentKind::TraitItems => {
                 AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
             }
@@ -347,10 +357,10 @@ pub enum InvocationKind {
     },
     Attr {
         attr: ast::Attribute,
-        // Re-insertion position for inert attributes.
+        /// Re-insertion position for inert attributes.
         pos: usize,
         item: Annotatable,
-        // Required for resolving derive helper attributes.
+        /// Required for resolving derive helper attributes.
         derives: Vec<ast::Path>,
     },
     Derive {
@@ -360,6 +370,8 @@ pub enum InvocationKind {
     },
     GlobDelegation {
         item: P<ast::AssocItem>,
+        /// Whether this is a trait impl or an inherent impl
+        of_trait: bool,
     },
 }
 
@@ -388,7 +400,7 @@ impl Invocation {
             InvocationKind::Bang { span, .. } => *span,
             InvocationKind::Attr { attr, .. } => attr.span,
             InvocationKind::Derive { path, .. } => path.span,
-            InvocationKind::GlobDelegation { item } => item.span,
+            InvocationKind::GlobDelegation { item, .. } => item.span,
         }
     }
 
@@ -397,7 +409,7 @@ impl Invocation {
             InvocationKind::Bang { span, .. } => span,
             InvocationKind::Attr { attr, .. } => &mut attr.span,
             InvocationKind::Derive { path, .. } => &mut path.span,
-            InvocationKind::GlobDelegation { item } => &mut item.span,
+            InvocationKind::GlobDelegation { item, .. } => &mut item.span,
         }
     }
 }
@@ -732,6 +744,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     item_inner.kind,
                                     ItemKind::Mod(
                                         _,
+                                        _,
                                         ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
                                     )
                                 ) =>
@@ -820,7 +833,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 _ => unreachable!(),
             },
-            InvocationKind::GlobDelegation { item } => {
+            InvocationKind::GlobDelegation { item, of_trait } => {
                 let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
                 let suffixes = match ext {
                     SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx)
@@ -829,7 +842,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         ExpandResult::Retry(()) => {
                             // Reassemble the original invocation for retrying.
                             return ExpandResult::Retry(Invocation {
-                                kind: InvocationKind::GlobDelegation { item },
+                                kind: InvocationKind::GlobDelegation { item, of_trait },
                                 ..invoc
                             });
                         }
@@ -847,7 +860,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     self.cx, deleg, &item, &suffixes, item.span, true,
                 );
                 fragment_kind.expect_from_annotatables(
-                    single_delegations.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl)),
+                    single_delegations
+                        .map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl { of_trait })),
                 )
             }
         })
@@ -898,7 +912,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
-                    ItemKind::Mod(_, mod_kind)
+                    ItemKind::Mod(_, _, mod_kind)
                         if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
                     {
                         feature_err(
@@ -973,6 +987,13 @@ pub fn parse_ast_fragment<'a>(
             }
             AstFragment::ImplItems(items)
         }
+        AstFragmentKind::TraitImplItems => {
+            let mut items = SmallVec::new();
+            while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
+                items.extend(item);
+            }
+            AstFragment::TraitImplItems(items)
+        }
         AstFragmentKind::ForeignItems => {
             let mut items = SmallVec::new();
             while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
@@ -1201,9 +1222,8 @@ impl InvocationCollectorNode for P<ast::Item> {
         }
 
         // Work around borrow checker not seeing through `P`'s deref.
-        let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs));
-        let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() };
-
+        let (span, mut attrs) = (node.span, mem::take(&mut node.attrs));
+        let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
             ModKind::Loaded(_, inline, _, _) => {
@@ -1285,6 +1305,7 @@ impl InvocationCollectorNode for P<ast::Item> {
         collector.cx.current_expansion.module = orig_module;
         res
     }
+
     fn declared_names(&self) -> Vec<Ident> {
         if let ItemKind::Use(ut) = &self.kind {
             fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
@@ -1304,7 +1325,7 @@ impl InvocationCollectorNode for P<ast::Item> {
             return idents;
         }
 
-        vec![self.ident]
+        if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] }
     }
 }
 
@@ -1355,13 +1376,13 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl)
+        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false })
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_impl_items()
     }
     fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl)
+        walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: false })
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
@@ -1390,6 +1411,47 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
     }
 }
 
+struct TraitImplItemTag;
+impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItemTag> {
+    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+    type ItemKind = AssocItemKind;
+    const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;
+    fn to_annotatable(self) -> Annotatable {
+        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true })
+    }
+    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
+        fragment.make_trait_impl_items()
+    }
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: true })
+    }
+    fn is_mac_call(&self) -> bool {
+        matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
+    }
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
+        let item = self.wrapped.into_inner();
+        match item.kind {
+            AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
+            _ => unreachable!(),
+        }
+    }
+    fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        match &self.wrapped.kind {
+            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
+            _ => None,
+        }
+    }
+    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        AssocItemKind::Delegation(deleg)
+    }
+    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
+        AstNodeWrapper::new(P(item), TraitImplItemTag)
+    }
+    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        items.flatten().collect()
+    }
+}
+
 impl InvocationCollectorNode for P<ast::ForeignItem> {
     const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;
     fn to_annotatable(self) -> Annotatable {
@@ -1783,11 +1845,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
             id: ast::DUMMY_NODE_ID,
             span: if from_glob { item_span } else { ident.span },
             vis: item.vis.clone(),
-            ident: rename.unwrap_or(ident),
             kind: Node::delegation_item_kind(Box::new(ast::Delegation {
                 id: ast::DUMMY_NODE_ID,
                 qself: deleg.qself.clone(),
                 path,
+                ident: rename.unwrap_or(ident),
                 rename,
                 body: deleg.body.clone(),
                 from_glob,
@@ -1855,9 +1917,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect_glob_delegation(
         &mut self,
         item: P<ast::AssocItem>,
+        of_trait: bool,
         kind: AstFragmentKind,
     ) -> AstFragment {
-        self.collect(kind, InvocationKind::GlobDelegation { item })
+        self.collect(kind, InvocationKind::GlobDelegation { item, of_trait })
     }
 
     /// If `item` is an attribute invocation, remove the attribute and return it together with
@@ -1941,7 +2004,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 let attr_name = attr.ident().unwrap().name;
                 // `#[cfg]` and `#[cfg_attr]` are special - they are
                 // eagerly evaluated.
-                if attr_name != sym::cfg && attr_name != sym::cfg_attr {
+                if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {
                     self.cx.sess.psess.buffer_lint(
                         UNUSED_ATTRIBUTES,
                         attr.span,
@@ -1965,11 +2028,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     ) -> (bool, Option<ast::MetaItem>) {
         let (res, meta_item) = self.cfg().cfg_true(&attr);
         if res {
-            // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
-            // and some tools like rustdoc and clippy rely on that. Find a way to remove them
-            // while keeping the tools working.
-            self.cx.expanded_inert_attrs.mark(&attr);
-            node.visit_attrs(|attrs| attrs.insert(pos, attr));
+            // A trace attribute left in AST in place of the original `cfg` attribute.
+            // It can later be used by lints or other diagnostics.
+            let trace_attr = attr_into_trace(attr, sym::cfg_trace);
+            node.visit_attrs(|attrs| attrs.insert(pos, trace_attr));
         }
 
         (res, meta_item)
@@ -2030,8 +2092,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     let Some(suffixes) = &deleg.suffixes else {
                         let traitless_qself =
                             matches!(&deleg.qself, Some(qself) if qself.position == 0);
-                        let item = match node.to_annotatable() {
-                            Annotatable::AssocItem(item, AssocCtxt::Impl) => item,
+                        let (item, of_trait) = match node.to_annotatable() {
+                            Annotatable::AssocItem(item, AssocCtxt::Impl { of_trait }) => {
+                                (item, of_trait)
+                            }
                             ann @ (Annotatable::Item(_)
                             | Annotatable::AssocItem(..)
                             | Annotatable::Stmt(_)) => {
@@ -2046,7 +2110,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                             self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
                             return Default::default();
                         }
-                        return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>();
+                        return self
+                            .collect_glob_delegation(item, of_trait, Node::KIND)
+                            .make_ast::<Node>();
                     };
 
                     let single_delegations = build_single_delegations::<Node>(
@@ -2126,7 +2192,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     ) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match ctxt {
             AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
-            AssocCtxt::Impl => self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)),
+            AssocCtxt::Impl { of_trait: false } => {
+                self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
+            }
+            AssocCtxt::Impl { of_trait: true } => {
+                self.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag))
+            }
         }
     }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index cffa4af6ac3..6e47ed6eb67 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -3,11 +3,10 @@ use std::sync::Arc;
 
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{
-    self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token,
-    TokenKind,
+    self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind,
 };
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
-use rustc_ast::{ExprKind, StmtKind, TyKind};
+use rustc_ast::{ExprKind, StmtKind, TyKind, UnOp};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
 use rustc_parse::lexer::nfc_normalize;
@@ -340,6 +339,30 @@ pub(super) fn transcribe<'a>(
                             MetaVarKind::Pat(*pat_kind),
                             TokenStream::from_ast(pat),
                         ),
+                        MatchedSingle(ParseNtResult::Expr(expr, kind)) => {
+                            let (can_begin_literal_maybe_minus, can_begin_string_literal) =
+                                match &expr.kind {
+                                    ExprKind::Lit(_) => (true, true),
+                                    ExprKind::Unary(UnOp::Neg, e)
+                                        if matches!(&e.kind, ExprKind::Lit(_)) =>
+                                    {
+                                        (true, false)
+                                    }
+                                    _ => (false, false),
+                                };
+                            mk_delimited(
+                                expr.span,
+                                MetaVarKind::Expr {
+                                    kind: *kind,
+                                    can_begin_literal_maybe_minus,
+                                    can_begin_string_literal,
+                                },
+                                TokenStream::from_ast(expr),
+                            )
+                        }
+                        MatchedSingle(ParseNtResult::Literal(lit)) => {
+                            mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit))
+                        }
                         MatchedSingle(ParseNtResult::Ty(ty)) => {
                             let is_path = matches!(&ty.kind, TyKind::Path(None, _path));
                             mk_delimited(
@@ -869,10 +892,8 @@ fn extract_symbol_from_pnr<'a>(
             },
             _,
         )) => Ok(*symbol),
-        ParseNtResult::Nt(nt)
-            if let Nonterminal::NtLiteral(expr) = &**nt
-                && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) =
-                    &expr.kind =>
+        ParseNtResult::Literal(expr)
+            if let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind =>
         {
             Ok(*symbol)
         }
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 3a470924c7f..0136292decb 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -26,7 +26,7 @@ pub(crate) fn placeholder(
         })
     }
 
-    let ident = Ident::empty();
+    let ident = Ident::dummy();
     let attrs = ast::AttrVec::new();
     let vis = vis.unwrap_or(ast::Visibility {
         span: DUMMY_SP,
@@ -62,7 +62,6 @@ pub(crate) fn placeholder(
         AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::ItemKind::MacCall(mac_placeholder()),
@@ -71,7 +70,6 @@ pub(crate) fn placeholder(
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -80,17 +78,25 @@ pub(crate) fn placeholder(
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
+        AstFragmentKind::TraitImplItems => {
+            AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
+                id,
+                span,
+                vis,
+                attrs,
+                kind: ast::AssocItemKind::MacCall(mac_placeholder()),
+                tokens: None,
+            })])
+        }
         AstFragmentKind::ForeignItems => {
             AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
                 id,
                 span,
-                ident,
                 vis,
                 attrs,
                 kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
@@ -308,7 +314,8 @@ impl MutVisitor for PlaceholderExpander {
                 let it = self.remove(item.id);
                 match ctxt {
                     AssocCtxt::Trait => it.make_trait_items(),
-                    AssocCtxt::Impl => it.make_impl_items(),
+                    AssocCtxt::Impl { of_trait: false } => it.make_impl_items(),
+                    AssocCtxt::Impl { of_trait: true } => it.make_trait_impl_items(),
                 }
             }
             _ => walk_flat_map_assoc_item(self, item, ctxt),
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 980f3946035..88e6593572b 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -331,6 +331,8 @@ declare_features! (
     (accepted, pattern_parentheses, "1.31.0", Some(51087)),
     /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
     (accepted, precise_capturing, "1.82.0", Some(123432)),
+    /// Allows `use<..>` precise capturign on impl Trait in traits.
+    (accepted, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)),
     /// Allows procedural macros in `proc-macro` crates.
     (accepted, proc_macro, "1.29.0", Some(38356)),
     /// Allows multi-segment paths in attributes and derives.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 5430bfde785..1e33e2e9393 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -661,6 +661,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "`rustc_never_type_options` is used to experiment with never type fallback and work on \
          never type stabilization, and will never be stable"
     ),
+    rustc_attr!(
+        rustc_macro_edition_2021,
+        Normal,
+        template!(Word),
+        ErrorFollowing,
+        EncodeCrossCrate::No,
+        "makes spans in this macro edition 2021"
+    ),
 
     // ==========================================================================
     // Internal attributes: Runtime related:
@@ -752,10 +760,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word, List: r#""...""#), DuplicatesOk,
         EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
     ),
-    // Trace that is left when a `cfg_attr` attribute is expanded.
-    // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or
-    // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only
-    // be generated by the compiler.
+    // Traces that are left when `cfg` and `cfg_attr` attributes are expanded.
+    // The attributes are not gated, to avoid stability errors, but they cannot be used in stable
+    // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they
+    // can only be generated by the compiler.
+    ungated!(
+        cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
+        EncodeCrossCrate::No
+    ),
     ungated!(
         cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
         EncodeCrossCrate::No
@@ -1075,9 +1087,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         WarnFollowing, EncodeCrossCrate::No
     ),
     rustc_attr!(
-        TEST, rustc_error, Normal,
-        template!(Word, List: "delayed_bug_from_inside_query"),
-        WarnFollowingWordOnly, EncodeCrossCrate::Yes
+        TEST, rustc_delayed_bug_from_inside_query, Normal,
+        template!(Word),
+        WarnFollowing, EncodeCrossCrate::No
     ),
     rustc_attr!(
         TEST, rustc_dump_user_args, Normal, template!(Word),
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 47e4f9a2fe8..6ba7b22a0df 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -142,6 +142,9 @@ declare_features! (
     /// Allows inferring `'static` outlives requirements (RFC 2093).
     (removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
      Some("removed as it caused some confusion and discussion was inactive for years")),
+    /// Allow anonymous constants from an inline `const` block in pattern position
+    (removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001),
+     Some("removed due to implementation concerns as it requires significant refactorings")),
     /// Lazily evaluate constants. This allows constants to depend on type parameters.
     (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
     /// Changes `impl Trait` to capture all lifetimes in scope.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3b75c69132c..87b88bb4223 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -324,6 +324,7 @@ declare_features! (
     (unstable, loongarch_target_feature, "1.73.0", Some(44839)),
     (unstable, m68k_target_feature, "1.85.0", Some(134328)),
     (unstable, mips_target_feature, "1.27.0", Some(44839)),
+    (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)),
     (unstable, powerpc_target_feature, "1.27.0", Some(44839)),
     (unstable, prfchw_target_feature, "1.78.0", Some(44839)),
     (unstable, riscv_target_feature, "1.45.0", Some(44839)),
@@ -531,8 +532,6 @@ declare_features! (
     (unstable, import_trait_associated_functions, "1.86.0", Some(134691)),
     /// Allows associated types in inherent impls.
     (incomplete, inherent_associated_types, "1.52.0", Some(8995)),
-    /// Allow anonymous constants from an inline `const` block in pattern position
-    (unstable, inline_const_pat, "1.58.0", Some(76001)),
     /// Allows using `pointer` and `reference` in intra-doc links
     (unstable, intra_doc_pointers, "1.51.0", Some(80896)),
     // Allows using the `kl` and `widekl` target features and the associated intrinsics
@@ -566,6 +565,8 @@ declare_features! (
     (incomplete, mut_ref, "1.79.0", Some(123076)),
     /// Allows using `#[naked]` on functions.
     (unstable, naked_functions, "1.9.0", Some(90957)),
+    /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.
+    (unstable, naked_functions_target_feature, "1.86.0", Some(138568)),
     /// Allows specifying the as-needed link modifier
     (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)),
     /// Allow negative trait implementations.
@@ -598,8 +599,6 @@ declare_features! (
     (incomplete, pin_ergonomics, "1.83.0", Some(130494)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
-    /// Allows `use<..>` precise capturign on impl Trait in traits.
-    (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows the use of raw-dylibs on ELF platforms
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 4e9d21c900d..0df1b243d69 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -55,25 +55,31 @@ pub enum LinkOrCopy {
     Copy,
 }
 
-/// Copies `p` into `q`, preferring to use hard-linking if possible. If
-/// `q` already exists, it is removed first.
+/// Copies `p` into `q`, preferring to use hard-linking if possible.
 /// The result indicates which of the two operations has been performed.
 pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
+    // Creating a hard-link will fail if the destination path already exists. We could defensively
+    // call remove_file in this function, but that pessimizes callers who can avoid such calls.
+    // Incremental compilation calls this function a lot, and is able to avoid calls that
+    // would fail the first hard_link attempt.
+
     let p = p.as_ref();
     let q = q.as_ref();
-    match fs::remove_file(q) {
-        Ok(()) => (),
-        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
-        Err(err) => return Err(err),
-    }
 
-    match fs::hard_link(p, q) {
-        Ok(()) => Ok(LinkOrCopy::Link),
-        Err(_) => match fs::copy(p, q) {
-            Ok(_) => Ok(LinkOrCopy::Copy),
-            Err(e) => Err(e),
-        },
+    let err = match fs::hard_link(p, q) {
+        Ok(()) => return Ok(LinkOrCopy::Link),
+        Err(err) => err,
+    };
+
+    if err.kind() == io::ErrorKind::AlreadyExists {
+        fs::remove_file(q)?;
+        if fs::hard_link(p, q).is_ok() {
+            return Ok(LinkOrCopy::Link);
+        }
     }
+
+    // Hard linking failed, fall back to copying.
+    fs::copy(p, q).map(|_| LinkOrCopy::Copy)
 }
 
 #[cfg(any(unix, all(target_os = "wasi", target_env = "p1")))]
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 5f8941d4754..dc00b52a593 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -294,7 +294,7 @@ impl DefKind {
             DefKind::GlobalAsm => DefPathData::GlobalAsm,
             DefKind::Impl { .. } => DefPathData::Impl,
             DefKind::Closure => DefPathData::Closure,
-            DefKind::SyntheticCoroutineBody => DefPathData::Closure,
+            DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
         }
     }
 
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 61f5efd9978..c52954aa96f 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -291,6 +291,8 @@ pub enum DefPathData {
     /// An existential `impl Trait` type node.
     /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
     OpaqueTy,
+    /// A synthetic body for a coroutine's by-move body.
+    SyntheticCoroutineBody,
 }
 
 impl Definitions {
@@ -415,8 +417,16 @@ impl DefPathData {
 
             ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
 
-            Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
-            | OpaqueTy => None,
+            Impl
+            | ForeignMod
+            | CrateRoot
+            | Use
+            | GlobalAsm
+            | Closure
+            | Ctor
+            | AnonConst
+            | OpaqueTy
+            | SyntheticCoroutineBody => None,
         }
     }
 
@@ -441,6 +451,7 @@ impl DefPathData {
             Ctor => DefPathDataName::Anon { namespace: sym::constructor },
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
             OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
+            SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 751c379b21a..f8af1b81ca9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -35,20 +35,60 @@ use crate::def_id::{DefId, LocalDefIdMap};
 pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
 use crate::intravisit::{FnKind, VisitorExt};
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
+pub enum IsAnonInPath {
+    No,
+    Yes,
+}
+
+/// A lifetime. The valid field combinations are non-obvious. The following
+/// example shows some of them. See also the comments on `LifetimeName`.
+/// ```
+/// #[repr(C)]
+/// struct S<'a>(&'a u32);       // res=Param, name='a, IsAnonInPath::No
+/// unsafe extern "C" {
+///     fn f1(s: S);             // res=Param, name='_, IsAnonInPath::Yes
+///     fn f2(s: S<'_>);         // res=Param, name='_, IsAnonInPath::No
+///     fn f3<'a>(s: S<'a>);     // res=Param, name='a, IsAnonInPath::No
+/// }
+///
+/// struct St<'a> { x: &'a u32 } // res=Param, name='a, IsAnonInPath::No
+/// fn f() {
+///     _ = St { x: &0 };        // res=Infer, name='_, IsAnonInPath::Yes
+///     _ = St::<'_> { x: &0 };  // res=Infer, name='_, IsAnonInPath::No
+/// }
+///
+/// struct Name<'a>(&'a str);    // res=Param,  name='a, IsAnonInPath::No
+/// const A: Name = Name("a");   // res=Static, name='_, IsAnonInPath::Yes
+/// const B: &str = "";          // res=Static, name='_, IsAnonInPath::No
+/// static C: &'_ str = "";      // res=Static, name='_, IsAnonInPath::No
+/// static D: &'static str = ""; // res=Static, name='static, IsAnonInPath::No
+///
+/// trait Tr {}
+/// fn tr(_: Box<dyn Tr>) {}     // res=ImplicitObjectLifetimeDefault, name='_, IsAnonInPath::No
+///
+/// // (commented out because these cases trigger errors)
+/// // struct S1<'a>(&'a str);   // res=Param, name='a, IsAnonInPath::No
+/// // struct S2(S1);            // res=Error, name='_, IsAnonInPath::Yes
+/// // struct S3(S1<'_>);        // res=Error, name='_, IsAnonInPath::No
+/// // struct S4(S1<'a>);        // res=Error, name='a, IsAnonInPath::No
+/// ```
 #[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub struct Lifetime {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
 
-    /// Either "`'a`", referring to a named lifetime definition,
-    /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`),
-    /// or "``" (i.e., `kw::Empty`) when appearing in path.
-    ///
-    /// See `Lifetime::suggestion_position` for practical use.
+    /// Either a named lifetime definition (e.g. `'a`, `'static`) or an
+    /// anonymous lifetime (`'_`, either explicitly written, or inserted for
+    /// things like `&type`).
     pub ident: Ident,
 
     /// Semantics of this lifetime.
     pub res: LifetimeName,
+
+    /// Is the lifetime anonymous and in a path? Used only for error
+    /// suggestions. See `Lifetime::suggestion` for example use.
+    pub is_anon_in_path: IsAnonInPath,
 }
 
 #[derive(Debug, Copy, Clone, HashStable_Generic)]
@@ -111,11 +151,12 @@ pub enum LifetimeName {
     /// that was already reported.
     Error,
 
-    /// User wrote an anonymous lifetime, either `'_` or nothing.
-    /// The semantics of this lifetime should be inferred by typechecking code.
+    /// User wrote an anonymous lifetime, either `'_` or nothing (which gets
+    /// converted to `'_`). The semantics of this lifetime should be inferred
+    /// by typechecking code.
     Infer,
 
-    /// User wrote `'static`.
+    /// User wrote `'static` or nothing (which gets converted to `'_`).
     Static,
 }
 
@@ -135,59 +176,57 @@ impl LifetimeName {
 
 impl fmt::Display for Lifetime {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
+        self.ident.name.fmt(f)
     }
 }
 
-pub enum LifetimeSuggestionPosition {
-    /// The user wrote `'a` or `'_`.
-    Normal,
-    /// The user wrote `&type` or `&mut type`.
-    Ampersand,
-    /// The user wrote `Path` and omitted the `<'_>`.
-    ElidedPath,
-    /// The user wrote `Path<T>`, and omitted the `'_,`.
-    ElidedPathArgument,
-    /// The user wrote `dyn Trait` and omitted the `+ '_`.
-    ObjectDefault,
-}
-
 impl Lifetime {
+    pub fn new(
+        hir_id: HirId,
+        ident: Ident,
+        res: LifetimeName,
+        is_anon_in_path: IsAnonInPath,
+    ) -> Lifetime {
+        let lifetime = Lifetime { hir_id, ident, res, is_anon_in_path };
+
+        // Sanity check: elided lifetimes form a strict subset of anonymous lifetimes.
+        #[cfg(debug_assertions)]
+        match (lifetime.is_elided(), lifetime.is_anonymous()) {
+            (false, false) => {} // e.g. `'a`
+            (false, true) => {}  // e.g. explicit `'_`
+            (true, true) => {}   // e.g. `&x`
+            (true, false) => panic!("bad Lifetime"),
+        }
+
+        lifetime
+    }
+
     pub fn is_elided(&self) -> bool {
         self.res.is_elided()
     }
 
     pub fn is_anonymous(&self) -> bool {
-        self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
-    }
-
-    pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
-        if self.ident.name == kw::Empty {
-            if self.ident.span.is_empty() {
-                (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span)
-            } else {
-                (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi())
-            }
-        } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault {
-            (LifetimeSuggestionPosition::ObjectDefault, self.ident.span)
-        } else if self.ident.span.is_empty() {
-            (LifetimeSuggestionPosition::Ampersand, self.ident.span)
-        } else {
-            (LifetimeSuggestionPosition::Normal, self.ident.span)
-        }
+        self.ident.name == kw::UnderscoreLifetime
     }
 
     pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
         debug_assert!(new_lifetime.starts_with('\''));
-        let (pos, span) = self.suggestion_position();
-        let code = match pos {
-            LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
-            LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
-            LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
-            LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
-            LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
-        };
-        (span, code)
+
+        match (self.is_anon_in_path, self.ident.span.is_empty()) {
+            // The user wrote `Path<T>`, and omitted the `'_,`.
+            (IsAnonInPath::Yes, true) => (self.ident.span, format!("{new_lifetime}, ")),
+
+            // The user wrote `Path` and omitted the `<'_>`.
+            (IsAnonInPath::Yes, false) => {
+                (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
+            }
+
+            // The user wrote `&type` or `&mut type`.
+            (IsAnonInPath::No, true) => (self.ident.span, format!("{new_lifetime} ")),
+
+            // The user wrote `'a` or `'_`.
+            (IsAnonInPath::No, false) => (self.ident.span, format!("{new_lifetime}")),
+        }
     }
 }
 
@@ -2084,7 +2123,7 @@ pub type Lit = Spanned<LitKind>;
 /// explicit discriminant values for enum variants.
 ///
 /// You can check if this anon const is a default in a const param
-/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)`
+/// `const N: usize = { ... }` with `tcx.hir_opt_const_param_default_param_def_id(..)`
 #[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub struct AnonConst {
     #[stable_hasher(ignore)]
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index f75b9662132..62ef02d2f50 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -58,6 +58,7 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
                     hir_id: HirId::INVALID,
                     ident: Ident::new(sym::name, DUMMY_SP),
                     res: LifetimeName::Static,
+                    is_anon_in_path: IsAnonInPath::No,
                 }
             },
             syntax,
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 29f4d5b8076..e625514e9ff 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -322,7 +322,6 @@ language_item_table! {
     BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn,             GenericRequirement::None;
 
     // Lang items needed for `format_args!()`.
-    FormatAlignment,         sym::format_alignment,    format_alignment,           Target::Enum,           GenericRequirement::None;
     FormatArgument,          sym::format_argument,     format_argument,            Target::Struct,         GenericRequirement::None;
     FormatArguments,         sym::format_arguments,    format_arguments,           Target::Struct,         GenericRequirement::None;
     FormatCount,             sym::format_count,        format_count,               Target::Enum,           GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs
index 8a841a11556..58c3020f60e 100644
--- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs
+++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs
@@ -36,10 +36,8 @@ use crate::hir::def_id::{DefId, LocalDefId};
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 pub(crate) fn check_drop_impl(
     tcx: TyCtxt<'_>,
-    drop_impl_did: DefId,
+    drop_impl_did: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
-    let drop_impl_did = drop_impl_did.expect_local();
-
     match tcx.impl_polarity(drop_impl_did) {
         ty::ImplPolarity::Positive => {}
         ty::ImplPolarity::Negative => {
@@ -56,9 +54,9 @@ pub(crate) fn check_drop_impl(
 
     tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
 
-    let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
+    let self_ty = tcx.type_of(drop_impl_did).instantiate_identity();
 
-    match dtor_impl_trait_ref.self_ty().kind() {
+    match self_ty.kind() {
         ty::Adt(adt_def, adt_to_impl_args) => {
             ensure_impl_params_and_item_params_correspond(
                 tcx,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 07b5837bd87..a0798656763 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -578,10 +578,8 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
                 }
             }
             _ => {
-                tcx.dcx().span_delayed_bug(
-                    tcx.hir().span(hir_id),
-                    "parameter should have been resolved",
-                );
+                tcx.dcx()
+                    .span_delayed_bug(tcx.hir_span(hir_id), "parameter should have been resolved");
             }
         }
     }
@@ -1049,7 +1047,7 @@ fn check_impl_items_against_trait<'tcx>(
                 leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
 
             if !is_implemented_here {
-                let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
+                let full_impl_span = tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(impl_id));
                 match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
                     EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
                         tcx,
@@ -1105,7 +1103,7 @@ fn check_impl_items_against_trait<'tcx>(
         }
 
         if !missing_items.is_empty() {
-            let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
+            let full_impl_span = tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(impl_id));
             missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
         }
 
@@ -1321,7 +1319,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
         let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did);
         let layout = tcx.layout_of(typing_env.as_query_input(ty));
         // We are currently checking the type this field came from, so it must be local
-        let span = tcx.hir().span_if_local(field.did).unwrap();
+        let span = tcx.hir_span_if_local(field.did).unwrap();
         let trivial = layout.is_ok_and(|layout| layout.is_1zst());
         if !trivial {
             return (span, trivial, None);
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 84d07c711fa..aec9518494c 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1208,7 +1208,7 @@ fn extract_spans_for_error_reporting<'tcx>(
         TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
             (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
         }
-        _ => (cause.span, tcx.hir().span_if_local(trait_m.def_id)),
+        _ => (cause.span, tcx.hir_span_if_local(trait_m.def_id)),
     }
 }
 
@@ -1261,7 +1261,7 @@ fn compare_self_type<'tcx>(
                 self_descr
             );
             err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
-            if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
+            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("trait method declared without `{self_descr}`"));
             } else {
                 err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
@@ -1281,7 +1281,7 @@ fn compare_self_type<'tcx>(
                 self_descr
             );
             err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
-            if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
+            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("`{self_descr}` used in trait"));
             } else {
                 err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
@@ -1389,7 +1389,7 @@ fn compare_number_of_generics<'tcx>(
                     .collect();
                 (Some(arg_spans), impl_trait_spans)
             } else {
-                let trait_span = tcx.hir().span_if_local(trait_.def_id);
+                let trait_span = tcx.hir_span_if_local(trait_.def_id);
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
@@ -1481,7 +1481,7 @@ fn compare_number_of_method_arguments<'tcx>(
                     }
                 })
             })
-            .or_else(|| tcx.hir().span_if_local(trait_m.def_id));
+            .or_else(|| tcx.hir_span_if_local(trait_m.def_id));
 
         let (impl_m_sig, _) = &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         let pos = impl_number_args.saturating_sub(1);
@@ -2366,7 +2366,7 @@ fn try_report_async_mismatch<'tcx>(
             return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture {
                 span: tcx.def_span(impl_m.def_id),
                 method_name: tcx.item_ident(impl_m.def_id),
-                trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
+                trait_item_span: tcx.hir_span_if_local(trait_m.def_id),
             }));
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index d63165f0f16..32a582aadc1 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -29,6 +29,7 @@ enum NonAsmTypeReason<'tcx> {
     Invalid(Ty<'tcx>),
     InvalidElement(DefId, Ty<'tcx>),
     NotSizedPtr(Ty<'tcx>),
+    EmptySIMDArray(Ty<'tcx>),
 }
 
 impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
@@ -102,6 +103,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             }
             ty::Adt(adt, args) if adt.repr().simd() => {
                 let fields = &adt.non_enum_variant().fields;
+                if fields.is_empty() {
+                    return Err(NonAsmTypeReason::EmptySIMDArray(ty));
+                }
                 let field = &fields[FieldIdx::ZERO];
                 let elem_ty = field.ty(self.tcx(), args);
 
@@ -226,6 +230,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                             can be used as arguments for inline assembly",
                         ).emit();
                     }
+                    NonAsmTypeReason::EmptySIMDArray(ty) => {
+                        let msg = format!("use of empty SIMD vector `{ty}`");
+                        self.infcx.dcx().struct_span_err(expr.span, msg).emit();
+                    }
                 }
                 return None;
             }
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index d8ae4214527..177243b1b76 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
-    tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
+    tcx.calculate_dtor(def_id, always_applicable::check_drop_impl)
 }
 
 fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
-    tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
+    tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl)
 }
 
 /// Given a `DefId` for an opaque type in return position, find its parent item's return
@@ -243,7 +243,7 @@ fn missing_items_err(
             tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
         ));
         let code = format!("{padding}{snippet}\n{padding}");
-        if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
+        if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) {
             missing_trait_item_label
                 .push(errors::MissingTraitItemLabel { span, item: trait_item.name });
             missing_trait_item.push(errors::MissingTraitItemSuggestion {
@@ -534,7 +534,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d
     let variant_spans: Vec<_> = adt
         .variants()
         .iter()
-        .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
+        .map(|variant| tcx.hir_span_if_local(variant.def_id).unwrap())
         .collect();
     let (mut spans, mut many) = (Vec::new(), None);
     if let [start @ .., end] = &*variant_spans {
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 255f5fee52a..cf66ab708bb 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -8,7 +8,6 @@
 
 use std::mem;
 
-use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
@@ -23,12 +22,11 @@ use tracing::debug;
 
 #[derive(Debug, Copy, Clone)]
 struct Context {
-    /// The scope that contains any new variables declared, plus its depth in
-    /// the scope tree.
-    var_parent: Option<(Scope, ScopeDepth)>,
+    /// The scope that contains any new variables declared.
+    var_parent: Option<Scope>,
 
-    /// Region parent of expressions, etc., plus its depth in the scope tree.
-    parent: Option<(Scope, ScopeDepth)>,
+    /// Region parent of expressions, etc.
+    parent: Option<Scope>,
 }
 
 struct ScopeResolutionVisitor<'tcx> {
@@ -46,28 +44,6 @@ struct ScopeResolutionVisitor<'tcx> {
     scope_tree: ScopeTree,
 
     cx: Context,
-
-    /// `terminating_scopes` is a set containing the ids of each
-    /// statement, or conditional/repeating expression. These scopes
-    /// are calling "terminating scopes" because, when attempting to
-    /// find the scope of a temporary, by default we search up the
-    /// enclosing scopes until we encounter the terminating scope. A
-    /// conditional/repeating expression is one which is not
-    /// guaranteed to execute exactly once upon entering the parent
-    /// scope. This could be because the expression only executes
-    /// conditionally, such as the expression `b` in `a && b`, or
-    /// because the expression may execute many times, such as a loop
-    /// body. The reason that we distinguish such expressions is that,
-    /// upon exiting the parent scope, we cannot statically know how
-    /// many times the expression executed, and thus if the expression
-    /// creates temporaries we cannot know statically how many such
-    /// temporaries we would have to cleanup. Therefore, we ensure that
-    /// the temporaries never outlast the conditional/repeating
-    /// expression, preventing the need for dynamic checks and/or
-    /// arbitrary amounts of stack space. Terminating scopes end
-    /// up being contained in a DestructionScope that contains the
-    /// destructor's execution.
-    terminating_scopes: FxHashSet<hir::ItemLocalId>,
 }
 
 /// Records the lifetime of a local variable as `cx.var_parent`
@@ -78,11 +54,15 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It
             //
             // extern fn isalnum(c: c_int) -> c_int
         }
-        Some((parent_scope, _)) => visitor.scope_tree.record_var_scope(var_id, parent_scope),
+        Some(parent_scope) => visitor.scope_tree.record_var_scope(var_id, parent_scope),
     }
 }
 
-fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hir::Block<'tcx>) {
+fn resolve_block<'tcx>(
+    visitor: &mut ScopeResolutionVisitor<'tcx>,
+    blk: &'tcx hir::Block<'tcx>,
+    terminating: bool,
+) {
     debug!("resolve_block(blk.hir_id={:?})", blk.hir_id);
 
     let prev_cx = visitor.cx;
@@ -112,7 +92,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
     // `other_argument()` has run and also the call to `quux(..)`
     // itself has returned.
 
-    visitor.enter_node_scope_with_dtor(blk.hir_id.local_id);
+    visitor.enter_node_scope_with_dtor(blk.hir_id.local_id, terminating);
     visitor.cx.var_parent = visitor.cx.parent;
 
     {
@@ -141,8 +121,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
                     // the sequence of visits agree with the order in the default
                     // `hir::intravisit` visitor.
                     mem::swap(&mut prev_cx, &mut visitor.cx);
-                    visitor.terminating_scopes.insert(els.hir_id.local_id);
-                    visitor.visit_block(els);
+                    resolve_block(visitor, els, true);
                     // From now on, we continue normally.
                     visitor.cx = prev_cx;
                 }
@@ -170,12 +149,12 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
         if let Some(tail_expr) = blk.expr {
             let local_id = tail_expr.hir_id.local_id;
             let edition = blk.span.edition();
-            if edition.at_least_rust_2024() {
-                visitor.terminating_scopes.insert(local_id);
-            } else if !visitor
-                .tcx
-                .lints_that_dont_need_to_run(())
-                .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER))
+            let terminating = edition.at_least_rust_2024();
+            if !terminating
+                && !visitor
+                    .tcx
+                    .lints_that_dont_need_to_run(())
+                    .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER))
             {
                 // If this temporary scope will be changing once the codebase adopts Rust 2024,
                 // and we are linting about possible semantic changes that would result,
@@ -186,7 +165,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi
                     .backwards_incompatible_scope
                     .insert(local_id, Scope { local_id, data: ScopeData::Node });
             }
-            visitor.visit_expr(tail_expr);
+            resolve_expr(visitor, tail_expr, terminating);
         }
     }
 
@@ -204,25 +183,19 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:
 
     let prev_cx = visitor.cx;
 
-    visitor.terminating_scopes.insert(arm.hir_id.local_id);
-
-    visitor.enter_node_scope_with_dtor(arm.hir_id.local_id);
+    visitor.enter_node_scope_with_dtor(arm.hir_id.local_id, true);
     visitor.cx.var_parent = visitor.cx.parent;
 
-    if let Some(expr) = arm.guard
-        && !has_let_expr(expr)
-    {
-        visitor.terminating_scopes.insert(expr.hir_id.local_id);
+    resolve_pat(visitor, arm.pat);
+    if let Some(guard) = arm.guard {
+        resolve_expr(visitor, guard, !has_let_expr(guard));
     }
-
-    intravisit::walk_arm(visitor, arm);
+    resolve_expr(visitor, arm.body, false);
 
     visitor.cx = prev_cx;
 }
 
 fn resolve_pat<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
-    visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node });
-
     // If this is a binding then record the lifetime of that binding.
     if let PatKind::Binding(..) = pat.kind {
         record_var_lifetime(visitor, pat.hir_id.local_id);
@@ -246,126 +219,24 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi
     // associated destruction scope that represents the scope of the
     // statement plus its destructors, and thus the scope for which
     // regions referenced by the destructors need to survive.
-    visitor.terminating_scopes.insert(stmt_id);
 
     let prev_parent = visitor.cx.parent;
-    visitor.enter_node_scope_with_dtor(stmt_id);
+    visitor.enter_node_scope_with_dtor(stmt_id, true);
 
     intravisit::walk_stmt(visitor, stmt);
 
     visitor.cx.parent = prev_parent;
 }
 
-fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+fn resolve_expr<'tcx>(
+    visitor: &mut ScopeResolutionVisitor<'tcx>,
+    expr: &'tcx hir::Expr<'tcx>,
+    terminating: bool,
+) {
     debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
 
     let prev_cx = visitor.cx;
-    visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
-
-    {
-        let terminating_scopes = &mut visitor.terminating_scopes;
-        let mut terminating = |id: hir::ItemLocalId| {
-            terminating_scopes.insert(id);
-        };
-        match expr.kind {
-            // Conditional or repeating scopes are always terminating
-            // scopes, meaning that temporaries cannot outlive them.
-            // This ensures fixed size stacks.
-            hir::ExprKind::Binary(
-                source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
-                l,
-                r,
-            ) => {
-                // expr is a short circuiting operator (|| or &&). As its
-                // functionality can't be overridden by traits, it always
-                // processes bool sub-expressions. bools are Copy and thus we
-                // can drop any temporaries in evaluation (read) order
-                // (with the exception of potentially failing let expressions).
-                // We achieve this by enclosing the operands in a terminating
-                // scope, both the LHS and the RHS.
-
-                // We optimize this a little in the presence of chains.
-                // Chains like a && b && c get lowered to AND(AND(a, b), c).
-                // In here, b and c are RHS, while a is the only LHS operand in
-                // that chain. This holds true for longer chains as well: the
-                // leading operand is always the only LHS operand that is not a
-                // binop itself. Putting a binop like AND(a, b) into a
-                // terminating scope is not useful, thus we only put the LHS
-                // into a terminating scope if it is not a binop.
-
-                let terminate_lhs = match l.kind {
-                    // let expressions can create temporaries that live on
-                    hir::ExprKind::Let(_) => false,
-                    // binops already drop their temporaries, so there is no
-                    // need to put them into a terminating scope.
-                    // This is purely an optimization to reduce the number of
-                    // terminating scopes.
-                    hir::ExprKind::Binary(
-                        source_map::Spanned {
-                            node: hir::BinOpKind::And | hir::BinOpKind::Or, ..
-                        },
-                        ..,
-                    ) => false,
-                    // otherwise: mark it as terminating
-                    _ => true,
-                };
-                if terminate_lhs {
-                    terminating(l.hir_id.local_id);
-                }
-
-                // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
-                // should live beyond the immediate expression
-                if !matches!(r.kind, hir::ExprKind::Let(_)) {
-                    terminating(r.hir_id.local_id);
-                }
-            }
-            hir::ExprKind::If(_, then, Some(otherwise)) => {
-                terminating(then.hir_id.local_id);
-                terminating(otherwise.hir_id.local_id);
-            }
-
-            hir::ExprKind::If(_, then, None) => {
-                terminating(then.hir_id.local_id);
-            }
-
-            hir::ExprKind::Loop(body, _, _, _) => {
-                terminating(body.hir_id.local_id);
-            }
-
-            hir::ExprKind::DropTemps(expr) => {
-                // `DropTemps(expr)` does not denote a conditional scope.
-                // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
-                terminating(expr.hir_id.local_id);
-            }
-
-            hir::ExprKind::AssignOp(..)
-            | hir::ExprKind::Index(..)
-            | hir::ExprKind::Unary(..)
-            | hir::ExprKind::Call(..)
-            | hir::ExprKind::MethodCall(..) => {
-                // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls
-                //
-                // The lifetimes for a call or method call look as follows:
-                //
-                // call.id
-                // - arg0.id
-                // - ...
-                // - argN.id
-                // - call.callee_id
-                //
-                // The idea is that call.callee_id represents *the time when
-                // the invoked function is actually running* and call.id
-                // represents *the time to prepare the arguments and make the
-                // call*. See the section "Borrows in Calls" borrowck/README.md
-                // for an extended explanation of why this distinction is
-                // important.
-                //
-                // record_superlifetime(new_cx, expr.callee_id);
-            }
-
-            _ => {}
-        }
-    }
+    visitor.enter_node_scope_with_dtor(expr.hir_id.local_id, terminating);
 
     let prev_pessimistic = visitor.pessimistic_yield;
 
@@ -420,6 +291,53 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
     // properly, we can't miss any types.
 
     match expr.kind {
+        // Conditional or repeating scopes are always terminating
+        // scopes, meaning that temporaries cannot outlive them.
+        // This ensures fixed size stacks.
+        hir::ExprKind::Binary(
+            source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+            left,
+            right,
+        ) => {
+            // expr is a short circuiting operator (|| or &&). As its
+            // functionality can't be overridden by traits, it always
+            // processes bool sub-expressions. bools are Copy and thus we
+            // can drop any temporaries in evaluation (read) order
+            // (with the exception of potentially failing let expressions).
+            // We achieve this by enclosing the operands in a terminating
+            // scope, both the LHS and the RHS.
+
+            // We optimize this a little in the presence of chains.
+            // Chains like a && b && c get lowered to AND(AND(a, b), c).
+            // In here, b and c are RHS, while a is the only LHS operand in
+            // that chain. This holds true for longer chains as well: the
+            // leading operand is always the only LHS operand that is not a
+            // binop itself. Putting a binop like AND(a, b) into a
+            // terminating scope is not useful, thus we only put the LHS
+            // into a terminating scope if it is not a binop.
+
+            let terminate_lhs = match left.kind {
+                // let expressions can create temporaries that live on
+                hir::ExprKind::Let(_) => false,
+                // binops already drop their temporaries, so there is no
+                // need to put them into a terminating scope.
+                // This is purely an optimization to reduce the number of
+                // terminating scopes.
+                hir::ExprKind::Binary(
+                    source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+                    ..,
+                ) => false,
+                // otherwise: mark it as terminating
+                _ => true,
+            };
+
+            // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
+            // should live beyond the immediate expression
+            let terminate_rhs = !matches!(right.kind, hir::ExprKind::Let(_));
+
+            resolve_expr(visitor, left, terminate_lhs);
+            resolve_expr(visitor, right, terminate_rhs);
+        }
         // Manually recurse over closures, because they are nested bodies
         // that share the parent environment. We handle const blocks in
         // `visit_inline_const`.
@@ -488,9 +406,9 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
             visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
-            visitor.visit_expr(then);
+            resolve_expr(visitor, then, true);
             visitor.cx = expr_cx;
-            visitor.visit_expr(otherwise);
+            resolve_expr(visitor, otherwise, true);
         }
 
         hir::ExprKind::If(cond, then, None) => {
@@ -503,10 +421,20 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
             visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
-            visitor.visit_expr(then);
+            resolve_expr(visitor, then, true);
             visitor.cx = expr_cx;
         }
 
+        hir::ExprKind::Loop(body, _, _, _) => {
+            resolve_block(visitor, body, true);
+        }
+
+        hir::ExprKind::DropTemps(expr) => {
+            // `DropTemps(expr)` does not denote a conditional scope.
+            // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
+            resolve_expr(visitor, expr, true);
+        }
+
         _ => intravisit::walk_expr(visitor, expr),
     }
 
@@ -541,7 +469,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi
             // Keep traversing up while we can.
             match visitor.scope_tree.parent_map.get(&scope) {
                 // Don't cross from closure bodies to their parent.
-                Some(&(superscope, _)) => match superscope.data {
+                Some(&superscope) => match superscope.data {
                     ScopeData::CallSite => break,
                     _ => scope = superscope,
                 },
@@ -560,7 +488,7 @@ fn resolve_local<'tcx>(
 ) {
     debug!("resolve_local(pat={:?}, init={:?})", pat, init);
 
-    let blk_scope = visitor.cx.var_parent.map(|(p, _)| p);
+    let blk_scope = visitor.cx.var_parent;
 
     // As an exception to the normal rules governing temporary
     // lifetimes, initializers in a let have a temporary lifetime
@@ -625,10 +553,7 @@ fn resolve_local<'tcx>(
             if is_binding_pat(pat) {
                 visitor.scope_tree.record_rvalue_candidate(
                     expr.hir_id,
-                    RvalueCandidateType::Pattern {
-                        target: expr.hir_id.local_id,
-                        lifetime: blk_scope,
-                    },
+                    RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope },
                 );
             }
         }
@@ -733,10 +658,7 @@ fn resolve_local<'tcx>(
                 record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
                 visitor.scope_tree.record_rvalue_candidate(
                     subexpr.hir_id,
-                    RvalueCandidateType::Borrow {
-                        target: subexpr.hir_id.local_id,
-                        lifetime: blk_id,
-                    },
+                    RvalueCandidate { target: subexpr.hir_id.local_id, lifetime: blk_id },
                 );
             }
             hir::ExprKind::Struct(_, fields, _) => {
@@ -783,28 +705,24 @@ fn resolve_local<'tcx>(
 
 impl<'tcx> ScopeResolutionVisitor<'tcx> {
     /// Records the current parent (if any) as the parent of `child_scope`.
-    /// Returns the depth of `child_scope`.
-    fn record_child_scope(&mut self, child_scope: Scope) -> ScopeDepth {
+    fn record_child_scope(&mut self, child_scope: Scope) {
         let parent = self.cx.parent;
         self.scope_tree.record_scope_parent(child_scope, parent);
-        // If `child_scope` has no parent, it must be the root node, and so has
-        // a depth of 1. Otherwise, its depth is one more than its parent's.
-        parent.map_or(1, |(_p, d)| d + 1)
     }
 
     /// Records the current parent (if any) as the parent of `child_scope`,
     /// and sets `child_scope` as the new current parent.
     fn enter_scope(&mut self, child_scope: Scope) {
-        let child_depth = self.record_child_scope(child_scope);
-        self.cx.parent = Some((child_scope, child_depth));
+        self.record_child_scope(child_scope);
+        self.cx.parent = Some(child_scope);
     }
 
-    fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) {
+    fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId, terminating: bool) {
         // If node was previously marked as a terminating scope during the
         // recursive visit of its parent node in the HIR, then we need to
         // account for the destruction scope representing the scope of
         // the destructors that run immediately after it completes.
-        if self.terminating_scopes.contains(&id) {
+        if terminating {
             self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction });
         }
         self.enter_scope(Scope { local_id: id, data: ScopeData::Node });
@@ -816,13 +734,11 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> {
         // visited the body.
         let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
         let outer_cx = self.cx;
-        let outer_ts = mem::take(&mut self.terminating_scopes);
         // The 'pessimistic yield' flag is set to true when we are
         // processing a `+=` statement and have to make pessimistic
         // control flow assumptions. This doesn't apply to nested
         // bodies within the `+=` statements. See #69307.
         let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
-        self.terminating_scopes.insert(hir_id.local_id);
 
         self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite });
         self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments });
@@ -832,14 +748,13 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> {
         // Restore context we had at the start.
         self.expr_and_pat_count = outer_ec;
         self.cx = outer_cx;
-        self.terminating_scopes = outer_ts;
         self.pessimistic_yield = outer_pessimistic_yield;
     }
 }
 
 impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
     fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
-        resolve_block(self, b);
+        resolve_block(self, b, false);
     }
 
     fn visit_body(&mut self, body: &hir::Body<'tcx>) {
@@ -857,14 +772,13 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
         self.enter_body(body.value.hir_id, |this| {
             if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() {
                 // The arguments and `self` are parented to the fn.
-                this.cx.var_parent = this.cx.parent.take();
+                this.cx.var_parent = this.cx.parent;
                 for param in body.params {
                     this.visit_pat(param.pat);
                 }
 
                 // The body of the every fn is a root scope.
-                this.cx.parent = this.cx.var_parent;
-                this.visit_expr(body.value)
+                resolve_expr(this, body.value, true);
             } else {
                 // Only functions have an outer terminating (drop) scope, while
                 // temporaries in constant initializers may be 'static, but only
@@ -885,6 +799,10 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
                 // (i.e., `'static`), which means that after `g` returns, it drops,
                 // and all the associated destruction scope rules apply.
                 this.cx.var_parent = None;
+                this.enter_scope(Scope {
+                    local_id: body.value.hir_id.local_id,
+                    data: ScopeData::Destruction,
+                });
                 resolve_local(this, None, Some(body.value));
             }
         })
@@ -900,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
         resolve_stmt(self, s);
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        resolve_expr(self, ex);
+        resolve_expr(self, ex, false);
     }
     fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) {
         resolve_local(self, Some(l.pat), l.init)
@@ -930,7 +848,6 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
             scope_tree: ScopeTree::default(),
             expr_and_pat_count: 0,
             cx: Context { parent: None, var_parent: None },
-            terminating_scopes: Default::default(),
             pessimistic_yield: false,
             fixup_scopes: vec![],
         };
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 952af592311..83d095ab72e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -188,10 +188,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
 /// definition itself. For example, this definition would be illegal:
 ///
 /// ```rust
-/// struct Ref<'a, T> { x: &'a T }
+/// struct StaticRef<T> { x: &'static T }
 /// ```
 ///
-/// because the type did not declare that `T:'a`.
+/// because the type did not declare that `T: 'static`.
 ///
 /// We do this check as a pre-pass before checking fn bodies because if these constraints are
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 15e0a72fdcb..16bac430491 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
+    let impls = tcx.local_trait_impls(def_id);
     // If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything
     // anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge.
-    let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) };
+    if impls.is_empty() {
+        return Ok(());
+    }
     // Trigger building the specialization graph for the trait. This will detect and report any
     // overlap errors.
     let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index a153ce8ea90..2bed28d7b71 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -116,8 +116,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 {
                     // enum variant discriminants are not allowed to use any kind of generics
                     None
-                } else if let Some(param_id) =
-                    tcx.hir().opt_const_param_default_param_def_id(hir_id)
+                } else if let Some(param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id)
                 {
                     // If the def_id we are calling generics_of on is an anon ct default i.e:
                     //
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 4bd89861a9e..98da8449d5e 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -508,7 +508,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
         if matches!(def_kind, DefKind::AnonConst)
             && tcx.features().generic_const_exprs()
             && let Some(defaulted_param_def_id) =
-                tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
+                tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
         {
             // In `generics_of` we set the generics' parent to be our parent's parent which means that
             // we lose out on the predicates of our actual parent if we dont return those predicates here.
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 9b0d57bd75b..404753875ee 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1529,7 +1529,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             if let ResolvedArg::LateBound(..) = def
                 && let Some(what) = crossed_late_boundary
             {
-                let use_span = self.tcx.hir().span(hir_id);
+                let use_span = self.tcx.hir_span(hir_id);
                 let def_span = self.tcx.def_span(param_def_id);
                 let guar = match self.tcx.def_kind(param_def_id) {
                     DefKind::ConstParam => {
@@ -1576,11 +1576,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 } => {
                     let guar = self.tcx.dcx().emit_err(match self.tcx.def_kind(param_def_id) {
                         DefKind::TyParam => errors::LateBoundInApit::Type {
-                            span: self.tcx.hir().span(hir_id),
+                            span: self.tcx.hir_span(hir_id),
                             param_span: self.tcx.def_span(param_def_id),
                         },
                         DefKind::ConstParam => errors::LateBoundInApit::Const {
-                            span: self.tcx.hir().span(hir_id),
+                            span: self.tcx.hir_span(hir_id),
                             param_span: self.tcx.def_span(param_def_id),
                         },
                         kind => {
@@ -1605,7 +1605,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
         self.tcx
             .dcx()
-            .span_bug(self.tcx.hir().span(hir_id), format!("could not resolve {param_def_id:?}"));
+            .span_bug(self.tcx.hir_span(hir_id), format!("could not resolve {param_def_id:?}"));
     }
 
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 142078900f0..3dec1e286b4 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -258,9 +258,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         self.tcx
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        if let hir::ExprKind::Closure(closure) = ex.kind {
-            self.check(closure.def_id);
-        }
         intravisit::walk_expr(self, ex);
     }
     fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
@@ -371,14 +368,8 @@ impl RpitConstraintChecker<'_> {
         // Use borrowck to get the type with unerased regions.
         let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
         debug!(?concrete_opaque_types);
-        for (&def_id, &concrete_type) in concrete_opaque_types {
-            if def_id != self.def_id {
-                // Ignore constraints for other opaque types.
-                continue;
-            }
-
+        if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
             debug!(?concrete_type, "found constraint");
-
             if concrete_type.ty != self.found.ty {
                 if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) {
                     d.emit();
@@ -395,9 +386,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
         self.tcx
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        if let hir::ExprKind::Closure(closure) = ex.kind {
-            self.check(closure.def_id);
-        }
         intravisit::walk_expr(self, ex);
     }
     fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
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 f0dffd780bc..302abc27324 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -684,7 +684,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
                 span: path_span,
                 ty: tcx.liberate_late_bound_regions(item_def_id, output),
-                fn_span: tcx.hir().span_if_local(item_def_id),
+                fn_span: tcx.hir_span_if_local(item_def_id),
                 note: (),
             }));
         };
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 170500c7a16..ecb453bced0 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -32,7 +32,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
                         span,
                         ..
                     }) => *span,
-                    _ => tcx.hir().span(hir_id),
+                    _ => tcx.hir_span(hir_id),
                 };
                 struct_span_code_err!(
                     tcx.dcx(),
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 3b007c77198..6e9c178d33a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -882,7 +882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
 
-            if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
+            if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
                 err.span_label(
                     sp,
                     format!("`{}{}` defined here{}", prefix, item.name, rename_message),
@@ -1381,7 +1381,7 @@ pub(crate) fn fn_trait_to_string(
         .find_map(|c| {
             if c.ident.name == sym::Output
                 && let Some(ty) = c.ty()
-                && ty.span != tcx.hir().span(trait_segment.hir_id)
+                && ty.span != tcx.hir_span(trait_segment.hir_id)
             {
                 tcx.sess.source_map().span_to_snippet(ty.span).ok()
             } else {
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 60a60f6415a..21f0f9648ea 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -92,7 +92,7 @@ fn generic_arg_mismatch_err(
             GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
             GenericParamDefKind::Const { .. },
         ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
-            let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
+            let snippet = sess.source_map().span_to_snippet(tcx.hir_span(len.hir_id));
             if let Ok(snippet) = snippet {
                 err.span_suggestion(
                     arg.span(),
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 55886312284..8e62dce2191 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -86,6 +86,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 "expected a type, found a trait"
             );
             if self_ty.span.can_be_used_for_suggestions()
+                && poly_trait_ref.trait_ref.trait_def_id().is_some()
                 && !self.maybe_suggest_impl_trait(self_ty, &mut diag)
                 && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
             {
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 76a880da418..83925b5ec52 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1066,7 +1066,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let bound_span = tcx
                     .associated_items(bound_id)
                     .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id)
-                    .and_then(|item| tcx.hir().span_if_local(item.def_id));
+                    .and_then(|item| tcx.hir_span_if_local(item.def_id));
 
                 if let Some(bound_span) = bound_span {
                     err.span_label(
@@ -1400,7 +1400,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         );
                     }
 
-                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
+                    if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
                         err.span_label(sp, format!("variant `{assoc_ident}` not found here"));
                     }
 
@@ -1730,25 +1730,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         .is_accessible_from(self.item_def_id(), tcx)
                     && tcx.all_impls(*trait_def_id)
                         .any(|impl_def_id| {
-                            let impl_header = tcx.impl_trait_header(impl_def_id);
-                            impl_header.is_some_and(|header| {
-                                let trait_ref = header.trait_ref.instantiate(
-                                    tcx,
-                                    infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
-                                );
-
-                                let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
-                                // FIXME: Don't bother dealing with non-lifetime binders here...
-                                if value.has_escaping_bound_vars() {
-                                    return false;
-                                }
-                                infcx
-                                    .can_eq(
-                                        ty::ParamEnv::empty(),
-                                        trait_ref.self_ty(),
-                                        value,
-                                    ) && header.polarity != ty::ImplPolarity::Negative
-                            })
+                            let header = tcx.impl_trait_header(impl_def_id).unwrap();
+                            let trait_ref = header.trait_ref.instantiate(
+                                tcx,
+                                infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
+                            );
+
+                            let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
+                            // FIXME: Don't bother dealing with non-lifetime binders here...
+                            if value.has_escaping_bound_vars() {
+                                return false;
+                            }
+                            infcx
+                                .can_eq(
+                                    ty::ParamEnv::empty(),
+                                    trait_ref.self_ty(),
+                                    value,
+                                ) && header.polarity != ty::ImplPolarity::Negative
                         })
             })
             .map(|trait_def_id| tcx.def_path_str(trait_def_id))
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index e27a81d4976..c01b81563dc 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -170,7 +170,7 @@ fn diagnostic_hir_wf_check<'tcx>(
                 ..
             }) => vec![*ty],
             hir::Node::AnonConst(_) => {
-                if let Some(const_param_id) = tcx.hir().opt_const_param_default_param_def_id(hir_id)
+                if let Some(const_param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id)
                     && let hir::Node::GenericParam(hir::GenericParam {
                         kind: hir::GenericParamKind::Const { ty, .. },
                         ..
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 32b05dcc569..daa908c8c78 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -25,7 +25,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
         }
         DefKind::AnonConst if tcx.features().generic_const_exprs() => {
             let id = tcx.local_def_id_to_hir_id(item_def_id);
-            if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
+            if tcx.hir_opt_const_param_default_param_def_id(id).is_some() {
                 // In `generics_of` we set the generics' parent to be our parent's parent which means that
                 // we lose out on the predicates of our actual parent if we dont return those predicates here.
                 // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index ddaca89ccf8..1c23761b2e5 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1193,7 +1193,8 @@ impl<'a> State<'a> {
         wth: hir::StructTailExpr<'_>,
     ) {
         self.print_qpath(qpath, true);
-        self.word("{");
+        self.nbsp();
+        self.word_space("{");
         self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
         match wth {
             hir::StructTailExpr::Base(expr) => {
@@ -1215,20 +1216,13 @@ impl<'a> State<'a> {
                 self.word("..");
                 self.end();
             }
-            hir::StructTailExpr::None => {
-                if !fields.is_empty() {
-                    self.word(",");
-                }
-            }
+            hir::StructTailExpr::None => {}
         }
-
+        self.space();
         self.word("}");
     }
 
     fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
-        if self.attrs(field.hir_id).is_empty() {
-            self.space();
-        }
         self.cbox(INDENT_UNIT);
         self.print_attrs_as_outer(self.attrs(field.hir_id));
         if !field.is_shorthand {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 5e2daa69628..02fd7367e2f 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -771,7 +771,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
                 );
                 if let DefIdOrName::DefId(def_id) = maybe_def
-                    && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
+                    && let Some(def_span) = self.tcx.hir_span_if_local(def_id)
                 {
                     err.span_label(def_span, "the callable type is defined here");
                 }
@@ -780,7 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        if let Some(span) = self.tcx.hir().res_span(def) {
+        if let Some(span) = self.tcx.hir_res_span(def) {
             let callee_ty = callee_ty.to_string();
             let label = match (unit_variant, inner_callee_path) {
                 (Some((_, kind, path)), _) => {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index a4776338f6c..467ca26e7ea 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -970,7 +970,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
 
         // Normalize only after registering in `user_provided_sigs`.
-        self.normalize(self.tcx.hir().span(hir_id), result)
+        self.normalize(self.tcx.hir_span(hir_id), result)
     }
 
     /// Invoked when we are translating the coroutine that results
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 4cbc42b99ea..f42ca3af2b3 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -41,8 +41,8 @@ use rustc_abi::ExternAbi;
 use rustc_attr_parsing::InlineAttr;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, struct_span_code_err};
+use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, LangItem};
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::infer::relate::RelateResult;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
@@ -55,7 +55,7 @@ use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
 };
 use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -592,63 +592,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
         let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
-        let root_obligation = Obligation::new(
-            self.tcx,
-            cause.clone(),
-            self.fcx.param_env,
-            ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]),
-        );
-
-        // If the root `Source: CoerceUnsized<Target>` obligation can't possibly hold,
-        // we don't have to assume that this is unsizing coercion (it will always lead to an error)
-        //
-        // However, we don't want to bail early all the time, since the unholdable obligations
-        // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
-        // so we only bail if there (likely) is another way to convert the types.
-        if !self.infcx.predicate_may_hold(&root_obligation) {
-            if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata)
-                && let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata)
-            {
-                self.probe(|_| {
-                    let ocx = ObligationCtxt::new(&self.infcx);
-
-                    // returns `true` if `<ty as Pointee>::Metadata` is `DynMetadata<_>`
-                    let has_dyn_trait_metadata = |ty| {
-                        let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty(
-                            &ObligationCause::dummy(),
-                            self.fcx.param_env,
-                            Ty::new_alias(
-                                self.tcx,
-                                ty::AliasTyKind::Projection,
-                                AliasTy::new(self.tcx, metadata_type_def_id, [ty]),
-                            ),
-                        );
-
-                        metadata_ty.is_ok_and(|metadata_ty| {
-                            metadata_ty
-                                .ty_adt_def()
-                                .is_some_and(|d| d.did() == dyn_metadata_adt_def_id)
-                        })
-                    };
-
-                    // If both types are raw pointers to a (wrapper over a) trait object,
-                    // this might be a cast like `*const W<dyn Trait> -> *const dyn Trait`.
-                    // So it's better to bail and try that. (even if the cast is not possible, for
-                    // example due to vtables not matching, cast diagnostic will likely still be better)
-                    //
-                    // N.B. use `target`, not `coerce_target` (the latter is a var)
-                    if let &ty::RawPtr(source_pointee, _) = coerce_source.kind()
-                        && let &ty::RawPtr(target_pointee, _) = target.kind()
-                        && has_dyn_trait_metadata(source_pointee)
-                        && has_dyn_trait_metadata(target_pointee)
-                    {
-                        return Err(TypeError::Mismatch);
-                    }
-
-                    Ok(())
-                })?;
-            }
-        }
 
         // Use a FIFO queue for this custom fulfillment procedure.
         //
@@ -657,7 +600,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // and almost never more than 3. By using a SmallVec we avoid an
         // allocation, at the (very small) cost of (occasionally) having to
         // shift subsequent elements down when removing the front element.
-        let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![root_obligation];
+        let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new(
+            self.tcx,
+            cause,
+            self.fcx.param_env,
+            ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
+        )];
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 41bdd0ca43e..b845e2190ef 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -999,10 +999,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
         for def_id in pick.import_ids {
             let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-            path_span.push_span_label(
-                self.tcx.hir().span(hir_id),
-                format!("`{container}` imported here"),
-            );
+            path_span
+                .push_span_label(self.tcx.hir_span(hir_id), format!("`{container}` imported here"));
         }
         let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
             [] => return,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index a75f6f4caac..a882ea27af6 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3239,7 +3239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(x) => self.tcx.local_def_id_to_hir_id(x),
             None => return,
         };
-        let param_span = self.tcx.hir().span(param_hir_id);
+        let param_span = self.tcx.hir_span(param_hir_id);
         let param_name = self.tcx.hir_ty_param_name(param_def_id.expect_local());
 
         err.span_label(param_span, format!("type parameter '{param_name}' declared here"));
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c71a5ea8b97..64176dacb73 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1,6 +1,9 @@
 //! A different sort of visitor for walking fn bodies. Unlike the
 //! normal visitor, which just walks the entire body in one shot, the
 //! `ExprUseVisitor` determines how expressions are being used.
+//!
+//! In the compiler, this is only used for upvar inference, but there
+//! are many uses within clippy.
 
 use std::cell::{Ref, RefCell};
 use std::ops::Deref;
@@ -25,7 +28,7 @@ use rustc_middle::ty::{
 use rustc_middle::{bug, span_bug};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
-use tracing::{debug, trace};
+use tracing::{debug, instrument, trace};
 
 use crate::fn_ctxt::FnCtxt;
 
@@ -35,11 +38,8 @@ pub trait Delegate<'tcx> {
     /// The value found at `place` is moved, depending
     /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
     ///
-    /// Use of a `Copy` type in a ByValue context is considered a use
-    /// by `ImmBorrow` and `borrow` is called instead. This is because
-    /// a shared borrow is the "minimum access" that would be needed
-    /// to perform a copy.
-    ///
+    /// If the value is `Copy`, [`copy`][Self::copy] is called instead, which
+    /// by default falls back to [`borrow`][Self::borrow].
     ///
     /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
     /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
@@ -73,6 +73,10 @@ pub trait Delegate<'tcx> {
 
     /// The value found at `place` is being copied.
     /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
+    ///
+    /// If an implementation is not provided, use of a `Copy` type in a ByValue context is instead
+    /// considered a use by `ImmBorrow` and `borrow` is called instead. This is because a shared
+    /// borrow is the "minimum access" that would be needed to perform a copy.
     fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
         // we treat a copy of `x` as a borrow of `x`.
@@ -141,6 +145,8 @@ impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D {
     }
 }
 
+/// This trait makes `ExprUseVisitor` usable with both [`FnCtxt`]
+/// and [`LateContext`], depending on where in the compiler it is used.
 pub trait TypeInformationCtxt<'tcx> {
     type TypeckResults<'a>: Deref<Target = ty::TypeckResults<'tcx>>
     where
@@ -154,7 +160,7 @@ pub trait TypeInformationCtxt<'tcx> {
 
     fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
 
-    fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error;
+    fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error;
 
     fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>;
 
@@ -189,7 +195,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
         (**self).try_structurally_resolve_type(sp, ty)
     }
 
-    fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error {
+    fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error {
         self.dcx().span_delayed_bug(span, msg.to_string())
     }
 
@@ -239,7 +245,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
         t
     }
 
-    fn report_error(&self, span: Span, msg: impl ToString) -> ! {
+    fn report_bug(&self, span: Span, msg: impl ToString) -> ! {
         span_bug!(span, "{}", msg.to_string())
     }
 
@@ -268,9 +274,9 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
     }
 }
 
-/// The ExprUseVisitor type
+/// A visitor that reports how each expression is being used.
 ///
-/// This is the code that actually walks the tree.
+/// See [module-level docs][self] and [`Delegate`] for details.
 pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
     cx: Cx,
     /// We use a `RefCell` here so that delegates can mutate themselves, but we can
@@ -314,9 +320,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         Ok(())
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
-        debug!("delegate_consume(place_with_id={:?})", place_with_id);
-
         if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
             self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
         } else {
@@ -324,9 +329,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
-        debug!("delegate_consume_or_clone(place_with_id={:?})", place_with_id);
-
         // `x.use` will do one of the following
         // * if it implements `Copy`, it will be a copy
         // * if it implements `UseCloned`, it will be a call to `clone`
@@ -351,18 +355,16 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
     }
 
     // FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`.
+    #[instrument(skip(self), level = "debug")]
     pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
-        debug!("consume_expr(expr={:?})", expr);
-
         let place_with_id = self.cat_expr(expr)?;
         self.consume_or_copy(&place_with_id, place_with_id.hir_id);
         self.walk_expr(expr)?;
         Ok(())
     }
 
+    #[instrument(skip(self), level = "debug")]
     pub fn consume_or_clone_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
-        debug!("consume_or_clone_expr(expr={:?})", expr);
-
         let place_with_id = self.cat_expr(expr)?;
         self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
         self.walk_expr(expr)?;
@@ -376,17 +378,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         Ok(())
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> {
-        debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk);
-
         let place_with_id = self.cat_expr(expr)?;
         self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
         self.walk_expr(expr)
     }
 
+    #[instrument(skip(self), level = "debug")]
     pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> {
-        debug!("walk_expr(expr={:?})", expr);
-
         self.walk_adjustment(expr)?;
 
         match expr.kind {
@@ -733,9 +733,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
 
     /// Indicates that the value of `blk` will be consumed, meaning either copied or moved
     /// depending on its type.
+    #[instrument(skip(self), level = "debug")]
     fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> {
-        debug!("walk_block(blk.hir_id={})", blk.hir_id);
-
         for stmt in blk.stmts {
             self.walk_stmt(stmt)?;
         }
@@ -861,7 +860,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
     }
 
     /// Walks the autoref `autoref` applied to the autoderef'd
-    /// `expr`. `base_place` is the mem-categorized form of `expr`
+    /// `expr`. `base_place` is `expr` represented as a place,
     /// after all relevant autoderefs have occurred.
     fn walk_autoref(
         &self,
@@ -942,14 +941,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
     }
 
     /// The core driver for walking a pattern
+    #[instrument(skip(self), level = "debug")]
     fn walk_pat(
         &self,
         discr_place: &PlaceWithHirId<'tcx>,
         pat: &hir::Pat<'_>,
         has_guard: bool,
     ) -> Result<(), Cx::Error> {
-        debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard);
-
         let tcx = self.cx.tcx();
         self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| {
             match pat.kind {
@@ -1042,6 +1040,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
     ///
     /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
     /// closure as the DefId.
+    #[instrument(skip(self), level = "debug")]
     fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> {
         fn upvar_is_local_variable(
             upvars: Option<&FxIndexMap<HirId, hir::Upvar>>,
@@ -1051,8 +1050,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure)
         }
 
-        debug!("walk_captures({:?})", closure_expr);
-
         let tcx = self.cx.tcx();
         let closure_def_id = closure_expr.def_id;
         // For purposes of this function, coroutine and closures are equivalent.
@@ -1164,55 +1161,17 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
     }
 }
 
-/// The job of the categorization methods is to analyze an expression to
-/// determine what kind of memory is used in evaluating it (for example,
-/// where dereferences occur and what kind of pointer is dereferenced;
-/// whether the memory is mutable, etc.).
-///
-/// Categorization effectively transforms all of our expressions into
-/// expressions of the following forms (the actual enum has many more
-/// possibilities, naturally, but they are all variants of these base
-/// forms):
-/// ```ignore (not-rust)
-/// E = rvalue    // some computed rvalue
-///   | x         // address of a local variable or argument
-///   | *E        // deref of a ptr
-///   | E.comp    // access to an interior component
-/// ```
-/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
-/// address where the result is to be found. If Expr is a place, then this
-/// is the address of the place. If `Expr` is an rvalue, this is the address of
-/// some temporary spot in memory where the result is stored.
-///
-/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
-/// as follows:
-///
-/// - `cat`: what kind of expression was this? This is a subset of the
-///   full expression forms which only includes those that we care about
-///   for the purpose of the analysis.
-/// - `mutbl`: mutability of the address `A`.
-/// - `ty`: the type of data found at the address `A`.
-///
-/// The resulting categorization tree differs somewhat from the expressions
-/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
-/// decomposed into two operations: a dereference to reach the array data and
-/// then an index to jump forward to the relevant item.
+/// The job of the methods whose name starts with `cat_` is to analyze
+/// expressions and construct the corresponding [`Place`]s. The `cat`
+/// stands for "categorize", this is a leftover from long ago when
+/// places were called "categorizations".
 ///
-/// ## By-reference upvars
-///
-/// One part of the codegen which may be non-obvious is that we translate
-/// closure upvars into the dereference of a borrowed pointer; this more closely
-/// resembles the runtime codegen. So, for example, if we had:
-///
-///     let mut x = 3;
-///     let y = 5;
-///     let inc = || x += y;
-///
-/// Then when we categorize `x` (*within* the closure) we would yield a
-/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
-/// tied to `x`. The type of `x'` will be a borrowed pointer.
+/// Note that a [`Place`] differs somewhat from the expression itself. For
+/// example, auto-derefs are explicit. Also, an index `a[b]` is decomposed into
+/// two operations: a dereference to reach the array data and then an index to
+/// jump forward to the relevant item.
 impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> {
-    fn resolve_type_vars_or_error(
+    fn resolve_type_vars_or_bug(
         &self,
         id: HirId,
         ty: Option<Ty<'tcx>>,
@@ -1222,10 +1181,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 let ty = self.cx.resolve_vars_if_possible(ty);
                 self.cx.error_reported_in_ty(ty)?;
                 if ty.is_ty_var() {
-                    debug!("resolve_type_vars_or_error: infer var from {:?}", ty);
-                    Err(self
-                        .cx
-                        .report_error(self.cx.tcx().hir().span(id), "encountered type variable"))
+                    debug!("resolve_type_vars_or_bug: infer var from {:?}", ty);
+                    Err(self.cx.report_bug(self.cx.tcx().hir_span(id), "encountered type variable"))
                 } else {
                     Ok(ty)
                 }
@@ -1233,24 +1190,21 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             None => {
                 // FIXME: We shouldn't be relying on the infcx being tainted.
                 self.cx.tainted_by_errors()?;
-                bug!(
-                    "no type for node {} in mem_categorization",
-                    self.cx.tcx().hir_id_to_string(id)
-                );
+                bug!("no type for node {} in ExprUseVisitor", self.cx.tcx().hir_id_to_string(id));
             }
         }
     }
 
     fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error> {
-        self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
+        self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id))
     }
 
     fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
-        self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
+        self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr))
     }
 
     fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result<Ty<'tcx>, Cx::Error> {
-        self.resolve_type_vars_or_error(
+        self.resolve_type_vars_or_bug(
             expr.hir_id,
             self.cx.typeck_results().expr_ty_adjusted_opt(expr),
         )
@@ -1285,7 +1239,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         self.pat_ty_unadjusted(pat)
     }
 
-    /// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns.
+    /// Like [`Self::pat_ty_adjusted`], but ignores implicit `&` patterns.
     fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
         let base_ty = self.node_ty(pat.hir_id)?;
         trace!(?base_ty);
@@ -1315,7 +1269,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                             debug!("By-ref binding of non-derefable type");
                             Err(self
                                 .cx
-                                .report_error(pat.span, "by-ref binding of non-derefable type"))
+                                .report_bug(pat.span, "by-ref binding of non-derefable type"))
                         }
                     }
                 } else {
@@ -1511,7 +1465,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 }
             }
 
-            def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def),
+            def => span_bug!(span, "unexpected definition in ExprUseVisitor: {:?}", def),
         }
     }
 
@@ -1553,10 +1507,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         if node_ty != place_ty
             && self
                 .cx
-                .try_structurally_resolve_type(
-                    self.cx.tcx().hir().span(base_place.hir_id),
-                    place_ty,
-                )
+                .try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
                 .is_impl_trait()
         {
             projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
@@ -1595,17 +1546,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         let base_curr_ty = base_place.place.ty();
         let deref_ty = match self
             .cx
-            .try_structurally_resolve_type(
-                self.cx.tcx().hir().span(base_place.hir_id),
-                base_curr_ty,
-            )
+            .try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
             .builtin_deref(true)
         {
             Some(ty) => ty,
             None => {
                 debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
-                return Err(self.cx.report_error(
-                    self.cx.tcx().hir().span(node),
+                return Err(self.cx.report_bug(
+                    self.cx.tcx().hir_span(node),
                     "explicit deref of non-derefable type",
                 ));
             }
@@ -1629,7 +1577,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else {
             return Err(self
                 .cx
-                .report_error(span, "struct or tuple struct pattern not applied to an ADT"));
+                .report_bug(span, "struct or tuple struct pattern not applied to an ADT"));
         };
 
         match res {
@@ -1675,7 +1623,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         let ty = self.cx.typeck_results().node_type(pat_hir_id);
         match self.cx.try_structurally_resolve_type(span, ty).kind() {
             ty::Tuple(args) => Ok(args.len()),
-            _ => Err(self.cx.report_error(span, "tuple pattern not applied to a tuple")),
+            _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")),
         }
     }
 
@@ -1854,7 +1802,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                     debug!("explicit index of non-indexable type {:?}", place_with_id);
                     return Err(self
                         .cx
-                        .report_error(pat.span, "explicit index of non-indexable type"));
+                        .report_bug(pat.span, "explicit index of non-indexable type"));
                 };
                 let elt_place = self.cat_projection(
                     pat.hir_id,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index d75c2853ba0..91190a32ff5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -157,7 +157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Lots of that diagnostics code relies on subtle effects of re-lowering, so we'll
                 // let it keep doing that and just ensure that compilation won't succeed.
                 self.dcx().span_delayed_bug(
-                    self.tcx.hir().span(id),
+                    self.tcx.hir_span(id),
                     format!("`{prev}` overridden by `{ty}` for {id:?} in {:?}", self.body_id),
                 );
             }
@@ -532,7 +532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ct = self.lowerer().lower_const_arg(const_arg, feed);
         self.register_wf_obligation(
             ct.into(),
-            self.tcx.hir().span(const_arg.hir_id),
+            self.tcx.hir_span(const_arg.hir_id),
             ObligationCauseCode::WellFormed(None),
         );
         ct
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index 95b9cb3be62..e068e607902 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -1,7 +1,7 @@
 //! A utility module to inspect currently ambiguous obligations in the current context.
 
 use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
-use rustc_middle::traits::solve::{Goal, GoalSource};
+use rustc_middle::traits::solve::GoalSource;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_span::Span;
 use rustc_trait_selection::solve::inspect::{
@@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 root_cause: &obligation.cause,
             };
 
-            let goal = Goal::new(self.tcx, obligation.param_env, obligation.predicate);
+            let goal = obligation.as_goal();
             self.visit_proof_tree(goal, &mut visitor);
         }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 264719ca569..0097b6ea123 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -351,7 +351,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if self.suggest_fn_call(err, expr, found, |output| self.may_coerce(output, expected))
             && let ty::FnDef(def_id, ..) = *found.kind()
-            && let Some(sp) = self.tcx.hir().span_if_local(def_id)
+            && let Some(sp) = self.tcx.hir_span_if_local(def_id)
         {
             let name = self.tcx.item_name(def_id);
             let kind = self.tcx.def_kind(def_id);
@@ -407,7 +407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
                     };
                     let struct_pat_shorthand_field =
-                        self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr);
+                        self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr);
                     if let Some(name) = struct_pat_shorthand_field {
                         sugg.insert(0, (expr.span.shrink_to_lo(), format!("{name}: ")));
                     }
@@ -449,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
 
             let prefix_wrap = |sugg: &str| {
-                if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+                if let Some(name) = self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                     format!(": {}{}", name, sugg)
                 } else {
                     sugg.to_string()
@@ -671,7 +671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                         _ => {
                             let prefix = if let Some(name) =
-                                self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
+                                self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr)
                             {
                                 format!("{}: ", name)
                             } else {
@@ -1153,7 +1153,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         if can_return
             && let Some(span) = expr.span.find_ancestor_inside(
-                self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
+                self.tcx.hir_span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
             )
         {
             // When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.
@@ -1275,7 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 )
                 .must_apply_modulo_regions()
         {
-            let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+            let suggestion = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                 Some(ident) => format!(": {ident}.clone()"),
                 None => ".clone()".to_string(),
             };
@@ -1381,7 +1381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     (span.shrink_to_hi(), ").into()".to_owned()),
                 ]
             };
-            if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+            if let Some(name) = self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                 sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
             }
             diag.multipart_suggestion(
@@ -1436,7 +1436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+        let suggestion = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
             Some(ident) => format!(": {ident}.is_some()"),
             None => ".is_some()".to_string(),
         };
@@ -2032,7 +2032,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             )
         };
 
-        let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+        let sugg = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
             Some(ident) => format!(": {ident}{sugg}"),
             None => sugg.to_string(),
         };
@@ -2289,7 +2289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Unroll desugaring, to make sure this works for `for` loops etc.
                 loop {
                     parent = self.tcx.parent_hir_id(id);
-                    let parent_span = self.tcx.hir().span(parent);
+                    let parent_span = self.tcx.hir_span(parent);
                     if parent_span.find_ancestor_inside(expr.span).is_some() {
                         // The parent node is part of the same span, so is the result of the
                         // same expansion/desugaring and not the 'real' parent node.
@@ -2378,7 +2378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .collect();
 
             let suggestions_for = |variant: &_, ctor_kind, field_name| {
-                let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+                let prefix = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                     Some(ident) => format!("{ident}: "),
                     None => String::new(),
                 };
@@ -2700,8 +2700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ));
                     }
 
-                    let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
-                    {
+                    let prefix = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                         Some(ident) => format!("{ident}: "),
                         None => String::new(),
                     };
@@ -2911,7 +2910,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         };
 
                         let prefix =
-                            match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+                            match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) {
                                 Some(ident) => format!("{ident}: "),
                                 None => String::new(),
                             };
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 54e9e699353..194e420b606 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -45,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
         let tcx = self.tcx;
         let dl = &tcx.data_layout;
-        let span = tcx.hir().span(hir_id);
+        let span = tcx.hir_span(hir_id);
         let normalize = |ty| {
             let ty = self.resolve_vars_if_possible(ty);
             if let Ok(ty) =
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 4968998fd51..46389668de7 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -117,7 +117,7 @@ fn typeck_with_inspect<'tcx>(
 
     let id = tcx.local_def_id_to_hir_id(def_id);
     let node = tcx.hir_node(id);
-    let span = tcx.hir().span(id);
+    let span = tcx.hir_span(id);
 
     // Figure out what primary body this item has.
     let body_id = node.body_id().unwrap_or_else(|| {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 908c3ee2eb8..246b23f11b6 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -254,11 +254,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     item_name
                 );
                 err.span_label(item_name.span, format!("private {kind}"));
-                let sp = self
-                    .tcx
-                    .hir()
-                    .span_if_local(def_id)
-                    .unwrap_or_else(|| self.tcx.def_span(def_id));
+                let sp =
+                    self.tcx.hir_span_if_local(def_id).unwrap_or_else(|| self.tcx.def_span(def_id));
                 err.span_label(sp, format!("private {kind} defined here"));
                 if let Some(within_macro_span) = within_macro_span {
                     err.span_label(within_macro_span, "due to this macro variable");
@@ -566,7 +563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     span.push_span_label(sugg_let.span,
                             format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
                     span.push_span_label(
-                        self.tcx.hir().span(recv_id),
+                        self.tcx.hir_span(recv_id),
                         format!(
                             "earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
                         ),
@@ -2561,7 +2558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ExprKind::Path(QPath::Resolved(_, path)) => {
                     // local binding
                     if let hir::def::Res::Local(hir_id) = path.res {
-                        let span = tcx.hir().span(hir_id);
+                        let span = tcx.hir_span(hir_id);
                         let filename = tcx.sess.source_map().span_to_filename(span);
 
                         let parent_node = self.tcx.parent_hir_node(hir_id);
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index f1f956779c9..9766ceda569 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -632,10 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 let tcx = self.tcx;
                 trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
-                self.typeck_results
-                    .borrow_mut()
-                    .treat_byte_string_as_slice
-                    .insert(lt.hir_id.local_id);
                 pat_ty =
                     Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
             }
@@ -944,10 +940,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let var_ty = self.local_ty(span, var_id);
         if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
-            let hir = self.tcx.hir();
             let var_ty = self.resolve_vars_if_possible(var_ty);
             let msg = format!("first introduced with type `{var_ty}` here");
-            err.span_label(hir.span(var_id), msg);
+            err.span_label(self.tcx.hir_span(var_id), msg);
             let in_match = self.tcx.hir_parent_iter(var_id).any(|(_, n)| {
                 matches!(
                     n,
@@ -1255,7 +1250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 })) => match self.tcx.hir_node(body_id.hir_id) {
                     hir::Node::Expr(expr) => {
                         if hir::is_range_literal(expr) {
-                            let span = self.tcx.hir().span(body_id.hir_id);
+                            let span = self.tcx.hir_span(body_id.hir_id);
                             if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
                                 e.span_suggestion_verbose(
                                     ident.span,
@@ -1286,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_ty: Ty<'tcx>,
         segments: &'tcx [hir::PathSegment<'tcx>],
     ) {
-        if let Some(span) = self.tcx.hir().res_span(pat_res) {
+        if let Some(span) = self.tcx.hir_res_span(pat_res) {
             e.span_label(span, format!("{} defined here", res.descr()));
             if let [hir::PathSegment { ident, .. }] = &*segments {
                 e.span_label(
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 98d7f777d6b..973dc7141e6 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -2,7 +2,7 @@ use hir::Node;
 use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_middle::bug;
-use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
+use rustc_middle::middle::region::{RvalueCandidate, Scope, ScopeTree};
 use rustc_middle::ty::RvalueScopes;
 use tracing::debug;
 
@@ -55,15 +55,11 @@ fn record_rvalue_scope_rec(
 fn record_rvalue_scope(
     rvalue_scopes: &mut RvalueScopes,
     expr: &hir::Expr<'_>,
-    candidate: &RvalueCandidateType,
+    candidate: &RvalueCandidate,
 ) {
     debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})");
-    match candidate {
-        RvalueCandidateType::Borrow { lifetime, .. }
-        | RvalueCandidateType::Pattern { lifetime, .. } => {
-            record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime)
-        } // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments
-    }
+    record_rvalue_scope_rec(rvalue_scopes, expr, candidate.lifetime)
+    // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments
 }
 
 pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>(
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index fc98a603dd8..b4ac143f513 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -18,12 +18,12 @@
 //! from there).
 //!
 //! The fact that we are inferring borrow kinds as we go results in a
-//! semi-hacky interaction with mem-categorization. In particular,
-//! mem-categorization will query the current borrow kind as it
-//! categorizes, and we'll return the *current* value, but this may get
+//! semi-hacky interaction with the way `ExprUseVisitor` is computing
+//! `Place`s. In particular, it will query the current borrow kind as it
+//! goes, and we'll return the *current* value, but this may get
 //! adjusted later. Therefore, in this module, we generally ignore the
-//! borrow kind (and derived mutabilities) that are returned from
-//! mem-categorization, since they may be inaccurate. (Another option
+//! borrow kind (and derived mutabilities) that `ExprUseVisitor` returns
+//! within `Place`s, since they may be inaccurate. (Another option
 //! would be to use a unification scheme, where instead of returning a
 //! concrete borrow kind like `ty::ImmBorrow`, we return a
 //! `ty::InferBorrow(upvar_id)` or something like that, but this would
@@ -635,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let (place, capture_kind) = truncate_capture_for_optimization(place, capture_kind);
 
                 let usage_span = if let Some(usage_expr) = capture_info.path_expr_id {
-                    self.tcx.hir().span(usage_expr)
+                    self.tcx.hir_span(usage_expr)
                 } else {
                     unreachable!()
                 };
@@ -986,7 +986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         for lint_note in diagnostics_info.iter() {
                             match &lint_note.captures_info {
                                 UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
-                                    let cause_span = self.tcx.hir().span(*capture_expr_id);
+                                    let cause_span = self.tcx.hir_span(*capture_expr_id);
                                     lint.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
                                         self.tcx.hir_name(*var_hir_id),
                                         captured_name,
@@ -1047,13 +1047,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "add a dummy let to cause {migrated_variables_concat} to be fully captured"
                     );
 
-                    let closure_span = self.tcx.hir().span_with_body(closure_hir_id);
+                    let closure_span = self.tcx.hir_span_with_body(closure_hir_id);
                     let mut closure_body_span = {
                         // If the body was entirely expanded from a macro
                         // invocation, i.e. the body is not contained inside the
                         // closure span, then we walk up the expansion until we
                         // find the span before the expansion.
-                        let s = self.tcx.hir().span_with_body(body_id.hir_id);
+                        let s = self.tcx.hir_span_with_body(body_id.hir_id);
                         s.find_ancestor_inside(closure_span).unwrap_or(s)
                     };
 
@@ -1752,8 +1752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let capture_str = construct_capture_info_string(self.tcx, place, capture_info);
                 let output_str = format!("Capturing {capture_str}");
 
-                let span =
-                    capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
+                let span = capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir_span(e));
                 diag.span_note(span, output_str);
             }
             diag.emit();
@@ -1780,10 +1779,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if capture.info.path_expr_id != capture.info.capture_kind_expr_id {
                             let path_span = capture_info
                                 .path_expr_id
-                                .map_or(closure_span, |e| self.tcx.hir().span(e));
+                                .map_or(closure_span, |e| self.tcx.hir_span(e));
                             let capture_kind_span = capture_info
                                 .capture_kind_expr_id
-                                .map_or(closure_span, |e| self.tcx.hir().span(e));
+                                .map_or(closure_span, |e| self.tcx.hir_span(e));
 
                             let mut multi_span: MultiSpan =
                                 MultiSpan::from_spans(vec![path_span, capture_kind_span]);
@@ -1799,7 +1798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         } else {
                             let span = capture_info
                                 .path_expr_id
-                                .map_or(closure_span, |e| self.tcx.hir().span(e));
+                                .map_or(closure_span, |e| self.tcx.hir_span(e));
 
                             diag.span_note(span, output_str);
                         };
@@ -1828,8 +1827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut is_mutbl = bm.1;
 
         for pointer_ty in place.deref_tys() {
-            match self.structurally_resolve_type(self.tcx.hir().span(var_hir_id), pointer_ty).kind()
-            {
+            match self.structurally_resolve_type(self.tcx.hir_span(var_hir_id), pointer_ty).kind() {
                 // We don't capture derefs of raw ptrs
                 ty::RawPtr(_, _) => unreachable!(),
 
@@ -1844,7 +1842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Adt(def, ..) if def.is_box() => {}
 
                 unexpected_ty => span_bug!(
-                    self.tcx.hir().span(var_hir_id),
+                    self.tcx.hir_span(var_hir_id),
                     "deref of unexpected pointer type {:?}",
                     unexpected_ty
                 ),
@@ -1975,14 +1973,14 @@ fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
     let owner_node = tcx.hir_node(owner_id);
     let owner_span = match owner_node {
         hir::Node::Item(item) => match item.kind {
-            hir::ItemKind::Fn { body: owner_id, .. } => tcx.hir().span(owner_id.hir_id),
+            hir::ItemKind::Fn { body: owner_id, .. } => tcx.hir_span(owner_id.hir_id),
             _ => {
                 bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind);
             }
         },
-        hir::Node::Block(block) => tcx.hir().span(block.hir_id),
-        hir::Node::TraitItem(item) => tcx.hir().span(item.hir_id()),
-        hir::Node::ImplItem(item) => tcx.hir().span(item.hir_id()),
+        hir::Node::Block(block) => tcx.hir_span(block.hir_id),
+        hir::Node::TraitItem(item) => tcx.hir_span(item.hir_id()),
+        hir::Node::ImplItem(item) => tcx.hir_span(item.hir_id()),
         _ => {
             bug!("Drop location span error: need to handle more Node '{:?}'", owner_node);
         }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 6a3417ae5d6..588383534f6 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -81,9 +81,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
         wbcx.typeck_results.used_trait_imports = used_trait_imports;
 
-        wbcx.typeck_results.treat_byte_string_as_slice =
-            mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
-
         debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
 
         self.tcx.arena.alloc(wbcx.typeck_results)
@@ -491,7 +488,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
                 if let ty::UserTypeKind::TypeOf(_, user_args) = c_ty.value.kind {
                     // This is a unit-testing mechanism.
-                    let span = self.tcx().hir().span(hir_id);
+                    let span = self.tcx().hir_span(hir_id);
                     // We need to buffer the errors in order to guarantee a consistent
                     // order when emitting them.
                     let err =
@@ -548,7 +545,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
         for (predicate, cause) in &fcx_typeck_results.coroutine_stalled_predicates {
-            let (predicate, cause) = self.resolve((*predicate, cause.clone()), &cause.span);
+            let (predicate, cause) =
+                self.resolve_coroutine_predicate((*predicate, cause.clone()), &cause.span);
             self.typeck_results.coroutine_stalled_predicates.insert((predicate, cause));
         }
     }
@@ -730,7 +728,25 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let value = self.fcx.resolve_vars_if_possible(value);
-        let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body));
+        let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true));
+        assert!(!value.has_infer());
+
+        // We may have introduced e.g. `ty::Error`, if inference failed, make sure
+        // to mark the `TypeckResults` as tainted in that case, so that downstream
+        // users of the typeck results don't produce extra errors, or worse, ICEs.
+        if let Err(guar) = value.error_reported() {
+            self.typeck_results.tainted_by_errors = Some(guar);
+        }
+
+        value
+    }
+
+    fn resolve_coroutine_predicate<T>(&mut self, value: T, span: &dyn Locatable) -> T
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        let value = self.fcx.resolve_vars_if_possible(value);
+        let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false));
         assert!(!value.has_infer());
 
         // We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -756,7 +772,7 @@ impl Locatable for Span {
 
 impl Locatable for HirId {
     fn to_span(&self, tcx: TyCtxt<'_>) -> Span {
-        tcx.hir().span(*self)
+        tcx.hir_span(*self)
     }
 }
 
@@ -774,8 +790,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         fcx: &'cx FnCtxt<'cx, 'tcx>,
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
+        should_normalize: bool,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { fcx, span, body, should_normalize: fcx.next_trait_solver() }
+        Resolver { fcx, span, body, should_normalize }
     }
 
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -805,10 +822,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         T: Into<ty::GenericArg<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
     {
         let tcx = self.fcx.tcx;
-        // We must deeply normalize in the new solver, since later lints
-        // expect that types that show up in the typeck are fully
-        // normalized.
-        let mut value = if self.should_normalize {
+        // We must deeply normalize in the new solver, since later lints expect
+        // that types that show up in the typeck are fully normalized.
+        let mut value = if self.should_normalize && self.fcx.next_trait_solver() {
             let body_id = tcx.hir_body_owner_def_id(self.body.id());
             let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
             let at = self.fcx.at(&cause, self.fcx.param_env);
@@ -864,20 +880,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
-            ty::Const::new_error(tcx, guar)
-        })
-        .super_fold_with(self)
+        self.handle_term(ct, ty::Const::outer_exclusive_binder, ty::Const::new_error)
     }
 
     fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
-        // Do not normalize predicates in the new solver. The new solver is
-        // supposed to handle unnormalized predicates and incorrectly normalizing
-        // them can be unsound, e.g. for `WellFormed` predicates.
-        let prev = mem::replace(&mut self.should_normalize, false);
-        let predicate = predicate.super_fold_with(self);
-        self.should_normalize = prev;
-        predicate
+        assert!(
+            !self.should_normalize,
+            "normalizing predicates in writeback is not generally sound"
+        );
+        predicate.super_fold_with(self)
     }
 }
 
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 50e47533ab6..0e646b136c4 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -91,7 +91,10 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) {
     work_product::delete_workproduct_files(sess, &swp.work_product);
 }
 
-fn load_dep_graph(sess: &Session) -> LoadResult<(Arc<SerializedDepGraph>, WorkProductMap)> {
+fn load_dep_graph(
+    sess: &Session,
+    deps: &DepsType,
+) -> LoadResult<(Arc<SerializedDepGraph>, WorkProductMap)> {
     let prof = sess.prof.clone();
 
     if sess.opts.incremental.is_none() {
@@ -171,7 +174,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(Arc<SerializedDepGraph>, WorkPr
                 return LoadResult::DataOutOfDate;
             }
 
-            let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder);
+            let dep_graph = SerializedDepGraph::decode::<DepsType>(&mut decoder, deps);
 
             LoadResult::Ok { data: (dep_graph, prev_work_products) }
         }
@@ -205,11 +208,11 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache> {
 
 /// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
 /// new graph to an incremental session directory.
-pub fn setup_dep_graph(sess: &Session, crate_name: Symbol) -> DepGraph {
+pub fn setup_dep_graph(sess: &Session, crate_name: Symbol, deps: &DepsType) -> DepGraph {
     // `load_dep_graph` can only be called after `prepare_session_directory`.
     prepare_session_directory(sess, crate_name);
 
-    let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
+    let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess, deps));
 
     if sess.opts.incremental.is_some() {
         sess.time("incr_comp_garbage_collect_session_directories", || {
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 8fc50ca1b43..94ce6d9fa81 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -173,7 +173,7 @@ pub(crate) fn build_dep_graph(
     sess.opts.dep_tracking_hash(false).encode(&mut encoder);
 
     Some(DepGraph::new(
-        &sess.prof,
+        sess,
         prev_graph,
         prev_work_products,
         encoder,
diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs
index 048981f0d5c..7b1eb0a82e3 100644
--- a/compiler/rustc_incremental/src/persist/work_product.rs
+++ b/compiler/rustc_incremental/src/persist/work_product.rs
@@ -3,7 +3,7 @@
 //! [work products]: WorkProduct
 
 use std::fs as std_fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use rustc_data_structures::unord::UnordMap;
 use rustc_fs_util::link_or_copy;
@@ -20,6 +20,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
     sess: &Session,
     cgu_name: &str,
     files: &[(&'static str, &Path)],
+    known_links: &[PathBuf],
 ) -> Option<(WorkProductId, WorkProduct)> {
     debug!(?cgu_name, ?files);
     sess.opts.incremental.as_ref()?;
@@ -28,6 +29,10 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
     for (ext, path) in files {
         let file_name = format!("{cgu_name}.{ext}");
         let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
+        if known_links.contains(&path_in_incr_dir) {
+            let _ = saved_files.insert(ext.to_string(), file_name);
+            continue;
+        }
         match link_or_copy(path, &path_in_incr_dir) {
             Ok(_) => {
                 let _ = saved_files.insert(ext.to_string(), file_name);
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index fa8dea064da..5fc44b8f356 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -27,6 +27,7 @@ use rustc_middle::bug;
 use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::select;
+use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{
     self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
@@ -268,7 +269,7 @@ pub struct InferCtxt<'tcx> {
     /// The set of predicates on which errors have been reported, to
     /// avoid reporting the same error twice.
     pub reported_trait_errors:
-        RefCell<FxIndexMap<Span, (Vec<ty::Predicate<'tcx>>, ErrorGuaranteed)>>,
+        RefCell<FxIndexMap<Span, (Vec<Goal<'tcx, ty::Predicate<'tcx>>>, ErrorGuaranteed)>>,
 
     pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
 
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 3fa1923121a..d9297fb4194 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -198,13 +198,12 @@ impl<'tcx> InferCtxt<'tcx> {
     /// it hasn't previously been defined. This does not emit any
     /// constraints and it's the responsibility of the caller to make
     /// sure that the item bounds of the opaque are checked.
-    pub fn inject_new_hidden_type_unchecked(
+    pub fn register_hidden_type_in_storage(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         hidden_ty: OpaqueHiddenType<'tcx>,
-    ) {
-        let prev = self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty);
-        assert_eq!(prev, None);
+    ) -> Option<Ty<'tcx>> {
+        self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty)
     }
 
     /// Insert a hidden type into the opaque type storage, equating it
@@ -246,8 +245,7 @@ impl<'tcx> InferCtxt<'tcx> {
                             .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
                             .obligations
                             .into_iter()
-                            // FIXME: Shuttling between obligations and goals is awkward.
-                            .map(Goal::from),
+                            .map(|obligation| obligation.as_goal()),
                     );
                 }
             }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index ac641ef5652..b537750f1b5 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -54,6 +54,12 @@ pub struct Obligation<'tcx, T> {
     pub recursion_depth: usize,
 }
 
+impl<'tcx, T: Copy> Obligation<'tcx, T> {
+    pub fn as_goal(&self) -> solve::Goal<'tcx, T> {
+        solve::Goal { param_env: self.param_env, predicate: self.predicate }
+    }
+}
+
 impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
     #[inline]
     fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
@@ -75,12 +81,6 @@ impl<T: Hash> Hash for Obligation<'_, T> {
     }
 }
 
-impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
-    fn from(value: Obligation<'tcx, P>) -> Self {
-        solve::Goal { param_env: value.param_env, predicate: value.predicate }
-    }
-}
-
 pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
 pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index adc7ed54e14..4b9c71d7172 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -3,9 +3,6 @@ interface_abi_required_feature =
     .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 interface_abi_required_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
 
-interface_cant_emit_mir =
-    could not emit MIR: {$error}
-
 interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`
 
 interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen
@@ -53,11 +50,5 @@ interface_out_dir_error =
 interface_proc_macro_crate_panic_abort =
     building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
 
-interface_rustc_error_fatal =
-    fatal error triggered by #[rustc_error]
-
-interface_rustc_error_unexpected_annotation =
-    unexpected annotation used with `#[rustc_error(...)]`!
-
 interface_temps_dir_error =
     failed to find or create the directory specified by `--temps-dir`
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index eed729a1777..6b39b4f1891 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -74,26 +74,6 @@ pub struct TempsDirError;
 pub struct OutDirError;
 
 #[derive(Diagnostic)]
-#[diag(interface_cant_emit_mir)]
-pub struct CantEmitMIR {
-    pub error: io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(interface_rustc_error_fatal)]
-pub struct RustcErrorFatal {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(interface_rustc_error_unexpected_annotation)]
-pub struct RustcErrorUnexpectedAnnotation {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(interface_failed_writing_file)]
 pub struct FailedWritingFile<'a> {
     pub path: &'a Path,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index e47385d0899..93013c8b3f6 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1,5 +1,5 @@
 use std::any::Any;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::io::{self, BufWriter, Write};
 use std::path::{Path, PathBuf};
 use std::sync::{Arc, LazyLock, OnceLock};
@@ -19,6 +19,7 @@ use rustc_incremental::setup_dep_graph;
 use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
+use rustc_middle::dep_graph::DepsType;
 use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_middle::util::Providers;
 use rustc_parse::{
@@ -360,6 +361,31 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
     )
 }
 
+fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> {
+    let value = env::var_os(key);
+
+    let value_tcx = value.as_ref().map(|value| {
+        let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes());
+        debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes);
+        // SAFETY: The bytes came from `as_encoded_bytes`, and we assume that
+        // `alloc_slice` is implemented correctly, and passes the same bytes
+        // back (debug asserted above).
+        unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) }
+    });
+
+    // Also add the variable to Cargo's dependency tracking
+    //
+    // NOTE: This only works for passes run before `write_dep_info`. See that
+    // for extension points for configuring environment variables to be
+    // properly change-tracked.
+    tcx.sess.psess.env_depinfo.borrow_mut().insert((
+        Symbol::intern(&key.to_string_lossy()),
+        value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(&value)),
+    ));
+
+    value_tcx
+}
+
 // Returns all the paths that correspond to generated files.
 fn generated_output_paths(
     tcx: TyCtxt<'_>,
@@ -724,6 +750,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
         |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
     providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
     providers.early_lint_checks = early_lint_checks;
+    providers.env_var_os = env_var_os;
     limits::provide(providers);
     proc_macro_decls::provide(providers);
     rustc_const_eval::provide(providers);
@@ -774,7 +801,9 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
         sess.cfg_version,
     );
     let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
-    let dep_graph = setup_dep_graph(sess, crate_name);
+
+    let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() };
+    let dep_graph = setup_dep_graph(sess, crate_name, &dep_type);
 
     let cstore =
         FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
@@ -1038,46 +1067,25 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
     });
 }
 
-/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
-/// to write UI tests that actually test that compilation succeeds without reporting
-/// an error.
-fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
-    let Some((def_id, _)) = tcx.entry_fn(()) else { return };
-    for attr in tcx.get_attrs(def_id, sym::rustc_error) {
-        match attr.meta_item_list() {
-            // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
-            Some(list)
-                if list.iter().any(|list_item| {
-                    matches!(
-                        list_item.ident().map(|i| i.name),
-                        Some(sym::delayed_bug_from_inside_query)
-                    )
-                }) =>
-            {
-                tcx.ensure_ok().trigger_delayed_bug(def_id);
-            }
-
-            // Bare `#[rustc_error]`.
-            None => {
-                tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) });
-            }
-
-            // Some other attribute.
-            Some(_) => {
-                tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation {
-                    span: tcx.def_span(def_id),
-                });
-            }
-        }
-    }
-}
-
 /// Runs the codegen backend, after which the AST and analysis can
 /// be discarded.
 pub(crate) fn start_codegen<'tcx>(
     codegen_backend: &dyn CodegenBackend,
     tcx: TyCtxt<'tcx>,
 ) -> Box<dyn Any> {
+    // Hook for tests.
+    if let Some((def_id, _)) = tcx.entry_fn(())
+        && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query)
+    {
+        tcx.ensure_ok().trigger_delayed_bug(def_id);
+    }
+
+    // Don't run this test assertions when not doing codegen. Compiletest tries to build
+    // build-fail tests in check mode first and expects it to not give an error in that case.
+    if tcx.sess.opts.output_types.should_codegen() {
+        rustc_symbol_mangling::test::report_symbol_names(tcx);
+    }
+
     // Don't do code generation if there were any errors. Likewise if
     // there were any delayed bugs, because codegen will likely cause
     // more ICEs, obscuring the original problem.
@@ -1085,9 +1093,6 @@ pub(crate) fn start_codegen<'tcx>(
         guar.raise_fatal();
     }
 
-    // Hook for UI tests.
-    check_for_rustc_errors_attr(tcx);
-
     info!("Pre-codegen\n{:?}", tcx.debug_stats());
 
     let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
@@ -1096,20 +1101,8 @@ pub(crate) fn start_codegen<'tcx>(
         codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
     });
 
-    // Don't run this test assertions when not doing codegen. Compiletest tries to build
-    // build-fail tests in check mode first and expects it to not give an error in that case.
-    if tcx.sess.opts.output_types.should_codegen() {
-        rustc_symbol_mangling::test::report_symbol_names(tcx);
-    }
-
     info!("Post-codegen\n{:?}", tcx.debug_stats());
 
-    if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
-        if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
-            tcx.dcx().emit_fatal(errors::CantEmitMIR { error });
-        }
-    }
-
     // This must run after monomorphization so that all generic types
     // have been instantiated.
     if tcx.sess.opts.unstable_opts.print_type_sizes {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index b44be1710ed..4592e014438 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -787,6 +787,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(direct_access_external_data, Some(true));
     tracked!(dual_proc_macros, true);
     tracked!(dwarf_version, Some(5));
+    tracked!(embed_metadata, false);
     tracked!(embed_source, true);
     tracked!(emit_thin_lto, false);
     tracked!(emscripten_wasm_eh, true);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 5cccab893bb..83d80938b4e 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -18,7 +18,7 @@ use rustc_session::{EarlyDiagCtxt, Session, filesearch};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMapInputs;
-use rustc_span::{Symbol, sym};
+use rustc_span::{SessionGlobals, Symbol, sym};
 use rustc_target::spec::Target;
 use tracing::info;
 
@@ -188,25 +188,38 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
             // On deadlock, creates a new thread and forwards information in thread
             // locals to it. The new thread runs the deadlock handler.
 
-            // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a
-            // `TyCtxt` TLS reference here.
-            let query_map = current_gcx2.access(|gcx| {
-                tls::enter_context(&tls::ImplicitCtxt::new(gcx), || {
-                    tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())
-                })
-            });
-            let query_map = FromDyn::from(query_map);
+            let current_gcx2 = current_gcx2.clone();
             let registry = rayon_core::Registry::current();
+            let session_globals = rustc_span::with_session_globals(|session_globals| {
+                session_globals as *const SessionGlobals as usize
+            });
             thread::Builder::new()
                 .name("rustc query cycle handler".to_string())
                 .spawn(move || {
                     let on_panic = defer(|| {
-                        eprintln!("query cycle handler thread panicked, aborting process");
+                        eprintln!("internal compiler error: query cycle handler thread panicked, aborting process");
                         // We need to abort here as we failed to resolve the deadlock,
                         // otherwise the compiler could just hang,
                         process::abort();
                     });
-                    break_query_cycles(query_map.into_inner(), &registry);
+
+                    // Get a `GlobalCtxt` reference from `CurrentGcx` as we cannot rely on having a
+                    // `TyCtxt` TLS reference here.
+                    current_gcx2.access(|gcx| {
+                        tls::enter_context(&tls::ImplicitCtxt::new(gcx), || {
+                            tls::with(|tcx| {
+                                // Accessing session globals is sound as they outlive `GlobalCtxt`.
+                                // They are needed to hash query keys containing spans or symbols.
+                                let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || {
+                                    // Ensure there was no errors collecting all active jobs.
+                                    // We need the complete map to ensure we find a cycle to break.
+                                    QueryCtxt::new(tcx).collect_active_jobs().ok().expect("failed to collect active queries in deadlock handler")
+                                });
+                                break_query_cycles(query_map, &registry);
+                            })
+                        })
+                    });
+
                     on_panic.disable();
                 })
                 .unwrap();
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index d51865810b9..782d328a951 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -456,6 +456,10 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir
 
 lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable
 
+lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+    .origin = null pointer originates from here
+    .doc = for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
 lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
     .label = casting happened here
 
@@ -680,15 +684,6 @@ lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cann
 lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope
     .label = names from parent modules are not accessible without an explicit import
 
-lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
-    .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
-    .label = expression has type `{$orig_ty}`
-
-lint_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false
-
-lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false
-    .label = expression has type `{$orig_ty}`
-
 lint_query_instability = using `{$query}` can result in unstable query results
     .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
 
@@ -799,6 +794,9 @@ lint_tykind_kind = usage of `ty::TyKind::<kind>`
 lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
     .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
 
+lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+    .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
+
 lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
     .label = argument has type `{$arg_ty}`
     .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
@@ -978,6 +976,15 @@ lint_unused_result = unused result of type `{$ty}`
 
 lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result
 
+lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
+    .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+    .label = expression has type `{$orig_ty}`
+
+lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false
+
+lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false
+    .label = expression has type `{$orig_ty}`
+
 lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type
 
 lint_variant_size_differences =
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9dccd4a0552..c56dbc2e1c4 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -330,7 +330,6 @@ impl EarlyLintPass for UnsafeCode {
         if let FnKind::Fn(
             ctxt,
             _,
-            _,
             ast::Fn {
                 sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. },
                 body,
@@ -3116,6 +3115,7 @@ impl EarlyLintPass for SpecialModuleName {
         for item in &krate.items {
             if let ast::ItemKind::Mod(
                 _,
+                ident,
                 ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
             ) = item.kind
             {
@@ -3123,7 +3123,7 @@ impl EarlyLintPass for SpecialModuleName {
                     continue;
                 }
 
-                match item.ident.name.as_str() {
+                match ident.name.as_str() {
                     "lib" => cx.emit_span_lint(
                         SPECIAL_MODULE_NAME,
                         item.span,
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 723b894c43b..f9601fa5ef1 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -241,7 +241,7 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
                 ast_visit::AssocCtxt::Trait => {
                     lint_callback!(cx, check_trait_item, item);
                 }
-                ast_visit::AssocCtxt::Impl => {
+                ast_visit::AssocCtxt::Impl { .. } => {
                     lint_callback!(cx, check_impl_item, item);
                 }
             }
@@ -250,7 +250,7 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
                 ast_visit::AssocCtxt::Trait => {
                     lint_callback!(cx, check_trait_item_post, item);
                 }
-                ast_visit::AssocCtxt::Impl => {
+                ast_visit::AssocCtxt::Impl { .. } => {
                     lint_callback!(cx, check_impl_item_post, item);
                 }
             }
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index c2404a7b843..26481b97076 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -392,7 +392,7 @@ where
                         }
                         _ => {
                             self.tcx.dcx().span_delayed_bug(
-                                self.tcx.hir().span(arg.hir_id()),
+                                self.tcx.hir_span(arg.hir_id()),
                                 "no valid for captured arg",
                             );
                         }
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index b359ee790a5..1d4be24ea9f 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -1,24 +1,21 @@
 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
 //! Clippy.
 
-use rustc_ast as ast;
+use rustc_hir::HirId;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{
-    AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
-    PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
-};
 use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::{Span, sym};
 use tracing::debug;
+use {rustc_ast as ast, rustc_hir as hir};
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
     NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
     SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
-    UntranslatableDiag,
+    TypeIrTraitUsage, UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 
@@ -37,9 +34,12 @@ declare_tool_lint! {
 declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
 
 impl LateLintPass<'_> for DefaultHashTypes {
-    fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
+    fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
         let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
-        if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) {
+        if matches!(
+            cx.tcx.hir_node(hir_id),
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
+        ) {
             // Don't lint imports, only actual usages.
             return;
         }
@@ -60,10 +60,10 @@ impl LateLintPass<'_> for DefaultHashTypes {
 /// get the `DefId` and `GenericArgsRef` of the function.
 fn typeck_results_of_method_fn<'tcx>(
     cx: &LateContext<'tcx>,
-    expr: &Expr<'_>,
+    expr: &hir::Expr<'_>,
 ) -> Option<(Span, DefId, ty::GenericArgsRef<'tcx>)> {
     match expr.kind {
-        ExprKind::MethodCall(segment, ..)
+        hir::ExprKind::MethodCall(segment, ..)
             if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) =>
         {
             Some((segment.ident.span, def_id, cx.typeck_results().node_args(expr.hir_id)))
@@ -102,7 +102,7 @@ declare_tool_lint! {
 declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
 
 impl LateLintPass<'_> for QueryStability {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
         let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
         if let Ok(Some(instance)) = ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, args)
         {
@@ -164,21 +164,25 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
         }
     }
 
-    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) {
+    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
         match &ty.kind {
-            TyKind::Path(QPath::Resolved(_, path)) => {
+            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
                 if lint_ty_kind_usage(cx, &path.res) {
                     let span = match cx.tcx.parent_hir_node(ty.hir_id) {
-                        Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. })
-                        | Node::Pat(Pat {
-                            kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
+                        hir::Node::PatExpr(hir::PatExpr {
+                            kind: hir::PatExprKind::Path(qpath),
+                            ..
+                        })
+                        | hir::Node::Pat(hir::Pat {
+                            kind:
+                                hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
                             ..
                         })
-                        | Node::Expr(
-                            Expr { kind: ExprKind::Path(qpath), .. }
-                            | &Expr { kind: ExprKind::Struct(qpath, ..), .. },
+                        | hir::Node::Expr(
+                            hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
+                            | &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
                         ) => {
-                            if let QPath::TypeRelative(qpath_ty, ..) = qpath
+                            if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
                                 && qpath_ty.hir_id == ty.hir_id
                             {
                                 Some(path.span)
@@ -223,7 +227,7 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
     }
 }
 
-fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
+fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
     match &path.res {
         Res::Def(_, def_id) => {
             if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) {
@@ -244,13 +248,17 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
     None
 }
 
-fn gen_args(segment: &PathSegment<'_>) -> String {
+fn gen_args(segment: &hir::PathSegment<'_>) -> String {
     if let Some(args) = &segment.args {
         let lifetimes = args
             .args
             .iter()
             .filter_map(|arg| {
-                if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
+                if let hir::GenericArg::Lifetime(lt) = arg {
+                    Some(lt.ident.to_string())
+                } else {
+                    None
+                }
             })
             .collect::<Vec<_>>();
 
@@ -272,7 +280,7 @@ declare_tool_lint! {
 }
 
 declare_tool_lint! {
-    /// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`.
+    /// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
     ///
     /// This module should only be used within the trait solver.
     pub rustc::USAGE_OF_TYPE_IR_INHERENT,
@@ -281,10 +289,43 @@ declare_tool_lint! {
     report_in_external_macro: true
 }
 
-declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]);
+declare_tool_lint! {
+    /// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
+    /// or `rustc_infer::InferCtxtLike`.
+    ///
+    /// Methods of this trait should only be used within the type system abstraction layer,
+    /// and in the generic next trait solver implementation. Look for an analogously named
+    /// method on `TyCtxt` or `InferCtxt` (respectively).
+    pub rustc::USAGE_OF_TYPE_IR_TRAITS,
+    Allow,
+    "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
 
 impl<'tcx> LateLintPass<'tcx> for TypeIr {
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        let res_def_id = match expr.kind {
+            hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
+            hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
+                cx.typeck_results().type_dependent_def_id(expr.hir_id)
+            }
+            _ => return,
+        };
+        let Some(res_def_id) = res_def_id else {
+            return;
+        };
+        if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
+            && let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
+            && (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
+                | cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
+        {
+            cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::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);
@@ -394,15 +435,15 @@ declare_tool_lint! {
 declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
 
 impl LateLintPass<'_> for Diagnostics {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
+        let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
             let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
             result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
             result
         };
         // Only check function calls and method calls.
         let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind {
-            ExprKind::Call(callee, args) => {
+            hir::ExprKind::Call(callee, args) => {
                 match cx.typeck_results().node_type(callee.hir_id).kind() {
                     &ty::FnDef(def_id, fn_gen_args) => {
                         (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false))
@@ -410,7 +451,7 @@ impl LateLintPass<'_> for Diagnostics {
                     _ => return, // occurs for fns passed as args
                 }
             }
-            ExprKind::MethodCall(_segment, _recv, args, _span) => {
+            hir::ExprKind::MethodCall(_segment, _recv, args, _span) => {
                 let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
                 else {
                     return;
@@ -514,8 +555,8 @@ impl Diagnostics {
         let mut is_inside_appropriate_impl = false;
         for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
             debug!(?parent);
-            if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
-                && let Impl { of_trait: Some(of_trait), .. } = impl_
+            if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
+                && let hir::Impl { of_trait: Some(of_trait), .. } = impl_
                 && let Some(def_id) = of_trait.trait_def_id()
                 && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
                 && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
@@ -543,8 +584,8 @@ declare_tool_lint! {
 declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
 
 impl LateLintPass<'_> for BadOptAccess {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let ExprKind::Field(base, target) = expr.kind else { return };
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
+        let hir::ExprKind::Field(base, target) = expr.kind else { return };
         let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
         // Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
         // avoided.
@@ -581,9 +622,12 @@ declare_tool_lint! {
 declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
 
 impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-        if let ExprKind::Binary(BinOp { node: BinOpKind::Eq | BinOpKind::Ne, .. }, lhs, rhs) =
-            expr.kind
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
+        if let hir::ExprKind::Binary(
+            hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. },
+            lhs,
+            rhs,
+        ) = expr.kind
         {
             if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
                 cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
@@ -592,9 +636,9 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
     }
 }
 
-fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
     match &expr.kind {
-        ExprKind::MethodCall(..) => cx
+        hir::ExprKind::MethodCall(..) => cx
             .typeck_results()
             .type_dependent_def_id(expr.hir_id)
             .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
@@ -617,11 +661,11 @@ declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
 
 impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
-        if let ExprKind::Call(path, [arg]) = expr.kind
-            && let ExprKind::Path(ref qpath) = path.kind
+        if let hir::ExprKind::Call(path, [arg]) = expr.kind
+            && let hir::ExprKind::Path(ref qpath) = path.kind
             && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
             && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
-            && let ExprKind::Lit(kind) = arg.kind
+            && let hir::ExprKind::Lit(kind) = arg.kind
             && let rustc_ast::LitKind::Str(_, _) = kind.node
         {
             cx.emit_span_lint(
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 8718fb807ec..313d8f6ba8f 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -450,6 +450,19 @@ impl<'s> LintLevelsBuilder<'s, TopDown> {
         builder
     }
 
+    pub fn crate_root(
+        sess: &'s Session,
+        features: &'s Features,
+        lint_added_lints: bool,
+        store: &'s LintStore,
+        registered_tools: &'s RegisteredTools,
+        crate_attrs: &[ast::Attribute],
+    ) -> Self {
+        let mut builder = Self::new(sess, features, lint_added_lints, store, registered_tools);
+        builder.add(crate_attrs, true, None);
+        builder
+    }
+
     fn process_command_line(&mut self) {
         self.provider.cur = self
             .provider
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c38a7540018..9b5c564d332 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -80,6 +80,7 @@ mod types;
 mod unit_bindings;
 mod unqualified_local_imports;
 mod unused;
+mod utils;
 
 use async_closures::AsyncClosureUsage;
 use async_fn_in_trait::AsyncFnInTrait;
@@ -129,6 +130,7 @@ pub use context::{
 };
 pub use early::{EarlyCheckNode, check_ast_node};
 pub use late::{check_crate, late_lint_mod, unerased_lint_store};
+pub use levels::LintLevelsBuilder;
 pub use passes::{EarlyLintPass, LateLintPass};
 pub use rustc_session::lint::Level::{self, *};
 pub use rustc_session::lint::{
@@ -645,6 +647,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(USAGE_OF_QUALIFIED_TY),
             LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
             LintId::of(USAGE_OF_TYPE_IR_INHERENT),
+            LintId::of(USAGE_OF_TYPE_IR_TRAITS),
             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 00586309572..55d010e6d34 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -591,24 +591,40 @@ pub(crate) struct ExpectationNote {
 
 // ptr_nulls.rs
 #[derive(LintDiagnostic)]
-pub(crate) enum PtrNullChecksDiag<'a> {
-    #[diag(lint_ptr_null_checks_fn_ptr)]
-    #[help(lint_help)]
+pub(crate) enum UselessPtrNullChecksDiag<'a> {
+    #[diag(lint_useless_ptr_null_checks_fn_ptr)]
+    #[help]
     FnPtr {
         orig_ty: Ty<'a>,
         #[label]
         label: Span,
     },
-    #[diag(lint_ptr_null_checks_ref)]
+    #[diag(lint_useless_ptr_null_checks_ref)]
     Ref {
         orig_ty: Ty<'a>,
         #[label]
         label: Span,
     },
-    #[diag(lint_ptr_null_checks_fn_ret)]
+    #[diag(lint_useless_ptr_null_checks_fn_ret)]
     FnRet { fn_name: Ident },
 }
 
+#[derive(LintDiagnostic)]
+pub(crate) enum InvalidNullArgumentsDiag {
+    #[diag(lint_invalid_null_arguments)]
+    #[help(lint_doc)]
+    NullPtrInline {
+        #[label(lint_origin)]
+        null_span: Span,
+    },
+    #[diag(lint_invalid_null_arguments)]
+    #[help(lint_doc)]
+    NullPtrThroughBinding {
+        #[note(lint_origin)]
+        null_span: Span,
+    },
+}
+
 // for_loops_over_fallibles.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_for_loops_over_fallibles)]
@@ -944,6 +960,11 @@ pub(crate) struct TyQualified {
 pub(crate) struct TypeIrInherentUsage;
 
 #[derive(LintDiagnostic)]
+#[diag(lint_type_ir_trait_usage)]
+#[note]
+pub(crate) struct TypeIrTraitUsage;
+
+#[derive(LintDiagnostic)]
 #[diag(lint_non_glob_import_type_ir_inherent)]
 pub(crate) struct NonGlobImportTypeIrInherent {
     #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index ac9f8d92dac..16c06100808 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -7,7 +7,7 @@ use rustc_parse_format::{ParseMode, Parser, Piece};
 use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::{InnerSpan, Span, Symbol, hygiene, kw, sym};
+use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
@@ -167,7 +167,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                     .get_diagnostic_item(sym::Debug)
                     .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply());
 
-            let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
+            let suggest_panic_any = !is_str && panic == Some(sym::std_panic_macro);
 
             let fmt_applicability = if suggest_panic_any {
                 // If we can use panic_any, use that as the MachineApplicable suggestion.
@@ -297,10 +297,13 @@ fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char
     ))
 }
 
-fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, Symbol) {
+fn panic_call<'tcx>(
+    cx: &LateContext<'tcx>,
+    f: &'tcx hir::Expr<'tcx>,
+) -> (Span, Option<Symbol>, Symbol) {
     let mut expn = f.span.ctxt().outer_expn_data();
 
-    let mut panic_macro = kw::Empty;
+    let mut panic_macro = None;
 
     // Unwrap more levels of macro expansion, as panic_2015!()
     // was likely expanded from panic!() and possibly from
@@ -320,7 +323,7 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span,
             break;
         }
         expn = parent;
-        panic_macro = name;
+        panic_macro = Some(name);
     }
 
     let macro_symbol =
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index f8e0a94f9ec..9ed11d9cc82 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -104,8 +104,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
         // determining if we are in a doctest context can't currently be determined
         // by the code itself (there are no specific attributes), but fortunately rustdoc
         // sets a perma-unstable env var for libtest so we just reuse that for now
-        let is_at_toplevel_doctest =
-            || self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok();
+        let is_at_toplevel_doctest = || {
+            self.body_depth == 2
+                && cx.tcx.env_var_os("UNSTABLE_RUSTDOC_TEST_PATH".as_ref()).is_some()
+        };
 
         match item.kind {
             ItemKind::Impl(impl_) => {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 752636ccaf0..df567e80e55 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -172,20 +172,22 @@ impl EarlyLintPass for NonCamelCaseTypes {
         }
 
         match &it.kind {
-            ast::ItemKind::TyAlias(..)
-            | ast::ItemKind::Enum(..)
-            | ast::ItemKind::Struct(..)
-            | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
-            ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
-            ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+            ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. })
+            | ast::ItemKind::Enum(ident, ..)
+            | ast::ItemKind::Struct(ident, ..)
+            | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident),
+            ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
+                self.check_case(cx, "trait", ident)
+            }
+            ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident),
 
             // N.B. This check is only for inherent associated types, so that we don't lint against
             // trait impls where we should have warned for the trait definition already.
             ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
                 for it in items {
                     // FIXME: this doesn't respect `#[allow(..)]` on the item itself.
-                    if let ast::AssocItemKind::Type(..) = it.kind {
-                        self.check_case(cx, "associated type", &it.ident);
+                    if let ast::AssocItemKind::Type(alias) = &it.kind {
+                        self.check_case(cx, "associated type", &alias.ident);
                     }
                 }
             }
@@ -194,8 +196,8 @@ impl EarlyLintPass for NonCamelCaseTypes {
     }
 
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
-        if let ast::AssocItemKind::Type(..) = it.kind {
-            self.check_case(cx, "associated type", &it.ident);
+        if let ast::AssocItemKind::Type(alias) = &it.kind {
+            self.check_case(cx, "associated type", &alias.ident);
         }
     }
 
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 1489f9de819..826bce2c315 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -1,9 +1,11 @@
 use rustc_ast::LitKind;
 use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
+use rustc_middle::ty::RawPtr;
 use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::sym;
+use rustc_span::{Span, sym};
 
-use crate::lints::PtrNullChecksDiag;
+use crate::lints::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag};
+use crate::utils::peel_casts;
 use crate::{LateContext, LateLintPass, LintContext};
 
 declare_lint! {
@@ -31,17 +33,40 @@ declare_lint! {
     "useless checking of non-null-typed pointer"
 }
 
-declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]);
+declare_lint! {
+    /// The `invalid_null_arguments` lint checks for invalid usage of null pointers in arguments.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// # use std::{slice, ptr};
+    /// // Undefined behavior
+    /// # let _slice: &[u8] =
+    /// unsafe { slice::from_raw_parts(ptr::null(), 0) };
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Calling methods whos safety invariants requires non-null ptr with a null pointer
+    /// is [Undefined Behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)!
+    INVALID_NULL_ARGUMENTS,
+    Deny,
+    "invalid null pointer in arguments"
+}
+
+declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS, INVALID_NULL_ARGUMENTS]);
 
 /// This function checks if the expression is from a series of consecutive casts,
 /// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either
 /// a fn ptr, a reference, or a function call whose definition is
 /// annotated with `#![rustc_never_returns_null_ptr]`.
 /// If this situation is present, the function returns the appropriate diagnostic.
-fn incorrect_check<'a, 'tcx: 'a>(
+fn useless_check<'a, 'tcx: 'a>(
     cx: &'a LateContext<'tcx>,
     mut e: &'a Expr<'a>,
-) -> Option<PtrNullChecksDiag<'tcx>> {
+) -> Option<UselessPtrNullChecksDiag<'tcx>> {
     let mut had_at_least_one_cast = false;
     loop {
         e = e.peel_blocks();
@@ -50,14 +75,14 @@ fn incorrect_check<'a, 'tcx: 'a>(
             && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr)
             && let Some(fn_name) = cx.tcx.opt_item_ident(def_id)
         {
-            return Some(PtrNullChecksDiag::FnRet { fn_name });
+            return Some(UselessPtrNullChecksDiag::FnRet { fn_name });
         } else if let ExprKind::Call(path, _args) = e.kind
             && let ExprKind::Path(ref qpath) = path.kind
             && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
             && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr)
             && let Some(fn_name) = cx.tcx.opt_item_ident(def_id)
         {
-            return Some(PtrNullChecksDiag::FnRet { fn_name });
+            return Some(UselessPtrNullChecksDiag::FnRet { fn_name });
         }
         e = if let ExprKind::Cast(expr, t) = e.kind
             && let TyKind::Ptr(_) = t.kind
@@ -73,9 +98,9 @@ fn incorrect_check<'a, 'tcx: 'a>(
         } else if had_at_least_one_cast {
             let orig_ty = cx.typeck_results().expr_ty(e);
             return if orig_ty.is_fn() {
-                Some(PtrNullChecksDiag::FnPtr { orig_ty, label: e.span })
+                Some(UselessPtrNullChecksDiag::FnPtr { orig_ty, label: e.span })
             } else if orig_ty.is_ref() {
-                Some(PtrNullChecksDiag::Ref { orig_ty, label: e.span })
+                Some(UselessPtrNullChecksDiag::Ref { orig_ty, label: e.span })
             } else {
                 None
             };
@@ -85,6 +110,25 @@ fn incorrect_check<'a, 'tcx: 'a>(
     }
 }
 
+/// Checks if the given expression is a null pointer (modulo casting)
+fn is_null_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Span> {
+    let (expr, _) = peel_casts(cx, expr);
+
+    if let ExprKind::Call(path, []) = expr.kind
+        && let ExprKind::Path(ref qpath) = path.kind
+        && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+        && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+    {
+        (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut).then_some(expr.span)
+    } else if let ExprKind::Lit(spanned) = expr.kind
+        && let LitKind::Int(v, _) = spanned.node
+    {
+        (v == 0).then_some(expr.span)
+    } else {
+        None
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         match expr.kind {
@@ -97,12 +141,68 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
                         cx.tcx.get_diagnostic_name(def_id),
                         Some(sym::ptr_const_is_null | sym::ptr_is_null)
                     )
-                    && let Some(diag) = incorrect_check(cx, arg) =>
+                    && let Some(diag) = useless_check(cx, arg) =>
             {
                 cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
             }
 
             // Catching:
+            // <path>(arg...) where `arg` is null-ptr and `path` is a fn that expect non-null-ptr
+            ExprKind::Call(path, args)
+                if let ExprKind::Path(ref qpath) = path.kind
+                    && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                    && let Some(diag_name) = cx.tcx.get_diagnostic_name(def_id) =>
+            {
+                // `arg` positions where null would cause U.B and whenever ZST are allowed.
+                //
+                // We should probably have a `rustc` attribute, but checking them is costly,
+                // maybe if we checked for null ptr first, it would be acceptable?
+                let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
+                    sym::ptr_read
+                    | sym::ptr_read_unaligned
+                    | sym::ptr_read_volatile
+                    | sym::ptr_replace
+                    | sym::ptr_write
+                    | sym::ptr_write_bytes
+                    | sym::ptr_write_unaligned
+                    | sym::ptr_write_volatile => (&[0], true),
+                    sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
+                    sym::ptr_copy
+                    | sym::ptr_copy_nonoverlapping
+                    | sym::ptr_swap
+                    | sym::ptr_swap_nonoverlapping => (&[0, 1], true),
+                    _ => return,
+                };
+
+                for &arg_idx in arg_indices {
+                    if let Some(arg) = args.get(arg_idx)
+                        && let Some(null_span) = is_null_ptr(cx, arg)
+                        && let Some(ty) = cx.typeck_results().expr_ty_opt(arg)
+                        && let RawPtr(ty, _mutbl) = ty.kind()
+                    {
+                        // If ZST are fine, don't lint on them
+                        let typing_env = cx.typing_env();
+                        if are_zsts_allowed
+                            && cx
+                                .tcx
+                                .layout_of(typing_env.as_query_input(*ty))
+                                .is_ok_and(|layout| layout.is_1zst())
+                        {
+                            break;
+                        }
+
+                        let diag = if arg.span.contains(null_span) {
+                            InvalidNullArgumentsDiag::NullPtrInline { null_span }
+                        } else {
+                            InvalidNullArgumentsDiag::NullPtrThroughBinding { null_span }
+                        };
+
+                        cx.emit_span_lint(INVALID_NULL_ARGUMENTS, expr.span, diag)
+                    }
+                }
+            }
+
+            // Catching:
             // (fn_ptr as *<const/mut> <ty>).is_null()
             ExprKind::MethodCall(_, receiver, _, _)
                 if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
@@ -110,18 +210,18 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
                         cx.tcx.get_diagnostic_name(def_id),
                         Some(sym::ptr_const_is_null | sym::ptr_is_null)
                     )
-                    && let Some(diag) = incorrect_check(cx, receiver) =>
+                    && let Some(diag) = useless_check(cx, receiver) =>
             {
                 cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
             }
 
             ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
                 let to_check: &Expr<'_>;
-                let diag: PtrNullChecksDiag<'_>;
-                if let Some(ddiag) = incorrect_check(cx, left) {
+                let diag: UselessPtrNullChecksDiag<'_>;
+                if let Some(ddiag) = useless_check(cx, left) {
                     to_check = right;
                     diag = ddiag;
-                } else if let Some(ddiag) = incorrect_check(cx, right) {
+                } else if let Some(ddiag) = useless_check(cx, right) {
                     to_check = left;
                     diag = ddiag;
                 } else {
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 7c6656f91c9..1d4d380cb68 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -6,6 +6,7 @@ use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::sym;
 
 use crate::lints::InvalidReferenceCastingDiag;
+use crate::utils::peel_casts;
 use crate::{LateContext, LateLintPass, LintContext};
 
 declare_lint! {
@@ -235,46 +236,3 @@ fn is_cast_to_bigger_memory_layout<'tcx>(
         None
     }
 }
-
-fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
-    let mut gone_trough_unsafe_cell_raw_get = false;
-
-    loop {
-        e = e.peel_blocks();
-        // <expr> as ...
-        e = if let ExprKind::Cast(expr, _) = e.kind {
-            expr
-        // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
-        } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
-            && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
-            && matches!(
-                cx.tcx.get_diagnostic_name(def_id),
-                Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
-            )
-        {
-            expr
-        // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _>(<expr>)
-        } else if let ExprKind::Call(path, [arg]) = e.kind
-            && let ExprKind::Path(ref qpath) = path.kind
-            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
-            && matches!(
-                cx.tcx.get_diagnostic_name(def_id),
-                Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute)
-            )
-        {
-            if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
-                gone_trough_unsafe_cell_raw_get = true;
-            }
-            arg
-        } else {
-            let init = cx.expr_or_init(e);
-            if init.hir_id != e.hir_id {
-                init
-            } else {
-                break;
-            }
-        };
-    }
-
-    (e, gone_trough_unsafe_cell_raw_get)
-}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 7109fefbe78..fec5db64bf2 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1403,7 +1403,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             CItemKind::Definition => "fn",
         };
         let span_note = if let ty::Adt(def, _) = ty.kind()
-            && let Some(sp) = self.cx.tcx.hir().span_if_local(def.did())
+            && let Some(sp) = self.cx.tcx.hir_span_if_local(def.did())
         {
             Some(sp)
         } else {
@@ -1634,6 +1634,9 @@ impl ImproperCTypesDefinitions {
             return true;
         } else if let Adt(adt_def, _) = ty.kind()
             && adt_def.is_struct()
+            && adt_def.repr().c()
+            && !adt_def.repr().packed()
+            && adt_def.repr().align.is_none()
         {
             let struct_variant = adt_def.variant(VariantIdx::ZERO);
             // Within a nested struct, all fields are examined to correctly
@@ -1655,8 +1658,11 @@ impl ImproperCTypesDefinitions {
         item: &'tcx hir::Item<'tcx>,
     ) {
         let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id());
+        // repr(C) structs also with packed or aligned representation
+        // should be ignored.
         if adt_def.repr().c()
             && !adt_def.repr().packed()
+            && adt_def.repr().align.is_none()
             && cx.tcx.sess.target.os == "aix"
             && !adt_def.all_fields().next().is_none()
         {
diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs
new file mode 100644
index 00000000000..a7295d9c532
--- /dev/null
+++ b/compiler/rustc_lint/src/utils.rs
@@ -0,0 +1,55 @@
+use rustc_hir::{Expr, ExprKind};
+use rustc_span::sym;
+
+use crate::LateContext;
+
+/// Given an expression, peel all of casts (`<expr> as ...`, `<expr>.cast{,_mut,_const}()`,
+/// `ptr::from_ref(<expr>)`, ...) and init expressions.
+///
+/// Returns the innermost expression and a boolean representing if one of the casts was
+/// `UnsafeCell::raw_get(<expr>)`
+pub(crate) fn peel_casts<'tcx>(
+    cx: &LateContext<'tcx>,
+    mut e: &'tcx Expr<'tcx>,
+) -> (&'tcx Expr<'tcx>, bool) {
+    let mut gone_trough_unsafe_cell_raw_get = false;
+
+    loop {
+        e = e.peel_blocks();
+        // <expr> as ...
+        e = if let ExprKind::Cast(expr, _) = e.kind {
+            expr
+        // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
+        } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
+            && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+            && matches!(
+                cx.tcx.get_diagnostic_name(def_id),
+                Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
+            )
+        {
+            expr
+        // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _>(<expr>)
+        } else if let ExprKind::Call(path, [arg]) = e.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && matches!(
+                cx.tcx.get_diagnostic_name(def_id),
+                Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute)
+            )
+        {
+            if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) {
+                gone_trough_unsafe_cell_raw_get = true;
+            }
+            arg
+        } else {
+            let init = cx.expr_or_init(e);
+            if init.hir_id != e.hir_id {
+                init
+            } else {
+                break;
+            }
+        };
+    }
+
+    (e, gone_trough_unsafe_cell_raw_get)
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 592c934997c..8a761a0a096 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -143,6 +143,7 @@ declare_lint_pass! {
         UNUSED_VARIABLES,
         USELESS_DEPRECATED,
         WARNINGS,
+        WASM_C_ABI,
         // tidy-alphabetical-end
     ]
 }
@@ -5082,6 +5083,8 @@ declare_lint! {
     /// }
     /// ```
     ///
+    /// This will produce:
+    ///
     /// ```text
     /// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
     ///  --> lint_example.rs:18:12
@@ -5125,3 +5128,46 @@ declare_lint! {
         reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
     };
 }
+
+declare_lint! {
+    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
+    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
+    /// of this target.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs wasm32-unknown-unknown)
+    /// #[repr(C)]
+    /// struct MyType(i32, i32);
+    ///
+    /// extern "C" my_fun(x: MyType) {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+    /// --> $DIR/wasm_c_abi_transition.rs:17:1
+    ///  |
+    ///  | pub extern "C" fn my_fun(_x: MyType) {}
+    ///  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///  |
+    ///  = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+    ///  = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
+    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
+    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
+    /// stop functioning.
+    pub WASM_C_ABI,
+    Warn,
+    "detects code relying on rustc's non-spec-compliant wasm C ABI",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
+    };
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 86f1bcc46ee..257bdc01993 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -855,10 +855,15 @@ extern "C" LLVMRustResult LLVMRustOptimize(
   }
 
   if (LintIR) {
-    PipelineStartEPCallbacks.push_back(
-        [](ModulePassManager &MPM, OptimizationLevel Level) {
-          MPM.addPass(createModuleToFunctionPassAdaptor(LintPass()));
-        });
+    PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM,
+                                          OptimizationLevel Level) {
+#if LLVM_VERSION_GE(21, 0)
+      MPM.addPass(
+          createModuleToFunctionPassAdaptor(LintPass(/*AbortOnError=*/true)));
+#else
+      MPM.addPass(createModuleToFunctionPassAdaptor(LintPass()));
+#endif
+    });
   }
 
   if (InstrumentCoverage) {
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 20f66fae5c0..d997ba198ac 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -97,6 +97,10 @@ metadata_found_staticlib =
     found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
     .help = please recompile that crate using --crate-type lib
 
+metadata_full_metadata_not_found =
+    only metadata stub found for `{$flavor}` dependency `{$crate_name}`
+    please provide path to the corresponding .rmeta file with full metadata
+
 metadata_global_alloc_required =
     no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
 
@@ -118,12 +122,23 @@ metadata_incompatible_rustc =
 
 metadata_incompatible_target_modifiers =
     mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
-    .note = `{$flag_name_prefixed}={$flag_local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$flag_extern_value}` in dependency `{$extern_crate}`
+    .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
     .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
-
 metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error
-metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$flag_extern_value}` in this crate or `{$flag_name_prefixed}={$flag_local_value}` in `{$extern_crate}`
+metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`
+
+metadata_incompatible_target_modifiers_help_fix_l_missed = set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}`
+
+metadata_incompatible_target_modifiers_help_fix_r_missed = unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`
 
+metadata_incompatible_target_modifiers_l_missed =
+    mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
+    .note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`
+    .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
+metadata_incompatible_target_modifiers_r_missed =
+    mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
+    .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
+    .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
 metadata_incompatible_wasm_link =
     `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 12503ffd1a6..16f87ab79be 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -358,30 +358,58 @@ impl CStore {
     ) {
         let span = krate.spans.inner_span.shrink_to_lo();
         let allowed_flag_mismatches = &tcx.sess.opts.cg.unsafe_allow_abi_mismatch;
-        let name = tcx.crate_name(LOCAL_CRATE);
+        let local_crate = tcx.crate_name(LOCAL_CRATE);
         let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone());
         let report_diff = |prefix: &String,
                            opt_name: &String,
-                           flag_local_value: &String,
-                           flag_extern_value: &String| {
+                           flag_local_value: Option<&String>,
+                           flag_extern_value: Option<&String>| {
             if allowed_flag_mismatches.contains(&opt_name) {
                 return;
             }
-            tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
-                span,
-                extern_crate: data.name(),
-                local_crate: name,
-                flag_name: opt_name.clone(),
-                flag_name_prefixed: format!("-{}{}", prefix, opt_name),
-                flag_local_value: flag_local_value.to_string(),
-                flag_extern_value: flag_extern_value.to_string(),
-            });
+            let extern_crate = data.name();
+            let flag_name = opt_name.clone();
+            let flag_name_prefixed = format!("-{}{}", prefix, opt_name);
+
+            match (flag_local_value, flag_extern_value) {
+                (Some(local_value), Some(extern_value)) => {
+                    tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
+                        span,
+                        extern_crate,
+                        local_crate,
+                        flag_name,
+                        flag_name_prefixed,
+                        local_value: local_value.to_string(),
+                        extern_value: extern_value.to_string(),
+                    })
+                }
+                (None, Some(extern_value)) => {
+                    tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed {
+                        span,
+                        extern_crate,
+                        local_crate,
+                        flag_name,
+                        flag_name_prefixed,
+                        extern_value: extern_value.to_string(),
+                    })
+                }
+                (Some(local_value), None) => {
+                    tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed {
+                        span,
+                        extern_crate,
+                        local_crate,
+                        flag_name,
+                        flag_name_prefixed,
+                        local_value: local_value.to_string(),
+                    })
+                }
+                (None, None) => panic!("Incorrect target modifiers report_diff(None, None)"),
+            };
         };
         let mut it1 = mods.iter().map(tmod_extender);
         let mut it2 = dep_mods.iter().map(tmod_extender);
         let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
         let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
-        let no_val = "*".to_string();
         loop {
             left_name_val = left_name_val.or_else(|| it1.next());
             right_name_val = right_name_val.or_else(|| it2.next());
@@ -389,26 +417,31 @@ impl CStore {
                 (Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
                     cmp::Ordering::Equal => {
                         if l.0.tech_value != r.0.tech_value {
-                            report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &r.1.value_name);
+                            report_diff(
+                                &l.0.prefix,
+                                &l.0.name,
+                                Some(&l.1.value_name),
+                                Some(&r.1.value_name),
+                            );
                         }
                         left_name_val = None;
                         right_name_val = None;
                     }
                     cmp::Ordering::Greater => {
-                        report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
+                        report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
                         right_name_val = None;
                     }
                     cmp::Ordering::Less => {
-                        report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
+                        report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
                         left_name_val = None;
                     }
                 },
                 (Some(l), None) => {
-                    report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
+                    report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None);
                     left_name_val = None;
                 }
                 (None, Some(r)) => {
-                    report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
+                    report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name));
                     right_name_val = None;
                 }
                 (None, None) => break,
@@ -999,14 +1032,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     }
 
     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
-        self.cstore.has_global_allocator = match &*global_allocator_spans(krate) {
-            [span1, span2, ..] => {
-                self.dcx().emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
-                true
-            }
-            spans => !spans.is_empty(),
-        };
-        self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
+        self.cstore.has_global_allocator =
+            match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) {
+                [span1, span2, ..] => {
+                    self.dcx()
+                        .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+                    true
+                }
+                spans => !spans.is_empty(),
+            };
+        self.cstore.has_alloc_error_handler = match &*fn_spans(
+            krate,
+            Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
+        ) {
             [span1, span2, ..] => {
                 self.dcx()
                     .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
@@ -1277,17 +1315,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         definitions: &Definitions,
     ) -> Option<CrateNum> {
         match item.kind {
-            ast::ItemKind::ExternCrate(orig_name) => {
-                debug!(
-                    "resolving extern crate stmt. ident: {} orig_name: {:?}",
-                    item.ident, orig_name
-                );
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
+                debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name);
                 let name = match orig_name {
                     Some(orig_name) => {
                         validate_crate_name(self.sess, orig_name, Some(item.span));
                         orig_name
                     }
-                    None => item.ident.name,
+                    None => ident.name,
                 };
                 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
                     CrateDepKind::MacrosOnly
@@ -1335,36 +1370,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     }
 }
 
-fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
-    struct Finder {
-        name: Symbol,
-        spans: Vec<Span>,
-    }
-    impl<'ast> visit::Visitor<'ast> for Finder {
-        fn visit_item(&mut self, item: &'ast ast::Item) {
-            if item.ident.name == self.name
-                && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
-            {
-                self.spans.push(item.span);
-            }
-            visit::walk_item(self, item)
-        }
-    }
-
-    let name = Symbol::intern(&global_fn_name(sym::alloc));
-    let mut f = Finder { name, spans: Vec::new() };
-    visit::walk_crate(&mut f, krate);
-    f.spans
-}
-
-fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
+fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec<Span> {
     struct Finder {
         name: Symbol,
         spans: Vec<Span>,
     }
     impl<'ast> visit::Visitor<'ast> for Finder {
         fn visit_item(&mut self, item: &'ast ast::Item) {
-            if item.ident.name == self.name
+            if let Some(ident) = item.kind.ident()
+                && ident.name == self.name
                 && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
             {
                 self.spans.push(item.span);
@@ -1373,7 +1387,6 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
         }
     }
 
-    let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
     let mut f = Finder { name, spans: Vec::new() };
     visit::walk_crate(&mut f, krate);
     f.spans
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 2ad6389c0b4..c45daeda85d 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -526,6 +526,15 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for MultipleCandidates {
 }
 
 #[derive(Diagnostic)]
+#[diag(metadata_full_metadata_not_found)]
+pub(crate) struct FullMetadataNotFound {
+    #[primary_span]
+    pub span: Span,
+    pub flavor: CrateFlavor,
+    pub crate_name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(metadata_symbol_conflicts_current, code = E0519)]
 pub struct SymbolConflictsCurrent {
     #[primary_span]
@@ -759,8 +768,40 @@ pub struct IncompatibleTargetModifiers {
     pub local_crate: Symbol,
     pub flag_name: String,
     pub flag_name_prefixed: String,
-    pub flag_local_value: String,
-    pub flag_extern_value: String,
+    pub local_value: String,
+    pub extern_value: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_target_modifiers_l_missed)]
+#[help]
+#[note]
+#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)]
+#[help(metadata_incompatible_target_modifiers_help_allow)]
+pub struct IncompatibleTargetModifiersLMissed {
+    #[primary_span]
+    pub span: Span,
+    pub extern_crate: Symbol,
+    pub local_crate: Symbol,
+    pub flag_name: String,
+    pub flag_name_prefixed: String,
+    pub extern_value: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_target_modifiers_r_missed)]
+#[help]
+#[note]
+#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)]
+#[help(metadata_incompatible_target_modifiers_help_allow)]
+pub struct IncompatibleTargetModifiersRMissed {
+    #[primary_span]
+    pub span: Span,
+    pub extern_crate: Symbol,
+    pub local_crate: Symbol,
+    pub flag_name: String,
+    pub flag_name_prefixed: String,
+    pub local_value: String,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 4450d050c8e..c4e1e0f1d1a 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -3,7 +3,7 @@ use std::{fs, io};
 
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{OutFileName, OutputType};
+use rustc_session::config::{CrateType, OutFileName, OutputType};
 use rustc_session::output::filename_for_metadata;
 use rustc_session::{MetadataKind, Session};
 use tempfile::Builder as TempFileBuilder;
@@ -50,7 +50,14 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
         .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new("")))
         .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err }));
     let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
-    let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME);
+    let metadata_filename = metadata_tmpdir.as_ref().join("full.rmeta");
+    let metadata_stub_filename = if !tcx.sess.opts.unstable_opts.embed_metadata
+        && !tcx.crate_types().contains(&CrateType::ProcMacro)
+    {
+        Some(metadata_tmpdir.as_ref().join("stub.rmeta"))
+    } else {
+        None
+    };
 
     // Always create a file at `metadata_filename`, even if we have nothing to write to it.
     // This simplifies the creation of the output `out_filename` when requested.
@@ -60,9 +67,15 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
             std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
                 tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
             });
+            if let Some(metadata_stub_filename) = &metadata_stub_filename {
+                std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
+                    tcx.dcx()
+                        .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
+                });
+            }
         }
         MetadataKind::Uncompressed | MetadataKind::Compressed => {
-            encode_metadata(tcx, &metadata_filename);
+            encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref())
         }
     };
 
@@ -100,9 +113,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
 
     // Load metadata back to memory: codegen may need to include it in object files.
     let metadata =
-        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
-            tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
-        });
+        EncodedMetadata::from_path(metadata_filename, metadata_stub_filename, metadata_tmpdir)
+            .unwrap_or_else(|err| {
+                tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
+            });
 
     let need_metadata_module = metadata_kind == MetadataKind::Compressed;
 
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index d5dd5059aac..112954eca0d 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -654,7 +654,24 @@ impl<'a> CrateLocator<'a> {
                     continue;
                 }
             }
-            *slot = Some((hash, metadata, lib.clone()));
+
+            // We error eagerly here. If we're locating a rlib, then in theory the full metadata
+            // could still be in a (later resolved) dylib. In practice, if the rlib and dylib
+            // were produced in a way where one has full metadata and the other hasn't, it would
+            // mean that they were compiled using different compiler flags and probably also have
+            // a different SVH value.
+            if metadata.get_header().is_stub {
+                // `is_stub` should never be true for .rmeta files.
+                assert_ne!(flavor, CrateFlavor::Rmeta);
+
+                // Because rmeta files are resolved before rlib/dylib files, if this is a stub and
+                // we haven't found a slot already, it means that the full metadata is missing.
+                if slot.is_none() {
+                    return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor));
+                }
+            } else {
+                *slot = Some((hash, metadata, lib.clone()));
+            }
             ret = Some((lib, kind));
         }
 
@@ -728,37 +745,25 @@ impl<'a> CrateLocator<'a> {
             let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else {
                 return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone()));
             };
-            // FnMut cannot return reference to captured value, so references
-            // must be taken outside the closure.
-            let rlibs = &mut rlibs;
-            let rmetas = &mut rmetas;
-            let dylibs = &mut dylibs;
-            let type_via_filename = (|| {
-                if file.starts_with("lib") {
-                    if file.ends_with(".rlib") {
-                        return Some(rlibs);
-                    }
-                    if file.ends_with(".rmeta") {
-                        return Some(rmetas);
-                    }
-                }
-                let dll_prefix = self.target.dll_prefix.as_ref();
-                let dll_suffix = self.target.dll_suffix.as_ref();
-                if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
-                    return Some(dylibs);
-                }
-                None
-            })();
-            match type_via_filename {
-                Some(type_via_filename) => {
-                    type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag);
+            if file.starts_with("lib") {
+                if file.ends_with(".rlib") {
+                    rlibs.insert(loc_canon.clone(), PathKind::ExternFlag);
+                    continue;
                 }
-                None => {
-                    self.crate_rejections
-                        .via_filename
-                        .push(CrateMismatch { path: loc_orig.clone(), got: String::new() });
+                if file.ends_with(".rmeta") {
+                    rmetas.insert(loc_canon.clone(), PathKind::ExternFlag);
+                    continue;
                 }
             }
+            let dll_prefix = self.target.dll_prefix.as_ref();
+            let dll_suffix = self.target.dll_suffix.as_ref();
+            if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
+                dylibs.insert(loc_canon.clone(), PathKind::ExternFlag);
+                continue;
+            }
+            self.crate_rejections
+                .via_filename
+                .push(CrateMismatch { path: loc_orig.clone(), got: String::new() });
         }
 
         // Extract the dylib/rlib/rmeta triple.
@@ -928,6 +933,7 @@ pub(crate) enum CrateError {
     ExternLocationNotExist(Symbol, PathBuf),
     ExternLocationNotFile(Symbol, PathBuf),
     MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>),
+    FullMetadataNotFound(Symbol, CrateFlavor),
     SymbolConflictsCurrent(Symbol),
     StableCrateIdCollision(Symbol, Symbol),
     DlOpen(String, String),
@@ -978,6 +984,9 @@ impl CrateError {
             CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
                 dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates });
             }
+            CrateError::FullMetadataNotFound(crate_name, flavor) => {
+                dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor });
+            }
             CrateError::SymbolConflictsCurrent(root_name) => {
                 dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name });
             }
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 1671b7e06b0..f63ae8079dc 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -95,14 +95,14 @@ pub fn try_find_native_static_library(
     name: &str,
     verbatim: bool,
 ) -> Option<PathBuf> {
+    let default = sess.staticlib_components(verbatim);
     let formats = if verbatim {
-        vec![("".into(), "".into())]
+        vec![default]
     } else {
-        let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone());
         // On Windows, static libraries sometimes show up as libfoo.a and other
         // times show up as foo.lib
-        let unix = ("lib".into(), ".a".into());
-        if os == unix { vec![os] } else { vec![os, unix] }
+        let unix = ("lib", ".a");
+        if default == unix { vec![default] } else { vec![default, unix] }
     };
 
     walk_native_lib_search_dirs(sess, None, |dir, is_framework| {
@@ -124,18 +124,17 @@ pub fn try_find_native_dynamic_library(
     name: &str,
     verbatim: bool,
 ) -> Option<PathBuf> {
+    let default = sess.staticlib_components(verbatim);
     let formats = if verbatim {
-        vec![("".into(), "".into())]
+        vec![default]
     } else {
         // While the official naming convention for MSVC import libraries
-        // is foo.lib...
-        let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone());
-        // ... Meson follows the libfoo.dll.a convention to
+        // is foo.lib, Meson follows the libfoo.dll.a convention to
         // disambiguate .a for static libraries
-        let meson = ("lib".into(), ".dll.a".into());
+        let meson = ("lib", ".dll.a");
         // and MinGW uses .a altogether
-        let mingw = ("lib".into(), ".a".into());
-        vec![os, meson, mingw]
+        let mingw = ("lib", ".a");
+        vec![default, meson, mingw]
     };
 
     walk_native_lib_search_dirs(sess, None, |dir, is_framework| {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 776b081a463..3dc82ce9d18 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -330,14 +330,8 @@ provide! { tcx, def_id, other, cdata,
 
     visibility => { cdata.get_visibility(def_id.index) }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
-    adt_destructor => {
-        let _ = cdata;
-        tcx.calculate_dtor(def_id, |_,_| Ok(()))
-    }
-    adt_async_destructor => {
-        let _ = cdata;
-        tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
-    }
+    adt_destructor => { table }
+    adt_async_destructor => { table }
     associated_item_def_ids => {
         tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
     }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7ab3d432bdf..167122a9793 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     triple: tcx.sess.opts.target_triple.clone(),
                     hash: tcx.crate_hash(LOCAL_CRATE),
                     is_proc_macro_crate: proc_macro_data.is_some(),
+                    is_stub: false,
                 },
                 extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
                 stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
@@ -1633,6 +1634,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
             }
         }
+
+        if let Some(destructor) = tcx.adt_destructor(local_def_id) {
+            record!(self.tables.adt_destructor[def_id] <- destructor);
+        }
+
+        if let Some(destructor) = tcx.adt_async_destructor(local_def_id) {
+            record!(self.tables.adt_async_destructor[def_id] <- destructor);
+        }
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1881,8 +1890,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let is_proc_macro = self.tcx.crate_types().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
-            let hir = tcx.hir();
-
             let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
             let stability = tcx.lookup_stability(CRATE_DEF_ID);
             let macros =
@@ -1915,7 +1922,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 let id = proc_macro;
                 let proc_macro = tcx.local_def_id_to_hir_id(proc_macro);
                 let mut name = tcx.hir_name(proc_macro);
-                let span = hir.span(proc_macro);
+                let span = tcx.hir_span(proc_macro);
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
                 let attrs = tcx.hir_attrs(proc_macro);
@@ -2231,8 +2238,12 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
 // generated regardless of trailing bytes that end up in it.
 
 pub struct EncodedMetadata {
-    // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
-    mmap: Option<Mmap>,
+    // The declaration order matters because `full_metadata` should be dropped
+    // before `_temp_dir`.
+    full_metadata: Option<Mmap>,
+    // This is an optional stub metadata containing only the crate header.
+    // The header should be very small, so we load it directly into memory.
+    stub_metadata: Option<Vec<u8>>,
     // We need to carry MaybeTempDir to avoid deleting the temporary
     // directory while accessing the Mmap.
     _temp_dir: Option<MaybeTempDir>,
@@ -2240,33 +2251,50 @@ pub struct EncodedMetadata {
 
 impl EncodedMetadata {
     #[inline]
-    pub fn from_path(path: PathBuf, temp_dir: Option<MaybeTempDir>) -> std::io::Result<Self> {
+    pub fn from_path(
+        path: PathBuf,
+        stub_path: Option<PathBuf>,
+        temp_dir: Option<MaybeTempDir>,
+    ) -> std::io::Result<Self> {
         let file = std::fs::File::open(&path)?;
         let file_metadata = file.metadata()?;
         if file_metadata.len() == 0 {
-            return Ok(Self { mmap: None, _temp_dir: None });
+            return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None });
         }
-        let mmap = unsafe { Some(Mmap::map(file)?) };
-        Ok(Self { mmap, _temp_dir: temp_dir })
+        let full_mmap = unsafe { Some(Mmap::map(file)?) };
+
+        let stub =
+            if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None };
+
+        Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir })
     }
 
     #[inline]
-    pub fn raw_data(&self) -> &[u8] {
-        self.mmap.as_deref().unwrap_or_default()
+    pub fn full(&self) -> &[u8] {
+        &self.full_metadata.as_deref().unwrap_or_default()
+    }
+
+    #[inline]
+    pub fn stub_or_full(&self) -> &[u8] {
+        self.stub_metadata.as_deref().unwrap_or(self.full())
     }
 }
 
 impl<S: Encoder> Encodable<S> for EncodedMetadata {
     fn encode(&self, s: &mut S) {
-        let slice = self.raw_data();
+        self.stub_metadata.encode(s);
+
+        let slice = self.full();
         slice.encode(s)
     }
 }
 
 impl<D: Decoder> Decodable<D> for EncodedMetadata {
     fn decode(d: &mut D) -> Self {
+        let stub = <Option<Vec<u8>>>::decode(d);
+
         let len = d.read_usize();
-        let mmap = if len > 0 {
+        let full_metadata = if len > 0 {
             let mut mmap = MmapMut::map_anon(len).unwrap();
             mmap.copy_from_slice(d.read_raw_bytes(len));
             Some(mmap.make_read_only().unwrap())
@@ -2274,11 +2302,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
             None
         };
 
-        Self { mmap, _temp_dir: None }
+        Self { full_metadata, stub_metadata: stub, _temp_dir: None }
     }
 }
 
-pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
+pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
     let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
 
     // Since encoding metadata is not in a query, and nothing is cached,
@@ -2292,6 +2320,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
         join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
     }
 
+    with_encode_metadata_header(tcx, path, |ecx| {
+        // Encode all the entries and extra information in the crate,
+        // culminating in the `CrateRoot` which points to all of it.
+        let root = ecx.encode_crate_root();
+
+        // Flush buffer to ensure backing file has the correct size.
+        ecx.opaque.flush();
+        // Record metadata size for self-profiling
+        tcx.prof.artifact_size(
+            "crate_metadata",
+            "crate_metadata",
+            ecx.opaque.file().metadata().unwrap().len(),
+        );
+
+        root.position.get()
+    });
+
+    if let Some(ref_path) = ref_path {
+        with_encode_metadata_header(tcx, ref_path, |ecx| {
+            let header: LazyValue<CrateHeader> = ecx.lazy(CrateHeader {
+                name: tcx.crate_name(LOCAL_CRATE),
+                triple: tcx.sess.opts.target_triple.clone(),
+                hash: tcx.crate_hash(LOCAL_CRATE),
+                is_proc_macro_crate: false,
+                is_stub: true,
+            });
+            header.position.get()
+        });
+    }
+}
+
+fn with_encode_metadata_header(
+    tcx: TyCtxt<'_>,
+    path: &Path,
+    f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize,
+) {
     let mut encoder = opaque::FileEncoder::new(path)
         .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
     encoder.emit_raw_bytes(METADATA_HEADER);
@@ -2326,9 +2390,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
     // Encode the rustc version string in a predictable location.
     rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
 
-    // Encode all the entries and extra information in the crate,
-    // culminating in the `CrateRoot` which points to all of it.
-    let root = ecx.encode_crate_root();
+    let root_position = f(&mut ecx);
 
     // Make sure we report any errors from writing to the file.
     // If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2338,12 +2400,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
     }
 
     let file = ecx.opaque.file();
-    if let Err(err) = encode_root_position(file, root.position.get()) {
+    if let Err(err) = encode_root_position(file, root_position) {
         tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err });
     }
-
-    // Record metadata size for self-profiling
-    tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len());
 }
 
 fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index dc453b1e747..b1bc4b43ab4 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -56,7 +56,7 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
 /// Metadata encoding version.
 /// N.B., increment this if you change the format of metadata such that
 /// the rustc version can't be found to compare with `rustc_version()`.
-const METADATA_VERSION: u8 = 9;
+const METADATA_VERSION: u8 = 10;
 
 /// Metadata header which includes `METADATA_VERSION`.
 ///
@@ -221,6 +221,12 @@ pub(crate) struct CrateHeader {
     /// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every
     /// time ProcMacroData changes.
     pub(crate) is_proc_macro_crate: bool,
+    /// Whether this crate metadata section is just a stub.
+    /// Stubs do not contain the full metadata (it will be typically stored
+    /// in a separate rmeta file).
+    ///
+    /// This is used inside rlibs and dylibs when using `-Zembed-metadata=no`.
+    pub(crate) is_stub: bool,
 }
 
 /// Serialized `.rmeta` data for a crate.
@@ -446,6 +452,8 @@ define_tables! {
     fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
     coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
     coroutine_for_closure: Table<DefIndex, RawDefId>,
+    adt_destructor: Table<DefIndex, LazyValue<ty::Destructor>>,
+    adt_async_destructor: Table<DefIndex, LazyValue<ty::AsyncDestructor>>,
     coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
     eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
     trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index f967d8b92c7..644cdac5d55 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -21,6 +21,15 @@ macro_rules! define_dep_nodes {
             ($mod:ident) => {[ $($mod::$variant()),* ]};
         }
 
+        #[macro_export]
+        macro_rules! make_dep_kind_name_array {
+            ($mod:ident) => {
+                vec! {
+                    $(*$mod::$variant().name),*
+                }
+            };
+        }
+
         /// This enum serves as an index into arrays built by `make_dep_kind_array`.
         // This enum has more than u8::MAX variants so we need some kind of multi-byte
         // encoding. The derived Encodable/Decodable uses leb128 encoding which is
@@ -80,6 +89,7 @@ rustc_query_append!(define_dep_nodes![
     /// We use this to create a forever-red node.
     [] fn Red() -> (),
     [] fn SideEffect() -> (),
+    [] fn AnonZeroDeps() -> (),
     [] fn TraitSelect() -> (),
     [] fn CompileCodegenUnit() -> (),
     [] fn CompileMonoItem() -> (),
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index c927538b4cf..931d67087ac 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -20,7 +20,9 @@ pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepsType>;
 pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct<TyCtxt<'tcx>>;
 
 #[derive(Clone)]
-pub struct DepsType;
+pub struct DepsType {
+    pub dep_names: Vec<&'static str>,
+}
 
 impl Deps for DepsType {
     fn with_deps<OP, R>(task_deps: TaskDepsRef<'_>, op: OP) -> R
@@ -44,9 +46,14 @@ impl Deps for DepsType {
         })
     }
 
+    fn name(&self, dep_kind: DepKind) -> &'static str {
+        self.dep_names[dep_kind.as_usize()]
+    }
+
     const DEP_KIND_NULL: DepKind = dep_kinds::Null;
     const DEP_KIND_RED: DepKind = dep_kinds::Red;
     const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect;
+    const DEP_KIND_ANON_ZERO_DEPS: DepKind = dep_kinds::AnonZeroDeps;
     const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
 }
 
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index f17efab81ec..21ab06c98a7 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -22,6 +22,7 @@ use crate::ty::TyCtxt;
 // only serves as "namespace" for HIR-related methods, and can be
 // removed if all the methods are reasonably renamed and moved to tcx
 // (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
+#[allow(unused)] // FIXME: temporary
 #[derive(Copy, Clone)]
 pub struct Map<'hir> {
     pub(super) tcx: TyCtxt<'hir>,
@@ -273,7 +274,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self.hir_maybe_body_owned_by(id).unwrap_or_else(|| {
             let hir_id = self.local_def_id_to_hir_id(id);
             span_bug!(
-                self.hir().span(hir_id),
+                self.hir_span(hir_id),
                 "body_owned_by: {} has no associated body",
                 self.hir_id_to_string(hir_id)
             );
@@ -367,10 +368,6 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] {
-        self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
-    }
-
     /// Gets the attributes on the crate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
@@ -681,9 +678,8 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn hir_id_to_string(self, id: HirId) -> String {
         let path_str = |def_id: LocalDefId| self.def_path_str(def_id);
 
-        let span_str = || {
-            self.sess.source_map().span_to_snippet(Map { tcx: self }.span(id)).unwrap_or_default()
-        };
+        let span_str =
+            || self.sess.source_map().span_to_snippet(self.hir_span(id)).unwrap_or_default();
         let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
 
         match self.hir_node(id) {
@@ -879,12 +875,10 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn hir_attrs(self, id: HirId) -> &'tcx [Attribute] {
         self.hir_attr_map(id.owner).get(id.local_id)
     }
-}
 
-impl<'hir> Map<'hir> {
     /// Gets the span of the definition of the specified HIR node.
     /// This is used by `tcx.def_span`.
-    pub fn span(self, hir_id: HirId) -> Span {
+    pub fn hir_span(self, hir_id: HirId) -> Span {
         fn until_within(outer: Span, end: Span) -> Span {
             if let Some(end) = end.find_ancestor_inside(outer) {
                 outer.with_hi(end.hi())
@@ -904,7 +898,7 @@ impl<'hir> Map<'hir> {
             span
         }
 
-        let span = match self.tcx.hir_node(hir_id) {
+        let span = match self.hir_node(hir_id) {
             // Function-like.
             Node::Item(Item { kind: ItemKind::Fn { sig, .. }, span: outer_span, .. })
             | Node::TraitItem(TraitItem {
@@ -984,7 +978,7 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => named_span(variant.span, variant.ident, None),
             Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
             Node::ForeignItem(item) => named_span(item.span, item.ident, None),
-            Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
+            Node::Ctor(_) => return self.hir_span(self.parent_hir_id(hir_id)),
             Node::Expr(Expr {
                 kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
                 span,
@@ -993,16 +987,16 @@ impl<'hir> Map<'hir> {
                 // Ensure that the returned span has the item's SyntaxContext.
                 fn_decl_span.find_ancestor_inside(*span).unwrap_or(*span)
             }
-            _ => self.span_with_body(hir_id),
+            _ => self.hir_span_with_body(hir_id),
         };
-        debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt());
+        debug_assert_eq!(span.ctxt(), self.hir_span_with_body(hir_id).ctxt());
         span
     }
 
-    /// Like `hir.span()`, but includes the body of items
+    /// Like `hir_span()`, but includes the body of items
     /// (instead of just the item header)
-    pub fn span_with_body(self, hir_id: HirId) -> Span {
-        match self.tcx.hir_node(hir_id) {
+    pub fn hir_span_with_body(self, hir_id: HirId) -> Span {
+        match self.hir_node(hir_id) {
             Node::Param(param) => param.span,
             Node::Item(item) => item.span,
             Node::ForeignItem(foreign_item) => foreign_item.span,
@@ -1011,7 +1005,7 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => variant.span,
             Node::Field(field) => field.span,
             Node::AnonConst(constant) => constant.span,
-            Node::ConstBlock(constant) => self.tcx.hir_body(constant.body).value.span,
+            Node::ConstBlock(constant) => self.hir_body(constant.body).value.span,
             Node::ConstArg(const_arg) => const_arg.span(),
             Node::Expr(expr) => expr.span,
             Node::ExprField(field) => field.span,
@@ -1031,7 +1025,7 @@ impl<'hir> Map<'hir> {
             Node::PatExpr(lit) => lit.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
-            Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
+            Node::Ctor(..) => self.hir_span_with_body(self.parent_hir_id(hir_id)),
             Node::Lifetime(lifetime) => lifetime.ident.span,
             Node::GenericParam(param) => param.span,
             Node::Infer(i) => i.span,
@@ -1044,23 +1038,23 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    pub fn span_if_local(self, id: DefId) -> Option<Span> {
-        id.is_local().then(|| self.tcx.def_span(id))
+    pub fn hir_span_if_local(self, id: DefId) -> Option<Span> {
+        id.is_local().then(|| self.def_span(id))
     }
 
-    pub fn res_span(self, res: Res) -> Option<Span> {
+    pub fn hir_res_span(self, res: Res) -> Option<Span> {
         match res {
             Res::Err => None,
-            Res::Local(id) => Some(self.span(id)),
-            res => self.span_if_local(res.opt_def_id()?),
+            Res::Local(id) => Some(self.hir_span(id)),
+            res => self.hir_span_if_local(res.opt_def_id()?),
         }
     }
 
     /// 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> {
-        let const_arg = self.tcx.parent_hir_id(anon_const);
-        match self.tcx.parent_hir_node(const_arg) {
+    pub fn hir_opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
+        let const_arg = self.parent_hir_id(anon_const);
+        match self.parent_hir_node(const_arg) {
             Node::GenericParam(GenericParam {
                 def_id: param_id,
                 kind: GenericParamKind::Const { .. },
@@ -1070,7 +1064,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> {
+    pub fn hir_maybe_get_struct_pattern_shorthand_field(self, expr: &Expr<'_>) -> Option<Symbol> {
         let local = match expr {
             Expr {
                 kind:
@@ -1085,7 +1079,7 @@ impl<'hir> Map<'hir> {
             _ => None,
         }?;
 
-        match self.tcx.parent_hir_node(expr.hir_id) {
+        match self.parent_hir_node(expr.hir_id) {
             Node::ExprField(field) => {
                 if field.ident.name == local.name && field.is_shorthand {
                     return Some(local.name);
@@ -1176,15 +1170,14 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
         debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
         if tcx.sess.opts.incremental.is_some() {
             let definitions = tcx.untracked().definitions.freeze();
-            let mut owner_spans: Vec<_> = krate
-                .owners
-                .iter_enumerated()
-                .filter_map(|(def_id, info)| {
-                    let _ = info.as_owner()?;
+            let mut owner_spans: Vec<_> = tcx
+                .hir_crate_items(())
+                .definitions()
+                .map(|def_id| {
                     let def_path_hash = definitions.def_path_hash(def_id);
                     let span = tcx.source_span(def_id);
                     debug_assert_eq!(span.parent(), None);
-                    Some((def_path_hash, span))
+                    (def_path_hash, span)
                 })
                 .collect();
             owner_spans.sort_unstable_by_key(|bn| bn.0);
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 68b9a4f56b9..74369b6636c 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -14,7 +14,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::*;
 use rustc_macros::{Decodable, Encodable, HashStable};
-use rustc_span::{ErrorGuaranteed, ExpnId};
+use rustc_span::{ErrorGuaranteed, ExpnId, Span};
 
 use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
@@ -157,6 +157,7 @@ impl<'tcx> TyCtxt<'tcx> {
         node: OwnerNode<'_>,
         bodies: &SortedMap<ItemLocalId, &Body<'_>>,
         attrs: &SortedMap<ItemLocalId, &[Attribute]>,
+        define_opaque: Option<&[(Span, LocalDefId)]>,
     ) -> (Option<Fingerprint>, Option<Fingerprint>) {
         if self.needs_crate_hash() {
             self.with_stable_hashing_context(|mut hcx| {
@@ -168,6 +169,10 @@ impl<'tcx> TyCtxt<'tcx> {
 
                 let mut stable_hasher = StableHasher::new();
                 attrs.hash_stable(&mut hcx, &mut stable_hasher);
+
+                // Hash the defined opaque types, which are not present in the attrs.
+                define_opaque.hash_stable(&mut hcx, &mut stable_hasher);
+
                 let h2 = stable_hasher.finish();
                 (Some(h1), Some(h2))
             })
@@ -205,13 +210,12 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_attr_map = |tcx, id| {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
-    providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
+    providers.def_span = |tcx, def_id| tcx.hir_span(tcx.local_def_id_to_hir_id(def_id));
     providers.def_ident_span = |tcx, def_id| {
         let hir_id = tcx.local_def_id_to_hir_id(def_id);
         tcx.hir_opt_ident_span(hir_id)
     };
     providers.fn_arg_names = |tcx, def_id| {
-        let hir = tcx.hir();
         if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() {
             tcx.arena.alloc_from_iter(tcx.hir_body_param_names(body_id))
         } else if let Node::TraitItem(&TraitItem {
@@ -226,13 +230,15 @@ pub fn provide(providers: &mut Providers) {
             idents
         } else {
             span_bug!(
-                hir.span(tcx.local_def_id_to_hir_id(def_id)),
+                tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)),
                 "fn_arg_names: unexpected item {:?}",
                 def_id
             );
         }
     };
     providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
+    providers.local_trait_impls =
+        |tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
     providers.expn_that_defined =
         |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
     providers.in_scope_traits_map = |tcx, id| {
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 316ad80eb98..60ce8544aa0 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -53,7 +53,10 @@ pub struct Projection<'tcx> {
     pub kind: ProjectionKind,
 }
 
-/// A `Place` represents how a value is located in memory.
+/// A `Place` represents how a value is located in memory. This does not
+/// always correspond to a syntactic place expression. For example, when
+/// processing a pattern, a `Place` can be used to refer to the sub-value
+/// currently being inspected.
 ///
 /// This is an HIR version of [`rustc_middle::mir::Place`].
 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
@@ -67,7 +70,10 @@ pub struct Place<'tcx> {
     pub projections: Vec<Projection<'tcx>>,
 }
 
-/// A `PlaceWithHirId` represents how a value is located in memory.
+/// A `PlaceWithHirId` represents how a value is located in memory. This does not
+/// always correspond to a syntactic place expression. For example, when
+/// processing a pattern, a `Place` can be used to refer to the sub-value
+/// currently being inspected.
 ///
 /// This is an HIR version of [`rustc_middle::mir::Place`].
 #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 0cc72a261a5..00da1a6aeec 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -172,6 +172,8 @@ impl CodegenFnAttrs {
     /// * `#[no_mangle]` is present
     /// * `#[export_name(...)]` is present
     /// * `#[linkage]` is present
+    ///
+    /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
     pub fn contains_extern_indicator(&self) -> bool {
         self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
             || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 66861519e17..92eab59dd02 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -175,7 +175,7 @@ impl Scope {
         let Some(hir_id) = self.hir_id(scope_tree) else {
             return DUMMY_SP;
         };
-        let span = tcx.hir().span(hir_id);
+        let span = tcx.hir_span(hir_id);
         if let ScopeData::Remainder(first_statement_index) = self.data {
             if let Node::Block(blk) = tcx.hir_node(hir_id) {
                 // Want span for scope starting after the
@@ -199,8 +199,6 @@ impl Scope {
     }
 }
 
-pub type ScopeDepth = u32;
-
 /// The region scope tree encodes information about region relationships.
 #[derive(Default, Debug, HashStable)]
 pub struct ScopeTree {
@@ -213,7 +211,7 @@ pub struct ScopeTree {
     /// conditional expression or repeating block. (Note that the
     /// enclosing scope ID for the block associated with a closure is
     /// the closure itself.)
-    pub parent_map: FxIndexMap<Scope, (Scope, ScopeDepth)>,
+    pub parent_map: FxIndexMap<Scope, Scope>,
 
     /// Maps from a variable or binding ID to the block in which that
     /// variable is declared.
@@ -224,7 +222,7 @@ pub struct ScopeTree {
     /// and not the enclosing *statement*. Expressions that are not present in this
     /// table are not rvalue candidates. The set of rvalue candidates is computed
     /// during type check based on a traversal of the AST.
-    pub rvalue_candidates: HirIdMap<RvalueCandidateType>,
+    pub rvalue_candidates: HirIdMap<RvalueCandidate>,
 
     /// Backwards incompatible scoping that will be introduced in future editions.
     /// This information is used later for linting to identify locals and
@@ -308,15 +306,14 @@ pub struct ScopeTree {
     pub yield_in_scope: UnordMap<Scope, Vec<YieldData>>,
 }
 
-/// Identifies the reason that a given expression is an rvalue candidate
-/// (see the `rvalue_candidates` field for more information what rvalue
-/// candidates in general). In constants, the `lifetime` field is None
-/// to indicate that certain expressions escape into 'static and
-/// should have no local cleanup scope.
+/// See the `rvalue_candidates` field for more information on rvalue
+/// candidates in general.
+/// The `lifetime` field is None to indicate that certain expressions escape
+/// into 'static and should have no local cleanup scope.
 #[derive(Debug, Copy, Clone, HashStable)]
-pub enum RvalueCandidateType {
-    Borrow { target: hir::ItemLocalId, lifetime: Option<Scope> },
-    Pattern { target: hir::ItemLocalId, lifetime: Option<Scope> },
+pub struct RvalueCandidate {
+    pub target: hir::ItemLocalId,
+    pub lifetime: Option<Scope>,
 }
 
 #[derive(Debug, Copy, Clone, HashStable)]
@@ -329,7 +326,7 @@ pub struct YieldData {
 }
 
 impl ScopeTree {
-    pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
+    pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
         debug!("{:?}.parent = {:?}", child, parent);
 
         if let Some(p) = parent {
@@ -344,21 +341,17 @@ impl ScopeTree {
         self.var_map.insert(var, lifetime);
     }
 
-    pub fn record_rvalue_candidate(&mut self, var: HirId, candidate_type: RvalueCandidateType) {
-        debug!("record_rvalue_candidate(var={var:?}, type={candidate_type:?})");
-        match &candidate_type {
-            RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. }
-            | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => {
-                assert!(var.local_id != lifetime.local_id)
-            }
-            _ => {}
+    pub fn record_rvalue_candidate(&mut self, var: HirId, candidate: RvalueCandidate) {
+        debug!("record_rvalue_candidate(var={var:?}, candidate={candidate:?})");
+        if let Some(lifetime) = &candidate.lifetime {
+            assert!(var.local_id != lifetime.local_id)
         }
-        self.rvalue_candidates.insert(var, candidate_type);
+        self.rvalue_candidates.insert(var, candidate);
     }
 
     /// Returns the narrowest scope that encloses `id`, if any.
     pub fn opt_encl_scope(&self, id: Scope) -> Option<Scope> {
-        self.parent_map.get(&id).cloned().map(|(p, _)| p)
+        self.parent_map.get(&id).cloned()
     }
 
     /// Returns the lifetime of the local variable `var_id`, if any.
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 34b27c2e1cc..2b2ffa71628 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -9,7 +9,9 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
 use rustc_type_ir::TypeVisitableExt;
 
 use super::interpret::ReportedErrorInfo;
-use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range};
+use crate::mir::interpret::{
+    AllocId, AllocRange, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar, alloc_range,
+};
 use crate::mir::{Promoted, pretty_print_const_value};
 use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
 use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt};
@@ -192,9 +194,31 @@ impl<'tcx> ConstValue<'tcx> {
                 .unwrap_memory()
                 .inner()
                 .provenance()
-                .range_empty(super::AllocRange::from(offset..offset + size), &tcx),
+                .range_empty(AllocRange::from(offset..offset + size), &tcx),
         }
     }
+
+    /// Check if a constant only contains uninitialized bytes.
+    pub fn all_bytes_uninit(&self, tcx: TyCtxt<'tcx>) -> bool {
+        let ConstValue::Indirect { alloc_id, .. } = self else {
+            return false;
+        };
+        let alloc = tcx.global_alloc(*alloc_id);
+        let GlobalAlloc::Memory(alloc) = alloc else {
+            return false;
+        };
+        let init_mask = alloc.0.init_mask();
+        let init_range = init_mask.is_range_initialized(AllocRange {
+            start: Size::ZERO,
+            size: Size::from_bytes(alloc.0.len()),
+        });
+        if let Err(range) = init_range {
+            if range.size == alloc.0.size() {
+                return true;
+            }
+        }
+        false
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 897119c0712..1ffe958dbdd 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -21,7 +21,7 @@ use tracing::debug;
 
 use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
+use crate::ty::{self, GenericArgs, Instance, InstanceKind, SymbolName, Ty, TyCtxt};
 
 /// Describes how a monomorphization will be instantiated in object files.
 #[derive(PartialEq)]
@@ -55,6 +55,39 @@ pub enum MonoItem<'tcx> {
     GlobalAsm(ItemId),
 }
 
+fn opt_incr_drop_glue_mode<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InstantiationMode {
+    // Non-ADTs can't have a Drop impl. This case is mostly hit by closures whose captures require
+    // dropping.
+    let ty::Adt(adt_def, _) = ty.kind() else {
+        return InstantiationMode::LocalCopy;
+    };
+
+    // Types that don't have a direct Drop impl, but have fields that require dropping.
+    let Some(dtor) = adt_def.destructor(tcx) else {
+        // We use LocalCopy for drops of enums only; this code is inherited from
+        // https://github.com/rust-lang/rust/pull/67332 and the theory is that we get to optimize
+        // out code like drop_in_place(Option::None) before crate-local ThinLTO, which improves
+        // compile time. At the time of writing, simply removing this entire check does seem to
+        // regress incr-opt compile times. But it sure seems like a more sophisticated check could
+        // do better here.
+        if adt_def.is_enum() {
+            return InstantiationMode::LocalCopy;
+        } else {
+            return InstantiationMode::GloballyShared { may_conflict: true };
+        }
+    };
+
+    // We've gotten to a drop_in_place for a type that directly implements Drop.
+    // The drop glue is a wrapper for the Drop::drop impl, and we are an optimized build, so in an
+    // effort to coordinate with the mode that the actual impl will get, we make the glue also
+    // LocalCopy.
+    if tcx.cross_crate_inlinable(dtor.did) {
+        InstantiationMode::LocalCopy
+    } else {
+        InstantiationMode::GloballyShared { may_conflict: true }
+    }
+}
+
 impl<'tcx> MonoItem<'tcx> {
     /// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims).
     pub fn is_user_defined(&self) -> bool {
@@ -117,6 +150,7 @@ impl<'tcx> MonoItem<'tcx> {
 
         // If the function is #[naked] or contains any other attribute that requires exactly-once
         // instantiation:
+        // We emit an unused_attributes lint for this case, which should be kept in sync if possible.
         let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id());
         if codegen_fn_attrs.contains_extern_indicator()
             || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
@@ -124,16 +158,36 @@ impl<'tcx> MonoItem<'tcx> {
             return InstantiationMode::GloballyShared { may_conflict: false };
         }
 
-        // FIXME: The logic for which functions are permitted to get LocalCopy is actually spread
-        // across 4 functions:
-        // * cross_crate_inlinable(def_id)
-        // * InstanceKind::requires_inline
-        // * InstanceKind::generate_cgu_internal_copy
-        // * MonoItem::instantiation_mode
-        // Since reachable_non_generics calls InstanceKind::generates_cgu_internal_copy to decide
-        // which symbols this crate exports, we are obligated to only generate LocalCopy when
-        // generates_cgu_internal_copy returns true.
-        if !instance.def.generates_cgu_internal_copy(tcx) {
+        // This is technically a heuristic even though it's in the "not a heuristic" part of
+        // instantiation mode selection.
+        // It is surely possible to untangle this; the root problem is that the way we instantiate
+        // InstanceKind other than Item is very complicated.
+        //
+        // The fallback case is to give everything else GloballyShared at OptLevel::No and
+        // LocalCopy at all other opt levels. This is a good default, except for one specific build
+        // configuration: Optimized incremental builds.
+        // In the current compiler architecture there is a fundamental tension between
+        // optimizations (which want big CGUs with as many things LocalCopy as possible) and
+        // incrementality (which wants small CGUs with as many things GloballyShared as possible).
+        // The heuristics implemented here do better than a completely naive approach in the
+        // compiler benchmark suite, but there is no reason to believe they are optimal.
+        if let InstanceKind::DropGlue(_, Some(ty)) = instance.def {
+            if tcx.sess.opts.optimize == OptLevel::No {
+                return InstantiationMode::GloballyShared { may_conflict: false };
+            }
+            if tcx.sess.opts.incremental.is_none() {
+                return InstantiationMode::LocalCopy;
+            }
+            return opt_incr_drop_glue_mode(tcx, ty);
+        }
+
+        // We need to ensure that we do not decide the InstantiationMode of an exported symbol is
+        // LocalCopy. Since exported symbols are computed based on the output of
+        // cross_crate_inlinable, we are beholden to our previous decisions.
+        //
+        // Note that just like above, this check for requires_inline is technically a heuristic
+        // even though it's in the "not a heuristic" part of instantiation mode selection.
+        if !tcx.cross_crate_inlinable(instance.def_id()) && !instance.def.requires_inline(tcx) {
             return InstantiationMode::GloballyShared { may_conflict: false };
         }
 
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 4f86703e953..6d6e6a1f185 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> {
     /// See [`Rvalue`] documentation for details on each of those.
     Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
 
-    /// This represents all the reading that a pattern match may do (e.g., inspecting constants and
-    /// discriminant values), and the kind of pattern it comes from. This is in order to adapt
-    /// potential error messages to these specific patterns.
+    /// When executed at runtime, this is a nop.
     ///
-    /// Note that this also is emitted for regular `let` bindings to ensure that locals that are
-    /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
+    /// During static analysis, a fake read:
+    /// - requires that the value being read is initialized (or, in the case
+    ///   of closures, that it was fully initialized at some point in the past)
+    /// - constitutes a use of a value for the purposes of NLL (i.e. if the
+    ///   value being fake-read is a reference, the lifetime of that reference
+    ///   will be extended to cover the `FakeRead`)
+    /// - but, unlike an actual read, does *not* invalidate any exclusive
+    ///   borrows.
     ///
-    /// When executed at runtime this is a nop.
+    /// See [`FakeReadCause`] for more details on the situations in which a
+    /// `FakeRead` is emitted.
     ///
     /// Disallowed after drop elaboration.
     FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
@@ -518,28 +523,59 @@ pub enum RetagKind {
 /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)]
 pub enum FakeReadCause {
-    /// Inject a fake read of the borrowed input at the end of each guards
-    /// code.
+    /// A fake read injected into a match guard to ensure that the discriminants
+    /// that are being matched on aren't modified while the match guard is being
+    /// evaluated.
+    ///
+    /// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is
+    /// inserted for each discriminant accessed in the entire `match` statement.
+    ///
+    /// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is
+    /// inserted to keep the fake borrows alive until that point.
     ///
     /// This should ensure that you cannot change the variant for an enum while
     /// you are in the midst of matching on it.
     ForMatchGuard,
 
-    /// `let x: !; match x {}` doesn't generate any read of x so we need to
-    /// generate a read of x to check that it is initialized and safe.
+    /// Fake read of the scrutinee of a `match` or destructuring `let`
+    /// (i.e. `let` with non-trivial pattern).
+    ///
+    /// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)`
+    /// and insert it into the `otherwise_block` (which is supposed to be
+    /// unreachable for irrefutable pattern-matches like `match` or `let`).
+    ///
+    /// This is necessary because `let x: !; match x {}` doesn't generate any
+    /// actual read of x, so we need to generate a `FakeRead` to check that it
+    /// is initialized.
     ///
-    /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
-    /// FakeRead for that Place outside the closure, in such a case this option would be
-    /// Some(closure_def_id).
-    /// Otherwise, the value of the optional LocalDefId will be None.
+    /// If the `FakeRead(ForMatchedPlace)` is being performed with a closure
+    /// that doesn't capture the required upvars, the `FakeRead` within the
+    /// closure is omitted entirely.
+    ///
+    /// To make sure that this is still sound, if a closure matches against
+    /// a Place starting with an Upvar, we hoist the `FakeRead` to the
+    /// definition point of the closure.
+    ///
+    /// If the `FakeRead` comes from being hoisted out of a closure like this,
+    /// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`.
     //
     // We can use LocalDefId here since fake read statements are removed
     // before codegen in the `CleanupNonCodegenStatements` pass.
     ForMatchedPlace(Option<LocalDefId>),
 
-    /// A fake read of the RefWithinGuard version of a bind-by-value variable
-    /// in a match guard to ensure that its value hasn't change by the time
-    /// we create the OutsideGuard version.
+    /// A fake read injected into a match guard to ensure that the places
+    /// bound by the pattern are immutable for the duration of the match guard.
+    ///
+    /// Within a match guard, references are created for each place that the
+    /// pattern creates a binding for — this is known as the `RefWithinGuard`
+    /// version of the variables. To make sure that the references stay
+    /// alive until the end of the match guard, and properly prevent the
+    /// places in question from being modified, a `FakeRead(ForGuardBinding)`
+    /// is inserted at the end of the match guard.
+    ///
+    /// For details on how these references are created, see the extensive
+    /// documentation on `bind_matched_candidate_for_guard` in
+    /// `rustc_mir_build`.
     ForGuardBinding,
 
     /// Officially, the semantics of
@@ -552,22 +588,42 @@ pub enum FakeReadCause {
     /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
     /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
     /// but in some cases it can affect the borrow checker, as in #53695.
-    /// Therefore, we insert a "fake read" here to ensure that we get
-    /// appropriate errors.
     ///
-    /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
-    /// FakeRead for that Place outside the closure, in such a case this option would be
-    /// Some(closure_def_id).
-    /// Otherwise, the value of the optional DefId will be None.
+    /// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let`
+    /// with a trivial pattern.
+    ///
+    /// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)`
+    /// is supposed to mean. If it was accurate to what MIR lowering does,
+    /// would it even make sense to hoist these out of closures like
+    /// `ForMatchedPlace`?
     ForLet(Option<LocalDefId>),
 
-    /// If we have an index expression like
+    /// Currently, index expressions overloaded through the `Index` trait
+    /// get lowered differently than index expressions with builtin semantics
+    /// for arrays and slices — the latter will emit code to perform
+    /// bound checks, and then return a MIR place that will only perform the
+    /// indexing "for real" when it gets incorporated into an instruction.
+    ///
+    /// This is observable in the fact that the following compiles:
+    ///
+    /// ```
+    /// fn f(x: &mut [&mut [u32]], i: usize) {
+    ///     x[i][x[i].len() - 1] += 1;
+    /// }
+    /// ```
+    ///
+    /// However, we need to be careful to not let the user invalidate the
+    /// bound check with an expression like
+    ///
+    /// `(*x)[1][{ x = y; 4}]`
     ///
-    /// (*x)[1][{ x = y; 4}]
+    /// Here, the first bounds check would be invalidated when we evaluate the
+    /// second index expression. To make sure that this doesn't happen, we
+    /// create a fake borrow of `x` and hold it while we evaluate the second
+    /// index.
     ///
-    /// then the first bounds check is invalidated when we evaluate the second
-    /// index expression. Thus we create a fake borrow of `x` across the second
-    /// indexer, which will cause a borrow check error.
+    /// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its
+    /// scope.
     ForIndex,
 }
 
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 7bbaa0496d5..6c6b9a5510c 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,3 +1,4 @@
+use std::ffi::OsStr;
 use std::intrinsics::transmute_unchecked;
 use std::mem::MaybeUninit;
 
@@ -67,6 +68,10 @@ impl<T> EraseType for &'_ [T] {
     type Result = [u8; size_of::<&'static [()]>()];
 }
 
+impl EraseType for &'_ OsStr {
+    type Result = [u8; size_of::<&'static OsStr>()];
+}
+
 impl<T> EraseType for &'_ ty::List<T> {
     type Result = [u8; size_of::<&'static ty::List<()>>()];
 }
@@ -174,6 +179,10 @@ impl<T> EraseType for Option<&'_ [T]> {
     type Result = [u8; size_of::<Option<&'static [()]>>()];
 }
 
+impl EraseType for Option<&'_ OsStr> {
+    type Result = [u8; size_of::<Option<&'static OsStr>>()];
+}
+
 impl EraseType for Option<mir::DestructuredConstant<'_>> {
     type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
 }
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 98314b5abfd..9ed1f10455a 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -1,5 +1,7 @@
 //! Defines the set of legal keys that can be used in queries.
 
+use std::ffi::OsStr;
+
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
 use rustc_hir::hir_id::{HirId, OwnerId};
 use rustc_query_system::dep_graph::DepNodeIndex;
@@ -498,6 +500,14 @@ impl Key for Option<Symbol> {
     }
 }
 
+impl<'tcx> Key for &'tcx OsStr {
+    type Cache<V> = DefaultCache<Self, V>;
+
+    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 /// Canonical query goals correspond to abstract trait operations that
 /// are not tied to any crate in particular.
 impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
@@ -576,7 +586,7 @@ impl Key for HirId {
     type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
-        tcx.hir().span(*self)
+        tcx.hir_span(*self)
     }
 
     #[inline(always)]
@@ -589,7 +599,7 @@ impl Key for (LocalDefId, HirId) {
     type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
-        tcx.hir().span(self.1)
+        tcx.hir_span(self.1)
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 527c18addbe..4b3236e4b84 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -6,6 +6,7 @@
 
 #![allow(unused_parens)]
 
+use std::ffi::OsStr;
 use std::mem;
 use std::path::PathBuf;
 use std::sync::Arc;
@@ -30,7 +31,9 @@ use rustc_index::IndexVec;
 use rustc_lint_defs::LintId;
 use rustc_macros::rustc_queries;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_query_system::query::{QueryCache, QueryMode, QueryState, try_get_cached};
+use rustc_query_system::query::{
+    QueryCache, QueryMode, QueryStackDeferred, QueryState, try_get_cached,
+};
 use rustc_session::Limits;
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::cstore::{
@@ -119,6 +122,21 @@ rustc_queries! {
         desc { "perform lints prior to AST lowering" }
     }
 
+    /// Tracked access to environment variables.
+    ///
+    /// Useful for the implementation of `std::env!`, `proc-macro`s change
+    /// detection and other changes in the compiler's behaviour that is easier
+    /// to control with an environment variable than a flag.
+    ///
+    /// NOTE: This currently does not work with dependency info in the
+    /// analysis, codegen and linking passes, place extra code at the top of
+    /// `rustc_interface::passes::write_dep_info` to make that work.
+    query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> {
+        // Environment variables are global state
+        eval_always
+        desc { "get the value of an environment variable" }
+    }
+
     query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
         no_hash
         desc { "getting the resolver outputs" }
@@ -1484,6 +1502,11 @@ rustc_queries! {
         desc { "finding local trait impls" }
     }
 
+    /// Return all `impl` blocks of the given trait in the current crate.
+    query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] {
+        desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) }
+    }
+
     /// Given a trait `trait_id`, return all known `impl` blocks.
     query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
         arena_cache
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 4834444ed1d..a099f770417 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -488,7 +488,7 @@ macro_rules! define_callbacks {
         #[derive(Default)]
         pub struct QueryStates<'tcx> {
             $(
-                pub $name: QueryState<$($K)*>,
+                pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>,
             )*
         }
 
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index bbcd509c558..6783bbf8bf4 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -800,9 +800,9 @@ pub enum PatKind<'tcx> {
     },
 
     /// One of the following:
-    /// * `&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.
+    /// * `&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.
     /// * 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.
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 811bd8fb458..aa2ee756bc5 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -95,10 +95,16 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>),
 /// parameter environment.
 #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)]
 pub enum SelectionCandidate<'tcx> {
+    /// A built-in implementation for the `Sized` trait. This is preferred
+    /// over all other candidates.
+    SizedCandidate {
+        has_nested: bool,
+    },
+
     /// A builtin implementation for some specific traits, used in cases
     /// where we cannot rely an ordinary library implementations.
     ///
-    /// The most notable examples are `sized`, `Copy` and `Clone`. This is also
+    /// The most notable examples are `Copy` and `Clone`. This is also
     /// used for the `DiscriminantKind` and `Pointee` trait, both of which have
     /// an associated type.
     BuiltinCandidate {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index cb245c0aec4..00fe5cb0c5d 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -236,7 +236,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
     }
 
     fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<AdtDestructorKind> {
-        Some(match self.destructor(tcx)?.constness {
+        Some(match tcx.constness(self.destructor(tcx)?.did) {
             hir::Constness::Const => AdtDestructorKind::Const,
             hir::Constness::NotConst => AdtDestructorKind::NotConst,
         })
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 703b6ce9247..ff9096695d4 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -150,9 +150,9 @@ impl<'tcx> CapturedPlace<'tcx> {
     /// Return span pointing to use that resulted in selecting the captured path
     pub fn get_path_span(&self, tcx: TyCtxt<'tcx>) -> Span {
         if let Some(path_expr_id) = self.info.path_expr_id {
-            tcx.hir().span(path_expr_id)
+            tcx.hir_span(path_expr_id)
         } else if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id {
-            tcx.hir().span(capture_kind_expr_id)
+            tcx.hir_span(capture_kind_expr_id)
         } else {
             // Fallback on upvars mentioned if neither path or capture expr id is captured
 
@@ -166,9 +166,9 @@ impl<'tcx> CapturedPlace<'tcx> {
     /// Return span pointing to use that resulted in selecting the current capture kind
     pub fn get_capture_kind_span(&self, tcx: TyCtxt<'tcx>) -> Span {
         if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id {
-            tcx.hir().span(capture_kind_expr_id)
+            tcx.hir_span(capture_kind_expr_id)
         } else if let Some(path_expr_id) = self.info.path_expr_id {
-            tcx.hir().span(path_expr_id)
+            tcx.hir_span(path_expr_id)
         } else {
             // Fallback on upvars mentioned if neither path or capture expr id is captured
 
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 72263d84580..2f21d19e03c 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -33,7 +33,7 @@ pub enum ValTreeKind<'tcx> {
     /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by
     /// listing their fields' values in order.
     ///
-    /// Enums are represented by storing their discriminant as a field, followed by all
+    /// Enums are represented by storing their variant index as a u32 field, followed by all
     /// the fields of the variant.
     ///
     /// ZST types are represented as an empty slice.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index f54dd2b0040..618a65a0186 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -7,6 +7,8 @@ pub mod tls;
 use std::assert_matches::{assert_matches, debug_assert_matches};
 use std::borrow::Borrow;
 use std::cmp::Ordering;
+use std::env::VarError;
+use std::ffi::OsStr;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::ops::{Bound, Deref};
@@ -1288,7 +1290,8 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
         let bodies = Default::default();
         let attrs = hir::AttributeMap::EMPTY;
 
-        let (opt_hash_including_bodies, _) = self.tcx.hash_owner_nodes(node, &bodies, &attrs.map);
+        let (opt_hash_including_bodies, _) =
+            self.tcx.hash_owner_nodes(node, &bodies, &attrs.map, attrs.define_opaque);
         let node = node.into();
         self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes {
             opt_hash_including_bodies,
@@ -1882,6 +1885,15 @@ impl<'tcx> TyCtxt<'tcx> {
         }
         None
     }
+
+    /// Helper to get a tracked environment variable via. [`TyCtxt::env_var_os`] and converting to
+    /// UTF-8 like [`std::env::var`].
+    pub fn env_var<K: ?Sized + AsRef<OsStr>>(self, key: &'tcx K) -> Result<&'tcx str, VarError> {
+        match self.env_var_os(key.as_ref()) {
+            Some(value) => value.to_str().ok_or_else(|| VarError::NotUnicode(value.to_os_string())),
+            None => Err(VarError::NotPresent),
+        }
+    }
 }
 
 impl<'tcx> TyCtxtAt<'tcx> {
@@ -1918,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> {
         // As a consequence, this LocalDefId is always re-created before it is needed by the incr.
         // comp. engine itself.
         //
-        // This call also writes to the value of `source_span` and `expn_that_defined` queries.
+        // This call also writes to the value of the `source_span` query.
         // This is fine because:
-        // - those queries are `eval_always` so we won't miss their result changing;
-        // - this write will have happened before these queries are called.
+        // - that query is `eval_always` so we won't miss its result changing;
+        // - this write will have happened before that query is called.
         let def_id = self.untracked.definitions.write().create_def(parent, data);
 
         // This function modifies `self.definitions` using a side-effect.
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 0b8f0e8cd41..b0c442d28f0 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -101,63 +101,13 @@ impl FlagComputation {
 
             &ty::Param(_) => {
                 self.add_flags(TypeFlags::HAS_TY_PARAM);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            ty::Coroutine(_, args) => {
-                let args = args.as_coroutine();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.resume_ty());
-                self.add_ty(args.return_ty());
-                self.add_ty(args.witness());
-                self.add_ty(args.yield_ty());
-                self.add_ty(args.tupled_upvars_ty());
-            }
-
-            ty::CoroutineWitness(_, args) => {
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+            &ty::Closure(_, args)
+            | &ty::Coroutine(_, args)
+            | &ty::CoroutineClosure(_, args)
+            | &ty::CoroutineWitness(_, args) => {
                 self.add_args(args);
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-                self.add_flags(TypeFlags::HAS_TY_COROUTINE);
-            }
-
-            &ty::Closure(_, args) => {
-                let args = args.as_closure();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.sig_as_fn_ptr_ty());
-                self.add_ty(args.kind_ty());
-                self.add_ty(args.tupled_upvars_ty());
-            }
-
-            &ty::CoroutineClosure(_, args) => {
-                let args = args.as_coroutine_closure();
-                let should_remove_further_specializable =
-                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                self.add_args(args.parent_args());
-                if should_remove_further_specializable {
-                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
-                }
-
-                self.add_ty(args.kind_ty());
-                self.add_ty(args.signature_parts_ty());
-                self.add_ty(args.tupled_upvars_ty());
-                self.add_ty(args.coroutine_captures_by_ref_ty());
-                self.add_ty(args.coroutine_witness_ty());
             }
 
             &ty::Bound(debruijn, _) => {
@@ -167,21 +117,17 @@ impl FlagComputation {
 
             &ty::Placeholder(..) => {
                 self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
-            &ty::Infer(infer) => {
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                match infer {
-                    ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
-                        self.add_flags(TypeFlags::HAS_TY_FRESH)
-                    }
+            &ty::Infer(infer) => match infer {
+                ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
+                    self.add_flags(TypeFlags::HAS_TY_FRESH)
+                }
 
-                    ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
-                        self.add_flags(TypeFlags::HAS_TY_INFER)
-                    }
+                ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
+                    self.add_flags(TypeFlags::HAS_TY_INFER)
                 }
-            }
+            },
 
             &ty::Adt(_, args) => {
                 self.add_args(args);
@@ -358,24 +304,19 @@ impl FlagComputation {
                 self.add_args(uv.args);
                 self.add_flags(TypeFlags::HAS_CT_PROJECTION);
             }
-            ty::ConstKind::Infer(infer) => {
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
-                match infer {
-                    InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
-                    InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
-                }
-            }
+            ty::ConstKind::Infer(infer) => match infer {
+                InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
+                InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
+            },
             ty::ConstKind::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
                 self.add_flags(TypeFlags::HAS_CT_BOUND);
             }
             ty::ConstKind::Param(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PARAM);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Placeholder(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
-                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Value(cv) => self.add_ty(cv.ty),
             ty::ConstKind::Expr(e) => self.add_args(e.args()),
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 85d9db7ee74..d4cc562e70c 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -73,9 +73,7 @@ impl GenericParamDef {
 
     pub fn is_anonymous_lifetime(&self) -> bool {
         match self.kind {
-            GenericParamDefKind::Lifetime => {
-                self.name == kw::UnderscoreLifetime || self.name == kw::Empty
-            }
+            GenericParamDefKind::Lifetime => self.name == kw::UnderscoreLifetime,
             _ => false,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 980d20f9d3b..55ebd15248c 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -302,50 +302,6 @@ impl<'tcx> InstanceKind<'tcx> {
         )
     }
 
-    /// Returns `true` if the machine code for this instance is instantiated in
-    /// each codegen unit that references it.
-    /// Note that this is only a hint! The compiler can globally decide to *not*
-    /// do this in order to speed up compilation. CGU-internal copies are
-    /// only exist to enable inlining. If inlining is not performed (e.g. at
-    /// `-Copt-level=0`) then the time for generating them is wasted and it's
-    /// better to create a single copy with external linkage.
-    pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
-        if self.requires_inline(tcx) {
-            return true;
-        }
-        if let ty::InstanceKind::DropGlue(.., Some(ty))
-        | ty::InstanceKind::AsyncDropGlueCtorShim(.., Some(ty)) = *self
-        {
-            // Drop glue generally wants to be instantiated at every codegen
-            // unit, but without an #[inline] hint. We should make this
-            // available to normal end-users.
-            if tcx.sess.opts.incremental.is_none() {
-                return true;
-            }
-            // When compiling with incremental, we can generate a *lot* of
-            // codegen units. Including drop glue into all of them has a
-            // considerable compile time cost.
-            //
-            // We include enums without destructors to allow, say, optimizing
-            // drops of `Option::None` before LTO. We also respect the intent of
-            // `#[inline]` on `Drop::drop` implementations.
-            return ty.ty_adt_def().is_none_or(|adt_def| {
-                match *self {
-                    ty::InstanceKind::DropGlue(..) => adt_def.destructor(tcx).map(|dtor| dtor.did),
-                    ty::InstanceKind::AsyncDropGlueCtorShim(..) => {
-                        adt_def.async_destructor(tcx).map(|dtor| dtor.ctor)
-                    }
-                    _ => unreachable!(),
-                }
-                .map_or_else(|| adt_def.is_enum(), |did| tcx.cross_crate_inlinable(did))
-            });
-        }
-        if let ty::InstanceKind::ThreadLocalShim(..) = *self {
-            return false;
-        }
-        tcx.cross_crate_inlinable(self.def_id())
-    }
-
     pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
         match *self {
             InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
@@ -764,7 +720,7 @@ impl<'tcx> Instance<'tcx> {
             ty::TypingEnv::fully_monomorphized(),
             def_id,
             args,
-            ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
+            ty.ty_adt_def().and_then(|adt| tcx.hir_span_if_local(adt.did())).unwrap_or(DUMMY_SP),
         )
     }
 
@@ -776,7 +732,7 @@ impl<'tcx> Instance<'tcx> {
             ty::TypingEnv::fully_monomorphized(),
             def_id,
             args,
-            ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
+            ty.ty_adt_def().and_then(|adt| tcx.hir_span_if_local(adt.did())).unwrap_or(DUMMY_SP),
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6bdd0a0647d..255d464d265 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -457,7 +457,7 @@ impl EarlyParamRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).
     pub fn has_name(&self) -> bool {
-        self.name != kw::UnderscoreLifetime && self.name != kw::Empty
+        self.name != kw::UnderscoreLifetime
     }
 }
 
@@ -953,7 +953,7 @@ impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> {
 /// environment. `ParamEnv` is the type that represents this information. See the
 /// [dev guide chapter][param_env_guide] for more information.
 ///
-/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 #[derive(HashStable, TypeVisitable, TypeFoldable)]
 pub struct ParamEnv<'tcx> {
@@ -977,7 +977,7 @@ impl<'tcx> ParamEnv<'tcx> {
     /// to use an empty environment. See the [dev guide section][param_env_guide]
     /// for information on what a `ParamEnv` is and how to acquire one.
     ///
-    /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+    /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
     #[inline]
     pub fn empty() -> Self {
         Self::new(ListWithCachedTypeInfo::empty())
@@ -1119,8 +1119,6 @@ pub struct PseudoCanonicalInput<'tcx, T> {
 pub struct Destructor {
     /// The `DefId` of the destructor method
     pub did: DefId,
-    /// The constness of the destructor method
-    pub constness: hir::Constness,
 }
 
 // FIXME: consider combining this definition with regular `Destructor`
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 19e2b574563..61b35b33a09 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -65,9 +65,11 @@ trivially_parameterized_over_tcx! {
     crate::middle::lib_features::FeatureStability,
     crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
+    ty::AsyncDestructor,
     ty::AssocItemContainer,
     ty::Asyncness,
     ty::DeducedParamAttrs,
+    ty::Destructor,
     ty::Generics,
     ty::ImplPolarity,
     ty::ImplTraitInTraitData,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index dc2040aa5cf..5904deaaaad 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized {
 
                     match key.disambiguated_data.data {
                         DefPathData::Closure => {
-                            // FIXME(async_closures): This is somewhat ugly.
-                            // We need to additionally print the `kind` field of a closure if
+                            // We need to additionally print the `kind` field of a coroutine if
                             // it is desugared from a coroutine-closure.
                             if let Some(hir::CoroutineKind::Desugared(
                                 _,
@@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized {
                                 // Closures' own generics are only captures, don't print them.
                             }
                         }
+                        DefPathData::SyntheticCoroutineBody => {
+                            // Synthetic coroutine bodies have no distinct generics, since like
+                            // closures they're all just internal state of the coroutine.
+                        }
                         // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
                         // Anon consts doesn't have their own generics, and inline consts' own
                         // generics are their inferred types, so don't print them.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3ef8ecc59e4..3281cb4135a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2591,11 +2591,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         // to fit that into a short string. Hence the recommendation to use
         // `explain_region()` or `note_and_explain_region()`.
         match *region {
-            ty::ReEarlyParam(ref data) => {
-                if data.name != kw::Empty {
-                    p!(write("{}", data.name));
-                    return Ok(());
-                }
+            ty::ReEarlyParam(data) => {
+                p!(write("{}", data.name));
+                return Ok(());
             }
             ty::ReLateParam(ty::LateParamRegion { kind, .. }) => {
                 if let Some(name) = kind.get_name() {
@@ -2834,7 +2832,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 
                         (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name))
                     }
-                    ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => {
+                    ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime) => {
                         let name = next_name(self);
 
                         if let Some(lt_idx) = lifetime_idx {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index fb52cf96b02..c78306f2ca3 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -400,9 +400,7 @@ impl LateParamRegionKind {
 
     pub fn is_named(&self) -> bool {
         match *self {
-            LateParamRegionKind::Named(_, name) => {
-                name != kw::UnderscoreLifetime && name != kw::Empty
-            }
+            LateParamRegionKind::Named(_, name) => name != kw::UnderscoreLifetime,
             _ => false,
         }
     }
@@ -475,7 +473,7 @@ impl core::fmt::Debug for BoundRegion {
 impl BoundRegionKind {
     pub fn is_named(&self) -> bool {
         match *self {
-            BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty,
+            BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime,
             _ => false,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index b00c8169a36..9bf6e3a7590 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -38,7 +38,7 @@ impl RvalueScopes {
         let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
         let mut backwards_incompatible = None;
 
-        while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) {
+        while let Some(&p) = region_scope_tree.parent_map.get(&id) {
             match p.data {
                 ScopeData::Destruction => {
                     debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 8fa1c569737..ea25ce65f77 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -129,21 +129,6 @@ impl<'tcx> TraitDef {
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    /// `trait_def_id` MUST BE the `DefId` of a trait.
-    pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
-        let impls = self.trait_impls_of(trait_def_id);
-
-        for &impl_def_id in impls.blanket_impls.iter() {
-            f(impl_def_id);
-        }
-
-        for v in impls.non_blanket_impls.values() {
-            for &impl_def_id in v {
-                f(impl_def_id);
-            }
-        }
-    }
-
     /// Iterate over every impl that could possibly match the self type `self_ty`.
     ///
     /// `trait_def_id` MUST BE the `DefId` of a trait.
@@ -235,7 +220,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
         }
     }
 
-    for &impl_def_id in tcx.hir_trait_impls(trait_id) {
+    for &impl_def_id in tcx.local_trait_impls(trait_id) {
         let impl_def_id = impl_def_id.to_def_id();
 
         let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 06054e22e76..3d3f4e2773a 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -197,12 +197,6 @@ pub struct TypeckResults<'tcx> {
     /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
     pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
 
-    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
-    /// as `&[u8]`, depending on the pattern in which they are used.
-    /// This hashset records all instances where we behave
-    /// like this to allow `const_to_pat` to reliably handle this situation.
-    pub treat_byte_string_as_slice: ItemLocalSet,
-
     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
     /// on closure size.
     pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
@@ -237,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
             coroutine_stalled_predicates: Default::default(),
-            treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
         }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c0d4130336e..7743e202aae 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -389,55 +389,65 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Calculate the destructor of a given type.
     pub fn calculate_dtor(
         self,
-        adt_did: DefId,
-        validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
+        adt_did: LocalDefId,
+        validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
     ) -> Option<ty::Destructor> {
         let drop_trait = self.lang_items().drop_trait()?;
         self.ensure_ok().coherent_trait(drop_trait).ok()?;
 
-        let ty = self.type_of(adt_did).instantiate_identity();
         let mut dtor_candidate = None;
-        self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
+        // `Drop` impls can only be written in the same crate as the adt, and cannot be blanket impls
+        for &impl_did in self.local_trait_impls(drop_trait) {
+            let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
+            if adt_def.did() != adt_did.to_def_id() {
+                continue;
+            }
+
             if validate(self, impl_did).is_err() {
                 // Already `ErrorGuaranteed`, no need to delay a span bug here.
-                return;
+                continue;
             }
 
             let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
                 self.dcx()
                     .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
-                return;
+                continue;
             };
 
-            if let Some((old_item_id, _)) = dtor_candidate {
+            if let Some(old_item_id) = dtor_candidate {
                 self.dcx()
                     .struct_span_err(self.def_span(item_id), "multiple drop impls found")
                     .with_span_note(self.def_span(old_item_id), "other impl here")
                     .delay_as_bug();
             }
 
-            dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
-        });
+            dtor_candidate = Some(*item_id);
+        }
 
-        let (did, constness) = dtor_candidate?;
-        Some(ty::Destructor { did, constness })
+        let did = dtor_candidate?;
+        Some(ty::Destructor { did })
     }
 
     /// Calculate the async destructor of a given type.
     pub fn calculate_async_dtor(
         self,
-        adt_did: DefId,
-        validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
+        adt_did: LocalDefId,
+        validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
     ) -> Option<ty::AsyncDestructor> {
         let async_drop_trait = self.lang_items().async_drop_trait()?;
         self.ensure_ok().coherent_trait(async_drop_trait).ok()?;
 
-        let ty = self.type_of(adt_did).instantiate_identity();
         let mut dtor_candidate = None;
-        self.for_each_relevant_impl(async_drop_trait, ty, |impl_did| {
+        // `AsyncDrop` impls can only be written in the same crate as the adt, and cannot be blanket impls
+        for &impl_did in self.local_trait_impls(async_drop_trait) {
+            let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
+            if adt_def.did() != adt_did.to_def_id() {
+                continue;
+            }
+
             if validate(self, impl_did).is_err() {
                 // Already `ErrorGuaranteed`, no need to delay a span bug here.
-                return;
+                continue;
             }
 
             let [future, ctor] = self.associated_item_def_ids(impl_did) else {
@@ -445,7 +455,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     self.def_span(impl_did),
                     "AsyncDrop impl without async_drop function or Dropper type",
                 );
-                return;
+                continue;
             };
 
             if let Some((_, _, old_impl_did)) = dtor_candidate {
@@ -456,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }
 
             dtor_candidate = Some((*future, *ctor, impl_did));
-        });
+        }
 
         let (future, ctor, _) = dtor_candidate?;
         Some(ty::AsyncDestructor { future, ctor })
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 7dda68b8393..c4357fae104 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -49,7 +49,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
 pub fn trigger_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
     tcx.dcx().span_delayed_bug(
         tcx.def_span(key),
-        "delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]",
+        "delayed bug triggered by #[rustc_delayed_bug_from_inside_query]",
     );
 }
 
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 9450ce7ec44..39fcc686c55 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -88,7 +88,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
             if info.query.dep_kind == dep_kinds::representability
                 && let Some(field_id) = info.query.def_id
                 && let Some(field_id) = field_id.as_local()
-                && let Some(DefKind::Field) = info.query.def_kind
+                && let Some(DefKind::Field) = info.query.info.def_kind
             {
                 let parent_id = tcx.parent(field_id.to_def_id());
                 let item_id = match tcx.def_kind(parent_id) {
@@ -216,7 +216,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
                             continue;
                         };
                         let frame_span =
-                            frame.query.default_span(cycle[(i + 1) % cycle.len()].span);
+                            frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span);
                         if frame_span.is_dummy() {
                             continue;
                         }
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
index f743ea60a45..64d092e0354 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
@@ -105,23 +105,19 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
         return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar));
     }
 
-    let trunc = |n, width: ty::UintTy| {
-        let width = width
-            .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap())
-            .bit_width()
-            .unwrap();
-        let width = Size::from_bits(width);
+    let lit_ty = match *ty.kind() {
+        ty::Pat(base, _) => base,
+        _ => ty,
+    };
+
+    let trunc = |n| {
+        let width = lit_ty.primitive_size(tcx);
         trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
         let result = width.truncate(n);
         trace!("trunc result: {}", result);
         ConstValue::Scalar(Scalar::from_uint(result, width))
     };
 
-    let lit_ty = match *ty.kind() {
-        ty::Pat(base, _) => base,
-        _ => ty,
-    };
-
     let value = match (lit, lit_ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
             let s = s.as_str();
@@ -149,11 +145,10 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
             ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
         }
-        (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui),
-        (ast::LitKind::Int(n, _), ty::Int(i)) => trunc(
-            if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() },
-            i.to_unsigned(),
-        ),
+        (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()),
+        (ast::LitKind::Int(n, _), ty::Int(_)) => {
+            trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })
+        }
         (ast::LitKind::Float(n, _), ty::Float(fty)) => {
             parse_float_into_constval(*n, *fty, neg).unwrap()
         }
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
index 50ca924baf9..90e27c85f74 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
@@ -258,7 +258,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
                 self.projection
             ),
             PlaceBase::Upvar { var_hir_id, closure_def_id: _ } => span_bug!(
-                cx.tcx.hir().span(var_hir_id.0),
+                cx.tcx.hir_span(var_hir_id.0),
                 "could not resolve upvar: {var_hir_id:?} + {:?}",
                 self.projection
             ),
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
index 97d34b85f50..f9791776f71 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
@@ -416,7 +416,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     if let Some(mir_place) = place_builder.try_to_place(this) {
                         this.cfg.push_fake_read(
                             block,
-                            this.source_info(this.tcx.hir().span(*hir_id)),
+                            this.source_info(this.tcx.hir_span(*hir_id)),
                             *cause,
                             mir_place,
                         );
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index f2ce0c46dd3..29d400a957b 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -115,7 +115,6 @@ impl<'tcx> MatchPairTree<'tcx> {
             place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
         }
 
-        // Place can be none if the pattern refers to a non-captured place in a closure.
         let place = place_builder.try_to_place(cx);
         let mut subpairs = Vec::new();
         let test_case = match pattern.kind {
@@ -321,7 +320,7 @@ impl<'tcx> MatchPairTree<'tcx> {
         if let Some(test_case) = test_case {
             // This pattern is refutable, so push a new match-pair node.
             match_pairs.push(MatchPairTree {
-                place: place.expect("refutable patterns should always have a place to inspect"),
+                place,
                 test_case,
                 subpairs,
                 pattern_ty: pattern.ty,
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index ea341b604e0..3acf2a6a2a6 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -13,13 +13,13 @@ use std::sync::Arc;
 use rustc_abi::VariantIdx;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir::{BindingMode, ByRef};
+use rustc_hir::{BindingMode, ByRef, LetStmt, LocalSource, Node};
 use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::mir::{self, *};
 use rustc_middle::thir::{self, *};
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
-use rustc_span::{BytePos, Pos, Span, Symbol};
+use rustc_span::{BytePos, Pos, Span, Symbol, sym};
 use tracing::{debug, instrument};
 
 use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
@@ -1279,7 +1279,13 @@ impl<'tcx> TestCase<'tcx> {
 #[derive(Debug, Clone)]
 pub(crate) struct MatchPairTree<'tcx> {
     /// This place...
-    place: Place<'tcx>,
+    ///
+    /// ---
+    /// This can be `None` if it referred to a non-captured place in a closure.
+    ///
+    /// Invariant: Can only be `None` when `test_case` is `Or`.
+    /// Therefore this must be `Some(_)` after or-pattern expansion.
+    place: Option<Place<'tcx>>,
 
     /// ... must pass this test...
     test_case: TestCase<'tcx>,
@@ -1326,8 +1332,8 @@ enum TestKind<'tcx> {
     Eq {
         value: Const<'tcx>,
         // Integer types are handled by `SwitchInt`, and constants with ADT
-        // types are converted back into patterns, so this can only be `&str`,
-        // `&[T]`, `f32` or `f64`.
+        // types and `&[T]` types are converted back into patterns, so this can
+        // only be `&str`, `f32` or `f64`.
         ty: Ty<'tcx>,
     },
 
@@ -2099,9 +2105,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Extract the match-pair from the highest priority candidate
         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);
 
-        (match_pair.place, test)
+        (match_place, test)
     }
 
     /// Given a test, we partition the input candidates into several buckets.
@@ -2796,13 +2804,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             )))),
         };
         let for_arm_body = self.local_decls.push(local);
-        self.var_debug_info.push(VarDebugInfo {
-            name,
-            source_info: debug_source_info,
-            value: VarDebugInfoContents::Place(for_arm_body.into()),
-            composite: None,
-            argument_index: None,
-        });
+        if self.should_emit_debug_info_for_binding(name, var_id) {
+            self.var_debug_info.push(VarDebugInfo {
+                name,
+                source_info: debug_source_info,
+                value: VarDebugInfoContents::Place(for_arm_body.into()),
+                composite: None,
+                argument_index: None,
+            });
+        }
         let locals = if has_guard.0 {
             let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
                 // This variable isn't mutated but has a name, so has to be
@@ -2815,13 +2825,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     BindingForm::RefForGuard,
                 ))),
             });
-            self.var_debug_info.push(VarDebugInfo {
-                name,
-                source_info: debug_source_info,
-                value: VarDebugInfoContents::Place(ref_for_guard.into()),
-                composite: None,
-                argument_index: None,
-            });
+            if self.should_emit_debug_info_for_binding(name, var_id) {
+                self.var_debug_info.push(VarDebugInfo {
+                    name,
+                    source_info: debug_source_info,
+                    value: VarDebugInfoContents::Place(ref_for_guard.into()),
+                    composite: None,
+                    argument_index: None,
+                });
+            }
             LocalsForNode::ForGuard { ref_for_guard, for_arm_body }
         } else {
             LocalsForNode::One(for_arm_body)
@@ -2829,4 +2841,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!(?locals);
         self.var_indices.insert(var_id, locals);
     }
+
+    /// Some bindings are introduced when producing HIR from the AST and don't
+    /// actually exist in the source. Skip producing debug info for those when
+    /// we can recognize them.
+    fn should_emit_debug_info_for_binding(&self, name: Symbol, var_id: LocalVarId) -> bool {
+        // For now we only recognize the output of desugaring assigns.
+        if name != sym::lhs {
+            return true;
+        }
+
+        let tcx = self.tcx;
+        for (_, node) in tcx.hir_parent_iter(var_id.0) {
+            // FIXME(khuey) at what point is it safe to bail on the iterator?
+            // Can we stop at the first non-Pat node?
+            if matches!(node, Node::LetStmt(&LetStmt { source: LocalSource::AssignDesugar(_), .. }))
+            {
+                return false;
+            }
+        }
+
+        true
+    }
 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index e5d61bc9e55..d1f9d4c34fe 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -11,7 +11,6 @@ use std::sync::Arc;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::{LangItem, RangeEnd};
 use rustc_middle::mir::*;
-use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -178,21 +177,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     _ => {}
                 }
 
+                assert_eq!(expect_ty, ty);
                 if !ty.is_scalar() {
                     // Use `PartialEq::eq` instead of `BinOp::Eq`
                     // (the binop can only handle primitives)
-                    self.non_scalar_compare(
+                    // Make sure that we do *not* call any user-defined code here.
+                    // The only type that can end up here is string literals, which have their
+                    // comparison defined in `core`.
+                    // (Interestingly this means that exhaustiveness analysis relies, for soundness,
+                    // on the `PartialEq` impl for `str` to b correct!)
+                    match *ty.kind() {
+                        ty::Ref(_, deref_ty, _) if deref_ty == self.tcx.types.str_ => {}
+                        _ => {
+                            span_bug!(source_info.span, "invalid type for non-scalar compare: {ty}")
+                        }
+                    };
+                    self.string_compare(
                         block,
                         success_block,
                         fail_block,
                         source_info,
                         expect,
-                        expect_ty,
                         Operand::Copy(place),
-                        ty,
                     );
                 } else {
-                    assert_eq!(expect_ty, ty);
                     self.compare(
                         block,
                         success_block,
@@ -370,97 +378,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         );
     }
 
-    /// Compare two values using `<T as std::compare::PartialEq>::eq`.
-    /// If the values are already references, just call it directly, otherwise
-    /// take a reference to the values first and then call it.
-    fn non_scalar_compare(
+    /// Compare two values of type `&str` using `<str as std::cmp::PartialEq>::eq`.
+    fn string_compare(
         &mut self,
         block: BasicBlock,
         success_block: BasicBlock,
         fail_block: BasicBlock,
         source_info: SourceInfo,
-        mut expect: Operand<'tcx>,
-        expect_ty: Ty<'tcx>,
-        mut val: Operand<'tcx>,
-        mut ty: Ty<'tcx>,
+        expect: Operand<'tcx>,
+        val: Operand<'tcx>,
     ) {
-        // If we're using `b"..."` as a pattern, we need to insert an
-        // unsizing coercion, as the byte string has the type `&[u8; N]`.
-        //
-        // We want to do this even when the scrutinee is a reference to an
-        // array, so we can call `<[u8]>::eq` rather than having to find an
-        // `<[u8; N]>::eq`.
-        let unsize = |ty: Ty<'tcx>| match ty.kind() {
-            ty::Ref(region, rty, _) => match rty.kind() {
-                ty::Array(inner_ty, n) => Some((region, inner_ty, n)),
-                _ => None,
-            },
-            _ => None,
-        };
-        let opt_ref_ty = unsize(ty);
-        let opt_ref_test_ty = unsize(expect_ty);
-        match (opt_ref_ty, opt_ref_test_ty) {
-            // nothing to do, neither is an array
-            (None, None) => {}
-            (Some((region, elem_ty, _)), _) | (None, Some((region, elem_ty, _))) => {
-                let tcx = self.tcx;
-                // make both a slice
-                ty = Ty::new_imm_ref(tcx, *region, Ty::new_slice(tcx, *elem_ty));
-                if opt_ref_ty.is_some() {
-                    let temp = self.temp(ty, source_info.span);
-                    self.cfg.push_assign(
-                        block,
-                        source_info,
-                        temp,
-                        Rvalue::Cast(
-                            CastKind::PointerCoercion(
-                                PointerCoercion::Unsize,
-                                CoercionSource::Implicit,
-                            ),
-                            val,
-                            ty,
-                        ),
-                    );
-                    val = Operand::Copy(temp);
-                }
-                if opt_ref_test_ty.is_some() {
-                    let slice = self.temp(ty, source_info.span);
-                    self.cfg.push_assign(
-                        block,
-                        source_info,
-                        slice,
-                        Rvalue::Cast(
-                            CastKind::PointerCoercion(
-                                PointerCoercion::Unsize,
-                                CoercionSource::Implicit,
-                            ),
-                            expect,
-                            ty,
-                        ),
-                    );
-                    expect = Operand::Move(slice);
-                }
-            }
-        }
-
-        // 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 str_ty = self.tcx.types.str_;
         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, [compare_ty, compare_ty]);
+        let method = trait_method(self.tcx, eq_def_id, sym::eq, [str_ty, str_ty]);
 
         let bool_ty = self.tcx.types.bool;
         let eq_result = self.temp(bool_ty, source_info.span);
@@ -540,8 +470,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // than one, but it'd be very unusual to have two sides that
         // both require tests; you'd expect one side to be simplified
         // away.)
-        let (match_pair_index, match_pair) =
-            candidate.match_pairs.iter().enumerate().find(|&(_, mp)| mp.place == test_place)?;
+        let (match_pair_index, match_pair) = candidate
+            .match_pairs
+            .iter()
+            .enumerate()
+            .find(|&(_, mp)| mp.place == Some(test_place))?;
 
         // If true, the match pair is completely entailed by its corresponding test
         // branch, so it can be removed. If false, the match pair is _compatible_
@@ -584,7 +517,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     candidate
                         .match_pairs
                         .iter()
-                        .any(|mp| mp.place == test_place && is_covering_range(&mp.test_case))
+                        .any(|mp| mp.place == Some(test_place) && is_covering_range(&mp.test_case))
                 };
                 if sorted_candidates
                     .get(&TestBranch::Failure)
diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs
index ed3b652e4ef..589e350a03f 100644
--- a/compiler/rustc_mir_build/src/builder/matches/util.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/util.rs
@@ -173,10 +173,14 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
             // }
             // ```
             // Hence we fake borrow using a deep borrow.
-            self.fake_borrow(match_pair.place, FakeBorrowKind::Deep);
+            if let Some(place) = match_pair.place {
+                self.fake_borrow(place, FakeBorrowKind::Deep);
+            }
         } else {
             // Insert a Shallow borrow of any place that is switched on.
-            self.fake_borrow(match_pair.place, FakeBorrowKind::Shallow);
+            if let Some(place) = match_pair.place {
+                self.fake_borrow(place, FakeBorrowKind::Shallow);
+            }
 
             for subpair in &match_pair.subpairs {
                 self.visit_match_pair(subpair);
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index c8b69a6ec62..7396591e185 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -457,7 +457,7 @@ fn construct_fn<'tcx>(
 
     // Figure out what primary body this item has.
     let body = tcx.hir_body_owned_by(fn_def);
-    let span_with_body = tcx.hir().span_with_body(fn_id);
+    let span_with_body = tcx.hir_span_with_body(fn_id);
     let return_ty_span = tcx
         .hir_fn_decl_by_hir_id(fn_id)
         .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 27ff01b4803..e42336a1dbb 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -305,27 +305,25 @@ impl DropTree {
     }
 
     /// Builds the MIR for a given drop tree.
-    ///
-    /// `blocks` should have the same length as `self.drops`, and may have its
-    /// first value set to some already existing block.
     fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>(
         &mut self,
         cfg: &mut CFG<'tcx>,
-        blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>,
-    ) {
+        root_node: Option<BasicBlock>,
+    ) -> IndexVec<DropIdx, Option<BasicBlock>> {
         debug!("DropTree::build_mir(drops = {:#?})", self);
-        assert_eq!(blocks.len(), self.drops.len());
 
-        self.assign_blocks::<T>(cfg, blocks);
-        self.link_blocks(cfg, blocks)
+        let mut blocks = self.assign_blocks::<T>(cfg, root_node);
+        self.link_blocks(cfg, &mut blocks);
+
+        blocks
     }
 
     /// Assign blocks for all of the drops in the drop tree that need them.
     fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>(
         &mut self,
         cfg: &mut CFG<'tcx>,
-        blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>,
-    ) {
+        root_node: Option<BasicBlock>,
+    ) -> IndexVec<DropIdx, Option<BasicBlock>> {
         // StorageDead statements can share blocks with each other and also with
         // a Drop terminator. We iterate through the drops to find which drops
         // need their own block.
@@ -342,8 +340,11 @@ impl DropTree {
             Own,
         }
 
+        let mut blocks = IndexVec::from_elem(None, &self.drops);
+        blocks[ROOT_NODE] = root_node;
+
         let mut needs_block = IndexVec::from_elem(Block::None, &self.drops);
-        if blocks[ROOT_NODE].is_some() {
+        if root_node.is_some() {
             // In some cases (such as drops for `continue`) the root node
             // already has a block. In this case, make sure that we don't
             // override it.
@@ -385,6 +386,8 @@ impl DropTree {
 
         debug!("assign_blocks: blocks = {:#?}", blocks);
         assert!(entry_points.is_empty());
+
+        blocks
     }
 
     fn link_blocks<'tcx>(
@@ -1493,7 +1496,7 @@ fn build_scope_drops<'tcx>(
                 // path, then don't generate the drop. (We only take this into
                 // account for non-unwind paths so as not to disturb the
                 // caching mechanism.)
-                if scope.moved_locals.iter().any(|&o| o == local) {
+                if scope.moved_locals.contains(&local) {
                     continue;
                 }
 
@@ -1574,10 +1577,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         span: Span,
         continue_block: Option<BasicBlock>,
     ) -> Option<BlockAnd<()>> {
-        let mut blocks = IndexVec::from_elem(None, &drops.drops);
-        blocks[ROOT_NODE] = continue_block;
-
-        drops.build_mir::<ExitScopes>(&mut self.cfg, &mut blocks);
+        let blocks = drops.build_mir::<ExitScopes>(&mut self.cfg, continue_block);
         let is_coroutine = self.coroutine.is_some();
 
         // Link the exit drop tree to unwind drop tree.
@@ -1633,8 +1633,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         let drops = &mut self.scopes.coroutine_drops;
         let cfg = &mut self.cfg;
         let fn_span = self.fn_span;
-        let mut blocks = IndexVec::from_elem(None, &drops.drops);
-        drops.build_mir::<CoroutineDrop>(cfg, &mut blocks);
+        let blocks = drops.build_mir::<CoroutineDrop>(cfg, None);
         if let Some(root_block) = blocks[ROOT_NODE] {
             cfg.terminate(
                 root_block,
@@ -1670,9 +1669,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         fn_span: Span,
         resume_block: &mut Option<BasicBlock>,
     ) {
-        let mut blocks = IndexVec::from_elem(None, &drops.drops);
-        blocks[ROOT_NODE] = *resume_block;
-        drops.build_mir::<Unwind>(cfg, &mut blocks);
+        let blocks = drops.build_mir::<Unwind>(cfg, *resume_block);
         if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
             cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);
 
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 7f2e7d5ca83..2a9bfb25b84 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -943,7 +943,7 @@ impl UnsafeOpKind {
             }
         });
         let unsafe_not_inherited_note = if let Some((id, _)) = note_non_inherited {
-            let span = tcx.hir().span(id);
+            let span = tcx.hir_span(id);
             let span = tcx.sess.source_map().guess_head_span(span);
             Some(UnsafeNotInheritedNote { span })
         } else {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 095d3e75da1..ea8c7303c0a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1174,7 +1174,7 @@ fn report_arm_reachability<'p, 'tcx>(
     for (arm, is_useful) in report.arm_usefulness.iter() {
         if let Usefulness::Redundant(explanation) = is_useful {
             let hir_id = arm.arm_data;
-            let arm_span = cx.tcx.hir().span(hir_id);
+            let arm_span = cx.tcx.hir_span(hir_id);
             let whole_arm_span = if is_match_arm {
                 // If the arm is followed by a comma, extend the span to include it.
                 let with_whitespace = sm.span_extend_while_whitespace(arm_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 667d59d858e..372453688d2 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
@@ -58,25 +58,13 @@ struct ConstToPat<'tcx> {
     span: Span,
     id: hir::HirId,
 
-    treat_byte_string_as_slice: bool,
-
     c: ty::Const<'tcx>,
 }
 
 impl<'tcx> ConstToPat<'tcx> {
     fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
         trace!(?pat_ctxt.typeck_results.hir_owner);
-        ConstToPat {
-            tcx: pat_ctxt.tcx,
-            typing_env: pat_ctxt.typing_env,
-            span,
-            id,
-            treat_byte_string_as_slice: pat_ctxt
-                .typeck_results
-                .treat_byte_string_as_slice
-                .contains(&id.local_id),
-            c,
-        }
+        ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
     }
 
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
@@ -108,8 +96,6 @@ impl<'tcx> ConstToPat<'tcx> {
         uv: ty::UnevaluatedConst<'tcx>,
         ty: Ty<'tcx>,
     ) -> Box<Pat<'tcx>> {
-        trace!(self.treat_byte_string_as_slice);
-
         // It's not *technically* correct to be revealing opaque types here as borrowcheck has
         // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
         // during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -307,21 +293,8 @@ impl<'tcx> ConstToPat<'tcx> {
                             ty,
                         );
                     } else {
-                        // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
-                        // matching against references, you can only use byte string literals.
-                        // The typechecker has a special case for byte string literals, by treating them
-                        // as slices. This means we turn `&[T; N]` constants into slice patterns, which
-                        // has no negative effects on pattern matching, even if we're actually matching on
-                        // arrays.
-                        let pointee_ty = match *pointee_ty.kind() {
-                            ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => {
-                                Ty::new_slice(tcx, elem_ty)
-                            }
-                            _ => *pointee_ty,
-                        };
                         // References have the same valtree representation as their pointee.
-                        let subpattern = self.valtree_to_pat(cv, pointee_ty);
-                        PatKind::Deref { subpattern }
+                        PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
                     }
                 }
             },
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 4bfeab44bf4..d20e051548b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer};
 use rustc_errors::codes::*;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, RangeEnd};
+use rustc_hir::{self as hir, LangItem, RangeEnd};
 use rustc_index::Idx;
 use rustc_middle::mir::interpret::LitToConstInput;
 use rustc_middle::thir::{
@@ -130,7 +130,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         // Lower the endpoint into a temporary `PatKind` that will then be
         // deconstructed to obtain the constant value and other data.
-        let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr);
+        let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None);
 
         // Unpeel any ascription or inline-const wrapper nodes.
         loop {
@@ -294,7 +294,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
             hir::PatKind::Never => PatKind::Never,
 
-            hir::PatKind::Expr(value) => self.lower_pat_expr(value),
+            hir::PatKind::Expr(value) => self.lower_pat_expr(value, Some(ty)),
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
                 let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
@@ -630,7 +630,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
     /// - Inline const blocks (e.g. `const { 1 + 1 }`)
     /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
-    fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
+    fn lower_pat_expr(
+        &mut self,
+        expr: &'tcx hir::PatExpr<'tcx>,
+        pat_ty: Option<Ty<'tcx>>,
+    ) -> PatKind<'tcx> {
         let (lit, neg) = match &expr.kind {
             hir::PatExprKind::Path(qpath) => {
                 return self.lower_path(qpath, expr.hir_id, expr.span).kind;
@@ -641,7 +645,31 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
         };
 
-        let ct_ty = self.typeck_results.node_type(expr.hir_id);
+        // We handle byte string literal patterns by using the pattern's type instead of the
+        // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference,
+        // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the
+        // pattern's type means we'll properly translate it to a slice reference pattern. This works
+        // because slices and arrays have the same valtree representation.
+        // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if
+        // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR.
+        // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is
+        // superseded by a more general implementation of deref patterns.
+        let ct_ty = match pat_ty {
+            Some(pat_ty)
+                if let ty::Adt(def, _) = *pat_ty.kind()
+                    && self.tcx.is_lang_item(def.did(), LangItem::String) =>
+            {
+                if !self.tcx.features().string_deref_patterns() {
+                    span_bug!(
+                        expr.span,
+                        "matching on `String` went through without enabling string_deref_patterns"
+                    );
+                }
+                self.typeck_results.node_type(expr.hir_id)
+            }
+            Some(pat_ty) => pat_ty,
+            None => self.typeck_results.node_type(expr.hir_id),
+        };
         let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
         let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
         self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index ceea72c6755..375db17fb73 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -53,9 +53,13 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
         //
         //     #[const_mutation_allowed]
         //     pub const LOG: Log = Log { msg: "" };
-        match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
-            Some(_) => None,
-            None => Some(def_id),
+        // FIXME: this should not be checking for `Drop` impls,
+        // but whether it or any field has a Drop impl (`needs_drop`)
+        // as fields' Drop impls may make this observable, too.
+        match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt| adt.has_dtor(self.tcx))
+        {
+            Some(true) => None,
+            Some(false) | None => Some(def_id),
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 89a306c6104..dd0e07f2218 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -219,6 +219,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
         mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
     dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));
 
+    // Feed HIR because we try to access this body's attrs in the inliner.
+    body_def.feed_hir();
     // Inherited from the by-ref coroutine.
     body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
     body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id));
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index d83c0d40a7e..73bd2d0705e 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -96,7 +96,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
         }
     } else {
         // Extract coverage spans from MIR statements/terminators as normal.
-        extract_refined_covspans(mir_body, hir_info, graph, &mut code_mappings);
+        extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut code_mappings);
     }
 
     branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, graph));
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 572dbae8fd2..aa4c0ef1e1f 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -273,8 +273,9 @@ struct ExtractedHirInfo {
     /// Must have the same context and filename as the body span.
     fn_sig_span_extended: Option<Span>,
     body_span: Span,
-    /// "Holes" are regions within the body span that should not be included in
-    /// coverage spans for this function (e.g. closures and nested items).
+    /// "Holes" are regions within the function body (or its expansions) that
+    /// should not be included in coverage spans for this function
+    /// (e.g. closures and nested items).
     hole_spans: Vec<Span>,
 }
 
@@ -323,7 +324,7 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
 
     let function_source_hash = hash_mir_source(tcx, hir_body);
 
-    let hole_spans = extract_hole_spans_from_hir(tcx, body_span, hir_body);
+    let hole_spans = extract_hole_spans_from_hir(tcx, hir_body);
 
     ExtractedHirInfo {
         function_source_hash,
@@ -340,14 +341,9 @@ fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) ->
     tcx.hir_owner_nodes(owner).opt_hash_including_bodies.unwrap().to_smaller_hash().as_u64()
 }
 
-fn extract_hole_spans_from_hir<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body_span: Span, // Usually `hir_body.value.span`, but not always
-    hir_body: &hir::Body<'tcx>,
-) -> Vec<Span> {
+fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tcx>) -> Vec<Span> {
     struct HolesVisitor<'tcx> {
         tcx: TyCtxt<'tcx>,
-        body_span: Span,
         hole_spans: Vec<Span>,
     }
 
@@ -387,14 +383,11 @@ fn extract_hole_spans_from_hir<'tcx>(
     }
     impl HolesVisitor<'_> {
         fn visit_hole_span(&mut self, hole_span: Span) {
-            // Discard any holes that aren't directly visible within the body span.
-            if self.body_span.contains(hole_span) && self.body_span.eq_ctxt(hole_span) {
-                self.hole_spans.push(hole_span);
-            }
+            self.hole_spans.push(hole_span);
         }
     }
 
-    let mut visitor = HolesVisitor { tcx, body_span, hole_spans: vec![] };
+    let mut visitor = HolesVisitor { tcx, hole_spans: vec![] };
 
     visitor.visit_body(hir_body);
     visitor.hole_spans
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index b9ed6984ddb..f57a158e3e4 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,30 +1,59 @@
 use std::collections::VecDeque;
+use std::iter;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::{debug, debug_span, instrument};
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
-use crate::coverage::spans::from_mir::{
-    ExtractedCovspans, Hole, SpanFromMir, extract_covspans_from_mir,
-};
-use crate::coverage::{ExtractedHirInfo, mappings};
+use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir, SpanFromMir};
+use crate::coverage::{ExtractedHirInfo, mappings, unexpand};
 
 mod from_mir;
 
-pub(super) fn extract_refined_covspans(
-    mir_body: &mir::Body<'_>,
+pub(super) fn extract_refined_covspans<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mir_body: &mir::Body<'tcx>,
     hir_info: &ExtractedHirInfo,
     graph: &CoverageGraph,
     code_mappings: &mut impl Extend<mappings::CodeMapping>,
 ) {
-    let ExtractedCovspans { mut covspans } = extract_covspans_from_mir(mir_body, hir_info, graph);
+    let &ExtractedHirInfo { body_span, .. } = hir_info;
+
+    let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph);
+    let mut covspans = raw_spans
+        .into_iter()
+        .filter_map(|RawSpanFromMir { raw_span, bcb }| try {
+            let (span, expn_kind) =
+                unexpand::unexpand_into_body_span_with_expn_kind(raw_span, body_span)?;
+            // Discard any spans that fill the entire body, because they tend
+            // to represent compiler-inserted code, e.g. implicitly returning `()`.
+            if span.source_equal(body_span) {
+                return None;
+            };
+            SpanFromMir { span, expn_kind, bcb }
+        })
+        .collect::<Vec<_>>();
+
+    // Only proceed if we found at least one usable span.
+    if covspans.is_empty() {
+        return;
+    }
+
+    // Also add the adjusted function signature span, if available.
+    // Otherwise, add a fake span at the start of the body, to avoid an ugly
+    // gap between the start of the body and the first real span.
+    // FIXME: Find a more principled way to solve this problem.
+    covspans.push(SpanFromMir::for_fn_sig(
+        hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()),
+    ));
 
     // First, perform the passes that need macro information.
     covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb));
     remove_unwanted_expansion_spans(&mut covspans);
-    split_visible_macro_spans(&mut covspans);
+    shrink_visible_macro_spans(tcx, &mut covspans);
 
     // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
     let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>();
@@ -43,16 +72,21 @@ pub(super) fn extract_refined_covspans(
     covspans.dedup_by(|b, a| a.span.source_equal(b.span));
 
     // Sort the holes, and merge overlapping/adjacent holes.
-    let mut holes = hir_info.hole_spans.iter().map(|&span| Hole { span }).collect::<Vec<_>>();
+    let mut holes = hir_info
+        .hole_spans
+        .iter()
+        .copied()
+        // Discard any holes that aren't directly visible within the body span.
+        .filter(|&hole_span| body_span.contains(hole_span) && body_span.eq_ctxt(hole_span))
+        .map(|span| Hole { span })
+        .collect::<Vec<_>>();
     holes.sort_by(|a, b| compare_spans(a.span, b.span));
     holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
 
     // Split the covspans into separate buckets that don't overlap any holes.
     let buckets = divide_spans_into_buckets(covspans, &holes);
 
-    for mut covspans in buckets {
-        // Make sure each individual bucket is internally sorted.
-        covspans.sort_by(compare_covspans);
+    for covspans in buckets {
         let _span = debug_span!("processing bucket", ?covspans).entered();
 
         let mut covspans = remove_unwanted_overlapping_spans(covspans);
@@ -96,82 +130,50 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
 }
 
 /// When a span corresponds to a macro invocation that is visible from the
-/// function body, split it into two parts. The first part covers just the
-/// macro name plus `!`, and the second part covers the rest of the macro
-/// invocation. This seems to give better results for code that uses macros.
-fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
-    let mut extra_spans = vec![];
-
-    covspans.retain(|covspan| {
-        let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
-            return true;
-        };
-
-        let split_len = visible_macro.as_str().len() as u32 + 1;
-        let (before, after) = covspan.span.split_at(split_len);
-        if !covspan.span.contains(before) || !covspan.span.contains(after) {
-            // Something is unexpectedly wrong with the split point.
-            // The debug assertion in `split_at` will have already caught this,
-            // but in release builds it's safer to do nothing and maybe get a
-            // bug report for unexpected coverage, rather than risk an ICE.
-            return true;
+/// function body, truncate it to just the macro name plus `!`.
+/// This seems to give better results for code that uses macros.
+fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec<SpanFromMir>) {
+    let source_map = tcx.sess.source_map();
+
+    for covspan in covspans {
+        if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) {
+            covspan.span = source_map.span_through_char(covspan.span, '!');
         }
-
-        extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
-        extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
-        false // Discard the original covspan that we just split.
-    });
-
-    // The newly-split spans are added at the end, so any previous sorting
-    // is not preserved.
-    covspans.extend(extra_spans);
+    }
 }
 
 /// Uses the holes to divide the given covspans into buckets, such that:
-/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
+/// - No span in any hole overlaps a bucket (discarding spans if necessary).
 /// - The spans in each bucket are strictly after all spans in previous buckets,
 ///   and strictly before all spans in subsequent buckets.
 ///
-/// The resulting buckets are sorted relative to each other, but might not be
-/// internally sorted.
+/// The lists of covspans and holes must be sorted.
+/// The resulting buckets are sorted relative to each other, and each bucket's
+/// contents are sorted.
 #[instrument(level = "debug")]
 fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
     debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
     debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
 
-    // Now we're ready to start carving holes out of the initial coverage spans,
-    // and grouping them in buckets separated by the holes.
+    // Now we're ready to start grouping spans into buckets separated by holes.
 
     let mut input_covspans = VecDeque::from(input_covspans);
-    let mut fragments = vec![];
 
     // For each hole:
     // - Identify the spans that are entirely or partly before the hole.
-    // - Put those spans in a corresponding bucket, truncated to the start of the hole.
-    // - If one of those spans also extends after the hole, put the rest of it
-    //   in a "fragments" vector that is processed by the next hole.
+    // - Discard any that overlap with the hole.
+    // - Add the remaining identified spans to the corresponding bucket.
     let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
     for (hole, bucket) in holes.iter().zip(&mut buckets) {
-        let fragments_from_prev = std::mem::take(&mut fragments);
-
-        // Only inspect spans that precede or overlap this hole,
-        // leaving the rest to be inspected by later holes.
-        // (This relies on the spans and holes both being sorted.)
-        let relevant_input_covspans =
-            drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
-
-        for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
-            let (before, after) = covspan.split_around_hole_span(hole.span);
-            bucket.extend(before);
-            fragments.extend(after);
-        }
+        bucket.extend(
+            drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi())
+                .filter(|c| !c.span.overlaps(hole.span)),
+        );
     }
 
-    // After finding the spans before each hole, any remaining fragments/spans
-    // form their own final bucket, after the final hole.
+    // Any remaining spans form their own final bucket, after the final hole.
     // (If there were no holes, this will just be all of the initial spans.)
-    fragments.extend(input_covspans);
-    buckets.push(fragments);
+    buckets.push(Vec::from(input_covspans));
 
     buckets
 }
@@ -182,7 +184,7 @@ fn drain_front_while<'a, T>(
     queue: &'a mut VecDeque<T>,
     mut pred_fn: impl FnMut(&T) -> bool,
 ) -> impl Iterator<Item = T> {
-    std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
+    iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x)))
 }
 
 /// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
@@ -225,22 +227,6 @@ struct Covspan {
 }
 
 impl Covspan {
-    /// Splits this covspan into 0-2 parts:
-    /// - The part that is strictly before the hole span, if any.
-    /// - The part that is strictly after the hole span, if any.
-    fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
-        let before = try {
-            let span = self.span.trim_end(hole_span)?;
-            Self { span, ..*self }
-        };
-        let after = try {
-            let span = self.span.trim_start(hole_span)?;
-            Self { span, ..*self }
-        };
-
-        (before, after)
-    }
-
     /// If `self` and `other` can be merged (i.e. they have the same BCB),
     /// mutates `self.span` to also include `other.span` and returns true.
     ///
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 73b68d7155c..804cd8ab3f7 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -1,3 +1,5 @@
+use std::iter;
+
 use rustc_middle::bug;
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::{
@@ -5,87 +7,50 @@ use rustc_middle::mir::{
 };
 use rustc_span::{ExpnKind, Span};
 
-use crate::coverage::ExtractedHirInfo;
-use crate::coverage::graph::{
-    BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
-};
+use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
 use crate::coverage::spans::Covspan;
-use crate::coverage::unexpand::unexpand_into_body_span_with_expn_kind;
 
-pub(crate) struct ExtractedCovspans {
-    pub(crate) covspans: Vec<SpanFromMir>,
+#[derive(Debug)]
+pub(crate) struct RawSpanFromMir {
+    /// A span that has been extracted from a MIR statement/terminator, but
+    /// hasn't been "unexpanded", so it might not lie within the function body
+    /// span and might be part of an expansion with a different context.
+    pub(crate) raw_span: Span,
+    pub(crate) bcb: BasicCoverageBlock,
 }
 
-/// Traverses the MIR body to produce an initial collection of coverage-relevant
-/// spans, each associated with a node in the coverage graph (BCB) and possibly
-/// other metadata.
-pub(crate) fn extract_covspans_from_mir(
-    mir_body: &mir::Body<'_>,
-    hir_info: &ExtractedHirInfo,
+/// Generates an initial set of coverage spans from the statements and
+/// terminators in the function's MIR body, each associated with its
+/// corresponding node in the coverage graph.
+///
+/// This is necessarily an inexact process, because MIR isn't designed to
+/// capture source spans at the level of detail we would want for coverage,
+/// but it's good enough to be better than nothing.
+pub(crate) fn extract_raw_spans_from_mir<'tcx>(
+    mir_body: &mir::Body<'tcx>,
     graph: &CoverageGraph,
-) -> ExtractedCovspans {
-    let &ExtractedHirInfo { body_span, .. } = hir_info;
-
-    let mut covspans = vec![];
+) -> Vec<RawSpanFromMir> {
+    let mut raw_spans = vec![];
 
+    // We only care about blocks that are part of the coverage graph.
     for (bcb, bcb_data) in graph.iter_enumerated() {
-        bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data, &mut covspans);
-    }
+        let make_raw_span = |raw_span: Span| RawSpanFromMir { raw_span, bcb };
 
-    // Only add the signature span if we found at least one span in the body.
-    if !covspans.is_empty() {
-        // If there is no usable signature span, add a fake one (before refinement)
-        // to avoid an ugly gap between the body start and the first real span.
-        // FIXME: Find a more principled way to solve this problem.
-        let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo());
-        covspans.push(SpanFromMir::for_fn_sig(fn_sig_span));
-    }
+        // A coverage graph node can consist of multiple basic blocks.
+        for &bb in &bcb_data.basic_blocks {
+            let bb_data = &mir_body[bb];
 
-    ExtractedCovspans { covspans }
-}
+            let statements = bb_data.statements.iter();
+            raw_spans.extend(statements.filter_map(filtered_statement_span).map(make_raw_span));
 
-// Generate a set of coverage spans from the filtered set of `Statement`s and `Terminator`s of
-// the `BasicBlock`(s) in the given `BasicCoverageBlockData`. One coverage span is generated
-// for each `Statement` and `Terminator`. (Note that subsequent stages of coverage analysis will
-// merge some coverage spans, at which point a coverage span may represent multiple
-// `Statement`s and/or `Terminator`s.)
-fn bcb_to_initial_coverage_spans<'a, 'tcx>(
-    mir_body: &'a mir::Body<'tcx>,
-    body_span: Span,
-    bcb: BasicCoverageBlock,
-    bcb_data: &'a BasicCoverageBlockData,
-    initial_covspans: &mut Vec<SpanFromMir>,
-) {
-    for &bb in &bcb_data.basic_blocks {
-        let data = &mir_body[bb];
-
-        let unexpand = move |expn_span| {
-            unexpand_into_body_span_with_expn_kind(expn_span, body_span)
-                // Discard any spans that fill the entire body, because they tend
-                // to represent compiler-inserted code, e.g. implicitly returning `()`.
-                .filter(|(span, _)| !span.source_equal(body_span))
-        };
-
-        let mut extract_statement_span = |statement| {
-            let expn_span = filtered_statement_span(statement)?;
-            let (span, expn_kind) = unexpand(expn_span)?;
-
-            initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
-            Some(())
-        };
-        for statement in data.statements.iter() {
-            extract_statement_span(statement);
+            // There's only one terminator, but wrap it in an iterator to
+            // mirror the handling of statements.
+            let terminator = iter::once(bb_data.terminator());
+            raw_spans.extend(terminator.filter_map(filtered_terminator_span).map(make_raw_span));
         }
-
-        let mut extract_terminator_span = |terminator| {
-            let expn_span = filtered_terminator_span(terminator)?;
-            let (span, expn_kind) = unexpand(expn_span)?;
-
-            initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
-            Some(())
-        };
-        extract_terminator_span(data.terminator());
     }
+
+    raw_spans
 }
 
 /// If the MIR `Statement` has a span contributive to computing coverage spans,
@@ -155,22 +120,20 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
         // an `if condition { block }` has a span that includes the executed block, if true,
         // but for coverage, the code region executed, up to *and* through the SwitchInt,
         // actually stops before the if's block.)
-        TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
+        TerminatorKind::Unreachable
         | TerminatorKind::Assert { .. }
         | TerminatorKind::Drop { .. }
         | TerminatorKind::SwitchInt { .. }
-        // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
         | TerminatorKind::FalseEdge { .. }
         | TerminatorKind::Goto { .. } => None,
 
         // Call `func` operand can have a more specific span when part of a chain of calls
-        TerminatorKind::Call { ref func, .. }
-        | TerminatorKind::TailCall { ref func, .. } => {
+        TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => {
             let mut span = terminator.source_info.span;
-            if let mir::Operand::Constant(box constant) = func {
-                if constant.span.lo() > span.lo() {
-                    span = span.with_lo(constant.span.lo());
-                }
+            if let mir::Operand::Constant(constant) = func
+                && span.contains(constant.span)
+            {
+                span = constant.span;
             }
             Some(span)
         }
@@ -182,9 +145,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
         | TerminatorKind::Yield { .. }
         | TerminatorKind::CoroutineDrop
         | TerminatorKind::FalseUnwind { .. }
-        | TerminatorKind::InlineAsm { .. } => {
-            Some(terminator.source_info.span)
-        }
+        | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
     }
 }
 
@@ -219,7 +180,7 @@ pub(crate) struct SpanFromMir {
 }
 
 impl SpanFromMir {
-    fn for_fn_sig(fn_sig_span: Span) -> Self {
+    pub(crate) fn for_fn_sig(fn_sig_span: Span) -> Self {
         Self::new(fn_sig_span, None, START_BCB)
     }
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 205d388f4fb..c372b77ad25 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -12,6 +12,7 @@
 #![feature(map_try_insert)]
 #![feature(never_type)]
 #![feature(try_blocks)]
+#![feature(vec_deque_pop_if)]
 #![feature(yeet_expr)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 231d7c2ef02..e7930f0a1e3 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
+use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
     self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
 };
@@ -56,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
                 ty::Coroutine(..) => ExternAbi::Rust,
                 // No need to do MIR validation on error bodies
                 ty::Error(_) => return,
-                _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"),
+                _ => span_bug!(body.span, "unexpected body ty: {body_ty}"),
             };
 
             ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
@@ -543,7 +544,13 @@ pub(super) fn validate_types<'tcx>(
     caller_body: &Body<'tcx>,
 ) -> Vec<(Location, String)> {
     let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() };
-    type_checker.visit_body(body);
+    // The type checker formats a bunch of strings with type names in it, but these strings
+    // are not always going to be encountered on the error path since the inliner also uses
+    // the validator, and there are certain kinds of inlining (even for valid code) that
+    // can cause validation errors (mostly around where clauses and rigid projections).
+    with_no_trimmed_paths!({
+        type_checker.visit_body(body);
+    });
     type_checker.failures
 }
 
@@ -655,7 +662,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             ProjectionElem::Index(index) => {
                 let index_ty = self.body.local_decls[index].ty;
                 if index_ty != self.tcx.types.usize {
-                    self.fail(location, format!("bad index ({index_ty:?} != usize)"))
+                    self.fail(location, format!("bad index ({index_ty} != usize)"))
                 }
             }
             ProjectionElem::Deref
@@ -664,10 +671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
 
                 if base_ty.is_box() {
-                    self.fail(
-                        location,
-                        format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"),
-                    )
+                    self.fail(location, format!("{base_ty} dereferenced after ElaborateBoxDerefs"))
                 }
             }
             ProjectionElem::Field(f, ty) => {
@@ -680,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         this.fail(
                             location,
                             format!(
-                                "Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`"
+                                "Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`"
                             )
                         )
                     }
@@ -806,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(
                         location,
                         format!(
-                            "Failed subtyping {ty:#?} and {:#?}",
+                            "Failed subtyping {ty} and {}",
                             place_ref.ty(&self.body.local_decls, self.tcx).ty
                         ),
                     )
@@ -826,7 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(
                         location,
                         format!(
-                            "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}"
+                            "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty}"
                         ),
                     );
                 }
@@ -841,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             if ty.is_union() || ty.is_enum() {
                 self.fail(
                     START_BLOCK.start_location(),
-                    format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name),
+                    format!("invalid type {ty} in debuginfo for {:?}", debuginfo.name),
                 );
             }
             if projection.is_empty() {
@@ -1064,15 +1068,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         if !self.mir_assign_valid_types(a, b) {
                             self.fail(
                                 location,
-                                format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"),
+                                format!("Cannot {op:?} compare incompatible types {a} and {b}"),
                             );
                         }
                     } else if a != b {
                         self.fail(
                             location,
-                            format!(
-                                "Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
-                            ),
+                            format!("Cannot perform binary op {op:?} on unequal types {a} and {b}"),
                         );
                     }
                 }
@@ -1081,7 +1083,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     Offset => {
                         check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
                         if b != self.tcx.types.isize && b != self.tcx.types.usize {
-                            self.fail(location, format!("Cannot offset by non-isize type {b:?}"));
+                            self.fail(location, format!("Cannot offset by non-isize type {b}"));
                         }
                     }
                     Eq | Lt | Le | Ne | Ge | Gt => {
@@ -1313,7 +1315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             {
                                 self.fail(
                                     location,
-                                    format!("Cannot transmute from non-`Sized` type {op_ty:?}"),
+                                    format!("Cannot transmute from non-`Sized` type {op_ty}"),
                                 );
                             }
                             if !self
@@ -1340,7 +1342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             }
             Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => {
                 let fail_out_of_bounds = |this: &mut Self, location, field, ty| {
-                    this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
+                    this.fail(location, format!("Out of bounds field {field:?} for {ty}"));
                 };
 
                 let mut current_ty = *container;
@@ -1374,7 +1376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         _ => {
                             self.fail(
                                 location,
-                                format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"),
+                                format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty}"),
                             );
                             return;
                         }
@@ -1403,7 +1405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
                     self.fail(
                         location,
-                        format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"),
+                        format!("Cannot wrap {unwrapped_ty} into unsafe binder {binder_ty:?}"),
                     );
                 }
             }
@@ -1489,24 +1491,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 // since CopyNonOverlapping is parametrized by 1 type,
                 // we only need to check that they are equal and not keep an extra parameter.
                 if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
-                    self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})"));
+                    self.fail(location, format!("bad arg ({op_src_ty} != {op_dst_ty})"));
                 }
 
                 let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
                 if op_cnt_ty != self.tcx.types.usize {
-                    self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)"))
+                    self.fail(location, format!("bad arg ({op_cnt_ty} != usize)"))
                 }
             }
             StatementKind::SetDiscriminant { place, .. } => {
                 if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
-                let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
-                if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) {
+                let pty = place.ty(&self.body.local_decls, self.tcx).ty;
+                if !matches!(
+                    pty.kind(),
+                    ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)
+                ) {
                     self.fail(
                         location,
                         format!(
-                            "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}"
+                            "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty}"
                         ),
                     );
                 }
@@ -1555,7 +1560,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     if ScalarInt::try_from_uint(value, size).is_none() {
                         self.fail(
                             location,
-                            format!("the value {value:#x} is not a proper {switch_ty:?}"),
+                            format!("the value {value:#x} is not a proper {switch_ty}"),
                         )
                     }
                 }
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index bdeab12ab50..6b6653e7de0 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -48,7 +48,7 @@ monomorphize_large_assignments =
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
 
 monomorphize_no_optimized_mir =
-    missing optimized MIR for an item in the crate `{$crate_name}`
+    missing optimized MIR for `{$instance}` in the crate `{$crate_name}`
     .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)
 
 monomorphize_recursion_limit =
@@ -63,4 +63,11 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
 monomorphize_unknown_cgu_collection_mode =
     unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
 
+monomorphize_wasm_c_abi_transition =
+    this function {$is_call ->
+      [true] call
+      *[false] definition
+    } involves an argument of type `{$ty}` which is affected by the wasm ABI transition
+    .help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
 monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 67fca1d7c29..6e676ac6b8d 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -225,13 +225,13 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths};
 use rustc_middle::ty::{
-    self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Interner, Ty, TyCtxt,
-    TypeFoldable, TypeVisitableExt, VtblEntry,
+    self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
+    TypeVisitableExt, VtblEntry,
 };
 use rustc_middle::util::Providers;
 use rustc_middle::{bug, span_bug};
 use rustc_session::Limit;
-use rustc_session::config::EntryFnType;
+use rustc_session::config::{DebugInfo, EntryFnType};
 use rustc_span::source_map::{Spanned, dummy_spanned, respan};
 use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument, trace};
@@ -967,7 +967,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
     {
         // `#[rustc_force_inline]` items should never be codegened. This should be caught by
         // the MIR validator.
-        tcx.delay_bug("attempt to codegen `#[rustc_force_inline]` item");
+        tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item");
     }
 
     if def_id.is_local() {
@@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
         tcx.dcx().emit_fatal(NoOptimizedMir {
             span: tcx.def_span(def_id),
             crate_name: tcx.crate_name(def_id.krate),
+            instance: instance.to_string(),
         });
     }
 
@@ -1235,6 +1236,11 @@ fn collect_items_of_instance<'tcx>(
     };
 
     if mode == CollectionMode::UsedItems {
+        if tcx.sess.opts.debuginfo == DebugInfo::Full {
+            for var_debug_info in &body.var_debug_info {
+                collector.visit_var_debug_info(var_debug_info);
+            }
+        }
         for (bb, data) in traversal::mono_reachable(body, tcx, instance) {
             collector.visit_basic_block_data(bb, data)
         }
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 8dafbbca905..adfe096f0cd 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir {
     #[note]
     pub span: Span,
     pub crate_name: Symbol,
+    pub instance: String,
 }
 
 #[derive(LintDiagnostic)]
@@ -103,3 +104,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
     /// Whether this is a problem at a call site or at a declaration.
     pub is_call: bool,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(monomorphize_wasm_c_abi_transition)]
+#[help]
+pub(crate) struct WasmCAbiTransition<'a> {
+    pub ty: Ty<'a>,
+    /// Whether this is a problem at a call site or at a declaration.
+    pub is_call: bool,
+}
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 06d6c3ab805..0f5bdc8d768 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,13 +1,15 @@
 //! This module ensures that if a function's ABI requires a particular target feature,
 //! that target feature is enabled both on the callee and all callers.
 use rustc_abi::{BackendRepr, RegKind};
-use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::mir::{self, traversal};
-use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
-use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
+use rustc_hir::{CRATE_HIR_ID, HirId};
+use rustc_middle::mir::{self, Location, traversal};
+use rustc_middle::ty::layout::LayoutCx;
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
+use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
-use rustc_target::callconv::{Conv, FnAbi, PassMode};
+use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
+use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
 
 use crate::errors;
 
@@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
 /// for a certain function.
 /// `is_call` indicates whether this is a call-site check or a definition-site check;
 /// this is only relevant for the wording in the emitted error.
-fn do_check_abi<'tcx>(
+fn do_check_simd_vector_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     abi: &FnAbi<'tcx, Ty<'tcx>>,
     def_id: DefId,
     is_call: bool,
-    span: impl Fn() -> Span,
+    loc: impl Fn() -> (Span, HirId),
 ) {
+    // We check this on all functions, including those using the "Rust" ABI.
+    // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
     let feature_def = tcx.sess.target.features_for_correct_vector_abi();
     let codegen_attrs = tcx.codegen_fn_attrs(def_id);
     let have_feature = |feat: Symbol| {
@@ -46,10 +50,10 @@ fn do_check_abi<'tcx>(
             let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
                 Some((_, feature)) => feature,
                 None => {
-                    let span = span();
+                    let (span, hir_id) = loc();
                     tcx.emit_node_span_lint(
                         ABI_UNSUPPORTED_VECTOR_TYPES,
-                        CRATE_HIR_ID,
+                        hir_id,
                         span,
                         errors::AbiErrorUnsupportedVectorType {
                             span,
@@ -62,10 +66,10 @@ fn do_check_abi<'tcx>(
             };
             if !have_feature(Symbol::intern(feature)) {
                 // Emit error.
-                let span = span();
+                let (span, hir_id) = loc();
                 tcx.emit_node_span_lint(
                     ABI_UNSUPPORTED_VECTOR_TYPES,
-                    CRATE_HIR_ID,
+                    hir_id,
                     span,
                     errors::AbiErrorDisabledVectorType {
                         span,
@@ -79,8 +83,9 @@ fn do_check_abi<'tcx>(
     }
     // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
     if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) {
+        let (span, _hir_id) = loc();
         tcx.dcx().emit_err(errors::AbiRequiredTargetFeature {
-            span: span(),
+            span,
             required_feature: "sse2",
             abi: "vectorcall",
             is_call,
@@ -88,6 +93,61 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Determines whether the given argument is passed the same way on the old and new wasm ABIs.
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    loc: impl Fn() -> (Span, HirId),
+) {
+    // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`),
+    // and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. Return values are not affected by this change.
+    for arg_abi in abi.args.iter() {
+        if wasm_abi_safe(tcx, arg_abi) {
+            continue;
+        }
+        let (span, hir_id) = loc();
+        tcx.emit_node_span_lint(
+            WASM_C_ABI,
+            hir_id,
+            span,
+            errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
+        );
+        // Let's only warn once per function.
+        break;
+    }
+}
+
 /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
 /// or return values for which the corresponding target feature is not enabled.
 fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@@ -98,13 +158,15 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
         // function.
         return;
     };
-    do_check_abi(
-        tcx,
-        abi,
-        instance.def_id(),
-        /*is_call*/ false,
-        || tcx.def_span(instance.def_id()),
-    )
+    let loc = || {
+        let def_id = instance.def_id();
+        (
+            tcx.def_span(def_id),
+            def_id.as_local().map(|did| tcx.local_def_id_to_hir_id(did)).unwrap_or(CRATE_HIR_ID),
+        )
+    };
+    do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc);
+    do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc);
 }
 
 /// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -112,8 +174,8 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
 fn check_call_site_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     callee: Ty<'tcx>,
-    span: Span,
     caller: InstanceKind<'tcx>,
+    loc: impl Fn() -> (Span, HirId) + Copy,
 ) {
     if callee.fn_sig(tcx).abi().is_rustic_abi() {
         // we directly handle the soundness of Rust ABIs
@@ -141,7 +203,8 @@ fn check_call_site_abi<'tcx>(
         // ABI failed to compute; this will not get through codegen.
         return;
     };
-    do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
+    do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc);
+    do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc);
 }
 
 fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
@@ -157,7 +220,19 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
                     ty::TypingEnv::fully_monomorphized(),
                     ty::EarlyBinder::bind(callee_ty),
                 );
-                check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance);
+                check_call_site_abi(tcx, callee_ty, body.source.instance, || {
+                    let loc = Location {
+                        block: bb,
+                        statement_index: body.basic_blocks[bb].statements.len(),
+                    };
+                    (
+                        *fn_span,
+                        body.source_info(loc)
+                            .scope
+                            .lint_root(&body.source_scopes)
+                            .unwrap_or(CRATE_HIR_ID),
+                    )
+                });
             }
             _ => {}
         }
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 259b39e2b9e..c4b6b18c45d 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -62,14 +62,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> <Self::Interner as Interner>::GenericArg;
 
-    // FIXME: Can we implement this in terms of `add` and `inject`?
-    fn insert_hidden_type(
+    fn register_hidden_type_in_storage(
         &self,
         opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
-        param_env: <Self::Interner as Interner>::ParamEnv,
         hidden_ty: <Self::Interner as Interner>::Ty,
-        goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
-    ) -> Result<(), NoSolution>;
+        span: <Self::Interner as Interner>::Span,
+    ) -> Option<<Self::Interner as Interner>::Ty>;
 
     fn add_item_bounds_for_hidden_type(
         &self,
@@ -79,14 +77,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
         hidden_ty: <Self::Interner as Interner>::Ty,
         goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
     );
-
-    fn inject_new_hidden_type_unchecked(
-        &self,
-        key: ty::OpaqueTypeKey<Self::Interner>,
-        hidden_ty: <Self::Interner as Interner>::Ty,
-        span: <Self::Interner as Interner>::Span,
-    );
-
     fn reset_opaque_types(&self);
 
     fn fetch_eligible_assoc_item(
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index f6963a79067..f575fe03019 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -6,6 +6,7 @@
 
 // tidy-alphabetical-start
 #![allow(rustc::usage_of_type_ir_inherent)]
+#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
 // tidy-alphabetical-end
 
 pub mod canonicalizer;
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index ac6b521f665..4edc293ad80 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -425,7 +425,8 @@ where
 
     fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
         for &(key, ty) in opaque_types {
-            self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span);
+            let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
+            assert_eq!(prev, None);
         }
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 0322c9e4ab0..148ba02252d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -387,7 +387,8 @@ where
         };
 
         for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
-            ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
+            let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
+            assert_eq!(prev, None);
         }
 
         if !ecx.nested_goals.is_empty() {
@@ -971,15 +972,17 @@ where
         rhs: T,
     ) -> Result<(), NoSolution> {
         let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
-        if cfg!(debug_assertions) {
-            for g in goals.iter() {
-                match g.predicate.kind().skip_binder() {
-                    ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {}
-                    p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
+        for &goal in goals.iter() {
+            let source = match goal.predicate.kind().skip_binder() {
+                ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
+                    GoalSource::TypeRelating
                 }
-            }
+                // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive?
+                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc,
+                p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
+            };
+            self.add_goal(source, goal);
         }
-        self.add_goals(GoalSource::TypeRelating, goals);
         Ok(())
     }
 
@@ -1068,16 +1071,12 @@ where
         self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
     }
 
-    pub(super) fn insert_hidden_type(
+    pub(super) fn register_hidden_type_in_storage(
         &mut self,
         opaque_type_key: ty::OpaqueTypeKey<I>,
-        param_env: I::ParamEnv,
         hidden_ty: I::Ty,
-    ) -> Result<(), NoSolution> {
-        let mut goals = Vec::new();
-        self.delegate.insert_hidden_type(opaque_type_key, param_env, hidden_ty, &mut goals)?;
-        self.add_goals(GoalSource::Misc, goals);
-        Ok(())
+    ) -> Option<I::Ty> {
+        self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span)
     }
 
     pub(super) fn add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 817dffa127b..82dae51b3d0 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -86,8 +86,8 @@ where
                 }
 
                 // Otherwise, define a new opaque type
-                // FIXME: should we use `inject_hidden_type_unchecked` here?
-                self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
+                let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
+                assert_eq!(prev, None);
                 self.add_item_bounds_for_hidden_type(
                     def_id.into(),
                     opaque_ty.args,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 6d4308cda1a..93fa89b68b9 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -757,10 +757,6 @@ parse_struct_literal_body_without_path =
     struct literal body without path
     .suggestion = you might have forgotten to add the struct literal inside the block
 
-parse_struct_literal_needing_parens =
-    invalid struct literal
-    .suggestion = you might need to surround the struct literal with parentheses
-
 parse_struct_literal_not_allowed_here = struct literals are not allowed here
     .suggestion = surround the struct literal with parentheses
 
@@ -842,8 +838,6 @@ parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression int
 
 parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard
 
-parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`)
-
 parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard
 
 parse_unexpected_if_with_if = unexpected `if` in the condition expression
@@ -864,7 +858,7 @@ parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surro
 parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
     .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
 
-parse_unexpected_token_after_dot = unexpected token: `{$actual}`
+parse_unexpected_token_after_dot = unexpected token: {$actual}
 
 parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
     .suggestion_remove_label = consider removing the label
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index e090d9cf760..dfdef018bc3 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -810,16 +810,16 @@ pub(crate) enum WrapInParentheses {
 
 #[derive(Diagnostic)]
 #[diag(parse_array_brackets_instead_of_braces)]
-pub(crate) struct ArrayBracketsInsteadOfSpaces {
+pub(crate) struct ArrayBracketsInsteadOfBraces {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sub: ArrayBracketsInsteadOfSpacesSugg,
+    pub sub: ArrayBracketsInsteadOfBracesSugg,
 }
 
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
-pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
+pub(crate) struct ArrayBracketsInsteadOfBracesSugg {
     #[suggestion_part(code = "[")]
     pub left: Span,
     #[suggestion_part(code = "]")]
@@ -1273,24 +1273,6 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_struct_literal_needing_parens)]
-pub(crate) struct StructLiteralNeedingParens {
-    #[primary_span]
-    pub span: Span,
-    #[subdiagnostic]
-    pub sugg: StructLiteralNeedingParensSugg,
-}
-
-#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
-pub(crate) struct StructLiteralNeedingParensSugg {
-    #[suggestion_part(code = "(")]
-    pub before: Span,
-    #[suggestion_part(code = ")")]
-    pub after: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(parse_unmatched_angle_brackets)]
 pub(crate) struct UnmatchedAngleBrackets {
     #[primary_span]
@@ -1714,10 +1696,10 @@ pub(crate) struct SelfArgumentPointer {
 
 #[derive(Diagnostic)]
 #[diag(parse_unexpected_token_after_dot)]
-pub(crate) struct UnexpectedTokenAfterDot<'a> {
+pub(crate) struct UnexpectedTokenAfterDot {
     #[primary_span]
     pub span: Span,
-    pub actual: Cow<'a, str>,
+    pub actual: String,
 }
 
 #[derive(Diagnostic)]
@@ -2787,17 +2769,6 @@ pub(crate) enum UnexpectedExpressionInPatternSugg {
         /// The statement's block's indentation.
         indentation: String,
     },
-
-    #[multipart_suggestion(
-        parse_unexpected_expr_in_pat_inline_const_sugg,
-        applicability = "maybe-incorrect"
-    )]
-    InlineConst {
-        #[suggestion_part(code = "const {{ ")]
-        start_span: Span,
-        #[suggestion_part(code = " }}")]
-        end_span: Span,
-    },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index c1cca1186af..ef044fe9d63 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -40,9 +40,8 @@ use crate::errors::{
     HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
     IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
     QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
-    StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
-    SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
-    UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
+    StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
+    TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
     UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
 };
 use crate::parser::attr::InnerAttrPolicy;
@@ -949,7 +948,6 @@ impl<'a> Parser<'a> {
         lo: Span,
         s: BlockCheckMode,
         maybe_struct_name: token::Token,
-        can_be_struct_literal: bool,
     ) -> Option<PResult<'a, P<Block>>> {
         if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) {
             // We might be having a struct literal where people forgot to include the path:
@@ -975,47 +973,23 @@ impl<'a> Parser<'a> {
                     // fn foo() -> Foo { Path {
                     //     field: value,
                     // } }
-                    let guar = err.delay_as_bug();
+                    err.cancel();
                     self.restore_snapshot(snapshot);
-                    let mut tail = self.mk_block(
+                    let guar = self.dcx().emit_err(StructLiteralBodyWithoutPath {
+                        span: expr.span,
+                        sugg: StructLiteralBodyWithoutPathSugg {
+                            before: expr.span.shrink_to_lo(),
+                            after: expr.span.shrink_to_hi(),
+                        },
+                    });
+                    Ok(self.mk_block(
                         thin_vec![self.mk_stmt_err(expr.span, guar)],
                         s,
                         lo.to(self.prev_token.span),
-                    );
-                    tail.could_be_bare_literal = true;
-                    if maybe_struct_name.is_ident() && can_be_struct_literal {
-                        // Account for `if Example { a: one(), }.is_pos() {}`.
-                        // expand `before` so that we take care of module path such as:
-                        // `foo::Bar { ... } `
-                        // we expect to suggest `(foo::Bar { ... })` instead of `foo::(Bar { ... })`
-                        let sm = self.psess.source_map();
-                        let before = maybe_struct_name.span.shrink_to_lo();
-                        if let Ok(extend_before) = sm.span_extend_prev_while(before, |t| {
-                            t.is_alphanumeric() || t == ':' || t == '_'
-                        }) {
-                            Err(self.dcx().create_err(StructLiteralNeedingParens {
-                                span: maybe_struct_name.span.to(expr.span),
-                                sugg: StructLiteralNeedingParensSugg {
-                                    before: extend_before.shrink_to_lo(),
-                                    after: expr.span.shrink_to_hi(),
-                                },
-                            }))
-                        } else {
-                            return None;
-                        }
-                    } else {
-                        self.dcx().emit_err(StructLiteralBodyWithoutPath {
-                            span: expr.span,
-                            sugg: StructLiteralBodyWithoutPathSugg {
-                                before: expr.span.shrink_to_lo(),
-                                after: expr.span.shrink_to_hi(),
-                            },
-                        });
-                        Ok(tail)
-                    }
+                    ))
                 }
                 (Err(err), Ok(tail)) => {
-                    // We have a block tail that contains a somehow valid type ascription expr.
+                    // We have a block tail that contains a somehow valid expr.
                     err.cancel();
                     Ok(tail)
                 }
@@ -1025,10 +999,7 @@ impl<'a> Parser<'a> {
                     self.consume_block(exp!(OpenBrace), exp!(CloseBrace), ConsumeClosingDelim::Yes);
                     Err(err)
                 }
-                (Ok(_), Ok(mut tail)) => {
-                    tail.could_be_bare_literal = true;
-                    Ok(tail)
-                }
+                (Ok(_), Ok(tail)) => Ok(tail),
             });
         }
         None
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c48f91643e8..e1e6b93abf3 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -4,10 +4,10 @@ use core::mem;
 use core::ops::{Bound, ControlFlow};
 
 use ast::mut_visit::{self, MutVisitor};
-use ast::token::{IdentIsRaw, MetaVarKind};
+use ast::token::IdentIsRaw;
 use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
 use rustc_ast::util::case::Case;
 use rustc_ast::util::classify;
@@ -19,7 +19,6 @@ use rustc_ast::{
     MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
     YieldKind,
 };
-use rustc_ast_pretty::pprust;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
 use rustc_lexer::unescape::unescape_char;
@@ -605,7 +604,7 @@ impl<'a> Parser<'a> {
             // can't continue an expression after an ident
             token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
             token::Literal(..) | token::Pound => true,
-            _ => t.is_whole_expr(),
+            _ => t.is_metavar_expr(),
         };
         self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr)
     }
@@ -641,6 +640,13 @@ impl<'a> Parser<'a> {
             TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => {
                 self.prev_token.span
             }
+            TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
+                // `expr.span` is the interpolated span, because invisible open
+                // and close delims both get marked with the same span, one
+                // that covers the entire thing between them. (See
+                // `rustc_expand::mbe::transcribe::transcribe`.)
+                self.prev_token.span
+            }
             _ => expr.span,
         }
     }
@@ -979,12 +985,30 @@ impl<'a> Parser<'a> {
     }
 
     fn error_unexpected_after_dot(&self) {
-        let actual = pprust::token_to_string(&self.token);
+        let actual = super::token_descr(&self.token);
         let span = self.token.span;
         let sm = self.psess.source_map();
         let (span, actual) = match (&self.token.kind, self.subparser_name) {
-            (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => {
-                (span.shrink_to_hi(), actual.into())
+            (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => {
+                (span.shrink_to_hi(), format!("`{}`", snippet))
+            }
+            (token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))), _) => {
+                // No need to report an error. This case will only occur when parsing a pasted
+                // metavariable, and we should have emitted an error when parsing the macro call in
+                // the first place. E.g. in this code:
+                // ```
+                // macro_rules! m { ($e:expr) => { $e }; }
+                //
+                // fn main() {
+                //     let f = 1;
+                //     m!(f.);
+                // }
+                // ```
+                // we'll get an error "unexpected token: `)` when parsing the `m!(f.)`, so we don't
+                // want to issue a second error when parsing the expansion `«f.»` (where `«`/`»`
+                // represent the invisible delimiters).
+                self.dcx().span_delayed_bug(span, "bad dot expr in metavariable");
+                return;
             }
             _ => (span, actual),
         };
@@ -1294,7 +1318,7 @@ impl<'a> Parser<'a> {
 
     /// Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
+        if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
             return Ok(self.mk_await_expr(self_arg, lo));
         }
 
@@ -1364,17 +1388,33 @@ impl<'a> Parser<'a> {
         let span = self.token.span;
         if let token::Interpolated(nt) = &self.token.kind {
             match &**nt {
-                token::NtExpr(e) | token::NtLiteral(e) => {
-                    let e = e.clone();
-                    self.bump();
-                    return Ok(e);
-                }
                 token::NtBlock(block) => {
                     let block = block.clone();
                     self.bump();
                     return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None)));
                 }
             };
+        } else if let Some(expr) = self.eat_metavar_seq_with_matcher(
+            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
+            |this| {
+                // Force collection (as opposed to just `parse_expr`) is required to avoid the
+                // attribute duplication seen in #138478.
+                let expr = this.parse_expr_force_collect();
+                // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly
+                // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line
+                // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in
+                // `compiler/rustc_index/src/bit_set/tests.rs`.
+                if this.token.kind == token::Comma {
+                    this.bump();
+                }
+                expr
+            },
+        ) {
+            return Ok(expr);
+        } else if let Some(lit) =
+            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
+        {
+            return Ok(lit);
         } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| {
             this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))
         }) {
@@ -1471,9 +1511,9 @@ impl<'a> Parser<'a> {
                 this.parse_expr_let(restrictions)
             } else if this.eat_keyword(exp!(Underscore)) {
                 Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
-            } else if this.token.uninterpolated_span().at_least_rust_2018() {
+            } else if this.token_uninterpolated_span().at_least_rust_2018() {
                 // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
-                if this.token.uninterpolated_span().at_least_rust_2024()
+                if this.token_uninterpolated_span().at_least_rust_2024()
                     // check for `gen {}` and `gen move {}`
                     // or `async gen {}` and `async gen move {}`
                     && (this.is_gen_block(kw::Gen, 0)
@@ -2062,87 +2102,107 @@ impl<'a> Parser<'a> {
             .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
     }
 
-    fn recover_after_dot(&mut self) -> Option<Token> {
-        let mut recovered = None;
+    fn recover_after_dot(&mut self) {
         if self.token == token::Dot {
             // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
             // dot would follow an optional literal, so we do this unconditionally.
-            recovered = self.look_ahead(1, |next_token| {
+            let recovered = self.look_ahead(1, |next_token| {
+                // If it's an integer that looks like a float, then recover as such.
+                //
+                // We will never encounter the exponent part of a floating
+                // point literal here, since there's no use of the exponent
+                // syntax that also constitutes a valid integer, so we need
+                // not check for that.
                 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
                     next_token.kind
+                    && suffix.is_none_or(|s| s == sym::f32 || s == sym::f64)
+                    && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
+                    && self.token.span.hi() == next_token.span.lo()
                 {
-                    // If this integer looks like a float, then recover as such.
-                    //
-                    // We will never encounter the exponent part of a floating
-                    // point literal here, since there's no use of the exponent
-                    // syntax that also constitutes a valid integer, so we need
-                    // not check for that.
-                    if suffix.is_none_or(|s| s == sym::f32 || s == sym::f64)
-                        && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
-                        && self.token.span.hi() == next_token.span.lo()
-                    {
-                        let s = String::from("0.") + symbol.as_str();
-                        let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
-                        return Some(Token::new(kind, self.token.span.to(next_token.span)));
-                    }
+                    let s = String::from("0.") + symbol.as_str();
+                    let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
+                    Some(Token::new(kind, self.token.span.to(next_token.span)))
+                } else {
+                    None
                 }
-                None
             });
-            if let Some(token) = &recovered {
-                self.bump();
+            if let Some(recovered) = recovered {
                 self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart {
-                    span: token.span,
-                    suggestion: token.span.shrink_to_lo(),
+                    span: recovered.span,
+                    suggestion: recovered.span.shrink_to_lo(),
                 });
+                self.bump();
+                self.token = recovered;
             }
         }
+    }
 
-        recovered
+    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
+    /// `Lit::from_token` (excluding unary negation).
+    fn eat_token_lit(&mut self) -> Option<token::Lit> {
+        match self.token.uninterpolate().kind {
+            token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => {
+                self.bump();
+                Some(token::Lit::new(token::Bool, name, None))
+            }
+            token::Literal(token_lit) => {
+                self.bump();
+                Some(token_lit)
+            }
+            token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
+                MetaVarKind::Literal,
+            ))) => {
+                let lit = self
+                    .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
+                    .expect("metavar seq literal");
+                let ast::ExprKind::Lit(token_lit) = lit.kind else {
+                    panic!("didn't reparse a literal");
+                };
+                Some(token_lit)
+            }
+            token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
+                mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. },
+            ))) => {
+                let expr = self
+                    .eat_metavar_seq(mv_kind, |this| this.parse_expr())
+                    .expect("metavar seq expr");
+                let ast::ExprKind::Lit(token_lit) = expr.kind else {
+                    panic!("didn't reparse an expr");
+                };
+                Some(token_lit)
+            }
+            _ => None,
+        }
     }
 
     /// Matches `lit = true | false | token_lit`.
     /// Returns `None` if the next token is not a literal.
-    pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
-        let recovered = self.recover_after_dot();
-        let token = recovered.as_ref().unwrap_or(&self.token);
-        let span = token.span;
-
-        token::Lit::from_token(token).map(|token_lit| {
-            self.bump();
-            (token_lit, span)
-        })
+    fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
+        self.recover_after_dot();
+        let span = self.token.span;
+        self.eat_token_lit().map(|token_lit| (token_lit, span))
     }
 
     /// Matches `lit = true | false | token_lit`.
     /// Returns `None` if the next token is not a literal.
-    pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
-        let recovered = self.recover_after_dot();
-        let token = recovered.as_ref().unwrap_or(&self.token);
-        match token::Lit::from_token(token) {
-            Some(lit) => {
-                match MetaItemLit::from_token_lit(lit, token.span) {
-                    Ok(lit) => {
-                        self.bump();
-                        Some(lit)
-                    }
-                    Err(err) => {
-                        let span = token.uninterpolated_span();
-                        self.bump();
-                        let guar = report_lit_error(self.psess, err, lit, span);
-                        // Pack possible quotes and prefixes from the original literal into
-                        // the error literal's symbol so they can be pretty-printed faithfully.
-                        let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
-                        let symbol = Symbol::intern(&suffixless_lit.to_string());
-                        let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix);
-                        Some(
-                            MetaItemLit::from_token_lit(lit, span)
-                                .unwrap_or_else(|_| unreachable!()),
-                        )
-                    }
+    fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
+        self.recover_after_dot();
+        let span = self.token.span;
+        let uninterpolated_span = self.token_uninterpolated_span();
+        self.eat_token_lit().map(|token_lit| {
+            match MetaItemLit::from_token_lit(token_lit, span) {
+                Ok(lit) => lit,
+                Err(err) => {
+                    let guar = report_lit_error(&self.psess, err, token_lit, uninterpolated_span);
+                    // Pack possible quotes and prefixes from the original literal into
+                    // the error literal's symbol so they can be pretty-printed faithfully.
+                    let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
+                    let symbol = Symbol::intern(&suffixless_lit.to_string());
+                    let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
+                    MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
                 }
             }
-            None => None,
-        }
+        })
     }
 
     pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
@@ -2166,9 +2226,10 @@ impl<'a> Parser<'a> {
     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
     pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
-        if let token::Interpolated(nt) = &self.token.kind {
-            match &**nt {
-                // FIXME(nnethercote) The `NtExpr` case should only match if
+        if let Some(expr) = self.eat_metavar_seq_with_matcher(
+            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
+            |this| {
+                // FIXME(nnethercote) The `expr` case should only match if
                 // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
                 // an `UnOp::Neg` and an `ExprKind::Lit`, like how
                 // `can_begin_literal_maybe_minus` works. But this method has
@@ -2178,13 +2239,14 @@ impl<'a> Parser<'a> {
                 // `ExprKind::Path` must be accepted when parsing range
                 // patterns. That requires some care. So for now, we continue
                 // being less strict here than we should be.
-                token::NtExpr(e) | token::NtLiteral(e) => {
-                    let e = e.clone();
-                    self.bump();
-                    return Ok(e);
-                }
-                _ => {}
-            };
+                this.parse_expr()
+            },
+        ) {
+            return Ok(expr);
+        } else if let Some(lit) =
+            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
+        {
+            return Ok(lit);
         }
 
         let lo = self.token.span;
@@ -2200,7 +2262,9 @@ impl<'a> Parser<'a> {
     }
 
     fn is_array_like_block(&mut self) -> bool {
-        self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
+        matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+            && self
+                .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
             && self.look_ahead(2, |t| t == &token::Comma)
             && self.look_ahead(3, |t| t.can_begin_expr())
     }
@@ -2212,9 +2276,9 @@ impl<'a> Parser<'a> {
         let mut snapshot = self.create_snapshot_for_diagnostic();
         match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
             Ok(arr) => {
-                let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces {
+                let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
                     span: arr.span,
-                    sub: errors::ArrayBracketsInsteadOfSpacesSugg {
+                    sub: errors::ArrayBracketsInsteadOfBracesSugg {
                         left: lo,
                         right: snapshot.prev_token.span,
                     },
@@ -2296,7 +2360,7 @@ impl<'a> Parser<'a> {
             });
         }
 
-        let (attrs, blk) = self.parse_block_common(lo, blk_mode, true, None)?;
+        let (attrs, blk) = self.parse_block_common(lo, blk_mode, None)?;
         Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
     }
 
@@ -2328,7 +2392,7 @@ impl<'a> Parser<'a> {
         let movability =
             if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable };
 
-        let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() {
+        let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() {
             self.parse_coroutine_kind(Case::Sensitive)
         } else {
             None
@@ -2337,7 +2401,8 @@ impl<'a> Parser<'a> {
         let capture_clause = self.parse_capture_clause()?;
         let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_token.span;
-        let mut body = match fn_decl.output {
+        let mut body = match &fn_decl.output {
+            // No return type.
             FnRetTy::Default(_) => {
                 let restrictions =
                     self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
@@ -2349,11 +2414,8 @@ impl<'a> Parser<'a> {
                     Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
                 }
             }
-            _ => {
-                // If an explicit return type is given, require a block to appear (RFC 968).
-                let body_lo = self.token.span;
-                self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
-            }
+            // Explicit return type (`->`) needs block `-> T { }`.
+            FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
         };
 
         match coroutine_kind {
@@ -2405,6 +2467,49 @@ impl<'a> Parser<'a> {
         Ok(closure)
     }
 
+    /// If an explicit return type is given, require a block to appear (RFC 968).
+    fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
+        if self.may_recover()
+            && self.token.can_begin_expr()
+            && !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
+            && !self.token.is_whole_block()
+        {
+            let snapshot = self.create_snapshot_for_diagnostic();
+            let restrictions =
+                self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
+            let tok = self.token.clone();
+            match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
+                Ok((expr, _)) => {
+                    let descr = super::token_descr(&tok);
+                    let mut diag = self
+                        .dcx()
+                        .struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
+                    diag.span_label(
+                        ret_span,
+                        "explicit return type requires closure body to be enclosed in braces",
+                    );
+                    diag.multipart_suggestion_verbose(
+                        "wrap the expression in curly braces",
+                        vec![
+                            (expr.span.shrink_to_lo(), "{ ".to_string()),
+                            (expr.span.shrink_to_hi(), " }".to_string()),
+                        ],
+                        Applicability::MachineApplicable,
+                    );
+                    diag.emit();
+                    return Ok(expr);
+                }
+                Err(diag) => {
+                    diag.cancel();
+                    self.restore_snapshot(snapshot);
+                }
+            }
+        }
+
+        let body_lo = self.token.span;
+        self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
+    }
+
     /// Parses an optional `move` or `use` prefix to a closure-like construct.
     fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
         if self.eat_keyword(exp!(Move)) {
@@ -2836,7 +2941,7 @@ impl<'a> Parser<'a> {
     /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
     fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
         let is_await =
-            self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));
+            self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));
 
         if is_await {
             self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
@@ -3426,7 +3531,7 @@ impl<'a> Parser<'a> {
         self.token.is_keyword(kw::Try)
             && self
                 .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
-            && self.token.uninterpolated_span().at_least_rust_2018()
+            && self.token_uninterpolated_span().at_least_rust_2018()
     }
 
     /// Parses an `async move? {...}` or `gen move? {...}` expression.
@@ -3474,19 +3579,9 @@ impl<'a> Parser<'a> {
     }
 
     fn is_certainly_not_a_block(&self) -> bool {
+        // `{ ident, ` and `{ ident: ` cannot start a block.
         self.look_ahead(1, |t| t.is_ident())
-            && (
-                // `{ ident, ` cannot start a block.
-                self.look_ahead(2, |t| t == &token::Comma)
-                    || self.look_ahead(2, |t| t == &token::Colon)
-                        && (
-                            // `{ ident: token, ` cannot start a block.
-                            self.look_ahead(4, |t| t == &token::Comma)
-                                // `{ ident: ` cannot start a block unless it's a type ascription
-                                // `ident: Type`.
-                                || self.look_ahead(3, |t| !t.can_begin_type())
-                        )
-            )
+            && self.look_ahead(2, |t| t == &token::Comma || t == &token::Colon)
     }
 
     fn maybe_parse_struct_expr(
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f4df4044dd2..9405b58ab3b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -34,10 +34,10 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
+    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         self.expect_keyword(exp!(Mod))?;
-        let id = self.parse_ident()?;
+        let ident = self.parse_ident()?;
         let mod_kind = if self.eat(exp!(Semi)) {
             ModKind::Unloaded
         } else {
@@ -46,7 +46,7 @@ impl<'a> Parser<'a> {
             attrs.extend(inner_attrs);
             ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
         };
-        Ok((id, ItemKind::Mod(safety, mod_kind)))
+        Ok(ItemKind::Mod(safety, ident, mod_kind))
     }
 
     /// Parses the contents of a module (inner attributes followed by module items).
@@ -115,8 +115,6 @@ impl<'a> Parser<'a> {
     }
 }
 
-pub(super) type ItemInfo = (Ident, ItemKind);
-
 impl<'a> Parser<'a> {
     pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
@@ -163,11 +161,11 @@ impl<'a> Parser<'a> {
                 fn_parse_mode,
                 Case::Sensitive,
             )?;
-            if let Some((ident, kind)) = kind {
+            if let Some(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 };
+                let item = Item { attrs, id, kind, vis, span, tokens: None };
                 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
             }
 
@@ -208,7 +206,7 @@ impl<'a> Parser<'a> {
         def: &mut Defaultness,
         fn_parse_mode: FnParseMode,
         case: Case,
-    ) -> PResult<'a, Option<ItemInfo>> {
+    ) -> PResult<'a, Option<ItemKind>> {
         let check_pub = def == &Defaultness::Final;
         let mut def_ = || mem::replace(def, Defaultness::Final);
 
@@ -218,17 +216,15 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             let (ident, sig, generics, contract, body) =
                 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
-            (
+            ItemKind::Fn(Box::new(Fn {
+                defaultness: def_(),
                 ident,
-                ItemKind::Fn(Box::new(Fn {
-                    defaultness: def_(),
-                    sig,
-                    generics,
-                    contract,
-                    body,
-                    define_opaque: None,
-                })),
-            )
+                sig,
+                generics,
+                contract,
+                body,
+                define_opaque: None,
+            }))
         } else if self.eat_keyword(exp!(Extern)) {
             if self.eat_keyword(exp!(Crate)) {
                 // EXTERN CRATE
@@ -247,8 +243,7 @@ impl<'a> Parser<'a> {
             // STATIC ITEM
             self.bump(); // `static`
             let mutability = self.parse_mutability();
-            let (ident, item) = self.parse_static_item(safety, mutability)?;
-            (ident, ItemKind::Static(Box::new(item)))
+            self.parse_static_item(safety, mutability)?
         } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
             // CONST ITEM
             if self.token.is_keyword(kw::Impl) {
@@ -258,15 +253,14 @@ impl<'a> Parser<'a> {
                 self.recover_const_mut(const_span);
                 self.recover_missing_kw_before_item()?;
                 let (ident, generics, ty, expr) = self.parse_const_item()?;
-                (
+                ItemKind::Const(Box::new(ConstItem {
+                    defaultness: def_(),
                     ident,
-                    ItemKind::Const(Box::new(ConstItem {
-                        defaultness: def_(),
-                        generics,
-                        ty,
-                        expr,
-                    })),
-                )
+                    generics,
+                    ty,
+                    expr,
+                    define_opaque: None,
+                }))
             }
         } else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() {
             // TRAIT ITEM
@@ -333,14 +327,14 @@ impl<'a> Parser<'a> {
                 self.recover_missing_kw_before_item()?;
             }
             // MACRO INVOCATION ITEM
-            (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?)))
+            ItemKind::MacCall(P(self.parse_item_macro(vis)?))
         } else {
             return Ok(None);
         };
         Ok(Some(info))
     }
 
-    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemInfo>> {
+    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
         let span = self.token.span;
         let token_name = super::token_descr(&self.token);
         let snapshot = self.create_snapshot_for_diagnostic();
@@ -358,7 +352,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
         let tree = self.parse_use_tree()?;
         if let Err(mut e) = self.expect_semi() {
             match tree.kind {
@@ -372,7 +366,7 @@ impl<'a> Parser<'a> {
             }
             return Err(e);
         }
-        Ok((Ident::empty(), ItemKind::Use(tree)))
+        Ok(ItemKind::Use(tree))
     }
 
     /// When parsing a statement, would the start of a path be an item?
@@ -482,7 +476,7 @@ impl<'a> Parser<'a> {
         if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
     }
 
-    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
+    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
         // To be expanded
         Ok(None)
     }
@@ -576,7 +570,7 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: &mut AttrVec,
         defaultness: Defaultness,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         self.expect_keyword(exp!(Impl))?;
 
@@ -597,7 +591,7 @@ impl<'a> Parser<'a> {
         }
 
         // Parse stray `impl async Trait`
-        if (self.token.uninterpolated_span().at_least_rust_2018()
+        if (self.token_uninterpolated_span().at_least_rust_2018()
             && self.token.is_keyword(kw::Async))
             || self.is_kw_followed_by_ident(kw::Async)
         {
@@ -686,7 +680,7 @@ impl<'a> Parser<'a> {
             }
             None => (None, ty_first), // impl Type
         };
-        let item_kind = ItemKind::Impl(Box::new(Impl {
+        Ok(ItemKind::Impl(Box::new(Impl {
             safety,
             polarity,
             defaultness,
@@ -695,12 +689,10 @@ impl<'a> Parser<'a> {
             of_trait,
             self_ty,
             items: impl_items,
-        }));
-
-        Ok((Ident::empty(), item_kind))
+        })))
     }
 
-    fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> {
         let span = self.token.span;
         self.expect_keyword(exp!(Reuse))?;
 
@@ -723,7 +715,7 @@ impl<'a> Parser<'a> {
             })
         };
 
-        let (ident, item_kind) = if self.eat_path_sep() {
+        let item_kind = if self.eat_path_sep() {
             let suffixes = if self.eat(exp!(Star)) {
                 None
             } else {
@@ -731,7 +723,7 @@ impl<'a> Parser<'a> {
                 Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0)
             };
             let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
-            (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
+            ItemKind::DelegationMac(Box::new(deleg))
         } else {
             let rename = rename(self)?;
             let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
@@ -739,17 +731,18 @@ impl<'a> Parser<'a> {
                 id: DUMMY_NODE_ID,
                 qself,
                 path,
+                ident,
                 rename,
                 body: body(self)?,
                 from_glob: false,
             };
-            (ident, ItemKind::Delegation(Box::new(deleg)))
+            ItemKind::Delegation(Box::new(deleg))
         };
 
         let span = span.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::fn_delegation, span);
 
-        Ok((ident, item_kind))
+        Ok(item_kind)
     }
 
     fn parse_item_list<T>(
@@ -884,7 +877,7 @@ impl<'a> Parser<'a> {
             && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
         {
             self.bump(); // `default`
-            Defaultness::Default(self.prev_token.uninterpolated_span())
+            Defaultness::Default(self.prev_token_uninterpolated_span())
         } else {
             Defaultness::Final
         }
@@ -899,7 +892,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(exp!(Auto)) {
@@ -940,15 +933,12 @@ impl<'a> Parser<'a> {
 
             self.psess.gated_spans.gate(sym::trait_alias, whole_span);
 
-            Ok((ident, ItemKind::TraitAlias(generics, bounds)))
+            Ok(ItemKind::TraitAlias(ident, generics, bounds))
         } else {
             // It's a normal trait.
             generics.where_clause = self.parse_where_clause()?;
             let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
-            Ok((
-                ident,
-                ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })),
-            ))
+            Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items })))
         }
     }
 
@@ -976,23 +966,32 @@ impl<'a> Parser<'a> {
         force_collect: ForceCollect,
     ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
-            |Item { attrs, id, span, vis, ident, kind, tokens }| {
+            |Item { attrs, id, span, vis, kind, tokens }| {
                 let kind = match AssocItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
-                        ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
+                        ItemKind::Static(box StaticItem {
+                            ident,
+                            ty,
+                            safety: _,
+                            mutability: _,
+                            expr,
+                            define_opaque,
+                        }) => {
                             self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
                             AssocItemKind::Const(Box::new(ConstItem {
                                 defaultness: Defaultness::Final,
+                                ident,
                                 generics: Generics::default(),
                                 ty,
                                 expr,
+                                define_opaque,
                             }))
                         }
                         _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+                Some(P(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1002,7 +1001,7 @@ impl<'a> Parser<'a> {
     /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ;
     /// ```
     /// The `"type"` has already been eaten.
-    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
+    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -1037,16 +1036,14 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((
+        Ok(ItemKind::TyAlias(Box::new(TyAlias {
+            defaultness,
             ident,
-            ItemKind::TyAlias(Box::new(TyAlias {
-                defaultness,
-                generics,
-                where_clauses,
-                bounds,
-                ty,
-            })),
-        ))
+            generics,
+            where_clauses,
+            bounds,
+            ty,
+        })))
     }
 
     /// Parses a `UseTree`.
@@ -1150,16 +1147,16 @@ impl<'a> Parser<'a> {
     /// extern crate foo;
     /// extern crate bar as foo;
     /// ```
-    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
         // Accept `extern crate name-like-this` for better diagnostics
-        let orig_name = self.parse_crate_name_with_dashes()?;
-        let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
-            (rename, Some(orig_name.name))
+        let orig_ident = self.parse_crate_name_with_dashes()?;
+        let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
+            (Some(orig_ident.name), rename)
         } else {
-            (orig_name, None)
+            (None, orig_ident)
         };
         self.expect_semi()?;
-        Ok((item_name, ItemKind::ExternCrate(orig_name)))
+        Ok(ItemKind::ExternCrate(orig_name, item_ident))
     }
 
     fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
@@ -1210,8 +1207,8 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: &mut AttrVec,
         mut safety: Safety,
-    ) -> PResult<'a, ItemInfo> {
-        let extern_span = self.prev_token.uninterpolated_span();
+    ) -> PResult<'a, ItemKind> {
+        let extern_span = self.prev_token_uninterpolated_span();
         let abi = self.parse_abi(); // ABI?
         // FIXME: This recovery should be tested better.
         if safety == Safety::Default
@@ -1222,13 +1219,12 @@ impl<'a> Parser<'a> {
             safety = Safety::Unsafe(self.token.span);
             let _ = self.eat_keyword(exp!(Unsafe));
         }
-        let module = ast::ForeignMod {
+        Ok(ItemKind::ForeignMod(ast::ForeignMod {
             extern_span,
             safety,
             abi,
             items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
-        };
-        Ok((Ident::empty(), ItemKind::ForeignMod(module)))
+        }))
     }
 
     /// Parses a foreign item (one in an `extern { ... }` block).
@@ -1238,11 +1234,11 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
-            |Item { attrs, id, span, vis, ident, kind, tokens }| {
+            |Item { attrs, id, span, vis, kind, tokens }| {
                 let kind = match ForeignItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
-                        ItemKind::Const(box ConstItem { ty, expr, .. }) => {
+                        ItemKind::Const(box ConstItem { ident, ty, expr, .. }) => {
                             let const_span = Some(span.with_hi(ident.span.lo()))
                                 .filter(|span| span.can_be_used_for_suggestions());
                             self.dcx().emit_err(errors::ExternItemCannotBeConst {
@@ -1250,16 +1246,18 @@ impl<'a> Parser<'a> {
                                 const_span,
                             });
                             ForeignItemKind::Static(Box::new(StaticItem {
+                                ident,
                                 ty,
                                 mutability: Mutability::Not,
                                 expr,
                                 safety: Safety::Default,
+                                define_opaque: None,
                             }))
                         }
                         _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+                Some(P(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1292,12 +1290,24 @@ impl<'a> Parser<'a> {
     }
 
     fn is_unsafe_foreign_mod(&self) -> bool {
-        self.token.is_keyword(kw::Unsafe)
-            && self.is_keyword_ahead(1, &[kw::Extern])
-            && self.look_ahead(
-                2 + self.look_ahead(2, |t| t.can_begin_string_literal() as usize),
-                |t| *t == token::OpenDelim(Delimiter::Brace),
-            )
+        // Look for `unsafe`.
+        if !self.token.is_keyword(kw::Unsafe) {
+            return false;
+        }
+        // Look for `extern`.
+        if !self.is_keyword_ahead(1, &[kw::Extern]) {
+            return false;
+        }
+
+        // Look for the optional ABI string literal.
+        let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 };
+
+        // Look for the `{`. Use `tree_look_ahead` because the ABI (if present)
+        // might be a metavariable i.e. an invisible-delimited sequence, and
+        // `tree_look_ahead` will consider that a single element when looking
+        // ahead.
+        self.tree_look_ahead(n, |t| matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _)))
+            == Some(true)
     }
 
     fn is_static_global(&mut self) -> bool {
@@ -1334,13 +1344,13 @@ impl<'a> Parser<'a> {
         const_span: Span,
         attrs: &mut AttrVec,
         defaultness: Defaultness,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         let impl_span = self.token.span;
         let err = self.expected_ident_found_err();
 
         // Only try to recover if this is implementing a trait for a type
-        let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
-            Ok(impl_info) => impl_info,
+        let mut item_kind = match self.parse_item_impl(attrs, defaultness) {
+            Ok(item_kind) => item_kind,
             Err(recovery_error) => {
                 // Recovery failed, raise the "expected identifier" error
                 recovery_error.cancel();
@@ -1348,7 +1358,7 @@ impl<'a> Parser<'a> {
             }
         };
 
-        match &mut impl_info.1 {
+        match &mut item_kind {
             ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => {
                 *constness = Const::Yes(const_span);
 
@@ -1365,10 +1375,11 @@ impl<'a> Parser<'a> {
             _ => unreachable!(),
         }
 
-        Ok(impl_info)
+        Ok(item_kind)
     }
 
-    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`.
+    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
+    /// `mutability`.
     ///
     /// ```ebnf
     /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
@@ -1377,7 +1388,7 @@ impl<'a> Parser<'a> {
         &mut self,
         safety: Safety,
         mutability: Mutability,
-    ) -> PResult<'a, (Ident, StaticItem)> {
+    ) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
 
         if self.token == TokenKind::Lt && self.may_recover() {
@@ -1389,7 +1400,8 @@ impl<'a> Parser<'a> {
         // FIXME: This could maybe benefit from `.may_recover()`?
         let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) {
             (true, false) => self.parse_ty()?,
-            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing type.
+            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing
+            // type.
             (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
         };
 
@@ -1397,7 +1409,8 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((ident, StaticItem { ty, safety, mutability, expr }))
+        let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
+        Ok(ItemKind::Static(Box::new(item)))
     }
 
     /// Parse a constant item with the prefix `"const"` already parsed.
@@ -1522,7 +1535,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an enum declaration.
-    fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
         if self.token.is_keyword(kw::Struct) {
             let span = self.prev_token.span.to(self.token.span);
             let err = errors::EnumStructMutuallyExclusive { span };
@@ -1535,7 +1548,7 @@ impl<'a> Parser<'a> {
         }
 
         let prev_span = self.prev_token.span;
-        let id = self.parse_ident()?;
+        let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
         generics.where_clause = self.parse_where_clause()?;
 
@@ -1546,10 +1559,10 @@ impl<'a> Parser<'a> {
             (thin_vec![], Trailing::No)
         } else {
             self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {
-                p.parse_enum_variant(id.span)
+                p.parse_enum_variant(ident.span)
             })
             .map_err(|mut err| {
-                err.span_label(id.span, "while parsing this enum");
+                err.span_label(ident.span, "while parsing this enum");
                 if self.token == token::Colon {
                     let snapshot = self.create_snapshot_for_diagnostic();
                     self.bump();
@@ -1575,7 +1588,7 @@ impl<'a> Parser<'a> {
         };
 
         let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
-        Ok((id, ItemKind::Enum(enum_definition, generics)))
+        Ok(ItemKind::Enum(ident, enum_definition, generics))
     }
 
     fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
@@ -1667,8 +1680,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `struct Foo { ... }`.
-    fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
-        let class_name = self.parse_ident()?;
+    fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
+        let ident = self.parse_ident()?;
 
         let mut generics = self.parse_generics()?;
 
@@ -1689,7 +1702,7 @@ impl<'a> Parser<'a> {
         let vdata = if self.token.is_keyword(kw::Where) {
             let tuple_struct_body;
             (generics.where_clause, tuple_struct_body) =
-                self.parse_struct_where_clause(class_name, generics.span)?;
+                self.parse_struct_where_clause(ident, generics.span)?;
 
             if let Some(body) = tuple_struct_body {
                 // If we see a misplaced tuple struct body: `struct Foo<T> where T: Copy, (T);`
@@ -1703,7 +1716,7 @@ impl<'a> Parser<'a> {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
                 let (fields, recovered) = self.parse_record_struct_body(
                     "struct",
-                    class_name.span,
+                    ident.span,
                     generics.where_clause.has_where_token,
                 )?;
                 VariantData::Struct { fields, recovered }
@@ -1715,7 +1728,7 @@ impl<'a> Parser<'a> {
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
             let (fields, recovered) = self.parse_record_struct_body(
                 "struct",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
@@ -1731,12 +1744,12 @@ impl<'a> Parser<'a> {
             return Err(self.dcx().create_err(err));
         };
 
-        Ok((class_name, ItemKind::Struct(vdata, generics)))
+        Ok(ItemKind::Struct(ident, vdata, generics))
     }
 
     /// Parses `union Foo { ... }`.
-    fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
-        let class_name = self.parse_ident()?;
+    fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
+        let ident = self.parse_ident()?;
 
         let mut generics = self.parse_generics()?;
 
@@ -1744,14 +1757,14 @@ impl<'a> Parser<'a> {
             generics.where_clause = self.parse_where_clause()?;
             let (fields, recovered) = self.parse_record_struct_body(
                 "union",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
             let (fields, recovered) = self.parse_record_struct_body(
                 "union",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
@@ -1763,7 +1776,7 @@ impl<'a> Parser<'a> {
             return Err(err);
         };
 
-        Ok((class_name, ItemKind::Union(vdata, generics)))
+        Ok(ItemKind::Union(ident, vdata, generics))
     }
 
     /// This function parses the fields of record structs:
@@ -2115,15 +2128,17 @@ impl<'a> Parser<'a> {
                 }
             } else if self.eat_keyword(exp!(Struct)) {
                 match self.parse_item_struct() {
-                    Ok((ident, _)) => self
-                        .dcx()
-                        .struct_span_err(
-                            lo.with_hi(ident.span.hi()),
-                            format!("structs are not allowed in {adt_ty} definitions"),
-                        )
-                        .with_help(
-                            "consider creating a new `struct` definition instead of nesting",
-                        ),
+                    Ok(item) => {
+                        let ItemKind::Struct(ident, ..) = item else { unreachable!() };
+                        self.dcx()
+                            .struct_span_err(
+                                lo.with_hi(ident.span.hi()),
+                                format!("structs are not allowed in {adt_ty} definitions"),
+                            )
+                            .with_help(
+                                "consider creating a new `struct` definition instead of nesting",
+                            )
+                    }
                     Err(err) => {
                         err.cancel();
                         self.restore_snapshot(snapshot);
@@ -2168,7 +2183,7 @@ impl<'a> Parser<'a> {
     /// MacParams = "(" TOKEN_STREAM ")" ;
     /// DeclMac = "macro" Ident MacParams? MacBody ;
     /// ```
-    fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
         let body = if self.check(exp!(OpenBrace)) {
             self.parse_delim_args()? // `MacBody`
@@ -2190,7 +2205,7 @@ impl<'a> Parser<'a> {
         };
 
         self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
+        Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: false }))
     }
 
     /// Is this a possibly malformed start of a `macro_rules! foo` item definition?
@@ -2219,7 +2234,7 @@ impl<'a> Parser<'a> {
         &mut self,
         vis: &Visibility,
         has_bang: bool,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         self.expect_keyword(exp!(MacroRules))?; // `macro_rules`
 
         if has_bang {
@@ -2237,7 +2252,7 @@ impl<'a> Parser<'a> {
         self.eat_semi_for_macro_if_needed(&body);
         self.complain_if_pub_macro(vis, true);
 
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true })))
+        Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: true }))
     }
 
     /// Item macro invocations or `macro_rules!` definitions need inherited visibility.
@@ -2529,7 +2544,7 @@ impl<'a> Parser<'a> {
             *sig_hi = self.prev_token.span;
             (AttrVec::new(), None)
         } else if self.check(exp!(OpenBrace)) || self.token.is_whole_block() {
-            self.parse_block_common(self.token.span, BlockCheckMode::Default, false, None)
+            self.parse_block_common(self.token.span, BlockCheckMode::Default, None)
                 .map(|(attrs, body)| (attrs, Some(body)))?
         } else if self.token == token::Eq {
             // Recover `fn foo() = $expr;`.
@@ -2601,13 +2616,36 @@ impl<'a> Parser<'a> {
                 })
             // `extern ABI fn`
             || self.check_keyword_case(exp!(Extern), case)
+                // Use `tree_look_ahead` because `ABI` might be a metavariable,
+                // i.e. an invisible-delimited sequence, and `tree_look_ahead`
+                // will consider that a single element when looking ahead.
                 && self.look_ahead(1, |t| t.can_begin_string_literal())
-                && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
+                && (self.tree_look_ahead(2, |tt| {
+                    match tt {
+                        TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
+                        TokenTree::Delimited(..) => false,
+                    }
+                }) == Some(true) ||
                     // This branch is only for better diagnostics; `pub`, `unsafe`, etc. are not
                     // allowed here.
                     (self.may_recover()
-                        && self.look_ahead(2, |t| ALL_QUALS.iter().any(|exp| t.is_keyword(exp.kw)))
-                        && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
+                        && self.tree_look_ahead(2, |tt| {
+                            match tt {
+                                TokenTree::Token(t, _) =>
+                                    ALL_QUALS.iter().any(|exp| {
+                                        t.is_keyword(exp.kw)
+                                    }),
+                                TokenTree::Delimited(..) => false,
+                            }
+                        }) == Some(true)
+                        && self.tree_look_ahead(3, |tt| {
+                            match tt {
+                                TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
+                                TokenTree::Delimited(..) => false,
+                            }
+                        }) == Some(true)
+                    )
+                )
     }
 
     /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
@@ -2743,7 +2781,7 @@ impl<'a> Parser<'a> {
                             .expect("Span extracted directly from keyword should always work");
 
                         err.span_suggestion(
-                            self.token.uninterpolated_span(),
+                            self.token_uninterpolated_span(),
                             format!("`{original_kw}` already used earlier, remove this one"),
                             "",
                             Applicability::MachineApplicable,
@@ -2754,7 +2792,7 @@ impl<'a> Parser<'a> {
                     else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
                         let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
                         if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
-                            let misplaced_qual_sp = self.token.uninterpolated_span();
+                            let misplaced_qual_sp = self.token_uninterpolated_span();
                             let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
 
                             err.span_suggestion(
@@ -2871,7 +2909,7 @@ impl<'a> Parser<'a> {
                 // Skip every token until next possible arg or end.
                 p.eat_to_tokens(&[exp!(Comma), exp!(CloseParen)]);
                 // Create a placeholder argument for proper arg count (issue #34264).
-                Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)), guar))
+                Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
             });
             // ...now that we've parsed the first argument, `self` is no longer allowed.
             first_param = false;
@@ -2922,13 +2960,30 @@ impl<'a> Parser<'a> {
                 let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
                 this.eat_incorrect_doc_comment_for_param_type();
                 let mut ty = this.parse_ty_for_param();
-                if ty.is_ok()
-                    && this.token != token::Comma
-                    && this.token != token::CloseDelim(Delimiter::Parenthesis)
-                {
-                    // This wasn't actually a type, but a pattern looking like a type,
-                    // so we are going to rollback and re-parse for recovery.
-                    ty = this.unexpected_any();
+
+                if let Ok(t) = &ty {
+                    // Check for trailing angle brackets
+                    if let TyKind::Path(_, Path { segments, .. }) = &t.kind {
+                        if let Some(segment) = segments.last() {
+                            if let Some(guar) =
+                                this.check_trailing_angle_brackets(segment, &[exp!(CloseParen)])
+                            {
+                                return Ok((
+                                    dummy_arg(segment.ident, guar),
+                                    Trailing::No,
+                                    UsePreAttrPos::No,
+                                ));
+                            }
+                        }
+                    }
+
+                    if this.token != token::Comma
+                        && this.token != token::CloseDelim(Delimiter::Parenthesis)
+                    {
+                        // This wasn't actually a type, but a pattern looking like a type,
+                        // so we are going to rollback and re-parse for recovery.
+                        ty = this.unexpected_any();
+                    }
                 }
                 match ty {
                     Ok(ty) => {
@@ -2939,6 +2994,7 @@ impl<'a> Parser<'a> {
                     }
                     // If this is a C-variadic argument and we hit an error, return the error.
                     Err(err) if this.token == token::DotDotDot => return Err(err),
+                    Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
                     // Recover from attempting to parse the argument as a type without pattern.
                     Err(err) => {
                         err.cancel();
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index a79b4048288..392a1c1057a 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -24,8 +24,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use path::PathStyle;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{
-    self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token,
-    TokenKind,
+    self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind,
+    Token, TokenKind,
 };
 use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
@@ -101,6 +101,7 @@ pub enum ForceCollect {
 #[macro_export]
 macro_rules! maybe_whole {
     ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
+        #[allow(irrefutable_let_patterns)] // FIXME: temporary
         if let token::Interpolated(nt) = &$p.token.kind
             && let token::$constructor(x) = &**nt
         {
@@ -299,6 +300,10 @@ impl TokenTreeCursor {
         self.stream.get(self.index)
     }
 
+    fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
+        self.stream.get(self.index + n)
+    }
+
     #[inline]
     fn bump(&mut self) {
         self.index += 1;
@@ -1290,6 +1295,17 @@ impl<'a> Parser<'a> {
         looker(&token)
     }
 
+    /// Like `lookahead`, but skips over token trees rather than tokens. Useful
+    /// when looking past possible metavariable pasting sites.
+    pub fn tree_look_ahead<R>(
+        &self,
+        dist: usize,
+        looker: impl FnOnce(&TokenTree) -> R,
+    ) -> Option<R> {
+        assert_ne!(dist, 0);
+        self.token_cursor.curr.look_ahead(dist - 1).map(looker)
+    }
+
     /// Returns whether any of the given keywords are `dist` tokens ahead of the current one.
     pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool {
         self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw)))
@@ -1297,14 +1313,14 @@ impl<'a> Parser<'a> {
 
     /// Parses asyncness: `async` or nothing.
     fn parse_coroutine_kind(&mut self, case: Case) -> Option<CoroutineKind> {
-        let span = self.token.uninterpolated_span();
+        let span = self.token_uninterpolated_span();
         if self.eat_keyword_case(exp!(Async), case) {
             // FIXME(gen_blocks): Do we want to unconditionally parse `gen` and then
             // error if edition <= 2024, like we do with async and edition <= 2018?
-            if self.token.uninterpolated_span().at_least_rust_2024()
+            if self.token_uninterpolated_span().at_least_rust_2024()
                 && self.eat_keyword_case(exp!(Gen), case)
             {
-                let gen_span = self.prev_token.uninterpolated_span();
+                let gen_span = self.prev_token_uninterpolated_span();
                 Some(CoroutineKind::AsyncGen {
                     span: span.to(gen_span),
                     closure_id: DUMMY_NODE_ID,
@@ -1317,7 +1333,7 @@ impl<'a> Parser<'a> {
                     return_impl_trait_id: DUMMY_NODE_ID,
                 })
             }
-        } else if self.token.uninterpolated_span().at_least_rust_2024()
+        } else if self.token_uninterpolated_span().at_least_rust_2024()
             && self.eat_keyword_case(exp!(Gen), case)
         {
             Some(CoroutineKind::Gen {
@@ -1333,9 +1349,9 @@ impl<'a> Parser<'a> {
     /// Parses fn unsafety: `unsafe`, `safe` or nothing.
     fn parse_safety(&mut self, case: Case) -> Safety {
         if self.eat_keyword_case(exp!(Unsafe), case) {
-            Safety::Unsafe(self.prev_token.uninterpolated_span())
+            Safety::Unsafe(self.prev_token_uninterpolated_span())
         } else if self.eat_keyword_case(exp!(Safe), case) {
-            Safety::Safe(self.prev_token.uninterpolated_span())
+            Safety::Safe(self.prev_token_uninterpolated_span())
         } else {
             Safety::Default
         }
@@ -1362,7 +1378,7 @@ impl<'a> Parser<'a> {
                 .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
             && self.eat_keyword_case(exp!(Const), case)
         {
-            Const::Yes(self.prev_token.uninterpolated_span())
+            Const::Yes(self.prev_token_uninterpolated_span())
         } else {
             Const::No
         }
@@ -1370,9 +1386,6 @@ impl<'a> Parser<'a> {
 
     /// Parses inline const expressions.
     fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
-        if pat {
-            self.psess.gated_spans.gate(sym::inline_const_pat, span);
-        }
         self.expect_keyword(exp!(Const))?;
         let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
         let anon_const = AnonConst {
@@ -1380,7 +1393,17 @@ impl<'a> Parser<'a> {
             value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
         };
         let blk_span = anon_const.value.span;
-        Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
+        let kind = if pat {
+            let guar = self
+                .dcx()
+                .struct_span_err(blk_span, "`inline_const_pat` has been removed")
+                .with_help("use a named `const`-item or an `if`-guard instead")
+                .emit();
+            ExprKind::Err(guar)
+        } else {
+            ExprKind::ConstBlock(anon_const)
+        };
+        Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs))
     }
 
     /// Parses mutability (`mut` or nothing).
@@ -1699,6 +1722,35 @@ impl<'a> Parser<'a> {
     pub fn approx_token_stream_pos(&self) -> u32 {
         self.num_bump_calls
     }
+
+    /// For interpolated `self.token`, returns a span of the fragment to which
+    /// the interpolated token refers. For all other tokens this is just a
+    /// regular span. It is particularly important to use this for identifiers
+    /// and lifetimes for which spans affect name resolution and edition
+    /// checks. Note that keywords are also identifiers, so they should use
+    /// this if they keep spans or perform edition checks.
+    pub fn token_uninterpolated_span(&self) -> Span {
+        match &self.token.kind {
+            token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
+            token::Interpolated(nt) => nt.use_span(),
+            token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
+                self.look_ahead(1, |t| t.span)
+            }
+            _ => self.token.span,
+        }
+    }
+
+    /// Like `token_uninterpolated_span`, but works on `self.prev_token`.
+    pub fn prev_token_uninterpolated_span(&self) -> Span {
+        match &self.prev_token.kind {
+            token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
+            token::Interpolated(nt) => nt.use_span(),
+            token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
+                self.look_ahead(0, |t| t.span)
+            }
+            _ => self.prev_token.span,
+        }
+    }
 }
 
 pub(crate) fn make_unclosed_delims_error(
@@ -1751,6 +1803,8 @@ pub enum ParseNtResult {
     Item(P<ast::Item>),
     Stmt(P<ast::Stmt>),
     Pat(P<ast::Pat>, NtPatKind),
+    Expr(P<ast::Expr>, NtExprKind),
+    Literal(P<ast::Expr>),
     Ty(P<ast::Ty>),
     Meta(P<ast::AttrItem>),
     Path(P<ast::Path>),
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 1123755ce00..b4e540d670d 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -48,10 +48,6 @@ impl<'a> Parser<'a> {
         /// Old variant of `may_be_ident`. Being phased out.
         fn nt_may_be_ident(nt: &Nonterminal) -> bool {
             match nt {
-                NtExpr(_)
-                | NtLiteral(_) // `true`, `false`
-                => true,
-
                 NtBlock(_) => false,
             }
         }
@@ -95,7 +91,7 @@ impl<'a> Parser<'a> {
                 token::OpenDelim(Delimiter::Brace) => true,
                 token::NtLifetime(..) => true,
                 token::Interpolated(nt) => match &**nt {
-                    NtBlock(_) | NtExpr(_) | NtLiteral(_) => true,
+                    NtBlock(_) => true,
                 },
                 token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
                     MetaVarKind::Block
@@ -179,10 +175,14 @@ impl<'a> Parser<'a> {
                     pat_kind,
                 ));
             }
-            NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?),
+            NonterminalKind::Expr(expr_kind) => {
+                return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind));
+            }
             NonterminalKind::Literal => {
-                // The `:literal` matcher does not support attributes
-                NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
+                // The `:literal` matcher does not support attributes.
+                return Ok(ParseNtResult::Literal(
+                    self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
+                ));
             }
             NonterminalKind::Ty => {
                 return Ok(ParseNtResult::Ty(
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index ec14c5718da..9612f71b2af 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -631,15 +631,6 @@ impl<'a> Parser<'a> {
                             ident,
                             indentation,
                         });
-
-                        // help: wrap the expr in a `const { expr }`
-                        // FIXME(inline_const_pat): once stabilized, remove this check and remove the `(requires #[feature(inline_const_pat)])` note from the message
-                        if self.parser.psess.unstable_features.is_nightly_build() {
-                            err.subdiagnostic(UnexpectedExpressionInPatternSugg::InlineConst {
-                                start_span: expr_span.shrink_to_lo(),
-                                end_span: expr_span.shrink_to_hi(),
-                            });
-                        }
                     },
                 );
             }
@@ -1261,7 +1252,7 @@ impl<'a> Parser<'a> {
                 || *t == token::Dot // e.g. `.5` for recovery;
                 || matches!(t.kind, token::Literal(..) | token::Minus)
                 || t.is_bool_lit()
-                || t.is_whole_expr()
+                || t.is_metavar_expr()
                 || t.is_lifetime() // recover `'a` instead of `'a'`
                 || (self.may_recover() // recover leading `(`
                     && *t == token::OpenDelim(Delimiter::Parenthesis)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 0fe247078d5..97cd4d2117f 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -668,7 +668,7 @@ impl<'a> Parser<'a> {
         &mut self,
         loop_header: Option<Span>,
     ) -> PResult<'a, (AttrVec, P<Block>)> {
-        self.parse_block_common(self.token.span, BlockCheckMode::Default, true, loop_header)
+        self.parse_block_common(self.token.span, BlockCheckMode::Default, loop_header)
     }
 
     /// Parses a block. Inner attributes are allowed, block labels are not.
@@ -679,7 +679,6 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         blk_mode: BlockCheckMode,
-        can_be_struct_literal: bool,
         loop_header: Option<Span>,
     ) -> PResult<'a, (AttrVec, P<Block>)> {
         maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block));
@@ -691,12 +690,7 @@ impl<'a> Parser<'a> {
         }
 
         let attrs = self.parse_inner_attributes()?;
-        let tail = match self.maybe_suggest_struct_literal(
-            lo,
-            blk_mode,
-            maybe_ident,
-            can_be_struct_literal,
-        ) {
+        let tail = match self.maybe_suggest_struct_literal(lo, blk_mode, maybe_ident) {
             Some(tail) => tail?,
             None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
         };
@@ -1043,14 +1037,7 @@ impl<'a> Parser<'a> {
         rules: BlockCheckMode,
         span: Span,
     ) -> P<Block> {
-        P(Block {
-            stmts,
-            id: DUMMY_NODE_ID,
-            rules,
-            span,
-            tokens: None,
-            could_be_bare_literal: false,
-        })
+        P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
     }
 
     pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 471966d086d..49ae6cb9b72 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2922,7 +2922,7 @@ fn out_of_line_mod() {
         .unwrap()
         .unwrap();
 
-        let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
+        let ast::ItemKind::Mod(_, _, mod_kind) = &item.kind else { panic!() };
         assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2);
     });
 }
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index b45ebae079c..93705da22c4 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -775,7 +775,7 @@ impl<'a> Parser<'a> {
     /// Is a `dyn B0 + ... + Bn` type allowed here?
     fn is_explicit_dyn_type(&mut self) -> bool {
         self.check_keyword(exp!(Dyn))
-            && (self.token.uninterpolated_span().at_least_rust_2018()
+            && (self.token_uninterpolated_span().at_least_rust_2018()
                 || self.look_ahead(1, |t| {
                     (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
                         && !can_continue_type_after_non_fn_ident(t)
@@ -998,13 +998,13 @@ impl<'a> Parser<'a> {
             BoundConstness::Never
         };
 
-        let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
+        let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
             && self.eat_keyword(exp!(Async))
         {
             self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else if self.may_recover()
-            && self.token.uninterpolated_span().is_rust_2015()
+            && self.token_uninterpolated_span().is_rust_2015()
             && self.is_kw_followed_by_ident(kw::Async)
         {
             self.bump(); // eat `async`
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 9ecde2a9eb5..6bbd650dcdf 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -16,7 +16,8 @@ use rustc_span::{Span, Symbol, sym};
 use crate::{errors, parse_in};
 
 pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
-    if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) {
+    if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
+    {
         return;
     }
 
@@ -215,11 +216,7 @@ pub fn check_builtin_meta_item(
     template: AttributeTemplate,
     deny_unsafety: bool,
 ) {
-    // Some special attributes like `cfg` must be checked
-    // before the generic check, so we skip them here.
-    let should_skip = |name| name == sym::cfg;
-
-    if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
+    if !is_attr_template_compatible(&template, &meta.kind) {
         emit_malformed_attribute(psess, style, meta.span, name, template);
     }
 
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index d6c3bd9877c..289e062fb5e 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -8,5 +8,7 @@ edition = "2024"
 rustc_lexer = { path = "../rustc_lexer" }
 # tidy-alphabetical-end
 
-[target.'cfg(target_pointer_width = "64")'.dependencies]
+[target.'cfg(target_pointer_width = "64")'.dev-dependencies]
+# tidy-alphabetical-start
 rustc_index = { path = "../rustc_index", default-features = false }
+# tidy-alphabetical-end
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 5b8a2fe52d3..97931742985 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -1105,7 +1105,7 @@ fn unescape_string(string: &str) -> Option<String> {
 }
 
 // Assert a reasonable size for `Piece`
-#[cfg(target_pointer_width = "64")]
+#[cfg(all(test, target_pointer_width = "64"))]
 rustc_index::static_assert_size!(Piece<'_>, 16);
 
 #[cfg(test)]
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index ed498d9d344..bea86801ed7 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -383,6 +383,10 @@ passes_inline_ignored_constants =
     .warn = {-passes_previously_accepted}
     .note = {-passes_see_issue(issue: "65833")}
 
+passes_inline_ignored_for_exported =
+    `#[inline]` is ignored on externally exported functions
+    .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
 passes_inline_ignored_function_prototype =
     `#[inline]` is ignored on function prototypes
 
@@ -811,8 +815,8 @@ passes_unused_duplicate =
 passes_unused_empty_lints_note =
     attribute `{$name}` with an empty list has no effect
 
-passes_unused_linker_warnings_note =
-    the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked
+passes_unused_linker_messages_note =
+    the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked
 
 passes_unused_multiple =
     multiple `{$name}` attributes
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e0739c342df..669349f3380 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{
     UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
 };
 use rustc_session::parse::feature_err;
-use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             | sym::forbid
                             | sym::cfg
                             | sym::cfg_attr
+                            | sym::cfg_trace
                             | sym::cfg_attr_trace
                             // need to be fixed
                             | sym::cfi_encoding // FIXME(cfi_encoding)
@@ -450,6 +451,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 });
             }
         }
+
+        // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported.
+        if let Some(did) = hir_id.as_owner()
+            && self.tcx.def_kind(did).has_codegen_attrs()
+            && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never))
+        {
+            let attrs = self.tcx.codegen_fn_attrs(did);
+            // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
+            if attrs.contains_extern_indicator() {
+                self.tcx.emit_node_span_lint(
+                    UNUSED_ATTRIBUTES,
+                    hir_id,
+                    attr.span(),
+                    errors::InlineIgnoredForExported {},
+                );
+            }
+        }
     }
 
     /// Checks that `#[coverage(..)]` is applied to a function/closure/method,
@@ -574,8 +592,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
         const ALLOW_LIST: &[rustc_span::Symbol] = &[
             // conditional compilation
-            sym::cfg,
-            sym::cfg_attr,
+            sym::cfg_trace,
             sym::cfg_attr_trace,
             // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
             sym::test,
@@ -600,7 +617,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             sym::repr,
             // code generation
             sym::cold,
-            sym::target_feature,
             // documentation
             sym::doc,
         ];
@@ -626,6 +642,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         _ => {}
                     }
 
+                    if other_attr.has_name(sym::target_feature) {
+                        if !self.tcx.features().naked_functions_target_feature() {
+                            feature_err(
+                                &self.tcx.sess,
+                                sym::naked_functions_target_feature,
+                                other_attr.span(),
+                                "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions",
+                            ).emit();
+
+                            return;
+                        } else {
+                            continue;
+                        }
+                    }
+
                     if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
                         self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
                             span: other_attr.span(),
@@ -1007,14 +1038,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
             // can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
             // `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`.
-            s <= kw::Union || s == sym::SelfTy
+            s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy
         }
 
-        let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
-        if doc_keyword == kw::Empty {
-            self.doc_attr_str_error(meta, "keyword");
-            return;
-        }
+        let doc_keyword = match meta.value_str() {
+            Some(value) if value != kw::Empty => value,
+            _ => return self.doc_attr_str_error(meta, "keyword"),
+        };
+
         let item_kind = match self.tcx.hir_node(hir_id) {
             hir::Node::Item(item) => Some(&item.kind),
             _ => None,
@@ -1126,7 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     errors::DocInlineOnlyUse {
                         attr_span: meta.span(),
                         item_span: (attr.style() == AttrStyle::Outer)
-                            .then(|| self.tcx.hir().span(hir_id)),
+                            .then(|| self.tcx.hir_span(hir_id)),
                     },
                 );
             }
@@ -1148,7 +1179,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 errors::DocMaskedOnlyExternCrate {
                     attr_span: meta.span(),
                     item_span: (attr.style() == AttrStyle::Outer)
-                        .then(|| self.tcx.hir().span(hir_id)),
+                        .then(|| self.tcx.hir_span(hir_id)),
                 },
             );
             return;
@@ -1162,7 +1193,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 errors::DocMaskedNotExternCrateSelf {
                     attr_span: meta.span(),
                     item_span: (attr.style() == AttrStyle::Outer)
-                        .then(|| self.tcx.hir().span(hir_id)),
+                        .then(|| self.tcx.hir_span(hir_id)),
                 },
             );
         }
@@ -2388,7 +2419,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     .iter()
                     .all(|kind| matches!(kind, CrateType::Rlib | CrateType::Staticlib));
                 if never_needs_link {
-                    errors::UnusedNote::LinkerWarningsBinaryCrateOnly
+                    errors::UnusedNote::LinkerMessagesBinaryCrateOnly
                 } else {
                     return;
                 }
@@ -2642,7 +2673,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
         // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
         // in where clauses. After that, only `self.check_attributes` should be enough.
-        const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace];
+        const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg_trace, sym::cfg_attr_trace];
         let spans = self
             .tcx
             .hir_attrs(where_predicate.hir_id)
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index f77e1db42d4..b62d94d65f1 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -421,10 +421,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                 }
                 hir::ItemKind::ForeignMod { .. } => {}
                 hir::ItemKind::Trait(..) => {
-                    for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
-                        if let Some(local_def_id) = impl_def_id.as_local()
-                            && let ItemKind::Impl(impl_ref) =
-                                self.tcx.hir_expect_item(local_def_id).kind
+                    for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) {
+                        if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind
                         {
                             // skip items
                             // mark dependent traits live
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index e13d94c1031..17a729f422a 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -41,8 +41,8 @@ fn report_duplicate_item(
     original_def_id: DefId,
     item_def_id: DefId,
 ) {
-    let orig_span = tcx.hir().span_if_local(original_def_id);
-    let duplicate_span = tcx.hir().span_if_local(item_def_id);
+    let orig_span = tcx.hir_span_if_local(original_def_id);
+    let duplicate_span = tcx.hir_span_if_local(item_def_id);
     tcx.dcx().emit_err(DuplicateDiagnosticItemInCrate {
         duplicate_span,
         orig_span,
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index d2729876ebb..2a435c4b2e0 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -24,7 +24,7 @@ struct EntryContext<'tcx> {
 }
 
 fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
-    let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable);
+    let any_exe = tcx.crate_types().contains(&CrateType::Executable);
     if !any_exe {
         // No need to find a main function.
         return None;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index b8359c27e53..4e3e0324205 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -770,8 +770,8 @@ pub(crate) enum UnusedNote {
     NoLints { name: Symbol },
     #[note(passes_unused_default_method_body_const_note)]
     DefaultMethodBodyConst,
-    #[note(passes_unused_linker_warnings_note)]
-    LinkerWarningsBinaryCrateOnly,
+    #[note(passes_unused_linker_messages_note)]
+    LinkerMessagesBinaryCrateOnly,
 }
 
 #[derive(LintDiagnostic)]
@@ -1348,12 +1348,12 @@ pub(crate) struct DuplicateLangItem {
     pub local_span: Option<Span>,
     pub lang_item_name: Symbol,
     pub crate_name: Symbol,
-    pub dependency_of: Symbol,
+    pub dependency_of: Option<Symbol>,
     pub is_local: bool,
     pub path: String,
     pub first_defined_span: Option<Span>,
-    pub orig_crate_name: Symbol,
-    pub orig_dependency_of: Symbol,
+    pub orig_crate_name: Option<Symbol>,
+    pub orig_dependency_of: Option<Symbol>,
     pub orig_is_local: bool,
     pub orig_path: String,
     pub(crate) duplicate: Duplicate,
@@ -1374,10 +1374,16 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
         diag.code(E0152);
         diag.arg("lang_item_name", self.lang_item_name);
         diag.arg("crate_name", self.crate_name);
-        diag.arg("dependency_of", self.dependency_of);
+        if let Some(dependency_of) = self.dependency_of {
+            diag.arg("dependency_of", dependency_of);
+        }
         diag.arg("path", self.path);
-        diag.arg("orig_crate_name", self.orig_crate_name);
-        diag.arg("orig_dependency_of", self.orig_dependency_of);
+        if let Some(orig_crate_name) = self.orig_crate_name {
+            diag.arg("orig_crate_name", orig_crate_name);
+        }
+        if let Some(orig_dependency_of) = self.orig_dependency_of {
+            diag.arg("orig_dependency_of", orig_dependency_of);
+        }
         diag.arg("orig_path", self.orig_path);
         if let Some(span) = self.local_span {
             diag.span(span);
@@ -1385,7 +1391,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
         if let Some(span) = self.first_defined_span {
             diag.span_note(span, fluent::passes_first_defined_span);
         } else {
-            if self.orig_dependency_of.is_empty() {
+            if self.orig_dependency_of.is_none() {
                 diag.note(fluent::passes_first_defined_crate);
             } else {
                 diag.note(fluent::passes_first_defined_crate_depends);
@@ -1435,6 +1441,11 @@ pub(crate) struct OnlyHasEffectOn {
     pub target_name: String,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(passes_inline_ignored_for_exported)]
+#[help]
+pub(crate) struct InlineIgnoredForExported {}
+
 #[derive(Diagnostic)]
 #[diag(passes_object_lifetime_err)]
 pub(crate) struct ObjectLifetimeErr {
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index fe1140d893e..664bd4ad0a2 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -16,7 +16,7 @@ use rustc_hir::{LangItem, LanguageItems, MethodKind, Target};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_session::cstore::ExternCrate;
-use rustc_span::{Span, kw};
+use rustc_span::Span;
 
 use crate::errors::{
     DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
@@ -98,7 +98,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
         {
             let lang_item_name = lang_item.name();
             let crate_name = self.tcx.crate_name(item_def_id.krate);
-            let mut dependency_of = kw::Empty;
+            let mut dependency_of = None;
             let is_local = item_def_id.is_local();
             let path = if is_local {
                 String::new()
@@ -112,8 +112,8 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
             };
 
             let first_defined_span = self.item_spans.get(&original_def_id).copied();
-            let mut orig_crate_name = kw::Empty;
-            let mut orig_dependency_of = kw::Empty;
+            let mut orig_crate_name = None;
+            let mut orig_dependency_of = None;
             let orig_is_local = original_def_id.is_local();
             let orig_path = if orig_is_local {
                 String::new()
@@ -127,11 +127,11 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
             };
 
             if first_defined_span.is_none() {
-                orig_crate_name = self.tcx.crate_name(original_def_id.krate);
+                orig_crate_name = Some(self.tcx.crate_name(original_def_id.krate));
                 if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) =
                     self.tcx.extern_crate(original_def_id.krate)
                 {
-                    orig_dependency_of = self.tcx.crate_name(*inner_dependency_of);
+                    orig_dependency_of = Some(self.tcx.crate_name(*inner_dependency_of));
                 }
             }
 
@@ -140,7 +140,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
             } else {
                 match self.tcx.extern_crate(item_def_id.krate) {
                     Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => {
-                        dependency_of = self.tcx.crate_name(*inner_dependency_of);
+                        dependency_of = Some(self.tcx.crate_name(*inner_dependency_of));
                         Duplicate::CrateDepends
                     }
                     _ => Duplicate::Crate,
@@ -268,22 +268,22 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
 impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
     fn visit_item(&mut self, i: &'ast ast::Item) {
         let target = match &i.kind {
-            ast::ItemKind::ExternCrate(_) => Target::ExternCrate,
+            ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
             ast::ItemKind::Use(_) => Target::Use,
             ast::ItemKind::Static(_) => Target::Static,
             ast::ItemKind::Const(_) => Target::Const,
             ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
-            ast::ItemKind::Mod(_, _) => Target::Mod,
+            ast::ItemKind::Mod(..) => Target::Mod,
             ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
             ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
             ast::ItemKind::TyAlias(_) => Target::TyAlias,
-            ast::ItemKind::Enum(_, _) => Target::Enum,
-            ast::ItemKind::Struct(_, _) => Target::Struct,
-            ast::ItemKind::Union(_, _) => Target::Union,
+            ast::ItemKind::Enum(..) => Target::Enum,
+            ast::ItemKind::Struct(..) => Target::Struct,
+            ast::ItemKind::Union(..) => Target::Union,
             ast::ItemKind::Trait(_) => Target::Trait,
-            ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
+            ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
             ast::ItemKind::Impl(_) => Target::Impl,
-            ast::ItemKind::MacroDef(_) => Target::MacroDef,
+            ast::ItemKind::MacroDef(..) => Target::MacroDef,
             ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
                 unreachable!("macros should have been expanded")
             }
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9e55914f8f2..6dec96f9f50 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -726,7 +726,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
 
         annotator.annotate(
             CRATE_DEF_ID,
-            tcx.hir().span(CRATE_HIR_ID),
+            tcx.hir_span(CRATE_HIR_ID),
             None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
@@ -1099,7 +1099,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if is_staged_api {
         let effective_visibilities = &tcx.effective_visibilities(());
         let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
-        missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
+        missing.check_missing_stability(CRATE_DEF_ID, tcx.hir_span(CRATE_HIR_ID));
         tcx.hir_walk_toplevel_module(&mut missing);
         tcx.hir_visit_all_item_likes_in_crate(&mut missing);
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index ed00d97c31d..643b82f4753 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -72,7 +72,9 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
 pub trait DefIdVisitor<'tcx> {
     type Result: VisitorResult = ();
     const SHALLOW: bool = false;
-    const SKIP_ASSOC_TYS: bool = false;
+    fn skip_assoc_tys(&self) -> bool {
+        false
+    }
 
     fn tcx(&self) -> TyCtxt<'tcx>;
     fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
@@ -213,7 +215,7 @@ where
                 }
             }
             ty::Alias(kind @ (ty::Inherent | ty::Weak | ty::Projection), data) => {
-                if V::SKIP_ASSOC_TYS {
+                if self.def_id_visitor.skip_assoc_tys() {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `Type::Alias`
                     // as visible/reachable even if `Type` is private.
@@ -324,7 +326,9 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
     for FindMin<'a, 'tcx, VL, SHALLOW>
 {
     const SHALLOW: bool = SHALLOW;
-    const SKIP_ASSOC_TYS: bool = true;
+    fn skip_assoc_tys(&self) -> bool {
+        true
+    }
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -342,7 +346,7 @@ trait VisibilityLike: Sized {
         def_id: LocalDefId,
     ) -> Self;
 
-    // Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to
+    // Returns an over-approximation (`skip_assoc_tys()` = true) of visibility due to
     // associated types for which we can't determine visibility precisely.
     fn of_impl<const SHALLOW: bool>(
         def_id: LocalDefId,
@@ -1352,6 +1356,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
     required_effective_vis: Option<EffectiveVisibility>,
     in_assoc_ty: bool,
     in_primary_interface: bool,
+    skip_assoc_tys: bool,
 }
 
 impl SearchInterfaceForPrivateItemsVisitor<'_> {
@@ -1398,6 +1403,14 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
         self
     }
 
+    fn trait_ref(&mut self) -> &mut Self {
+        self.in_primary_interface = true;
+        if let Some(trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) {
+            let _ = self.visit_trait(trait_ref.instantiate_identity());
+        }
+        self
+    }
+
     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
         if self.leaks_private_dep(def_id) {
             self.tcx.emit_node_span_lint(
@@ -1495,6 +1508,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
 
 impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
     type Result = ControlFlow<()>;
+    fn skip_assoc_tys(&self) -> bool {
+        self.skip_assoc_tys
+    }
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -1531,6 +1547,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             required_effective_vis,
             in_assoc_ty: false,
             in_primary_interface: true,
+            skip_assoc_tys: false,
         }
     }
 
@@ -1726,13 +1743,18 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
                         self.effective_visibilities,
                     );
 
-                    // check that private components do not appear in the generics or predicates of inherent impls
-                    // this check is intentionally NOT performed for impls of traits, per #90586
+                    let mut check = self.check(item.owner_id.def_id, impl_vis, Some(impl_ev));
+                    // Generics and predicates of trait impls are intentionally not checked
+                    // for private components (#90586).
                     if impl_.of_trait.is_none() {
-                        self.check(item.owner_id.def_id, impl_vis, Some(impl_ev))
-                            .generics()
-                            .predicates();
+                        check.generics().predicates();
                     }
+                    // Skip checking private components in associated types, due to lack of full
+                    // normalization they produce very ridiculous false positives.
+                    // FIXME: Remove this when full normalization is implemented.
+                    check.skip_assoc_tys = true;
+                    check.ty().trait_ref();
+
                     for impl_item_ref in impl_.items {
                         let impl_item_vis = if impl_.of_trait.is_none() {
                             min(
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index a83c388c747..30a9e718d23 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -26,8 +26,8 @@ use rustc_middle::ty::TyCtxt;
 use rustc_query_system::dep_graph::SerializedDepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{
-    CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState,
-    get_query_incr, get_query_non_incr,
+    CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryStackDeferred,
+    QueryState, get_query_incr, get_query_non_incr,
 };
 use rustc_query_system::{HandleCycleError, Value};
 use rustc_span::{ErrorGuaranteed, Span};
@@ -84,7 +84,10 @@ where
     }
 
     #[inline(always)]
-    fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key>
+    fn query_state<'a>(
+        self,
+        qcx: QueryCtxt<'tcx>,
+    ) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>>
     where
         QueryCtxt<'tcx>: 'a,
     {
@@ -93,7 +96,7 @@ where
         unsafe {
             &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
                 .byte_add(self.dynamic.query_state)
-                .cast::<QueryState<Self::Key>>()
+                .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
         }
     }
 
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 2b8457ace8e..19ccc5587d6 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -5,6 +5,7 @@
 use std::num::NonZero;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_data_structures::unord::UnordMap;
 use rustc_hashes::Hash64;
 use rustc_index::Idx;
@@ -24,8 +25,8 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{
-    QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame,
-    force_query,
+    QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect,
+    QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query,
 };
 use rustc_query_system::{QueryOverflow, QueryOverflowNote};
 use rustc_serialize::{Decodable, Encodable};
@@ -65,7 +66,9 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
     }
 }
 
-impl QueryContext for QueryCtxt<'_> {
+impl<'tcx> QueryContext for QueryCtxt<'tcx> {
+    type QueryInfo = QueryStackDeferred<'tcx>;
+
     #[inline]
     fn next_job_id(self) -> QueryJobId {
         QueryJobId(
@@ -79,14 +82,29 @@ impl QueryContext for QueryCtxt<'_> {
         tls::with_related_context(self.tcx, |icx| icx.query)
     }
 
-    fn collect_active_jobs(self) -> QueryMap {
+    /// Returns a query map representing active query jobs.
+    /// It returns an incomplete map as an error if it fails
+    /// to take locks.
+    fn collect_active_jobs(
+        self,
+    ) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> {
         let mut jobs = QueryMap::default();
+        let mut complete = true;
 
         for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
-            collect(self.tcx, &mut jobs);
+            if collect(self.tcx, &mut jobs).is_none() {
+                complete = false;
+            }
         }
 
-        jobs
+        if complete { Ok(jobs) } else { Err(jobs) }
+    }
+
+    fn lift_query_info(
+        self,
+        info: &QueryStackDeferred<'tcx>,
+    ) -> rustc_query_system::query::QueryStackFrameExtra {
+        info.extract()
     }
 
     // Interactions with on_disk_cache
@@ -139,7 +157,12 @@ impl QueryContext for QueryCtxt<'_> {
     }
 
     fn depth_limit_error(self, job: QueryJobId) {
-        let (info, depth) = job.find_dep_kind_root(self.collect_active_jobs());
+        // FIXME: `collect_active_jobs` expects no locks to be held, which doesn't hold for this call.
+        let query_map = match self.collect_active_jobs() {
+            Ok(query_map) => query_map,
+            Err(query_map) => query_map,
+        };
+        let (info, depth) = job.find_dep_kind_root(query_map);
 
         let suggested_limit = match self.recursion_limit() {
             Limit(0) => Limit(2),
@@ -148,7 +171,10 @@ impl QueryContext for QueryCtxt<'_> {
 
         self.sess.dcx().emit_fatal(QueryOverflow {
             span: info.job.span,
-            note: QueryOverflowNote { desc: info.query.description, depth },
+            note: QueryOverflowNote {
+                desc: self.lift_query_info(&info.query.info).description,
+                depth,
+            },
             suggested_limit,
             crate_name: self.crate_name(LOCAL_CRATE),
         });
@@ -285,16 +311,17 @@ macro_rules! should_ever_cache_on_disk {
     };
 }
 
-pub(crate) fn create_query_frame<
-    'tcx,
-    K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
->(
-    tcx: TyCtxt<'tcx>,
-    do_describe: fn(TyCtxt<'tcx>, K) -> String,
-    key: K,
-    kind: DepKind,
-    name: &'static str,
-) -> QueryStackFrame {
+fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>(
+    (tcx, key, kind, name, do_describe): (
+        TyCtxt<'tcx>,
+        K,
+        DepKind,
+        &'static str,
+        fn(TyCtxt<'tcx>, K) -> String,
+    ),
+) -> QueryStackFrameExtra {
+    let def_id = key.key_as_def_id();
+
     // If reduced queries are requested, we may be printing a query stack due
     // to a panic. Avoid using `default_span` and `def_kind` in that case.
     let reduce_queries = with_reduced_queries();
@@ -313,13 +340,28 @@ pub(crate) fn create_query_frame<
     } else {
         Some(key.default_span(tcx))
     };
-    let def_id = key.key_as_def_id();
+
     let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
         // Try to avoid infinite recursion.
         None
     } else {
         def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id))
     };
+    QueryStackFrameExtra::new(description, span, def_kind)
+}
+
+pub(crate) fn create_query_frame<
+    'tcx,
+    K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx,
+>(
+    tcx: TyCtxt<'tcx>,
+    do_describe: fn(TyCtxt<'tcx>, K) -> String,
+    key: K,
+    kind: DepKind,
+    name: &'static str,
+) -> QueryStackFrame<QueryStackDeferred<'tcx>> {
+    let def_id = key.key_as_def_id();
+
     let hash = || {
         tcx.with_stable_hashing_context(|mut hcx| {
             let mut hasher = StableHasher::new();
@@ -330,7 +372,10 @@ pub(crate) fn create_query_frame<
     };
     let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
 
-    QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash)
+    let info =
+        QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra);
+
+    QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle)
 }
 
 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
@@ -677,7 +722,10 @@ macro_rules! define_queries {
                 }
             }
 
-            pub(crate) fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) {
+            pub(crate) fn try_collect_active_jobs<'tcx>(
+                tcx: TyCtxt<'tcx>,
+                qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
+            ) -> Option<()> {
                 let make_query = |tcx, key| {
                     let kind = rustc_middle::dep_graph::dep_kinds::$name;
                     let name = stringify!($name);
@@ -697,6 +745,7 @@ macro_rules! define_queries {
                         stringify!($name)
                     );
                 }
+                res
             }
 
             pub(crate) fn alloc_self_profile_query_strings<'tcx>(
@@ -756,7 +805,9 @@ macro_rules! define_queries {
 
         // These arrays are used for iteration and can't be indexed by `DepKind`.
 
-        const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] =
+        const TRY_COLLECT_ACTIVE_JOBS: &[
+            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>) -> Option<()>
+        ] =
             &[$(query_impl::$name::try_collect_active_jobs),*];
 
         const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
@@ -819,6 +870,17 @@ macro_rules! define_queries {
                 }
             }
 
+            pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindStruct<'tcx> {
+                DepKindStruct {
+                    is_anon: true,
+                    is_eval_always: false,
+                    fingerprint_style: FingerprintStyle::Opaque,
+                    force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")),
+                    try_load_from_on_disk_cache: None,
+                    name: &"AnonZeroDeps",
+                }
+            }
+
             pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
                 DepKindStruct {
                     is_anon: true,
@@ -863,5 +925,9 @@ macro_rules! define_queries {
         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
             arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(query_callbacks))
         }
+
+        pub fn dep_kind_names() -> Vec<&'static str> {
+            rustc_middle::make_dep_kind_name_array!(query_callbacks)
+        }
     }
 }
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 78710efb7a9..7db06953aeb 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -24,3 +24,8 @@ rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 # tidy-alphabetical-end
+
+[dependencies.hashbrown]
+version = "0.15.2"
+default-features = false
+features = ["nightly"] # for may_dangle
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index bfd8b320715..9f34417973e 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -7,7 +7,8 @@ use std::sync::atomic::{AtomicU32, Ordering};
 
 use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
+use rustc_data_structures::outline;
+use rustc_data_structures::profiling::QueryInvocationId;
 use rustc_data_structures::sharded::{self, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU64, Lock};
@@ -16,6 +17,7 @@ use rustc_errors::DiagInner;
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
+use rustc_session::Session;
 use tracing::{debug, instrument};
 #[cfg(debug_assertions)]
 use {super::debug::EdgeFilter, std::env};
@@ -48,7 +50,7 @@ rustc_index::newtype_index! {
 rustc_data_structures::static_assert_size!(Option<DepNodeIndex>, 4);
 
 impl DepNodeIndex {
-    const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::ZERO;
+    const SINGLETON_ZERO_DEPS_ANON_NODE: DepNodeIndex = DepNodeIndex::ZERO;
     pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1);
 }
 
@@ -64,7 +66,8 @@ pub struct MarkFrame<'a> {
     parent: Option<&'a MarkFrame<'a>>,
 }
 
-enum DepNodeColor {
+#[derive(Debug)]
+pub(super) enum DepNodeColor {
     Red,
     Green(DepNodeIndex),
 }
@@ -117,7 +120,7 @@ where
 
 impl<D: Deps> DepGraph<D> {
     pub fn new(
-        profiler: &SelfProfilerRef,
+        session: &Session,
         prev_graph: Arc<SerializedDepGraph>,
         prev_work_products: WorkProductMap,
         encoder: FileEncoder,
@@ -127,7 +130,7 @@ impl<D: Deps> DepGraph<D> {
         let prev_graph_node_count = prev_graph.node_count();
 
         let current = CurrentDepGraph::new(
-            profiler,
+            session,
             prev_graph_node_count,
             encoder,
             record_graph,
@@ -137,35 +140,26 @@ impl<D: Deps> DepGraph<D> {
 
         let colors = DepNodeColorMap::new(prev_graph_node_count);
 
-        // Instantiate a dependy-less node only once for anonymous queries.
-        let _green_node_index = current.intern_new_node(
-            DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() },
+        // Instantiate a node with zero dependencies only once for anonymous queries.
+        let _green_node_index = current.alloc_node(
+            DepNode { kind: D::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() },
             EdgesVec::new(),
             Fingerprint::ZERO,
         );
-        assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
+        assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE);
 
         // Instantiate a dependy-less red node only once for anonymous queries.
-        let (red_node_index, red_node_prev_index_and_color) = current.intern_node(
-            &prev_graph,
+        let red_node_index = current.alloc_node(
             DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() },
             EdgesVec::new(),
-            None,
+            Fingerprint::ZERO,
         );
         assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE);
-        match red_node_prev_index_and_color {
-            None => {
-                // This is expected when we have no previous compilation session.
-                assert!(prev_graph_node_count == 0);
-            }
-            Some((prev_red_node_index, DepNodeColor::Red)) => {
-                assert_eq!(prev_red_node_index.as_usize(), red_node_index.as_usize());
-                colors.insert(prev_red_node_index, DepNodeColor::Red);
-            }
-            Some((_, DepNodeColor::Green(_))) => {
-                // There must be a logic error somewhere if we hit this branch.
-                panic!("DepNodeIndex::FOREVER_RED_NODE evaluated to DepNodeColor::Green")
-            }
+        if prev_graph_node_count > 0 {
+            colors.insert(
+                SerializedDepNodeIndex::from_u32(DepNodeIndex::FOREVER_RED_NODE.as_u32()),
+                DepNodeColor::Red,
+            );
         }
 
         DepGraph {
@@ -351,12 +345,13 @@ impl<D: Deps> DepGraphData<D> {
         //    in `DepGraph::try_mark_green()`.
         // 2. Two distinct query keys get mapped to the same `DepNode`
         //    (see for example #48923).
-        assert!(
-            !self.dep_node_exists(&key),
-            "forcing query with already existing `DepNode`\n\
+        self.assert_dep_node_not_yet_allocated_in_current_session(&key, || {
+            format!(
+                "forcing query with already existing `DepNode`\n\
                  - query-key: {arg:?}\n\
                  - dep-node: {key:?}"
-        );
+            )
+        });
 
         let with_deps = |task_deps| D::with_deps(task_deps, || task(cx, arg));
         let (result, edges) = if cx.dep_context().is_eval_always(key.kind) {
@@ -373,8 +368,7 @@ impl<D: Deps> DepGraphData<D> {
         };
 
         let dcx = cx.dep_context();
-        let dep_node_index =
-            self.hash_result_and_intern_node(dcx, key, edges, &result, hash_result);
+        let dep_node_index = self.hash_result_and_alloc_node(dcx, key, edges, &result, hash_result);
 
         (result, dep_node_index)
     }
@@ -413,7 +407,7 @@ impl<D: Deps> DepGraphData<D> {
                 // going to be (i.e. equal to the precomputed
                 // `SINGLETON_DEPENDENCYLESS_ANON_NODE`). As a consequence we can skip creating
                 // a `StableHasher` and sending the node through interning.
-                DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE
+                DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE
             }
             1 => {
                 // When there is only one dependency, don't bother creating a node.
@@ -436,7 +430,16 @@ impl<D: Deps> DepGraphData<D> {
                     hash: self.current.anon_id_seed.combine(hasher.finish()).into(),
                 };
 
-                self.current.intern_new_node(target_dep_node, task_deps, Fingerprint::ZERO)
+                // The DepNodes generated by the process above are not unique. 2 queries could
+                // have exactly the same dependencies. However, deserialization does not handle
+                // duplicated nodes, so we do the deduplication here directly.
+                //
+                // As anonymous nodes are a small quantity compared to the full dep-graph, the
+                // memory impact of this `anon_node_to_index` map remains tolerable, and helps
+                // us avoid useless growth of the graph with almost-equivalent nodes.
+                self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || {
+                    self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO)
+                })
             }
         };
 
@@ -444,7 +447,7 @@ impl<D: Deps> DepGraphData<D> {
     }
 
     /// Intern the new `DepNode` with the dependencies up-to-now.
-    fn hash_result_and_intern_node<Ctxt: DepContext<Deps = D>, R>(
+    fn hash_result_and_alloc_node<Ctxt: DepContext<Deps = D>, R>(
         &self,
         cx: &Ctxt,
         node: DepNode,
@@ -456,22 +459,8 @@ impl<D: Deps> DepGraphData<D> {
         let current_fingerprint = hash_result.map(|hash_result| {
             cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result))
         });
-
-        // Intern the new `DepNode` with the dependencies up-to-now.
-        let (dep_node_index, prev_and_color) =
-            self.current.intern_node(&self.previous, node, edges, current_fingerprint);
-
+        let dep_node_index = self.alloc_and_color_node(node, edges, current_fingerprint);
         hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-        if let Some((prev_index, color)) = prev_and_color {
-            debug_assert!(
-                self.colors.get(prev_index).is_none(),
-                "DepGraph::with_task() - Duplicate DepNodeColor insertion for {node:?}",
-            );
-
-            self.colors.insert(prev_index, color);
-        }
-
         dep_node_index
     }
 }
@@ -589,7 +578,7 @@ impl<D: Deps> DepGraph<D> {
             //
             // For sanity, we still check that the loaded stable hash and the new one match.
             if let Some(prev_index) = data.previous.node_to_index_opt(&node) {
-                let dep_node_index = data.current.prev_index_to_index.lock()[prev_index];
+                let dep_node_index = data.colors.current(prev_index);
                 if let Some(dep_node_index) = dep_node_index {
                     crate::query::incremental_verify_ich(
                         cx,
@@ -625,7 +614,7 @@ impl<D: Deps> DepGraph<D> {
                 }
             });
 
-            data.hash_result_and_intern_node(&cx, node, edges, result, hash_result)
+            data.hash_result_and_alloc_node(&cx, node, edges, result, hash_result)
         } else {
             // Incremental compilation is turned off. We just execute the task
             // without tracking. We still provide a dep-node index that uniquely
@@ -637,20 +626,22 @@ impl<D: Deps> DepGraph<D> {
 }
 
 impl<D: Deps> DepGraphData<D> {
-    #[inline]
-    fn dep_node_index_of_opt(&self, dep_node: &DepNode) -> Option<DepNodeIndex> {
+    fn assert_dep_node_not_yet_allocated_in_current_session<S: std::fmt::Display>(
+        &self,
+        dep_node: &DepNode,
+        msg: impl FnOnce() -> S,
+    ) {
         if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
-            self.current.prev_index_to_index.lock()[prev_index]
-        } else {
-            self.current.new_node_to_index.get(dep_node)
+            let current = self.colors.get(prev_index);
+            assert!(current.is_none(), "{}", msg())
+        } else if let Some(nodes_in_current_session) = &self.current.nodes_in_current_session {
+            outline(|| {
+                let seen = nodes_in_current_session.lock().contains_key(dep_node);
+                assert!(!seen, "{}", msg());
+            });
         }
     }
 
-    #[inline]
-    fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
-        self.dep_node_index_of_opt(dep_node).is_some()
-    }
-
     fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
         if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
             self.colors.get(prev_index)
@@ -722,23 +713,80 @@ impl<D: Deps> DepGraphData<D> {
                 }
             }
 
-            // Promote the previous diagnostics to the current session.
-            let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index);
-            // FIXME: Can this race with a parallel compiler?
-            qcx.store_side_effect(index, side_effect);
+            // Manually recreate the node as `promote_node_and_deps_to_current` expects all
+            // green dependencies.
+            let dep_node_index = self.current.encoder.send(
+                DepNode {
+                    kind: D::DEP_KIND_SIDE_EFFECT,
+                    hash: PackedFingerprint::from(Fingerprint::ZERO),
+                },
+                Fingerprint::ZERO,
+                std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
+            );
+            qcx.store_side_effect(dep_node_index, side_effect);
 
             // Mark the node as green.
-            self.colors.insert(prev_index, DepNodeColor::Green(index));
+            self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index));
         })
     }
-}
 
-impl<D: Deps> DepGraph<D> {
-    #[inline]
-    pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
-        self.data.as_ref().is_some_and(|data| data.dep_node_exists(dep_node))
+    fn alloc_and_color_node(
+        &self,
+        key: DepNode,
+        edges: EdgesVec,
+        fingerprint: Option<Fingerprint>,
+    ) -> DepNodeIndex {
+        let dep_node_index =
+            self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO));
+
+        if let Some(prev_index) = self.previous.node_to_index_opt(&key) {
+            // Determine the color and index of the new `DepNode`.
+            let color = if let Some(fingerprint) = fingerprint {
+                if fingerprint == self.previous.fingerprint_by_index(prev_index) {
+                    // This is a green node: it existed in the previous compilation,
+                    // its query was re-executed, and it has the same result as before.
+                    DepNodeColor::Green(dep_node_index)
+                } else {
+                    // This is a red node: it existed in the previous compilation, its query
+                    // was re-executed, but it has a different result from before.
+                    DepNodeColor::Red
+                }
+            } else {
+                // This is a red node, effectively: it existed in the previous compilation
+                // session, its query was re-executed, but it doesn't compute a result hash
+                // (i.e. it represents a `no_hash` query), so we have no way of determining
+                // whether or not the result was the same as before.
+                DepNodeColor::Red
+            };
+
+            debug_assert!(
+                self.colors.get(prev_index).is_none(),
+                "DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}",
+            );
+
+            self.colors.insert(prev_index, color);
+        }
+
+        dep_node_index
     }
 
+    fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex {
+        self.current.debug_assert_not_in_new_nodes(&self.previous, prev_index);
+
+        let dep_node_index = self.current.encoder.send_promoted(prev_index, &self.colors);
+
+        #[cfg(debug_assertions)]
+        self.current.record_edge(
+            dep_node_index,
+            self.previous.index_to_node(prev_index),
+            self.previous.fingerprint_by_index(prev_index),
+        );
+
+        dep_node_index
+    }
+}
+
+impl<D: Deps> DepGraph<D> {
     /// Checks whether a previous work product exists for `v` and, if
     /// so, return the path that leads to it. Used to skip doing work.
     pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
@@ -862,7 +910,7 @@ impl<D: Deps> DepGraphData<D> {
                 self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
 
             if node_index.is_some() {
-                debug!("managed to MARK dependency {dep_dep_node:?} as green",);
+                debug!("managed to MARK dependency {dep_dep_node:?} as green");
                 return Some(());
             }
         }
@@ -883,7 +931,7 @@ impl<D: Deps> DepGraphData<D> {
                 return Some(());
             }
             Some(DepNodeColor::Red) => {
-                debug!("dependency {dep_dep_node:?} was red after forcing",);
+                debug!("dependency {dep_dep_node:?} was red after forcing");
                 return None;
             }
             None => {}
@@ -903,7 +951,7 @@ impl<D: Deps> DepGraphData<D> {
         // invalid state will not be persisted to the
         // incremental compilation cache because of
         // compilation errors being present.
-        debug!("dependency {dep_dep_node:?} resulted in compilation error",);
+        debug!("dependency {dep_dep_node:?} resulted in compilation error");
         return None;
     }
 
@@ -937,14 +985,10 @@ impl<D: Deps> DepGraphData<D> {
 
         // We allocating an entry for the node in the current dependency graph and
         // adding all the appropriate edges imported from the previous graph
-        let dep_node_index =
-            self.current.promote_node_and_deps_to_current(&self.previous, prev_dep_node_index);
-
-        // ... emitting any stored diagnostic ...
+        let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index);
 
         // ... and finally storing a "Green" entry in the color map.
         // Multiple threads can all write the same color here
-        self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
 
         debug!("successfully marked {dep_node:?} as green");
         Some(dep_node_index)
@@ -964,6 +1008,16 @@ impl<D: Deps> DepGraph<D> {
         self.node_color(dep_node).is_some_and(|c| c.is_green())
     }
 
+    pub fn assert_dep_node_not_yet_allocated_in_current_session<S: std::fmt::Display>(
+        &self,
+        dep_node: &DepNode,
+        msg: impl FnOnce() -> S,
+    ) {
+        if let Some(data) = &self.data {
+            data.assert_dep_node_not_yet_allocated_in_current_session(dep_node, msg)
+        }
+    }
+
     /// This method loads all on-disk cacheable query results into memory, so
     /// they can be written out to the new cache file again. Most query results
     /// will already be in memory but in the case where we marked something as
@@ -1069,24 +1123,23 @@ rustc_index::newtype_index! {
 /// largest in the compiler.
 ///
 /// For this reason, we avoid storing `DepNode`s more than once as map
-/// keys. The `new_node_to_index` map only contains nodes not in the previous
+/// keys. The `anon_node_to_index` map only contains nodes of anonymous queries not in the previous
 /// graph, and we map nodes in the previous graph to indices via a two-step
 /// mapping. `SerializedDepGraph` maps from `DepNode` to `SerializedDepNodeIndex`,
 /// and the `prev_index_to_index` vector (which is more compact and faster than
 /// using a map) maps from `SerializedDepNodeIndex` to `DepNodeIndex`.
 ///
-/// This struct uses three locks internally. The `data`, `new_node_to_index`,
+/// This struct uses three locks internally. The `data`, `anon_node_to_index`,
 /// and `prev_index_to_index` fields are locked separately. Operations that take
 /// a `DepNodeIndex` typically just access the `data` field.
 ///
 /// We only need to manipulate at most two locks simultaneously:
-/// `new_node_to_index` and `data`, or `prev_index_to_index` and `data`. When
-/// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index`
+/// `anon_node_to_index` and `data`, or `prev_index_to_index` and `data`. When
+/// manipulating both, we acquire `anon_node_to_index` or `prev_index_to_index`
 /// first, and `data` second.
 pub(super) struct CurrentDepGraph<D: Deps> {
     encoder: GraphEncoder<D>,
-    new_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
-    prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
+    anon_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
 
     /// This is used to verify that fingerprints do not change between the creation of a node
     /// and its recomputation.
@@ -1098,6 +1151,13 @@ pub(super) struct CurrentDepGraph<D: Deps> {
     #[cfg(debug_assertions)]
     forbidden_edge: Option<EdgeFilter>,
 
+    /// Used to verify the absence of hash collisions among DepNodes.
+    /// This field is only `Some` if the `-Z incremental_verify_ich` option is present
+    /// or if `debug_assertions` are enabled.
+    ///
+    /// The map contains all DepNodes that have been allocated in the current session so far.
+    nodes_in_current_session: Option<Lock<FxHashMap<DepNode, DepNodeIndex>>>,
+
     /// Anonymous `DepNode`s are nodes whose IDs we compute from the list of
     /// their edges. This has the beneficial side-effect that multiple anonymous
     /// nodes can be coalesced into one without changing the semantics of the
@@ -1119,7 +1179,7 @@ pub(super) struct CurrentDepGraph<D: Deps> {
 
 impl<D: Deps> CurrentDepGraph<D> {
     fn new(
-        profiler: &SelfProfilerRef,
+        session: &Session,
         prev_graph_node_count: usize,
         encoder: FileEncoder,
         record_graph: bool,
@@ -1145,24 +1205,33 @@ impl<D: Deps> CurrentDepGraph<D> {
 
         let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200;
 
+        let new_node_dbg =
+            session.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions);
+
         CurrentDepGraph {
             encoder: GraphEncoder::new(
                 encoder,
                 prev_graph_node_count,
                 record_graph,
                 record_stats,
-                profiler,
+                &session.prof,
                 previous,
             ),
-            new_node_to_index: ShardedHashMap::with_capacity(
+            anon_node_to_index: ShardedHashMap::with_capacity(
+                // FIXME: The count estimate is off as anon nodes are only a portion of the nodes.
                 new_node_count_estimate / sharded::shards(),
             ),
-            prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)),
             anon_id_seed,
             #[cfg(debug_assertions)]
             forbidden_edge,
             #[cfg(debug_assertions)]
             fingerprints: Lock::new(IndexVec::from_elem_n(None, new_node_count_estimate)),
+            nodes_in_current_session: new_node_dbg.then(|| {
+                Lock::new(FxHashMap::with_capacity_and_hasher(
+                    new_node_count_estimate,
+                    Default::default(),
+                ))
+            }),
             total_read_count: AtomicU64::new(0),
             total_duplicate_read_count: AtomicU64::new(0),
         }
@@ -1180,102 +1249,26 @@ impl<D: Deps> CurrentDepGraph<D> {
     /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
     /// Assumes that this is a node that has no equivalent in the previous dep-graph.
     #[inline(always)]
-    fn intern_new_node(
+    fn alloc_node(
         &self,
         key: DepNode,
         edges: EdgesVec,
         current_fingerprint: Fingerprint,
     ) -> DepNodeIndex {
-        let dep_node_index = self
-            .new_node_to_index
-            .get_or_insert_with(key, || self.encoder.send(key, current_fingerprint, edges));
+        let dep_node_index = self.encoder.send(key, current_fingerprint, edges);
 
         #[cfg(debug_assertions)]
         self.record_edge(dep_node_index, key, current_fingerprint);
 
-        dep_node_index
-    }
-
-    fn intern_node(
-        &self,
-        prev_graph: &SerializedDepGraph,
-        key: DepNode,
-        edges: EdgesVec,
-        fingerprint: Option<Fingerprint>,
-    ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) {
-        if let Some(prev_index) = prev_graph.node_to_index_opt(&key) {
-            let get_dep_node_index = |fingerprint| {
-                let mut prev_index_to_index = self.prev_index_to_index.lock();
-
-                let dep_node_index = match prev_index_to_index[prev_index] {
-                    Some(dep_node_index) => dep_node_index,
-                    None => {
-                        let dep_node_index = self.encoder.send(key, fingerprint, edges);
-                        prev_index_to_index[prev_index] = Some(dep_node_index);
-                        dep_node_index
-                    }
-                };
-
-                #[cfg(debug_assertions)]
-                self.record_edge(dep_node_index, key, fingerprint);
-
-                dep_node_index
-            };
-
-            // Determine the color and index of the new `DepNode`.
-            if let Some(fingerprint) = fingerprint {
-                if fingerprint == prev_graph.fingerprint_by_index(prev_index) {
-                    // This is a green node: it existed in the previous compilation,
-                    // its query was re-executed, and it has the same result as before.
-                    let dep_node_index = get_dep_node_index(fingerprint);
-                    (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index))))
-                } else {
-                    // This is a red node: it existed in the previous compilation, its query
-                    // was re-executed, but it has a different result from before.
-                    let dep_node_index = get_dep_node_index(fingerprint);
-                    (dep_node_index, Some((prev_index, DepNodeColor::Red)))
+        if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
+            outline(|| {
+                if nodes_in_current_session.lock().insert(key, dep_node_index).is_some() {
+                    panic!("Found duplicate dep-node {key:?}");
                 }
-            } else {
-                // This is a red node, effectively: it existed in the previous compilation
-                // session, its query was re-executed, but it doesn't compute a result hash
-                // (i.e. it represents a `no_hash` query), so we have no way of determining
-                // whether or not the result was the same as before.
-                let dep_node_index = get_dep_node_index(Fingerprint::ZERO);
-                (dep_node_index, Some((prev_index, DepNodeColor::Red)))
-            }
-        } else {
-            let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO);
-
-            // This is a new node: it didn't exist in the previous compilation session.
-            let dep_node_index = self.intern_new_node(key, edges, fingerprint);
-
-            (dep_node_index, None)
+            });
         }
-    }
-
-    fn promote_node_and_deps_to_current(
-        &self,
-        prev_graph: &SerializedDepGraph,
-        prev_index: SerializedDepNodeIndex,
-    ) -> DepNodeIndex {
-        self.debug_assert_not_in_new_nodes(prev_graph, prev_index);
 
-        let mut prev_index_to_index = self.prev_index_to_index.lock();
-
-        match prev_index_to_index[prev_index] {
-            Some(dep_node_index) => dep_node_index,
-            None => {
-                let dep_node_index = self.encoder.send_promoted(prev_index, &*prev_index_to_index);
-                prev_index_to_index[prev_index] = Some(dep_node_index);
-                #[cfg(debug_assertions)]
-                self.record_edge(
-                    dep_node_index,
-                    prev_graph.index_to_node(prev_index),
-                    prev_graph.fingerprint_by_index(prev_index),
-                );
-                dep_node_index
-            }
-        }
+        dep_node_index
     }
 
     #[inline]
@@ -1284,11 +1277,14 @@ impl<D: Deps> CurrentDepGraph<D> {
         prev_graph: &SerializedDepGraph,
         prev_index: SerializedDepNodeIndex,
     ) {
-        let node = &prev_graph.index_to_node(prev_index);
-        debug_assert!(
-            !self.new_node_to_index.get(node).is_some(),
-            "node from previous graph present in new node collection"
-        );
+        if let Some(ref nodes_in_current_session) = self.nodes_in_current_session {
+            debug_assert!(
+                !nodes_in_current_session
+                    .lock()
+                    .contains_key(&prev_graph.index_to_node(prev_index)),
+                "node from previous graph present in new node collection"
+            );
+        }
     }
 }
 
@@ -1335,36 +1331,40 @@ impl Default for TaskDeps {
 }
 // A data structure that stores Option<DepNodeColor> values as a contiguous
 // array, using one u32 per entry.
-struct DepNodeColorMap {
+pub(super) struct DepNodeColorMap {
     values: IndexVec<SerializedDepNodeIndex, AtomicU32>,
 }
 
-const COMPRESSED_NONE: u32 = 0;
-const COMPRESSED_RED: u32 = 1;
-const COMPRESSED_FIRST_GREEN: u32 = 2;
+const COMPRESSED_NONE: u32 = u32::MAX;
+const COMPRESSED_RED: u32 = u32::MAX - 1;
 
 impl DepNodeColorMap {
     fn new(size: usize) -> DepNodeColorMap {
+        debug_assert!(COMPRESSED_RED > DepNodeIndex::MAX_AS_U32);
         DepNodeColorMap { values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect() }
     }
 
     #[inline]
-    fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
+    pub(super) fn current(&self, index: SerializedDepNodeIndex) -> Option<DepNodeIndex> {
+        let value = self.values[index].load(Ordering::Relaxed);
+        if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None }
+    }
+
+    #[inline]
+    pub(super) fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
         match self.values[index].load(Ordering::Acquire) {
             COMPRESSED_NONE => None,
             COMPRESSED_RED => Some(DepNodeColor::Red),
-            value => {
-                Some(DepNodeColor::Green(DepNodeIndex::from_u32(value - COMPRESSED_FIRST_GREEN)))
-            }
+            value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(value))),
         }
     }
 
     #[inline]
-    fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
+    pub(super) fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
         self.values[index].store(
             match color {
                 DepNodeColor::Red => COMPRESSED_RED,
-                DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
+                DepNodeColor::Green(index) => index.as_u32(),
             },
             Ordering::Release,
         )
@@ -1400,21 +1400,20 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
     let mut dep_node = None;
 
     // First try to find the dep node among those that already existed in the
-    // previous session
-    for (prev_index, index) in data.current.prev_index_to_index.lock().iter_enumerated() {
-        if index == &Some(dep_node_index) {
+    // previous session and has been marked green
+    for prev_index in data.colors.values.indices() {
+        if data.colors.current(prev_index) == Some(dep_node_index) {
             dep_node = Some(data.previous.index_to_node(prev_index));
             break;
         }
     }
 
-    if dep_node.is_none() {
-        // Try to find it among the new nodes
-        for shard in data.current.new_node_to_index.lock_shards() {
-            if let Some((node, _)) = shard.iter().find(|(_, index)| *index == dep_node_index) {
-                dep_node = Some(*node);
-                break;
-            }
+    if dep_node.is_none()
+        && let Some(nodes) = &data.current.nodes_in_current_session
+    {
+        // Try to find it among the nodes allocated so far in this session
+        if let Some((node, _)) = nodes.lock().iter().find(|&(_, index)| *index == dep_node_index) {
+            dep_node = Some(*node);
         }
     }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index e3d64d1c0f8..3a80835afad 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -100,6 +100,8 @@ pub trait Deps {
     where
         OP: for<'a> FnOnce(TaskDepsRef<'a>);
 
+    fn name(&self, dep_kind: DepKind) -> &'static str;
+
     /// We use this for most things when incr. comp. is turned off.
     const DEP_KIND_NULL: DepKind;
 
@@ -109,6 +111,9 @@ pub trait Deps {
     /// We use this to create a side effect node.
     const DEP_KIND_SIDE_EFFECT: DepKind;
 
+    /// We use this to create the anon node with zero dependencies.
+    const DEP_KIND_ANON_ZERO_DEPS: DepKind;
+
     /// This is the highest value a `DepKind` can have. It's used during encoding to
     /// pack information into the unused bits.
     const DEP_KIND_MAX: u16;
@@ -154,7 +159,7 @@ pub enum FingerprintStyle {
 
 impl FingerprintStyle {
     #[inline]
-    pub fn reconstructible(self) -> bool {
+    pub const fn reconstructible(self) -> bool {
         match self {
             FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => {
                 true
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 2c6fd7d494f..7750d6d1fef 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -50,6 +50,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use tracing::{debug, instrument};
 
+use super::graph::{DepNodeColor, DepNodeColorMap};
 use super::query::DepGraphQuery;
 use super::{DepKind, DepNode, DepNodeIndex, Deps};
 use crate::dep_graph::edges::EdgesVec;
@@ -179,8 +180,8 @@ fn mask(bits: usize) -> usize {
 }
 
 impl SerializedDepGraph {
-    #[instrument(level = "debug", skip(d))]
-    pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> Arc<SerializedDepGraph> {
+    #[instrument(level = "debug", skip(d, deps))]
+    pub fn decode<D: Deps>(d: &mut MemDecoder<'_>, deps: &D) -> Arc<SerializedDepGraph> {
         // The last 16 bytes are the node count and edge count.
         debug!("position: {:?}", d.position());
         let (node_count, edge_count) =
@@ -252,7 +253,18 @@ impl SerializedDepGraph {
             .collect();
 
         for (idx, node) in nodes.iter_enumerated() {
-            index[node.kind.as_usize()].insert(node.hash, idx);
+            if index[node.kind.as_usize()].insert(node.hash, idx).is_some() {
+                // Side effect nodes can have duplicates
+                if node.kind != D::DEP_KIND_SIDE_EFFECT {
+                    let name = deps.name(node.kind);
+                    panic!(
+                    "Error: A dep graph node ({name}) does not have an unique index. \
+                     Running a clean build on a nightly compiler with `-Z incremental-verify-ich` \
+                     can help narrow down the issue for reporting. A clean build may also work around the issue.\n
+                     DepNode: {node:?}"
+                )
+                }
+            }
         }
 
         Arc::new(SerializedDepGraph {
@@ -430,7 +442,7 @@ impl NodeInfo {
         node: DepNode,
         fingerprint: Fingerprint,
         prev_index: SerializedDepNodeIndex,
-        prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
+        colors: &DepNodeColorMap,
         previous: &SerializedDepGraph,
     ) -> usize {
         let edges = previous.edge_targets_from(prev_index);
@@ -438,7 +450,7 @@ impl NodeInfo {
 
         // Find the highest edge in the new dep node indices
         let edge_max =
-            edges.clone().map(|i| prev_index_to_index[i].unwrap().as_u32()).max().unwrap_or(0);
+            edges.clone().map(|i| colors.current(i).unwrap().as_u32()).max().unwrap_or(0);
 
         let header = SerializedNodeHeader::<D>::new(node, fingerprint, edge_max, edge_count);
         e.write_array(header.bytes);
@@ -449,7 +461,7 @@ impl NodeInfo {
 
         let bytes_per_index = header.bytes_per_index();
         for node_index in edges {
-            let node_index = prev_index_to_index[node_index].unwrap();
+            let node_index = colors.current(node_index).unwrap();
             e.write_with(|dest| {
                 *dest = node_index.as_u32().to_le_bytes();
                 bytes_per_index
@@ -554,7 +566,7 @@ impl<D: Deps> EncoderState<D> {
         &mut self,
         prev_index: SerializedDepNodeIndex,
         record_graph: &Option<Lock<DepGraphQuery>>,
-        prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
+        colors: &DepNodeColorMap,
     ) -> DepNodeIndex {
         let node = self.previous.index_to_node(prev_index);
 
@@ -564,7 +576,7 @@ impl<D: Deps> EncoderState<D> {
             node,
             fingerprint,
             prev_index,
-            prev_index_to_index,
+            colors,
             &self.previous,
         );
 
@@ -574,7 +586,7 @@ impl<D: Deps> EncoderState<D> {
             |this| {
                 this.previous
                     .edge_targets_from(prev_index)
-                    .map(|i| prev_index_to_index[i].unwrap())
+                    .map(|i| colors.current(i).unwrap())
                     .collect()
             },
             record_graph,
@@ -708,18 +720,31 @@ impl<D: Deps> GraphEncoder<D> {
 
     /// Encodes a node that was promoted from the previous graph. It reads the information directly from
     /// the previous dep graph and expects all edges to already have a new dep node index assigned.
+    ///
+    /// This will also ensure the dep node is marked green.
     #[inline]
     pub(crate) fn send_promoted(
         &self,
         prev_index: SerializedDepNodeIndex,
-        prev_index_to_index: &IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>,
+        colors: &DepNodeColorMap,
     ) -> DepNodeIndex {
         let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph");
-        self.status.lock().as_mut().unwrap().encode_promoted_node(
-            prev_index,
-            &self.record_graph,
-            prev_index_to_index,
-        )
+
+        let mut status = self.status.lock();
+        let status = status.as_mut().unwrap();
+
+        // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently
+        // on the same index.
+        match colors.get(prev_index) {
+            None => {
+                let dep_node_index =
+                    status.encode_promoted_node(prev_index, &self.record_graph, colors);
+                colors.insert(prev_index, DepNodeColor::Green(dep_node_index));
+                dep_node_index
+            }
+            Some(DepNodeColor::Green(dep_node_index)) => dep_node_index,
+            Some(DepNodeColor::Red) => panic!(),
+        }
     }
 
     pub(crate) fn finish(&self) -> FileEncodeResult {
diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs
index 852d93b711f..25778add60a 100644
--- a/compiler/rustc_query_system/src/ich/mod.rs
+++ b/compiler/rustc_query_system/src/ich/mod.rs
@@ -8,7 +8,7 @@ mod hcx;
 mod impls_syntax;
 
 pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
-    sym::cfg,
+    sym::cfg_trace, // FIXME should this really be ignored?
     sym::rustc_if_this_changed,
     sym::rustc_then_this_would_need,
     sym::rustc_dirty,
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 371b896400a..e508eadb73b 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -6,6 +6,7 @@ use std::hash::Hash;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_span::ErrorGuaranteed;
 
+use super::QueryStackFrameExtra;
 use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
 use crate::error::HandleCycleError;
 use crate::ich::StableHashingContext;
@@ -27,7 +28,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
     fn format_value(self) -> fn(&Self::Value) -> String;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key>
+    fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo>
     where
         Qcx: 'a;
 
@@ -57,7 +58,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
     fn value_from_cycle_error(
         self,
         tcx: Qcx::DepContext,
-        cycle_error: &CycleError,
+        cycle_error: &CycleError<QueryStackFrameExtra>,
         guar: ErrorGuaranteed,
     ) -> Self::Value;
 
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 37b305d0a8b..de35cd79ea2 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -1,3 +1,4 @@
+use std::fmt::Debug;
 use std::hash::Hash;
 use std::io::Write;
 use std::iter;
@@ -12,6 +13,7 @@ use rustc_hir::def::DefKind;
 use rustc_session::Session;
 use rustc_span::{DUMMY_SP, Span};
 
+use super::QueryStackFrameExtra;
 use crate::dep_graph::DepContext;
 use crate::error::CycleStack;
 use crate::query::plumbing::CycleError;
@@ -19,45 +21,54 @@ use crate::query::{QueryContext, QueryStackFrame};
 
 /// Represents a span and a query key.
 #[derive(Clone, Debug)]
-pub struct QueryInfo {
+pub struct QueryInfo<I> {
     /// The span corresponding to the reason for which this query was required.
     pub span: Span,
-    pub query: QueryStackFrame,
+    pub query: QueryStackFrame<I>,
 }
 
-pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
+impl<I> QueryInfo<I> {
+    pub(crate) fn lift<Qcx: QueryContext<QueryInfo = I>>(
+        &self,
+        qcx: Qcx,
+    ) -> QueryInfo<QueryStackFrameExtra> {
+        QueryInfo { span: self.span, query: self.query.lift(qcx) }
+    }
+}
+
+pub type QueryMap<I> = FxHashMap<QueryJobId, QueryJobInfo<I>>;
 
 /// A value uniquely identifying an active query job.
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
 pub struct QueryJobId(pub NonZero<u64>);
 
 impl QueryJobId {
-    fn query(self, map: &QueryMap) -> QueryStackFrame {
+    fn query<I: Clone>(self, map: &QueryMap<I>) -> QueryStackFrame<I> {
         map.get(&self).unwrap().query.clone()
     }
 
-    fn span(self, map: &QueryMap) -> Span {
+    fn span<I>(self, map: &QueryMap<I>) -> Span {
         map.get(&self).unwrap().job.span
     }
 
-    fn parent(self, map: &QueryMap) -> Option<QueryJobId> {
+    fn parent<I>(self, map: &QueryMap<I>) -> Option<QueryJobId> {
         map.get(&self).unwrap().job.parent
     }
 
-    fn latch(self, map: &QueryMap) -> Option<&QueryLatch> {
+    fn latch<I>(self, map: &QueryMap<I>) -> Option<&QueryLatch<I>> {
         map.get(&self).unwrap().job.latch.as_ref()
     }
 }
 
 #[derive(Clone, Debug)]
-pub struct QueryJobInfo {
-    pub query: QueryStackFrame,
-    pub job: QueryJob,
+pub struct QueryJobInfo<I> {
+    pub query: QueryStackFrame<I>,
+    pub job: QueryJob<I>,
 }
 
 /// Represents an active query job.
-#[derive(Clone, Debug)]
-pub struct QueryJob {
+#[derive(Debug)]
+pub struct QueryJob<I> {
     pub id: QueryJobId,
 
     /// The span corresponding to the reason for which this query was required.
@@ -67,17 +78,23 @@ pub struct QueryJob {
     pub parent: Option<QueryJobId>,
 
     /// The latch that is used to wait on this job.
-    latch: Option<QueryLatch>,
+    latch: Option<QueryLatch<I>>,
+}
+
+impl<I> Clone for QueryJob<I> {
+    fn clone(&self) -> Self {
+        Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() }
+    }
 }
 
-impl QueryJob {
+impl<I> QueryJob<I> {
     /// Creates a new query job.
     #[inline]
     pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
         QueryJob { id, span, parent, latch: None }
     }
 
-    pub(super) fn latch(&mut self) -> QueryLatch {
+    pub(super) fn latch(&mut self) -> QueryLatch<I> {
         if self.latch.is_none() {
             self.latch = Some(QueryLatch::new());
         }
@@ -97,12 +114,12 @@ impl QueryJob {
 }
 
 impl QueryJobId {
-    pub(super) fn find_cycle_in_stack(
+    pub(super) fn find_cycle_in_stack<I: Clone>(
         &self,
-        query_map: QueryMap,
+        query_map: QueryMap<I>,
         current_job: &Option<QueryJobId>,
         span: Span,
-    ) -> CycleError {
+    ) -> CycleError<I> {
         // Find the waitee amongst `current_job` parents
         let mut cycle = Vec::new();
         let mut current_job = Option::clone(current_job);
@@ -136,7 +153,7 @@ impl QueryJobId {
 
     #[cold]
     #[inline(never)]
-    pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) {
+    pub fn find_dep_kind_root<I: Clone>(&self, query_map: QueryMap<I>) -> (QueryJobInfo<I>, usize) {
         let mut depth = 1;
         let info = query_map.get(&self).unwrap();
         let dep_kind = info.query.dep_kind;
@@ -156,32 +173,31 @@ impl QueryJobId {
 }
 
 #[derive(Debug)]
-struct QueryWaiter {
+struct QueryWaiter<I> {
     query: Option<QueryJobId>,
     condvar: Condvar,
     span: Span,
-    cycle: Mutex<Option<CycleError>>,
+    cycle: Mutex<Option<CycleError<I>>>,
 }
 
-impl QueryWaiter {
-    fn notify(&self, registry: &rayon_core::Registry) {
-        rayon_core::mark_unblocked(registry);
-        self.condvar.notify_one();
-    }
+#[derive(Debug)]
+struct QueryLatchInfo<I> {
+    complete: bool,
+    waiters: Vec<Arc<QueryWaiter<I>>>,
 }
 
 #[derive(Debug)]
-struct QueryLatchInfo {
-    complete: bool,
-    waiters: Vec<Arc<QueryWaiter>>,
+pub(super) struct QueryLatch<I> {
+    info: Arc<Mutex<QueryLatchInfo<I>>>,
 }
 
-#[derive(Clone, Debug)]
-pub(super) struct QueryLatch {
-    info: Arc<Mutex<QueryLatchInfo>>,
+impl<I> Clone for QueryLatch<I> {
+    fn clone(&self) -> Self {
+        Self { info: Arc::clone(&self.info) }
+    }
 }
 
-impl QueryLatch {
+impl<I> QueryLatch<I> {
     fn new() -> Self {
         QueryLatch {
             info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
@@ -189,7 +205,11 @@ impl QueryLatch {
     }
 
     /// Awaits for the query job to complete.
-    pub(super) fn wait_on(&self, query: Option<QueryJobId>, span: Span) -> Result<(), CycleError> {
+    pub(super) fn wait_on(
+        &self,
+        query: Option<QueryJobId>,
+        span: Span,
+    ) -> Result<(), CycleError<I>> {
         let waiter =
             Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
         self.wait_on_inner(&waiter);
@@ -204,7 +224,7 @@ impl QueryLatch {
     }
 
     /// Awaits the caller on this latch by blocking the current thread.
-    fn wait_on_inner(&self, waiter: &Arc<QueryWaiter>) {
+    fn wait_on_inner(&self, waiter: &Arc<QueryWaiter<I>>) {
         let mut info = self.info.lock();
         if !info.complete {
             // We push the waiter on to the `waiters` list. It can be accessed inside
@@ -232,13 +252,14 @@ impl QueryLatch {
         info.complete = true;
         let registry = rayon_core::Registry::current();
         for waiter in info.waiters.drain(..) {
-            waiter.notify(&registry);
+            rayon_core::mark_unblocked(&registry);
+            waiter.condvar.notify_one();
         }
     }
 
     /// Removes a single waiter from the list of waiters.
     /// This is used to break query cycles.
-    fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter> {
+    fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<I>> {
         let mut info = self.info.lock();
         debug_assert!(!info.complete);
         // Remove the waiter from the list of waiters
@@ -258,7 +279,11 @@ type Waiter = (QueryJobId, usize);
 /// For visits of resumable waiters it returns Some(Some(Waiter)) which has the
 /// required information to resume the waiter.
 /// If all `visit` calls returns None, this function also returns None.
-fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option<Option<Waiter>>
+fn visit_waiters<I, F>(
+    query_map: &QueryMap<I>,
+    query: QueryJobId,
+    mut visit: F,
+) -> Option<Option<Waiter>>
 where
     F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>,
 {
@@ -288,8 +313,8 @@ where
 /// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
 /// If a cycle is detected, this initial value is replaced with the span causing
 /// the cycle.
-fn cycle_check(
-    query_map: &QueryMap,
+fn cycle_check<I>(
+    query_map: &QueryMap<I>,
     query: QueryJobId,
     span: Span,
     stack: &mut Vec<(Span, QueryJobId)>,
@@ -328,8 +353,8 @@ fn cycle_check(
 /// Finds out if there's a path to the compiler root (aka. code which isn't in a query)
 /// from `query` without going through any of the queries in `visited`.
 /// This is achieved with a depth first search.
-fn connected_to_root(
-    query_map: &QueryMap,
+fn connected_to_root<I>(
+    query_map: &QueryMap<I>,
     query: QueryJobId,
     visited: &mut FxHashSet<QueryJobId>,
 ) -> bool {
@@ -350,7 +375,7 @@ fn connected_to_root(
 }
 
 // Deterministically pick an query from a list
-fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T
+fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap<I>, queries: &'a [T], f: F) -> &'a T
 where
     F: Fn(&T) -> (Span, QueryJobId),
 {
@@ -375,10 +400,10 @@ where
 /// the function return true.
 /// If a cycle was not found, the starting query is removed from `jobs` and
 /// the function returns false.
-fn remove_cycle(
-    query_map: &QueryMap,
+fn remove_cycle<I: Clone>(
+    query_map: &QueryMap<I>,
     jobs: &mut Vec<QueryJobId>,
-    wakelist: &mut Vec<Arc<QueryWaiter>>,
+    wakelist: &mut Vec<Arc<QueryWaiter<I>>>,
 ) -> bool {
     let mut visited = FxHashSet::default();
     let mut stack = Vec::new();
@@ -477,9 +502,12 @@ fn remove_cycle(
 /// Detects query cycles by using depth first search over all active query jobs.
 /// If a query cycle is found it will break the cycle by finding an edge which
 /// uses a query latch and then resuming that waiter.
-/// There may be multiple cycles involved in a deadlock, but we only search
-/// one cycle at a call and resume one waiter at once. See `FIXME` below.
-pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry) {
+/// There may be multiple cycles involved in a deadlock, so this searches
+/// all active queries for cycles before finally resuming all the waiters at once.
+pub fn break_query_cycles<I: Clone + Debug>(
+    query_map: QueryMap<I>,
+    registry: &rayon_core::Registry,
+) {
     let mut wakelist = Vec::new();
     let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
 
@@ -488,19 +516,6 @@ pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry)
     while jobs.len() > 0 {
         if remove_cycle(&query_map, &mut jobs, &mut wakelist) {
             found_cycle = true;
-
-            // FIXME(#137731): Resume all the waiters at once may cause deadlocks,
-            // so we resume one waiter at a call for now. It's still unclear whether
-            // it's due to possible issues in rustc-rayon or instead in the handling
-            // of query cycles.
-            // This seem to only appear when multiple query cycles errors
-            // are involved, so this reduction in parallelism, while suboptimal, is not
-            // universal and only the deadlock handler will encounter these cases.
-            // The workaround shows loss of potential gains, but there still are big
-            // improvements in the common case, and no regressions compared to the
-            // single-threaded case. More investigation is still needed, and once fixed,
-            // we can wake up all the waiters up.
-            break;
         }
     }
 
@@ -519,9 +534,15 @@ pub fn break_query_cycles(query_map: QueryMap, registry: &rayon_core::Registry)
         );
     }
 
-    // FIXME: Ensure this won't cause a deadlock before we return
+    // Mark all the thread we're about to wake up as unblocked. This needs to be done before
+    // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we
+    // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked.
+    for _ in 0..wakelist.len() {
+        rayon_core::mark_unblocked(registry);
+    }
+
     for waiter in wakelist.into_iter() {
-        waiter.notify(registry);
+        waiter.condvar.notify_one();
     }
 }
 
@@ -533,7 +554,7 @@ pub fn report_cycle<'a>(
 ) -> Diag<'a> {
     assert!(!stack.is_empty());
 
-    let span = stack[0].query.default_span(stack[1 % stack.len()].span);
+    let span = stack[0].query.info.default_span(stack[1 % stack.len()].span);
 
     let mut cycle_stack = Vec::new();
 
@@ -542,31 +563,31 @@ pub fn report_cycle<'a>(
 
     for i in 1..stack.len() {
         let query = &stack[i].query;
-        let span = query.default_span(stack[(i + 1) % stack.len()].span);
-        cycle_stack.push(CycleStack { span, desc: query.description.to_owned() });
+        let span = query.info.default_span(stack[(i + 1) % stack.len()].span);
+        cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() });
     }
 
     let mut cycle_usage = None;
     if let Some((span, ref query)) = *usage {
         cycle_usage = Some(crate::error::CycleUsage {
-            span: query.default_span(span),
-            usage: query.description.to_string(),
+            span: query.info.default_span(span),
+            usage: query.info.description.to_string(),
         });
     }
 
-    let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias)))
-    {
-        Some(crate::error::Alias::Ty)
-    } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) {
-        Some(crate::error::Alias::Trait)
-    } else {
-        None
-    };
+    let alias =
+        if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) {
+            Some(crate::error::Alias::Ty)
+        } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) {
+            Some(crate::error::Alias::Trait)
+        } else {
+            None
+        };
 
     let cycle_diag = crate::error::Cycle {
         span,
         cycle_stack,
-        stack_bottom: stack[0].query.description.to_owned(),
+        stack_bottom: stack[0].query.info.description.to_owned(),
         alias,
         cycle_usage,
         stack_count,
@@ -588,7 +609,12 @@ pub fn print_query_stack<Qcx: QueryContext>(
     // state if it was responsible for triggering the panic.
     let mut count_printed = 0;
     let mut count_total = 0;
-    let query_map = qcx.collect_active_jobs();
+
+    // Make use of a partial query map if we fail to take locks collecting active queries.
+    let query_map = match qcx.collect_active_jobs() {
+        Ok(query_map) => query_map,
+        Err(query_map) => query_map,
+    };
 
     if let Some(ref mut file) = file {
         let _ = writeln!(file, "\n\nquery stack during panic:");
@@ -597,6 +623,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
         let Some(query_info) = query_map.get(&query) else {
             break;
         };
+        let query_extra = qcx.lift_query_info(&query_info.query.info);
         if Some(count_printed) < limit_frames || limit_frames.is_none() {
             // Only print to stderr as many stack frames as `num_frames` when present.
             // FIXME: needs translation
@@ -604,7 +631,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
             #[allow(rustc::untranslatable_diagnostic)]
             dcx.struct_failure_note(format!(
                 "#{} [{:?}] {}",
-                count_printed, query_info.query.dep_kind, query_info.query.description
+                count_printed, query_info.query.dep_kind, query_extra.description
             ))
             .with_span(query_info.job.span)
             .emit();
@@ -617,7 +644,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
                 "#{} [{}] {}",
                 count_total,
                 qcx.dep_context().dep_kind_info(query_info.query.dep_kind).name,
-                query_info.query.description
+                query_extra.description
             );
         }
 
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 2ed0c810b75..ef21af7dafb 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -1,4 +1,9 @@
 mod plumbing;
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::mem::transmute;
+use std::sync::Arc;
+
 pub use self::plumbing::*;
 
 mod job;
@@ -11,6 +16,7 @@ mod caches;
 pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
 
 mod config;
+use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_errors::DiagInner;
 use rustc_hashes::Hash64;
 use rustc_hir::def::DefKind;
@@ -25,31 +31,59 @@ use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIn
 ///
 /// This is mostly used in case of cycles for error reporting.
 #[derive(Clone, Debug)]
-pub struct QueryStackFrame {
-    pub description: String,
-    span: Option<Span>,
-    pub def_id: Option<DefId>,
-    pub def_kind: Option<DefKind>,
-    /// A def-id that is extracted from a `Ty` in a query key
-    pub def_id_for_ty_in_cycle: Option<DefId>,
+pub struct QueryStackFrame<I> {
+    /// This field initially stores a `QueryStackDeferred` during collection,
+    /// but can later be changed to `QueryStackFrameExtra` containing concrete information
+    /// by calling `lift`. This is done so that collecting query does not need to invoke
+    /// queries, instead `lift` will call queries in a more appropriate location.
+    pub info: I,
+
     pub dep_kind: DepKind,
     /// This hash is used to deterministically pick
     /// a query to remove cycles in the parallel compiler.
     hash: Hash64,
+    pub def_id: Option<DefId>,
+    /// A def-id that is extracted from a `Ty` in a query key
+    pub def_id_for_ty_in_cycle: Option<DefId>,
 }
 
-impl QueryStackFrame {
+impl<I> QueryStackFrame<I> {
     #[inline]
     pub fn new(
-        description: String,
-        span: Option<Span>,
-        def_id: Option<DefId>,
-        def_kind: Option<DefKind>,
+        info: I,
         dep_kind: DepKind,
-        def_id_for_ty_in_cycle: Option<DefId>,
         hash: impl FnOnce() -> Hash64,
+        def_id: Option<DefId>,
+        def_id_for_ty_in_cycle: Option<DefId>,
     ) -> Self {
-        Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() }
+        Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle }
+    }
+
+    fn lift<Qcx: QueryContext<QueryInfo = I>>(
+        &self,
+        qcx: Qcx,
+    ) -> QueryStackFrame<QueryStackFrameExtra> {
+        QueryStackFrame {
+            info: qcx.lift_query_info(&self.info),
+            dep_kind: self.dep_kind,
+            hash: self.hash,
+            def_id: self.def_id,
+            def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct QueryStackFrameExtra {
+    pub description: String,
+    span: Option<Span>,
+    pub def_kind: Option<DefKind>,
+}
+
+impl QueryStackFrameExtra {
+    #[inline]
+    pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
+        Self { description, span, def_kind }
     }
 
     // FIXME(eddyb) Get more valid `Span`s on queries.
@@ -62,7 +96,41 @@ impl QueryStackFrame {
     }
 }
 
-/// Track a 'side effects' for a particular query.
+/// Track a 'side effect' for a particular query.
+/// This is used to hold a closure which can create `QueryStackFrameExtra`.
+#[derive(Clone)]
+pub struct QueryStackDeferred<'tcx> {
+    _dummy: PhantomData<&'tcx ()>,
+
+    // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't
+    // access it in the destructor.
+    extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>,
+}
+
+impl<'tcx> QueryStackDeferred<'tcx> {
+    pub fn new<C: Copy + DynSync + DynSend + 'tcx>(
+        context: C,
+        extract: fn(C) -> QueryStackFrameExtra,
+    ) -> Self {
+        let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> =
+            Arc::new(move || extract(context));
+        // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only
+        // captured variable is `context` which is Copy and cannot have a destructor.
+        Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } }
+    }
+
+    pub fn extract(&self) -> QueryStackFrameExtra {
+        (self.extract)()
+    }
+}
+
+impl<'tcx> Debug for QueryStackDeferred<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str("QueryStackDeferred")
+    }
+}
+
+/// Tracks 'side effects' for a particular query.
 /// This struct is saved to disk along with the query result,
 /// and loaded from disk if we mark the query as green.
 /// This allows us to 'replay' changes to global state
@@ -81,12 +149,16 @@ pub enum QuerySideEffect {
 }
 
 pub trait QueryContext: HasDepContext {
+    type QueryInfo: Clone;
+
     fn next_job_id(self) -> QueryJobId;
 
     /// Get the query information from the TLS context.
     fn current_query_job(self) -> Option<QueryJobId>;
 
-    fn collect_active_jobs(self) -> QueryMap;
+    fn collect_active_jobs(self) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>;
+
+    fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra;
 
     /// Load a side effect associated to the node in the previous session.
     fn load_side_effect(
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 7578cb5e2ae..6ea8e3b9200 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -3,21 +3,20 @@
 //! manage the caches, and so forth.
 
 use std::cell::Cell;
-use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
 
+use hashbrown::hash_table::Entry;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sharded::Sharded;
+use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::{outline, sync};
 use rustc_errors::{Diag, FatalError, StashKey};
 use rustc_span::{DUMMY_SP, Span};
 use tracing::instrument;
 
-use super::QueryConfig;
+use super::{QueryConfig, QueryStackFrameExtra};
 use crate::HandleCycleError;
 use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
 use crate::ich::StableHashingContext;
@@ -25,23 +24,28 @@ use crate::query::caches::QueryCache;
 use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
 use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex};
 
-pub struct QueryState<K> {
-    active: Sharded<FxHashMap<K, QueryResult>>,
+#[inline]
+fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
+    move |x| x.0 == *k
+}
+
+pub struct QueryState<K, I> {
+    active: Sharded<hashbrown::HashTable<(K, QueryResult<I>)>>,
 }
 
 /// Indicates the state of a query for a given key in a query map.
-enum QueryResult {
+enum QueryResult<I> {
     /// An already executing query. The query job can be used to await for its completion.
-    Started(QueryJob),
+    Started(QueryJob<I>),
 
     /// The query panicked. Queries trying to wait on this will raise a fatal error which will
     /// silently panic.
     Poisoned,
 }
 
-impl QueryResult {
+impl<I> QueryResult<I> {
     /// Unwraps the query job expecting that it has started.
-    fn expect_job(self) -> QueryJob {
+    fn expect_job(self) -> QueryJob<I> {
         match self {
             Self::Started(job) => job,
             Self::Poisoned => {
@@ -51,7 +55,7 @@ impl QueryResult {
     }
 }
 
-impl<K> QueryState<K>
+impl<K, I> QueryState<K, I>
 where
     K: Eq + Hash + Copy + Debug,
 {
@@ -62,8 +66,8 @@ where
     pub fn try_collect_active_jobs<Qcx: Copy>(
         &self,
         qcx: Qcx,
-        make_query: fn(Qcx, K) -> QueryStackFrame,
-        jobs: &mut QueryMap,
+        make_query: fn(Qcx, K) -> QueryStackFrame<I>,
+        jobs: &mut QueryMap<I>,
     ) -> Option<()> {
         let mut active = Vec::new();
 
@@ -72,7 +76,7 @@ where
         for shard in self.active.try_lock_shards() {
             for (k, v) in shard?.iter() {
                 if let QueryResult::Started(ref job) = *v {
-                    active.push((*k, job.clone()));
+                    active.push((*k, (*job).clone()));
                 }
             }
         }
@@ -88,19 +92,19 @@ where
     }
 }
 
-impl<K> Default for QueryState<K> {
-    fn default() -> QueryState<K> {
+impl<K, I> Default for QueryState<K, I> {
+    fn default() -> QueryState<K, I> {
         QueryState { active: Default::default() }
     }
 }
 
 /// A type representing the responsibility to execute the job in the `job` field.
 /// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, K>
+struct JobOwner<'tcx, K, I>
 where
     K: Eq + Hash + Copy,
 {
-    state: &'tcx QueryState<K>,
+    state: &'tcx QueryState<K, I>,
     key: K,
 }
 
@@ -142,7 +146,7 @@ where
         }
         Stash => {
             let guar = if let Some(root) = cycle_error.cycle.first()
-                && let Some(span) = root.query.span
+                && let Some(span) = root.query.info.span
             {
                 error.stash(span, StashKey::Cycle).unwrap()
             } else {
@@ -153,13 +157,13 @@ where
     }
 }
 
-impl<'tcx, K> JobOwner<'tcx, K>
+impl<'tcx, K, I> JobOwner<'tcx, K, I>
 where
     K: Eq + Hash + Copy,
 {
     /// Completes the query by updating the query cache with the `result`,
     /// signals the waiter and forgets the JobOwner, so it won't poison the query
-    fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex)
+    fn complete<C>(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex)
     where
         C: QueryCache<Key = K>,
     {
@@ -174,22 +178,23 @@ where
         cache.complete(key, result, dep_node_index);
 
         let job = {
-            let val = {
-                // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
-                // underlying shard.
-                // since unwinding also wants to look at this map, this can also prevent a double
-                // panic.
-                let mut lock = state.active.lock_shard_by_value(&key);
-                lock.remove(&key)
-            };
-            val.unwrap().expect_job()
+            // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
+            // underlying shard.
+            // since unwinding also wants to look at this map, this can also prevent a double
+            // panic.
+            let mut shard = state.active.lock_shard_by_hash(key_hash);
+            match shard.find_entry(key_hash, equivalent_key(&key)) {
+                Err(_) => None,
+                Ok(occupied) => Some(occupied.remove().0.1),
+            }
         };
+        let job = job.expect("active query job entry").expect_job();
 
         job.signal_complete();
     }
 }
 
-impl<'tcx, K> Drop for JobOwner<'tcx, K>
+impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I>
 where
     K: Eq + Hash + Copy,
 {
@@ -199,11 +204,16 @@ where
         // Poison the query so jobs waiting on it panic.
         let state = self.state;
         let job = {
-            let mut shard = state.active.lock_shard_by_value(&self.key);
-            let job = shard.remove(&self.key).unwrap().expect_job();
-
-            shard.insert(self.key, QueryResult::Poisoned);
-            job
+            let key_hash = sharded::make_hash(&self.key);
+            let mut shard = state.active.lock_shard_by_hash(key_hash);
+            match shard.find_entry(key_hash, equivalent_key(&self.key)) {
+                Err(_) => panic!(),
+                Ok(occupied) => {
+                    let ((key, value), vacant) = occupied.remove();
+                    vacant.insert((key, QueryResult::Poisoned));
+                    value.expect_job()
+                }
+            }
         };
         // Also signal the completion of the job, so waiters
         // will continue execution.
@@ -212,10 +222,19 @@ where
 }
 
 #[derive(Clone, Debug)]
-pub struct CycleError {
+pub struct CycleError<I = QueryStackFrameExtra> {
     /// The query and related span that uses the cycle.
-    pub usage: Option<(Span, QueryStackFrame)>,
-    pub cycle: Vec<QueryInfo>,
+    pub usage: Option<(Span, QueryStackFrame<I>)>,
+    pub cycle: Vec<QueryInfo<I>>,
+}
+
+impl<I> CycleError<I> {
+    fn lift<Qcx: QueryContext<QueryInfo = I>>(&self, qcx: Qcx) -> CycleError<QueryStackFrameExtra> {
+        CycleError {
+            usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))),
+            cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(),
+        }
+    }
 }
 
 /// Checks whether there is already a value for this key in the in-memory
@@ -250,9 +269,12 @@ where
     Q: QueryConfig<Qcx>,
     Qcx: QueryContext,
 {
-    let error =
-        try_execute.find_cycle_in_stack(qcx.collect_active_jobs(), &qcx.current_query_job(), span);
-    (mk_cycle(query, qcx, error), None)
+    // Ensure there was no errors collecting all active jobs.
+    // We need the complete map to ensure we find a cycle to break.
+    let query_map = qcx.collect_active_jobs().ok().expect("failed to collect active queries");
+
+    let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span);
+    (mk_cycle(query, qcx, error.lift(qcx)), None)
 }
 
 #[inline(always)]
@@ -261,7 +283,7 @@ fn wait_for_query<Q, Qcx>(
     qcx: Qcx,
     span: Span,
     key: Q::Key,
-    latch: QueryLatch,
+    latch: QueryLatch<Qcx::QueryInfo>,
     current: Option<QueryJobId>,
 ) -> (Q::Value, Option<DepNodeIndex>)
 where
@@ -283,11 +305,11 @@ where
                 outline(|| {
                     // We didn't find the query result in the query cache. Check if it was
                     // poisoned due to a panic instead.
-                    let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock();
-
-                    match lock.get(&key) {
+                    let key_hash = sharded::make_hash(&key);
+                    let shard = query.query_state(qcx).active.lock_shard_by_hash(key_hash);
+                    match shard.find(key_hash, equivalent_key(&key)) {
                         // The query we waited on panicked. Continue unwinding here.
-                        Some(QueryResult::Poisoned) => FatalError.raise(),
+                        Some((_, QueryResult::Poisoned)) => FatalError.raise(),
                         _ => panic!(
                             "query '{}' result must be in the cache or the query must be poisoned after a wait",
                             query.name()
@@ -301,7 +323,7 @@ where
 
             (v, Some(index))
         }
-        Err(cycle) => (mk_cycle(query, qcx, cycle), None),
+        Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None),
     }
 }
 
@@ -318,7 +340,8 @@ where
     Qcx: QueryContext,
 {
     let state = query.query_state(qcx);
-    let mut state_lock = state.active.lock_shard_by_value(&key);
+    let key_hash = sharded::make_hash(&key);
+    let mut state_lock = state.active.lock_shard_by_hash(key_hash);
 
     // For the parallel compiler we need to check both the query cache and query state structures
     // while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -335,21 +358,21 @@ where
 
     let current_job_id = qcx.current_query_job();
 
-    match state_lock.entry(key) {
+    match state_lock.entry(key_hash, equivalent_key(&key), |(k, _)| sharded::make_hash(k)) {
         Entry::Vacant(entry) => {
             // Nothing has computed or is computing the query, so we start a new job and insert it in the
             // state map.
             let id = qcx.next_job_id();
             let job = QueryJob::new(id, span, current_job_id);
-            entry.insert(QueryResult::Started(job));
+            entry.insert((key, QueryResult::Started(job)));
 
             // Drop the lock before we start executing the query
             drop(state_lock);
 
-            execute_job::<_, _, INCR>(query, qcx, state, key, id, dep_node)
+            execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node)
         }
         Entry::Occupied(mut entry) => {
-            match entry.get_mut() {
+            match &mut entry.get_mut().1 {
                 QueryResult::Started(job) => {
                     if sync::is_dyn_thread_safe() {
                         // Get the latch out
@@ -378,8 +401,9 @@ where
 fn execute_job<Q, Qcx, const INCR: bool>(
     query: Q,
     qcx: Qcx,
-    state: &QueryState<Q::Key>,
+    state: &QueryState<Q::Key, Qcx::QueryInfo>,
     key: Q::Key,
+    key_hash: u64,
     id: QueryJobId,
     dep_node: Option<DepNode>,
 ) -> (Q::Value, Option<DepNodeIndex>)
@@ -440,7 +464,7 @@ where
             }
         }
     }
-    job_owner.complete(cache, result, dep_node_index);
+    job_owner.complete(cache, key_hash, result, dep_node_index);
 
     (result, Some(dep_node_index))
 }
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index f4771f1af2c..9ea9c58cfd1 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
+itertools = "0.12"
 pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 763e9207a12..4368f7882ff 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -10,8 +10,8 @@ use std::sync::Arc;
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
 use rustc_ast::{
-    self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item,
-    ItemKind, MetaItemKind, NodeId, StmtKind,
+    self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
+    ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias,
 };
 use rustc_attr_parsing as attr;
 use rustc_expand::base::ResolverExpand;
@@ -131,7 +131,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess);
                 return Some(self.new_module(
                     parent,
-                    ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)),
+                    ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))),
                     expn_id,
                     self.def_span(def_id),
                     // FIXME: Account for `#[no_implicit_prelude]` attributes.
@@ -594,7 +594,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         // HACK(eddyb) unclear how good this is, but keeping `$crate`
                         // in `source` breaks `tests/ui/imports/import-crate-var.rs`,
                         // while the current crate doesn't have a valid `crate_name`.
-                        if crate_name != kw::Empty {
+                        if let Some(crate_name) = crate_name {
                             // `crate_name` should not be interpreted as relative.
                             module_path.push(Segment::from_ident_and_id(
                                 Ident { name: kw::PathRoot, span: source.ident.span },
@@ -603,7 +603,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                             source.ident.name = crate_name;
                         }
                         if rename.is_none() {
-                            ident.name = crate_name;
+                            ident.name = sym::dummy;
                         }
 
                         self.r.dcx().emit_err(errors::CrateImported { span: item.span });
@@ -735,7 +735,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent_scope = &self.parent_scope;
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
-        let ident = item.ident;
         let sp = item.span;
         let vis = self.resolve_visibility(&item.vis);
         let feed = self.r.feed(item.id);
@@ -762,20 +761,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::ExternCrate(orig_name) => {
+            ItemKind::ExternCrate(orig_name, ident) => {
                 self.build_reduced_graph_for_extern_crate(
                     orig_name,
                     item,
+                    ident,
                     local_def_id,
                     vis,
                     parent,
                 );
             }
 
-            ItemKind::Mod(.., ref mod_kind) => {
+            ItemKind::Mod(_, ident, ref mod_kind) => {
                 let module = self.r.new_module(
                     Some(parent),
-                    ModuleKind::Def(def_kind, def_id, ident.name),
+                    ModuleKind::Def(def_kind, def_id, Some(ident.name)),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude
@@ -792,10 +792,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in the value namespace.
-            ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
+            ItemKind::Const(box ConstItem { ident, .. })
+            | ItemKind::Delegation(box Delegation { ident, .. })
+            | ItemKind::Static(box StaticItem { ident, .. }) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
             }
-            ItemKind::Fn(..) => {
+            ItemKind::Fn(box Fn { ident, .. }) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
 
                 // Functions introducing procedural macros reserve a slot
@@ -804,14 +806,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
+            ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
-            ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
+            ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
                 let module = self.r.new_module(
                     Some(parent),
-                    ModuleKind::Def(def_kind, def_id, ident.name),
+                    ModuleKind::Def(def_kind, def_id, Some(ident.name)),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude,
@@ -821,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in both the type and value namespaces.
-            ItemKind::Struct(ref vdata, _) => {
+            ItemKind::Struct(ident, ref vdata, _) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -872,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 }
             }
 
-            ItemKind::Union(ref vdata, _) => {
+            ItemKind::Union(ident, ref vdata, _) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -884,10 +886,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items do not add names to modules.
-            ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
-                self.r.trait_impl_items.insert(local_def_id);
-            }
-            ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
+            ItemKind::Impl(box Impl { of_trait: Some(..), .. })
+            | ItemKind::Impl { .. }
+            | ItemKind::ForeignMod(..)
+            | ItemKind::GlobalAsm(..) => {}
 
             ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
                 unreachable!()
@@ -899,11 +901,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         &mut self,
         orig_name: Option<Symbol>,
         item: &Item,
+        ident: Ident,
         local_def_id: LocalDefId,
         vis: ty::Visibility,
         parent: Module<'ra>,
     ) {
-        let ident = item.ident;
         let sp = item.span;
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
@@ -987,7 +989,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
+    fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) {
         let feed = self.r.feed(item.id);
         let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
@@ -1000,7 +1002,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
-        self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+        self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
         self.r.feed_visibility(feed, vis);
     }
 
@@ -1043,7 +1045,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         span: item.span,
                     });
                 }
-                if let ItemKind::ExternCrate(Some(orig_name)) = item.kind
+                if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
                     && orig_name == kw::SelfLower
                 {
                     self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
@@ -1115,7 +1117,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 }
             });
         } else {
-            #[allow(rustc::potential_query_instability)] // FIXME
             for ident in single_imports.iter().cloned() {
                 let result = self.r.maybe_resolve_ident_in_module(
                     ModuleOrUniformRoot::Module(module),
@@ -1178,11 +1179,15 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
     }
 
-    fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
+    fn proc_macro_stub(
+        &self,
+        item: &ast::Item,
+        fn_ident: Ident,
+    ) -> Option<(MacroKind, Ident, Span)> {
         if ast::attr::contains_name(&item.attrs, sym::proc_macro) {
-            return Some((MacroKind::Bang, item.ident, item.span));
+            return Some((MacroKind::Bang, fn_ident, item.span));
         } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
-            return Some((MacroKind::Attr, item.ident, item.span));
+            return Some((MacroKind::Attr, fn_ident, item.span));
         } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
             && let Some(meta_item_inner) =
                 attr.meta_item_list().and_then(|list| list.get(0).cloned())
@@ -1215,17 +1220,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let feed = self.r.feed(item.id);
         let def_id = feed.key();
         let (res, ident, span, macro_rules) = match &item.kind {
-            ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules),
-            ItemKind::Fn(..) => match self.proc_macro_stub(item) {
-                Some((macro_kind, ident, span)) => {
-                    let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
-                    let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
-                    self.r.macro_map.insert(def_id.to_def_id(), macro_data);
-                    self.r.proc_macro_stubs.insert(def_id);
-                    (res, ident, span, false)
+            ItemKind::MacroDef(ident, def) => {
+                (self.res(def_id), *ident, item.span, def.macro_rules)
+            }
+            ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => {
+                match self.proc_macro_stub(item, *fn_ident) {
+                    Some((macro_kind, ident, span)) => {
+                        let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
+                        let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
+                        self.r.macro_map.insert(def_id.to_def_id(), macro_data);
+                        self.r.proc_macro_stubs.insert(def_id);
+                        (res, ident, span, false)
+                    }
+                    None => return parent_scope.macro_rules,
                 }
-                None => return parent_scope.macro_rules,
-            },
+            }
             _ => unreachable!(),
         };
 
@@ -1328,8 +1337,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         // Visit attributes after items for backward compatibility.
                         // This way they can use `macro_rules` defined later.
                         self.visit_vis(&item.vis);
-                        self.visit_ident(&item.ident);
-                        item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self);
+                        item.kind.walk(item.span, item.id, &item.vis, (), self);
                         visit::walk_list!(self, visit_attribute, &item.attrs);
                     }
                     _ => visit::walk_item(self, item),
@@ -1354,12 +1362,17 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
-        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
-            self.visit_invoc_in_module(foreign_item.id);
-            return;
-        }
+        let ident = match foreign_item.kind {
+            ForeignItemKind::Static(box StaticItem { ident, .. })
+            | ForeignItemKind::Fn(box Fn { ident, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident,
+            ForeignItemKind::MacCall(_) => {
+                self.visit_invoc_in_module(foreign_item.id);
+                return;
+            }
+        };
 
-        self.build_reduced_graph_for_foreign_item(foreign_item);
+        self.build_reduced_graph_for_foreign_item(foreign_item, ident);
         visit::walk_item(self, foreign_item);
     }
 
@@ -1373,34 +1386,42 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if let AssocItemKind::MacCall(_) = item.kind {
-            match ctxt {
-                AssocCtxt::Trait => {
-                    self.visit_invoc_in_module(item.id);
-                }
-                AssocCtxt::Impl => {
-                    let invoc_id = item.id.placeholder_to_expn_id();
-                    if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
-                        self.r
-                            .impl_unexpanded_invocations
-                            .entry(self.r.invocation_parent(invoc_id))
-                            .or_default()
-                            .insert(invoc_id);
+        let (ident, ns) = match item.kind {
+            AssocItemKind::Const(box ConstItem { ident, .. })
+            | AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS),
+
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS),
+
+            AssocItemKind::MacCall(_) => {
+                match ctxt {
+                    AssocCtxt::Trait => {
+                        self.visit_invoc_in_module(item.id);
+                    }
+                    AssocCtxt::Impl { .. } => {
+                        let invoc_id = item.id.placeholder_to_expn_id();
+                        if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
+                            self.r
+                                .impl_unexpanded_invocations
+                                .entry(self.r.invocation_parent(invoc_id))
+                                .or_default()
+                                .insert(invoc_id);
+                        }
+                        self.visit_invoc(item.id);
                     }
-                    self.visit_invoc(item.id);
                 }
+                return;
             }
-            return;
-        }
 
+            AssocItemKind::DelegationMac(..) => bug!(),
+        };
         let vis = self.resolve_visibility(&item.vis);
         let feed = self.r.feed(item.id);
         let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
 
-        if !(ctxt == AssocCtxt::Impl
-            && matches!(item.vis.kind, ast::VisibilityKind::Inherited)
-            && self.r.trait_impl_items.contains(&self.r.tcx.local_parent(local_def_id)))
+        if !(matches!(ctxt, AssocCtxt::Impl { of_trait: true })
+            && matches!(item.vis.kind, ast::VisibilityKind::Inherited))
         {
             // Trait impl item visibility is inherited from its trait when not specified
             // explicitly. In that case we cannot determine it here in early resolve,
@@ -1408,20 +1429,13 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             self.r.feed_visibility(feed, vis);
         }
 
-        let ns = match item.kind {
-            AssocItemKind::Const(..) | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => {
-                ValueNS
-            }
-            AssocItemKind::Type(..) => TypeNS,
-            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
-        };
         if ctxt == AssocCtxt::Trait {
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
-            self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+            self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
         } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
             let impl_def_id = self.r.tcx.local_parent(local_def_id);
-            let key = BindingKey::new(item.ident.normalize_to_macros_2_0(), ns);
+            let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
             self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
         }
 
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 1c1e8494ffc..e97233e97ce 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -219,14 +219,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
             // because this means that they were generated in some fashion by the
             // compiler and we don't need to consider them.
             ast::ItemKind::Use(..) if item.span.is_dummy() => return,
-            ast::ItemKind::ExternCrate(orig_name) => {
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
                 self.extern_crate_items.push(ExternCrateToLint {
                     id: item.id,
                     span: item.span,
                     vis_span: item.vis.span,
                     span_with_attributes: item.span_with_attributes(),
                     has_attrs: !item.attrs.is_empty(),
-                    ident: item.ident,
+                    ident,
                     renames: orig_name.is_some(),
                 });
             }
@@ -337,7 +337,8 @@ fn calc_unused_spans(
                     }
                 }
                 contains_self |= use_tree.prefix == kw::SelfLower
-                    && matches!(use_tree.kind, ast::UseTreeKind::Simple(None));
+                    && matches!(use_tree.kind, ast::UseTreeKind::Simple(_))
+                    && !unused_import.unused.contains(&use_tree_id);
                 previous_unused = remove.is_some();
             }
             if unused_spans.is_empty() {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 33f529851ae..13dfb59f27f 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -19,18 +19,15 @@ pub(crate) fn collect_definitions(
     fragment: &AstFragment,
     expansion: LocalExpnId,
 ) {
-    let InvocationParent { parent_def, impl_trait_context, in_attr } =
-        resolver.invocation_parents[&expansion];
-    let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
+    let invocation_parent = resolver.invocation_parents[&expansion];
+    let mut visitor = DefCollector { resolver, expansion, invocation_parent };
     fragment.visit_with(&mut visitor);
 }
 
 /// Creates `DefId`s for nodes in the AST.
 struct DefCollector<'a, 'ra, 'tcx> {
     resolver: &'a mut Resolver<'ra, 'tcx>,
-    parent_def: LocalDefId,
-    impl_trait_context: ImplTraitContext,
-    in_attr: bool,
+    invocation_parent: InvocationParent,
     expansion: LocalExpnId,
 }
 
@@ -42,7 +39,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
-        let parent_def = self.parent_def;
+        let parent_def = self.invocation_parent.parent_def;
         debug!(
             "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
             node_id, def_kind, parent_def
@@ -60,9 +57,9 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
-        let orig_parent_def = mem::replace(&mut self.parent_def, parent_def);
+        let orig_parent_def = mem::replace(&mut self.invocation_parent.parent_def, parent_def);
         f(self);
-        self.parent_def = orig_parent_def;
+        self.invocation_parent.parent_def = orig_parent_def;
     }
 
     fn with_impl_trait<F: FnOnce(&mut Self)>(
@@ -70,9 +67,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
         impl_trait_context: ImplTraitContext,
         f: F,
     ) {
-        let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context);
+        let orig_itc =
+            mem::replace(&mut self.invocation_parent.impl_trait_context, impl_trait_context);
         f(self);
-        self.impl_trait_context = orig_itc;
+        self.invocation_parent.impl_trait_context = orig_itc;
     }
 
     fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) {
@@ -96,14 +94,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
 
     fn visit_macro_invoc(&mut self, id: NodeId) {
         let id = id.placeholder_to_expn_id();
-        let old_parent = self.resolver.invocation_parents.insert(
-            id,
-            InvocationParent {
-                parent_def: self.parent_def,
-                impl_trait_context: self.impl_trait_context,
-                in_attr: self.in_attr,
-            },
-        );
+        let old_parent = self.resolver.invocation_parents.insert(id, self.invocation_parent);
         assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
     }
 }
@@ -131,7 +122,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
             },
             ItemKind::Const(..) => DefKind::Const,
             ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
-            ItemKind::MacroDef(def) => {
+            ItemKind::MacroDef(ident, def) => {
                 let edition = i.span.edition();
 
                 // FIXME(jdonszelmann) make one of these in the resolver?
@@ -150,7 +141,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 );
 
                 let macro_data =
-                    self.resolver.compile_macro(def, i.ident, &attrs, i.span, i.id, edition);
+                    self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition);
                 let macro_kind = macro_data.ext.macro_kind();
                 opt_macro_data = Some(macro_data);
                 DefKind::Macro(macro_kind)
@@ -161,7 +152,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 return self.visit_macro_invoc(i.id);
             }
         };
-        let def_id = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+        let def_id =
+            self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span);
 
         if let Some(macro_data) = opt_macro_data {
             self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
@@ -170,7 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         self.with_parent(def_id, |this| {
             this.with_impl_trait(ImplTraitContext::Existential, |this| {
                 match i.kind {
-                    ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
+                    ItemKind::Struct(_, ref struct_def, _)
+                    | ItemKind::Union(_, ref struct_def, _) => {
                         // If this is a unit or tuple-like struct, register the constructor.
                         if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
                             this.create_def(
@@ -192,10 +185,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         match fn_kind {
             FnKind::Fn(
                 _ctxt,
-                _ident,
                 _vis,
-                Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. },
+                Fn {
+                    sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, ..
+                },
             ) if let Some(coroutine_kind) = header.coroutine_kind => {
+                self.visit_ident(ident);
                 self.visit_fn_header(header);
                 self.visit_generics(generics);
                 if let Some(contract) = contract {
@@ -243,21 +238,28 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        let def_kind = match fi.kind {
-            ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => {
+        let (ident, def_kind) = match fi.kind {
+            ForeignItemKind::Static(box StaticItem {
+                ident,
+                ty: _,
+                mutability,
+                expr: _,
+                safety,
+                define_opaque: _,
+            }) => {
                 let safety = match safety {
                     ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
                     ast::Safety::Safe(_) => hir::Safety::Safe,
                 };
 
-                DefKind::Static { safety, mutability, nested: false }
+                (ident, DefKind::Static { safety, mutability, nested: false })
             }
-            ForeignItemKind::Fn(_) => DefKind::Fn,
-            ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
+            ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn),
+            ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy),
             ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
         };
 
-        let def = self.create_def(fi.id, Some(fi.ident.name), def_kind, fi.span);
+        let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span);
 
         self.with_parent(def, |this| visit::walk_item(this, fi));
     }
@@ -321,16 +323,17 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
-        let def_kind = match &i.kind {
-            AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
-            AssocItemKind::Const(..) => DefKind::AssocConst,
-            AssocItemKind::Type(..) => DefKind::AssocTy,
+        let (ident, def_kind) = match &i.kind {
+            AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn),
+            AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst),
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy),
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 return self.visit_macro_invoc(i.id);
             }
         };
 
-        let def = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+        let def = self.create_def(i.id, Some(ident.name), def_kind, i.span);
         self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
     }
 
@@ -361,7 +364,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 self.with_parent(def, |this| visit::walk_anon_const(this, constant));
                 return;
             }
-            _ => self.parent_def,
+            _ => self.invocation_parent.parent_def,
         };
 
         self.with_parent(parent_def, |this| visit::walk_expr(this, expr))
@@ -376,13 +379,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 // output or built artifacts, so replace them here...
                 // Perhaps we should instead format APITs more robustly.
                 let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
-                let kind = match self.impl_trait_context {
+                let kind = match self.invocation_parent.impl_trait_context {
                     ImplTraitContext::Universal => DefKind::TyParam,
                     ImplTraitContext::Existential => DefKind::OpaqueTy,
                     ImplTraitContext::InBinding => return visit::walk_ty(self, ty),
                 };
                 let id = self.create_def(*id, Some(name), kind, ty.span);
-                match self.impl_trait_context {
+                match self.invocation_parent.impl_trait_context {
                     // Do not nest APIT, as we desugar them as `impl_trait: bounds`,
                     // so the `impl_trait` node is not a parent to `bounds`.
                     ImplTraitContext::Universal => visit::walk_ty(self, ty),
@@ -453,9 +456,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result {
-        let orig_in_attr = mem::replace(&mut self.in_attr, true);
+        let orig_in_attr = mem::replace(&mut self.invocation_parent.in_attr, true);
         visit::walk_attribute(self, attr);
-        self.in_attr = orig_in_attr;
+        self.invocation_parent.in_attr = orig_in_attr;
     }
 
     fn visit_inline_asm(&mut self, asm: &'a InlineAsm) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 5361af98f3c..6dc854758da 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1091,7 +1091,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     ));
                 }
                 Scope::BuiltinAttrs => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
+                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
                     if filter_fn(res) {
                         suggestions.extend(
                             BUILTIN_ATTRIBUTES
@@ -1325,11 +1325,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             })
         }
 
-        // If only some candidates are accessible, take just them
-        if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) {
-            candidates.retain(|x| x.accessible)
-        }
-
         candidates
     }
 
@@ -1468,7 +1463,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             return;
         }
 
-        #[allow(rustc::potential_query_instability)] // FIXME
         let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
             if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
         });
@@ -1794,7 +1788,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 &import_suggestions,
                 Instead::Yes,
                 FoundUse::Yes,
-                DiagMode::Import { append: single_nested },
+                DiagMode::Import { append: single_nested, unresolved_import: false },
                 vec![],
                 "",
             );
@@ -2439,7 +2433,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
             return None;
         };
-        let module_name = crate_module.kind.name().unwrap();
+        let module_name = crate_module.kind.name().unwrap_or(kw::Empty);
         let import_snippet = match import.kind {
             ImportKind::Single { source, target, .. } if source != target => {
                 format!("{source} as {target}")
@@ -2751,6 +2745,8 @@ pub(crate) enum DiagMode {
     Pattern,
     /// The binding is part of a use statement
     Import {
+        /// `true` means diagnostics is for unresolved import
+        unresolved_import: bool,
         /// `true` mean add the tips afterward for case `use a::{b,c}`,
         /// rather than replacing within.
         append: bool,
@@ -2801,6 +2797,7 @@ fn show_candidates(
         return false;
     }
 
+    let mut showed = false;
     let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
     let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
 
@@ -2959,8 +2956,11 @@ fn show_candidates(
             append_candidates(&mut msg, accessible_path_strings);
             err.help(msg);
         }
-        true
-    } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) {
+        showed = true;
+    }
+    if !inaccessible_path_strings.is_empty()
+        && (!matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
+    {
         let prefix =
             if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
         if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
@@ -3023,10 +3023,9 @@ fn show_candidates(
 
             err.span_note(multi_span, msg);
         }
-        true
-    } else {
-        false
+        showed = true;
     }
+    showed
 }
 
 #[derive(Debug)]
@@ -3064,7 +3063,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
 
     fn visit_item(&mut self, item: &'tcx ast::Item) {
         if self.target_module == item.id {
-            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
+            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
                 let inject = mod_spans.inject_use_span;
                 if is_span_suitable_for_use_injection(inject) {
                     self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 6ef4aa40725..a5ca4565d7b 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 self.current_private_vis = prev_private_vis;
             }
 
-            ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+            ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => {
                 self.set_bindings_effective_visibilities(def_id);
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
@@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 }
             }
 
-            ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+            ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => {
                 for field in def.fields() {
                     self.update_field(self.r.local_def_id(field.id), def_id);
                 }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 27d63198836..5f0a2a597e9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -946,7 +946,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
         // Check if one of single imports can still define the name,
         // if it can then our result is not determined and can be invalidated.
-        #[allow(rustc::potential_query_instability)] // FIXME
         for single_import in &resolution.single_imports {
             if ignore_import == Some(*single_import) {
                 // This branch handles a cycle in single imports.
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 89b9a074351..0b3633a452c 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -4,7 +4,7 @@ use std::cell::Cell;
 use std::mem;
 
 use rustc_ast::NodeId;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
@@ -233,7 +233,7 @@ impl<'ra> ImportData<'ra> {
 pub(crate) struct NameResolution<'ra> {
     /// Single imports that may define the name in the namespace.
     /// Imports are arena-allocated, so it's ok to use pointers as keys.
-    pub single_imports: FxHashSet<Import<'ra>>,
+    pub single_imports: FxIndexSet<Import<'ra>>,
     /// The least shadowable known binding for this name, or None if there are no known bindings.
     pub binding: Option<NameBinding<'ra>>,
     pub shadowed_glob: Option<NameBinding<'ra>>,
@@ -494,7 +494,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 let key = BindingKey::new(target, ns);
                 let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
                 this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
-                    resolution.single_imports.remove(&import);
+                    resolution.single_imports.swap_remove(&import);
                 })
             });
             self.record_use(target, dummy_binding, Used::Other);
@@ -734,7 +734,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         &mut diag,
                         Some(err.span),
                         candidates,
-                        DiagMode::Import { append: false },
+                        DiagMode::Import { append: false, unresolved_import: true },
                         (source != target)
                             .then(|| format!(" as {target}"))
                             .as_deref()
@@ -862,7 +862,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                         let key = BindingKey::new(target, ns);
                         this.update_resolution(parent, key, false, |_, resolution| {
-                            resolution.single_imports.remove(&import);
+                            resolution.single_imports.swap_remove(&import);
                         });
                     }
                 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6056a69ee71..20e19caf909 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -36,6 +36,7 @@ use rustc_session::parse::feature_err;
 use rustc_span::source_map::{Spanned, respan};
 use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
 use smallvec::{SmallVec, smallvec};
+use thin_vec::ThinVec;
 use tracing::{debug, instrument, trace};
 
 use crate::{
@@ -272,7 +273,7 @@ impl RibKind<'_> {
 /// resolving, the name is looked up from inside out.
 #[derive(Debug)]
 pub(crate) struct Rib<'ra, R = Res> {
-    pub bindings: FxHashMap<Ident, R>,
+    pub bindings: FxIndexMap<Ident, R>,
     pub patterns_with_skipped_bindings: UnordMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
     pub kind: RibKind<'ra>,
 }
@@ -672,12 +673,7 @@ struct DiagMetadata<'ast> {
 
     /// A list of labels as of yet unused. Labels will be removed from this map when
     /// they are used (in a `break` or `continue` statement)
-    unused_labels: FxHashMap<NodeId, Span>,
-
-    /// Only used for better errors on `let x = { foo: bar };`.
-    /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only
-    /// needed for cases where this parses as a correct type ascription.
-    current_block_could_be_bare_struct_literal: Option<Span>,
+    unused_labels: FxIndexMap<NodeId, Span>,
 
     /// Only used for better errors on `let <pat>: <expr, not type>;`.
     current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
@@ -1029,9 +1025,10 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         match fn_kind {
             // Bail if the function is foreign, and thus cannot validly have
             // a body, or if there's no body for some other reason.
-            FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. })
-            | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => {
+            FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, ident, generics, .. })
+            | FnKind::Fn(_, _, Fn { sig, ident, generics, body: None, .. }) => {
                 self.visit_fn_header(&sig.header);
+                self.visit_ident(ident);
                 self.visit_generics(generics);
                 self.with_lifetime_rib(
                     LifetimeRibKind::AnonymousCreateParameter {
@@ -1062,7 +1059,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
             // Create a label rib for the function.
             this.with_label_rib(RibKind::FnOrCoroutine, |this| {
                 match fn_kind {
-                    FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
+                    FnKind::Fn(_, _, Fn { sig, generics, contract, body, .. }) => {
                         this.visit_generics(generics);
 
                         let declaration = &sig.decl;
@@ -1544,20 +1541,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         ret
     }
 
-    fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
-        if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
-            // Move down in the graph.
-            let orig_module = replace(&mut self.parent_scope.module, module);
-            self.with_rib(ValueNS, RibKind::Module(module), |this| {
-                this.with_rib(TypeNS, RibKind::Module(module), |this| {
-                    let ret = f(this);
-                    this.parent_scope.module = orig_module;
-                    ret
-                })
+    fn with_mod_rib<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
+        let module = self.r.expect_module(self.r.local_def_id(id).to_def_id());
+        // Move down in the graph.
+        let orig_module = replace(&mut self.parent_scope.module, module);
+        self.with_rib(ValueNS, RibKind::Module(module), |this| {
+            this.with_rib(TypeNS, RibKind::Module(module), |this| {
+                let ret = f(this);
+                this.parent_scope.module = orig_module;
+                ret
             })
-        } else {
-            f(self)
-        }
+        })
     }
 
     fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
@@ -1642,8 +1636,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
 
                         // Allow all following defaults to refer to this type parameter.
                         let i = &Ident::with_dummy_span(param.ident.name);
-                        forward_ty_ban_rib.bindings.remove(i);
-                        forward_ty_ban_rib_const_param_ty.bindings.remove(i);
+                        forward_ty_ban_rib.bindings.swap_remove(i);
+                        forward_ty_ban_rib_const_param_ty.bindings.swap_remove(i);
                     }
                     GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                         // Const parameters can't have param bounds.
@@ -1678,8 +1672,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
 
                         // Allow all following defaults to refer to this const parameter.
                         let i = &Ident::with_dummy_span(param.ident.name);
-                        forward_const_ban_rib.bindings.remove(i);
-                        forward_const_ban_rib_const_param_ty.bindings.remove(i);
+                        forward_const_ban_rib.bindings.swap_remove(i);
+                        forward_const_ban_rib_const_param_ty.bindings.swap_remove(i);
                     }
                 }
             }
@@ -1840,7 +1834,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 }
                 LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
                     let mut lifetimes_in_scope = vec![];
-                    for rib in &self.lifetime_ribs[..i] {
+                    for rib in self.lifetime_ribs[..i].iter().rev() {
                         lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
                         // Consider any anonymous lifetimes, too
                         if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
@@ -1848,6 +1842,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         {
                             lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
                         }
+                        if let LifetimeRibKind::Item = rib.kind {
+                            break;
+                        }
                     }
                     if lifetimes_in_scope.is_empty() {
                         self.record_lifetime_res(
@@ -2636,8 +2633,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
         }
 
-        let name = item.ident.name;
-        debug!("(resolving item) resolving {} ({:?})", name, item.kind);
+        debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind);
 
         let def_kind = self.r.local_def_kind(item.id);
         match item.kind {
@@ -2665,15 +2661,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     },
                     |this| visit::walk_item(this, item),
                 );
-
-                for (id, path) in define_opaque.iter().flatten() {
-                    self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
-                }
+                self.resolve_define_opaques(define_opaque);
             }
 
-            ItemKind::Enum(_, ref generics)
-            | ItemKind::Struct(_, ref generics)
-            | ItemKind::Union(_, ref generics) => {
+            ItemKind::Enum(_, _, ref generics)
+            | ItemKind::Struct(_, _, ref generics)
+            | ItemKind::Union(_, _, ref generics) => {
                 self.resolve_adt(item, generics);
             }
 
@@ -2717,7 +2710,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::TraitAlias(ref generics, ref bounds) => {
+            ItemKind::TraitAlias(_, ref generics, ref bounds) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(
                     &generics.params,
@@ -2738,7 +2731,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             }
 
             ItemKind::Mod(..) => {
-                self.with_scope(item.id, |this| {
+                self.with_mod_rib(item.id, |this| {
                     if mod_inner_docs {
                         this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
                     }
@@ -2754,7 +2747,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 });
             }
 
-            ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
+            ItemKind::Static(box ast::StaticItem {
+                ident,
+                ref ty,
+                ref expr,
+                ref define_opaque,
+                ..
+            }) => {
                 self.with_static_rib(def_kind, |this| {
                     this.with_lifetime_rib(
                         LifetimeRibKind::Elided(LifetimeRes::Static {
@@ -2767,12 +2766,20 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     if let Some(expr) = expr {
                         // We already forbid generic params because of the above item rib,
                         // so it doesn't matter whether this is a trivial constant.
-                        this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
+                        this.resolve_const_body(expr, Some((ident, ConstantItemKind::Static)));
                     }
                 });
+                self.resolve_define_opaques(define_opaque);
             }
 
-            ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
+            ItemKind::Const(box ast::ConstItem {
+                ident,
+                ref generics,
+                ref ty,
+                ref expr,
+                ref define_opaque,
+                ..
+            }) => {
                 self.with_generic_param_rib(
                     &generics.params,
                     RibKind::Item(
@@ -2799,13 +2806,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         );
 
                         if let Some(expr) = expr {
-                            this.resolve_const_body(
-                                expr,
-                                Some((item.ident, ConstantItemKind::Const)),
-                            );
+                            this.resolve_const_body(expr, Some((ident, ConstantItemKind::Const)));
                         }
                     },
                 );
+                self.resolve_define_opaques(define_opaque);
             }
 
             ItemKind::Use(ref use_tree) => {
@@ -2818,7 +2823,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 self.future_proof_import(use_tree);
             }
 
-            ItemKind::MacroDef(ref macro_def) => {
+            ItemKind::MacroDef(_, ref macro_def) => {
                 // Maintain macro_rules scopes in the same way as during early resolution
                 // for diagnostics and doc links.
                 if macro_def.macro_rules {
@@ -2888,7 +2893,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         break;
                     }
 
-                    #[allow(rustc::potential_query_instability)] // FIXME
                     seen_bindings
                         .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
                 }
@@ -3106,7 +3110,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         for item in trait_items {
             self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
             match &item.kind {
-                AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
+                AssocItemKind::Const(box ast::ConstItem {
+                    generics,
+                    ty,
+                    expr,
+                    define_opaque,
+                    ..
+                }) => {
                     self.with_generic_param_rib(
                         &generics.params,
                         RibKind::AssocItem,
@@ -3139,13 +3149,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                             )
                         },
                     );
+
+                    self.resolve_define_opaques(define_opaque);
                 }
                 AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
                     walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
 
-                    for (id, path) in define_opaque.iter().flatten() {
-                        self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
-                    }
+                    self.resolve_define_opaques(define_opaque);
                 }
                 AssocItemKind::Delegation(delegation) => {
                     self.with_generic_param_rib(
@@ -3310,7 +3320,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         use crate::ResolutionError::*;
         self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
         match &item.kind {
-            AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
+            AssocItemKind::Const(box ast::ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => {
                 debug!("resolve_implementation AssocItemKind::Const");
                 self.with_generic_param_rib(
                     &generics.params,
@@ -3322,40 +3339,51 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     },
                     |this| {
                         this.with_lifetime_rib(
-                            LifetimeRibKind::StaticIfNoLifetimeInScope {
-                                lint_id: item.id,
-                                // In impls, it's not a hard error yet due to backcompat.
-                                emit_lint: true,
+                            // Until these are a hard error, we need to create them within the correct binder,
+                            // Otherwise the lifetimes of this assoc const think they are lifetimes of the trait.
+                            LifetimeRibKind::AnonymousCreateParameter {
+                                binder: item.id,
+                                report_in_path: true,
                             },
                             |this| {
-                                // If this is a trait impl, ensure the const
-                                // exists in trait
-                                this.check_trait_item(
-                                    item.id,
-                                    item.ident,
-                                    &item.kind,
-                                    ValueNS,
-                                    item.span,
-                                    seen_trait_items,
-                                    |i, s, c| ConstNotMemberOfTrait(i, s, c),
-                                );
+                                this.with_lifetime_rib(
+                                    LifetimeRibKind::StaticIfNoLifetimeInScope {
+                                        lint_id: item.id,
+                                        // In impls, it's not a hard error yet due to backcompat.
+                                        emit_lint: true,
+                                    },
+                                    |this| {
+                                        // If this is a trait impl, ensure the const
+                                        // exists in trait
+                                        this.check_trait_item(
+                                            item.id,
+                                            *ident,
+                                            &item.kind,
+                                            ValueNS,
+                                            item.span,
+                                            seen_trait_items,
+                                            |i, s, c| ConstNotMemberOfTrait(i, s, c),
+                                        );
 
-                                this.visit_generics(generics);
-                                this.visit_ty(ty);
-                                if let Some(expr) = expr {
-                                    // We allow arbitrary const expressions inside of associated consts,
-                                    // even if they are potentially not const evaluatable.
-                                    //
-                                    // Type parameters can already be used and as associated consts are
-                                    // not used as part of the type system, this is far less surprising.
-                                    this.resolve_const_body(expr, None);
-                                }
+                                        this.visit_generics(generics);
+                                        this.visit_ty(ty);
+                                        if let Some(expr) = expr {
+                                            // We allow arbitrary const expressions inside of associated consts,
+                                            // even if they are potentially not const evaluatable.
+                                            //
+                                            // Type parameters can already be used and as associated consts are
+                                            // not used as part of the type system, this is far less surprising.
+                                            this.resolve_const_body(expr, None);
+                                        }
+                                    },
+                                )
                             },
                         );
                     },
                 );
+                self.resolve_define_opaques(define_opaque);
             }
-            AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
+            AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => {
                 debug!("resolve_implementation AssocItemKind::Fn");
                 // We also need a new scope for the impl item type parameters.
                 self.with_generic_param_rib(
@@ -3371,7 +3399,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         // exists in trait
                         this.check_trait_item(
                             item.id,
-                            item.ident,
+                            *ident,
                             &item.kind,
                             ValueNS,
                             item.span,
@@ -3379,15 +3407,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                             |i, s, c| MethodNotMemberOfTrait(i, s, c),
                         );
 
-                        visit::walk_assoc_item(this, item, AssocCtxt::Impl)
+                        visit::walk_assoc_item(this, item, AssocCtxt::Impl { of_trait: true })
                     },
                 );
 
-                for (id, path) in define_opaque.iter().flatten() {
-                    self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
-                }
+                self.resolve_define_opaques(define_opaque);
             }
-            AssocItemKind::Type(box TyAlias { generics, .. }) => {
+            AssocItemKind::Type(box TyAlias { ident, generics, .. }) => {
                 self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
                 debug!("resolve_implementation AssocItemKind::Type");
                 // We also need a new scope for the impl item type parameters.
@@ -3405,7 +3431,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                             // exists in trait
                             this.check_trait_item(
                                 item.id,
-                                item.ident,
+                                *ident,
                                 &item.kind,
                                 TypeNS,
                                 item.span,
@@ -3413,7 +3439,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                                 |i, s, c| TypeNotMemberOfTrait(i, s, c),
                             );
 
-                            visit::walk_assoc_item(this, item, AssocCtxt::Impl)
+                            visit::walk_assoc_item(this, item, AssocCtxt::Impl { of_trait: true })
                         });
                     },
                 );
@@ -3432,7 +3458,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     |this| {
                         this.check_trait_item(
                             item.id,
-                            item.ident,
+                            delegation.ident,
                             &item.kind,
                             ValueNS,
                             item.span,
@@ -4003,7 +4029,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         }
     }
 
-    fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap<Ident, Res> {
+    fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxIndexMap<Ident, Res> {
         &mut self.ribs[ns].last_mut().unwrap().bindings
     }
 
@@ -4318,7 +4344,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 if let Some(items) = self.diag_metadata.current_trait_assoc_items
                     && let [Segment { ident, .. }] = path
                     && items.iter().any(|item| {
-                        item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
+                        if let AssocItemKind::Type(alias) = &item.kind
+                            && alias.ident == *ident
+                        {
+                            true
+                        } else {
+                            false
+                        }
                     })
                 {
                     let mut diag = self.r.tcx.dcx().struct_allow("");
@@ -4650,13 +4682,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
         }
 
-        let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take();
-        if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
-            (block.could_be_bare_literal, &block.stmts[..])
-            && let ExprKind::Type(..) = expr.kind
-        {
-            self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
-        }
         // Descend into the block.
         for stmt in &block.stmts {
             if let StmtKind::Item(ref item) = stmt.kind
@@ -4670,7 +4695,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
 
             self.visit_stmt(stmt);
         }
-        self.diag_metadata.current_block_could_be_bare_struct_literal = prev;
 
         // Move back up.
         self.parent_scope.module = orig_module;
@@ -4779,7 +4803,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     Ok((node_id, _)) => {
                         // Since this res is a label, it is never read.
                         self.r.label_res_map.insert(expr.id, node_id);
-                        self.diag_metadata.unused_labels.remove(&node_id);
+                        self.diag_metadata.unused_labels.swap_remove(&node_id);
                     }
                     Err(error) => {
                         self.report_error(label.ident.span, error);
@@ -5107,6 +5131,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             });
         }
     }
+
+    fn resolve_define_opaques(&mut self, define_opaque: &Option<ThinVec<(NodeId, Path)>>) {
+        if let Some(define_opaque) = define_opaque {
+            for (id, path) in define_opaque {
+                self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
+            }
+        }
+    }
 }
 
 /// Walks the whole crate in DFS order, visiting each item, counting the declared number of
@@ -5140,12 +5172,12 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
             ItemKind::TyAlias(box TyAlias { generics, .. })
             | ItemKind::Const(box ConstItem { generics, .. })
             | ItemKind::Fn(box Fn { generics, .. })
-            | ItemKind::Enum(_, generics)
-            | ItemKind::Struct(_, generics)
-            | ItemKind::Union(_, generics)
+            | ItemKind::Enum(_, _, generics)
+            | ItemKind::Struct(_, _, generics)
+            | ItemKind::Union(_, _, generics)
             | ItemKind::Impl(box Impl { generics, .. })
             | ItemKind::Trait(box Trait { generics, .. })
-            | ItemKind::TraitAlias(generics, _) => {
+            | ItemKind::TraitAlias(_, generics, _) => {
                 if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                     self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
                 }
@@ -5201,7 +5233,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
         visit::walk_crate(&mut late_resolution_visitor, krate);
-        #[allow(rustc::potential_query_instability)] // FIXME
         for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
             self.lint_buffer.buffer_lint(
                 lint::builtin::UNUSED_LABELS,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 3d666055a94..b62bc6c45e0 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -224,12 +224,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 let suggestion = if self.current_trait_ref.is_none()
                     && let Some((fn_kind, _)) = self.diag_metadata.current_function
                     && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
-                    && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind
+                    && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind
                     && let Some(items) = self.diag_metadata.current_impl_items
                     && let Some(item) = items.iter().find(|i| {
-                        i.ident.name == item_str.name
+                        i.kind.ident().is_some_and(|ident| {
                             // Don't suggest if the item is in Fn signature arguments (#112590).
-                            && !sig.span.contains(item_span)
+                            ident.name == item_str.name && !sig.span.contains(item_span)
+                        })
                     }) {
                     let sp = item_span.shrink_to_lo();
 
@@ -268,14 +269,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                             // you can't call `fn foo(&self)` from `fn bar()` (#115992).
                             // We also want to mention that the method exists.
                             span_label = Some((
-                                item.ident.span,
+                                fn_.ident.span,
                                 "a method by that name is available on `Self` here",
                             ));
                             None
                         }
                         AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
                             span_label = Some((
-                                item.ident.span,
+                                fn_.ident.span,
                                 "an associated function by that name is available on `Self` here",
                             ));
                             None
@@ -450,7 +451,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect);
         }
 
-        self.suggest_bare_struct_literal(&mut err);
         self.suggest_changing_type_to_const_param(&mut err, res, source, span);
         self.explain_functions_in_pattern(&mut err, res, source);
 
@@ -605,7 +605,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 Applicability::MaybeIncorrect,
             );
             if !self.self_value_is_available(path[0].ident.span) {
-                if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) =
+                if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) =
                     &self.diag_metadata.current_function
                 {
                     let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
@@ -830,7 +830,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         if let Some(rib) = &self.last_block_rib
             && let RibKind::Normal = rib.kind
         {
-            #[allow(rustc::potential_query_instability)] // FIXME
             for (ident, &res) in &rib.bindings {
                 if let Res::Local(_) = res
                     && path.len() == 1
@@ -1019,7 +1018,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         if let Some(err_code) = err.code {
             if err_code == E0425 {
                 for label_rib in &self.label_ribs {
-                    #[allow(rustc::potential_query_instability)] // FIXME
                     for (label_ident, node_id) in &label_rib.bindings {
                         let ident = path.last().unwrap().ident;
                         if format!("'{ident}") == label_ident.to_string() {
@@ -1036,7 +1034,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                                 // Do not lint against unused label when we suggest them.
-                                self.diag_metadata.unused_labels.remove(node_id);
+                                self.diag_metadata.unused_labels.swap_remove(node_id);
                             }
                         }
                     }
@@ -1067,15 +1065,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         }
         err.code(E0411);
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
-        if let Some(item_kind) = self.diag_metadata.current_item {
-            if !item_kind.ident.span.is_dummy() {
+        if let Some(item) = self.diag_metadata.current_item {
+            if let Some(ident) = item.kind.ident() {
                 err.span_label(
-                    item_kind.ident.span,
-                    format!(
-                        "`Self` not allowed in {} {}",
-                        item_kind.kind.article(),
-                        item_kind.kind.descr()
-                    ),
+                    ident.span,
+                    format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
                 );
             }
         }
@@ -1153,17 +1147,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     );
                 }
             }
-        } else if let Some(item_kind) = self.diag_metadata.current_item {
-            if matches!(item_kind.kind, ItemKind::Delegation(..)) {
-                err.span_label(item_kind.span, format!("delegation supports {self_from_macro}"));
+        } else if let Some(item) = self.diag_metadata.current_item {
+            if matches!(item.kind, ItemKind::Delegation(..)) {
+                err.span_label(item.span, format!("delegation supports {self_from_macro}"));
             } else {
+                let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span };
                 err.span_label(
-                    item_kind.ident.span,
-                    format!(
-                        "`self` not allowed in {} {}",
-                        item_kind.kind.article(),
-                        item_kind.kind.descr()
-                    ),
+                    span,
+                    format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
                 );
             }
         }
@@ -1281,19 +1272,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         }
     }
 
-    fn suggest_bare_struct_literal(&mut self, err: &mut Diag<'_>) {
-        if let Some(span) = self.diag_metadata.current_block_could_be_bare_struct_literal {
-            err.multipart_suggestion(
-                "you might have meant to write a `struct` literal",
-                vec![
-                    (span.shrink_to_lo(), "{ SomeStruct ".to_string()),
-                    (span.shrink_to_hi(), "}".to_string()),
-                ],
-                Applicability::HasPlaceholders,
-            );
-        }
-    }
-
     fn explain_functions_in_pattern(
         &mut self,
         err: &mut Diag<'_>,
@@ -1681,41 +1659,81 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         // the struct literal syntax at all, as that will cause a subsequent error.
                         let fields = this.r.field_idents(def_id);
                         let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());
-                        let (fields, applicability) = match fields {
-                            Some(fields) => {
-                                let fields = if let Some(old_fields) = old_fields {
-                                    fields
-                                        .iter()
-                                        .enumerate()
-                                        .map(|(idx, new)| (new, old_fields.get(idx)))
-                                        .map(|(new, old)| {
-                                            if let Some(Some(old)) = old
-                                                && new.as_str() != old
-                                            {
-                                                format!("{new}: {old}")
-                                            } else {
-                                                new.to_string()
-                                            }
-                                        })
-                                        .collect::<Vec<String>>()
-                                } else {
-                                    fields
-                                        .iter()
-                                        .map(|f| format!("{f}{tail}"))
-                                        .collect::<Vec<String>>()
-                                };
-
-                                (fields.join(", "), applicability)
-                            }
-                            None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
-                        };
-                        let pad = if has_fields { " " } else { "" };
-                        err.span_suggestion(
+
+                        if let PathSource::Expr(Some(Expr {
+                            kind: ExprKind::Call(path, args),
                             span,
-                            format!("use struct {descr} syntax instead"),
-                            format!("{path_str} {{{pad}{fields}{pad}}}"),
-                            applicability,
-                        );
+                            ..
+                        })) = source
+                            && !args.is_empty()
+                            && let Some(fields) = &fields
+                            && args.len() == fields.len()
+                        // Make sure we have same number of args as fields
+                        {
+                            let path_span = path.span;
+                            let mut parts = Vec::new();
+
+                            // Start with the opening brace
+                            parts.push((
+                                path_span.shrink_to_hi().until(args[0].span),
+                                "{".to_owned(),
+                            ));
+
+                            for (field, arg) in fields.iter().zip(args.iter()) {
+                                // Add the field name before the argument
+                                parts.push((arg.span.shrink_to_lo(), format!("{}: ", field)));
+                            }
+
+                            // Add the closing brace
+                            parts.push((
+                                args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()),
+                                "}".to_owned(),
+                            ));
+
+                            err.multipart_suggestion_verbose(
+                                format!("use struct {descr} syntax instead of calling"),
+                                parts,
+                                applicability,
+                            );
+                        } else {
+                            let (fields, applicability) = match fields {
+                                Some(fields) => {
+                                    let fields = if let Some(old_fields) = old_fields {
+                                        fields
+                                            .iter()
+                                            .enumerate()
+                                            .map(|(idx, new)| (new, old_fields.get(idx)))
+                                            .map(|(new, old)| {
+                                                if let Some(Some(old)) = old
+                                                    && new.as_str() != old
+                                                {
+                                                    format!("{new}: {old}")
+                                                } else {
+                                                    new.to_string()
+                                                }
+                                            })
+                                            .collect::<Vec<String>>()
+                                    } else {
+                                        fields
+                                            .iter()
+                                            .map(|f| format!("{f}{tail}"))
+                                            .collect::<Vec<String>>()
+                                    };
+
+                                    (fields.join(", "), applicability)
+                                }
+                                None => {
+                                    ("/* fields */".to_string(), Applicability::HasPlaceholders)
+                                }
+                            };
+                            let pad = if has_fields { " " } else { "" };
+                            err.span_suggestion(
+                                span,
+                                format!("use struct {descr} syntax instead"),
+                                format!("{path_str} {{{pad}{fields}{pad}}}"),
+                                applicability,
+                            );
+                        }
                     }
                     if let PathSource::Expr(Some(Expr {
                         kind: ExprKind::Call(path, args),
@@ -2172,7 +2190,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
 
         if let Some(items) = self.diag_metadata.current_trait_assoc_items {
             for assoc_item in items {
-                if assoc_item.ident == ident {
+                if let Some(assoc_ident) = assoc_item.kind.ident()
+                    && assoc_ident == ident
+                {
                     return Some(match &assoc_item.kind {
                         ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
                         ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
@@ -2265,7 +2285,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 };
 
                 // Locals and type parameters
-                #[allow(rustc::potential_query_instability)] // FIXME
                 for (ident, &res) in &rib.bindings {
                     if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
                         names.push(TypoSuggestion::typo_from_ident(*ident, res));
@@ -2712,7 +2731,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             return None;
         }
         match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
-            (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => {
+            (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
                 // Ignore `fn main()` as we don't want to suggest `fn main<T>()`
             }
             (
@@ -2793,7 +2812,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         let within_scope = self.is_label_valid_from_rib(rib_index);
 
         let rib = &self.label_ribs[rib_index];
-        #[allow(rustc::potential_query_instability)] // FIXME
         let names = rib
             .bindings
             .iter()
@@ -2805,7 +2823,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             // Upon finding a similar name, get the ident that it was from - the span
             // contained within helps make a useful diagnostic. In addition, determine
             // whether this candidate is within scope.
-            #[allow(rustc::potential_query_instability)] // FIXME
             let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap();
             (*ident, within_scope)
         })
@@ -3379,7 +3396,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     {
                         let pre = if lt.kind == MissingLifetimeKind::Ampersand
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && !sig.decl.inputs.is_empty()
                             && let sugg = sig
                                 .decl
@@ -3420,7 +3437,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         } else if (lt.kind == MissingLifetimeKind::Ampersand
                             || lt.kind == MissingLifetimeKind::Underscore)
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
                             && !sig.decl.inputs.is_empty()
                             && let arg_refs = sig
@@ -3480,7 +3497,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                         let mut sugg = vec![(lt.span, String::new())];
                         if let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && let ast::FnRetTy::Ty(ty) = &sig.decl.output
                         {
                             let mut lt_finder =
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ff31af0025b..3ac66840d87 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -88,6 +88,8 @@ mod late;
 mod macros;
 pub mod rustdoc;
 
+pub use macros::registered_tools_ast;
+
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 #[derive(Debug)]
@@ -503,18 +505,18 @@ enum ModuleKind {
     ///
     /// * A normal module – either `mod from_file;` or `mod from_block { }` –
     ///   or the crate root (which is conceptually a top-level module).
-    ///   Note that the crate root's [name][Self::name] will be [`kw::Empty`].
+    ///   The crate root will have `None` for the symbol.
     /// * A trait or an enum (it implicitly contains associated types, methods and variant
     ///   constructors).
-    Def(DefKind, DefId, Symbol),
+    Def(DefKind, DefId, Option<Symbol>),
 }
 
 impl ModuleKind {
     /// Get name of the module.
     fn name(&self) -> Option<Symbol> {
-        match self {
+        match *self {
             ModuleKind::Block => None,
-            ModuleKind::Def(.., name) => Some(*name),
+            ModuleKind::Def(.., name) => name,
         }
     }
 }
@@ -1137,7 +1139,7 @@ pub struct Resolver<'ra, 'tcx> {
     non_macro_attr: MacroData,
     local_macro_def_scopes: FxHashMap<LocalDefId, Module<'ra>>,
     ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>,
-    unused_macros: FxHashMap<LocalDefId, (NodeId, Ident)>,
+    unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>,
     /// A map from the macro to all its potentially unused arms.
     unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>,
     proc_macro_stubs: FxHashSet<LocalDefId>,
@@ -1191,10 +1193,6 @@ pub struct Resolver<'ra, 'tcx> {
     /// and how the `impl Trait` fragments were introduced.
     invocation_parents: FxHashMap<LocalExpnId, InvocationParent>,
 
-    /// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
-    /// FIXME: Replace with a more general AST map (together with some other fields).
-    trait_impl_items: FxHashSet<LocalDefId>,
-
     legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
     /// Amount of lifetime parameters for each item in the crate.
     item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
@@ -1402,7 +1400,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let mut module_self_bindings = FxHashMap::default();
         let graph_root = arenas.new_module(
             None,
-            ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
+            ModuleKind::Def(DefKind::Mod, root_def_id, None),
             ExpnId::root(),
             crate_span,
             attr::contains_name(attrs, sym::no_implicit_prelude),
@@ -1411,7 +1409,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         );
         let empty_module = arenas.new_module(
             None,
-            ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
+            ModuleKind::Def(DefKind::Mod, root_def_id, None),
             ExpnId::root(),
             DUMMY_SP,
             true,
@@ -1558,7 +1556,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             def_id_to_node_id,
             placeholder_field_indices: Default::default(),
             invocation_parents,
-            trait_impl_items: Default::default(),
             legacy_const_generic_args: Default::default(),
             item_generics_num_lifetimes: Default::default(),
             main_def: Default::default(),
@@ -2286,7 +2283,8 @@ fn module_to_string(mut module: Module<'_>) -> Option<String> {
     loop {
         if let ModuleKind::Def(.., name) = module.kind {
             if let Some(parent) = module.parent {
-                names.push(name);
+                // `unwrap` is safe: the presence of a parent means it's not the crate root.
+                names.push(name.unwrap());
                 module = parent
             } else {
                 break;
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index c94846e95d4..9d6ae0aa9d1 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -8,9 +8,9 @@ use std::sync::Arc;
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::{self as ast, Crate, NodeId, attr};
 use rustc_ast_pretty::pprust;
-use rustc_attr_parsing::StabilityLevel;
+use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr};
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{Applicability, StashKey};
+use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
 use rustc_expand::base::{
     DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind,
 };
@@ -28,7 +28,7 @@ use rustc_session::lint::builtin::{
     UNUSED_MACRO_RULES, UNUSED_MACROS,
 };
 use rustc_session::parse::feature_err;
-use rustc_span::edit_distance::edit_distance;
+use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -124,14 +124,21 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
 }
 
 pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
-    let mut registered_tools = RegisteredTools::default();
     let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow();
+    registered_tools_ast(tcx.dcx(), pre_configured_attrs)
+}
+
+pub fn registered_tools_ast(
+    dcx: DiagCtxtHandle<'_>,
+    pre_configured_attrs: &[ast::Attribute],
+) -> RegisteredTools {
+    let mut registered_tools = RegisteredTools::default();
     for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) {
         for meta_item_inner in attr.meta_item_list().unwrap_or_default() {
             match meta_item_inner.ident() {
                 Some(ident) => {
                     if let Some(old_ident) = registered_tools.replace(ident) {
-                        tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered {
+                        dcx.emit_err(errors::ToolWasAlreadyRegistered {
                             span: ident.span,
                             tool: ident,
                             old_ident_span: old_ident.span,
@@ -139,7 +146,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
                     }
                 }
                 None => {
-                    tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers {
+                    dcx.emit_err(errors::ToolOnlyAcceptsIdentifiers {
                         span: meta_item_inner.span(),
                         tool: sym::register_tool,
                     });
@@ -168,7 +175,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
         hygiene::update_dollar_crate_names(|ctxt| {
             let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
             match self.resolve_crate_root(ident).kind {
-                ModuleKind::Def(.., name) if name != kw::Empty => name,
+                ModuleKind::Def(.., name) if let Some(name) = name => name,
                 _ => kw::Crate,
             }
         });
@@ -264,7 +271,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
             }
             InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang),
             InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive),
-            InvocationKind::GlobDelegation { ref item } => {
+            InvocationKind::GlobDelegation { ref item, .. } => {
                 let ast::AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
                 deleg_impl = Some(self.invocation_parent(invoc_id));
                 // It is sufficient to consider glob delegation a bang macro for now.
@@ -323,7 +330,6 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
     }
 
     fn check_unused_macros(&mut self) {
-        #[allow(rustc::potential_query_instability)] // FIXME
         for (_, &(node_id, ident)) in self.unused_macros.iter() {
             self.lint_buffer.buffer_lint(
                 UNUSED_MACROS,
@@ -576,7 +582,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         match res {
             Res::Def(DefKind::Macro(_), def_id) => {
                 if let Some(def_id) = def_id.as_local() {
-                    self.unused_macros.remove(&def_id);
+                    self.unused_macros.swap_remove(&def_id);
                     if self.proc_macro_stubs.contains(&def_id) {
                         self.dcx().emit_err(errors::ProcMacroSameCrate {
                             span: path.span,
@@ -652,13 +658,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
             && let [namespace, attribute, ..] = &*path.segments
             && namespace.ident.name == sym::diagnostic
-            && !(attribute.ident.name == sym::on_unimplemented
-                || attribute.ident.name == sym::do_not_recommend)
+            && ![sym::on_unimplemented, sym::do_not_recommend].contains(&attribute.ident.name)
         {
-            let distance =
-                edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
-
-            let typo_name = distance.map(|_| sym::on_unimplemented);
+            let typo_name = find_best_match_for_name(
+                &[sym::on_unimplemented, sym::do_not_recommend],
+                attribute.ident.name,
+                Some(5),
+            );
 
             self.tcx.sess.psess.buffer_lint(
                 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@@ -1068,11 +1074,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             );
             if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
                 let location = match parent_scope.module.kind {
-                    ModuleKind::Def(_, _, name) if name == kw::Empty => {
-                        "the crate root".to_string()
-                    }
                     ModuleKind::Def(kind, def_id, name) => {
-                        format!("{} `{name}`", kind.descr(def_id))
+                        if let Some(name) = name {
+                            format!("{} `{name}`", kind.descr(def_id))
+                        } else {
+                            "the crate root".to_string()
+                        }
                     }
                     ModuleKind::Block => "this scope".to_string(),
                 };
@@ -1125,6 +1132,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             edition,
         );
 
+        // The #[rustc_macro_edition_2021] attribute is used by the pin!() macro
+        // as a temporary workaround for a regression in expressiveness in Rust 2024.
+        // See https://github.com/rust-lang/rust/issues/138718.
+        if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021) {
+            ext.edition = Edition::Edition2021;
+        }
+
         if let Some(builtin_name) = ext.builtin_name {
             // The macro was marked with `#[rustc_builtin_macro]`.
             if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) {
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 52aaab77ebe..a32fe699016 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,13 +1,15 @@
 use std::mem;
 use std::ops::Range;
 
+use itertools::Itertools;
 use pulldown_cmark::{
     BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser, Tag,
 };
 use rustc_ast as ast;
 use rustc_ast::attr::AttributeExt;
 use rustc_ast::util::comments::beautify_doc_string;
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::unord::UnordSet;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, kw, sym};
@@ -422,7 +424,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
     );
     let mut links = Vec::new();
 
-    let mut refids = FxHashSet::default();
+    let mut refids = UnordSet::default();
 
     while let Some(event) = event_iter.next() {
         match event {
@@ -454,7 +456,7 @@ fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
         }
     }
 
-    for (label, refdef) in event_iter.reference_definitions().iter() {
+    for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
         if !refids.contains(label) {
             links.push(preprocess_link(&refdef.dest));
         }
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 e088417d72e..d56ca9c2453 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
@@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             hir::definitions::DefPathData::Ctor => "c",
             hir::definitions::DefPathData::AnonConst => "k",
             hir::definitions::DefPathData::OpaqueTy => "i",
+            hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
             hir::definitions::DefPathData::CrateRoot
             | hir::definitions::DefPathData::Use
             | hir::definitions::DefPathData::GlobalAsm
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 43b78423c72..1b01efda2a9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -50,6 +50,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("check-cfg", PrintKind::CheckCfg),
     ("code-models", PrintKind::CodeModels),
     ("crate-name", PrintKind::CrateName),
+    ("crate-root-lint-levels", PrintKind::CrateRootLintLevels),
     ("deployment-target", PrintKind::DeploymentTarget),
     ("file-names", PrintKind::FileNames),
     ("host-tuple", PrintKind::HostTuple),
@@ -58,6 +59,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("relocation-models", PrintKind::RelocationModels),
     ("split-debuginfo", PrintKind::SplitDebuginfo),
     ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
+    ("supported-crate-types", PrintKind::SupportedCrateTypes),
     ("sysroot", PrintKind::Sysroot),
     ("target-cpus", PrintKind::TargetCPUs),
     ("target-features", PrintKind::TargetFeatures),
@@ -880,6 +882,7 @@ pub enum PrintKind {
     CheckCfg,
     CodeModels,
     CrateName,
+    CrateRootLintLevels,
     DeploymentTarget,
     FileNames,
     HostTuple,
@@ -888,6 +891,7 @@ pub enum PrintKind {
     RelocationModels,
     SplitDebuginfo,
     StackProtectorStrategies,
+    SupportedCrateTypes,
     Sysroot,
     TargetCPUs,
     TargetFeatures,
@@ -2063,7 +2067,11 @@ fn check_print_request_stability(
     (print_name, print_kind): (&str, PrintKind),
 ) {
     match print_kind {
-        PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::TargetSpecJson
+        PrintKind::AllTargetSpecsJson
+        | PrintKind::CheckCfg
+        | PrintKind::CrateRootLintLevels
+        | PrintKind::SupportedCrateTypes
+        | PrintKind::TargetSpecJson
             if !unstable_opts.unstable_options =>
         {
             early_dcx.early_fatal(format!(
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 50f09c57107..bdeca91eb64 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -60,66 +60,76 @@ pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
 
 #[cfg(unix)]
 fn current_dll_path() -> Result<PathBuf, String> {
-    use std::ffi::{CStr, OsStr};
-    use std::os::unix::prelude::*;
-
-    #[cfg(not(target_os = "aix"))]
-    unsafe {
-        let addr = current_dll_path as usize as *mut _;
-        let mut info = std::mem::zeroed();
-        if libc::dladdr(addr, &mut info) == 0 {
-            return Err("dladdr failed".into());
-        }
-        if info.dli_fname.is_null() {
-            return Err("dladdr returned null pointer".into());
-        }
-        let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
-        let os = OsStr::from_bytes(bytes);
-        Ok(PathBuf::from(os))
-    }
-
-    #[cfg(target_os = "aix")]
-    unsafe {
-        // On AIX, the symbol `current_dll_path` references a function descriptor.
-        // A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
-        // * The address of the entry point of the function.
-        // * The TOC base address for the function.
-        // * The environment pointer.
-        // The function descriptor is in the data section.
-        let addr = current_dll_path as u64;
-        let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
-        loop {
-            if libc::loadquery(
-                libc::L_GETINFO,
-                buffer.as_mut_ptr() as *mut u8,
-                (size_of::<libc::ld_info>() * buffer.len()) as u32,
-            ) >= 0
-            {
-                break;
-            } else {
-                if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
-                    return Err("loadquery failed".into());
+    use std::sync::OnceLock;
+
+    // This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr`
+    // needs to iterate over the symbol table of librustc_driver.so until it finds a match.
+    // As such cache this to avoid recomputing if we try to get the sysroot in multiple places.
+    static CURRENT_DLL_PATH: OnceLock<Result<PathBuf, String>> = OnceLock::new();
+    CURRENT_DLL_PATH
+        .get_or_init(|| {
+            use std::ffi::{CStr, OsStr};
+            use std::os::unix::prelude::*;
+
+            #[cfg(not(target_os = "aix"))]
+            unsafe {
+                let addr = current_dll_path as usize as *mut _;
+                let mut info = std::mem::zeroed();
+                if libc::dladdr(addr, &mut info) == 0 {
+                    return Err("dladdr failed".into());
                 }
-                buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
-            }
-        }
-        let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
-        loop {
-            let data_base = (*current).ldinfo_dataorg as u64;
-            let data_end = data_base + (*current).ldinfo_datasize;
-            if (data_base..data_end).contains(&addr) {
-                let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
+                if info.dli_fname.is_null() {
+                    return Err("dladdr returned null pointer".into());
+                }
+                let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
                 let os = OsStr::from_bytes(bytes);
-                return Ok(PathBuf::from(os));
+                Ok(PathBuf::from(os))
             }
-            if (*current).ldinfo_next == 0 {
-                break;
+
+            #[cfg(target_os = "aix")]
+            unsafe {
+                // On AIX, the symbol `current_dll_path` references a function descriptor.
+                // A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
+                // * The address of the entry point of the function.
+                // * The TOC base address for the function.
+                // * The environment pointer.
+                // The function descriptor is in the data section.
+                let addr = current_dll_path as u64;
+                let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
+                loop {
+                    if libc::loadquery(
+                        libc::L_GETINFO,
+                        buffer.as_mut_ptr() as *mut u8,
+                        (size_of::<libc::ld_info>() * buffer.len()) as u32,
+                    ) >= 0
+                    {
+                        break;
+                    } else {
+                        if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
+                            return Err("loadquery failed".into());
+                        }
+                        buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
+                    }
+                }
+                let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
+                loop {
+                    let data_base = (*current).ldinfo_dataorg as u64;
+                    let data_end = data_base + (*current).ldinfo_datasize;
+                    if (data_base..data_end).contains(&addr) {
+                        let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
+                        let os = OsStr::from_bytes(bytes);
+                        return Ok(PathBuf::from(os));
+                    }
+                    if (*current).ldinfo_next == 0 {
+                        break;
+                    }
+                    current = (current as *mut i8).offset((*current).ldinfo_next as isize)
+                        as *mut libc::ld_info;
+                }
+                return Err(format!("current dll's address {} is not in the load map", addr));
             }
-            current =
-                (current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info;
-        }
-        return Err(format!("current dll's address {} is not in the load map", addr));
-    }
+        })
+        .clone()
 }
 
 #[cfg(windows)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b3be4b611f0..cd5e2c4173e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -94,45 +94,49 @@ fn tmod_push_impl(
     tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
     tmods: &mut Vec<TargetModifier>,
 ) {
-    tmods.push(TargetModifier { opt, value_name: tmod_vals.get(&opt).cloned().unwrap_or_default() })
+    if let Some(v) = tmod_vals.get(&opt) {
+        tmods.push(TargetModifier { opt, value_name: v.clone() })
+    }
 }
 
 macro_rules! tmod_push {
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $mods:expr, $tmod_vals:expr) => {
-        tmod_push_impl(
-            OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
-            $tmod_vals,
-            $mods,
-        );
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr) => {
+        if *$opt_expr != $init {
+            tmod_push_impl(
+                OptionsTargetModifiers::$struct_name($tmod_enum_name::$opt_name),
+                $tmod_vals,
+                $mods,
+            );
+        }
     };
 }
 
 macro_rules! gather_tmods {
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [SUBSTRUCT], [TARGET_MODIFIER]) => {
         compile_error!("SUBSTRUCT can't be target modifier");
     };
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [UNTRACKED], [TARGET_MODIFIER]) => {
-        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
+        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
     };
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [TRACKED], [TARGET_MODIFIER]) => {
-        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
+        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
     };
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [TRACKED_NO_CRATE_HASH], [TARGET_MODIFIER]) => {
-        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $mods, $tmod_vals)
+        tmod_push!($struct_name, $tmod_enum_name, $opt_name, $opt_expr, $init, $mods, $tmod_vals)
     };
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [SUBSTRUCT], []) => {
         $opt_expr.gather_target_modifiers($mods, $tmod_vals);
     };
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [UNTRACKED], []) => {{}};
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [TRACKED], []) => {{}};
-    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $mods:expr, $tmod_vals:expr,
+    ($struct_name:ident, $tmod_enum_name:ident, $opt_name:ident, $opt_expr:expr, $init:expr, $mods:expr, $tmod_vals:expr,
         [TRACKED_NO_CRATE_HASH], []) => {{}};
 }
 
@@ -474,7 +478,8 @@ macro_rules! tmod_enum {
                 $($pout)*
                 Self::$opt => {
                     let mut parsed : $t = Default::default();
-                    parse::$parse(&mut parsed, Some($puser_value));
+                    let val = if $puser_value.is_empty() { None } else { Some($puser_value) };
+                    parse::$parse(&mut parsed, val);
                     ExtendedTargetModifierInfo {
                         prefix: $prefix.to_string(),
                         name: stringify!($opt).to_string().replace('_', "-"),
@@ -569,7 +574,7 @@ macro_rules! options {
             _tmod_vals: &BTreeMap<OptionsTargetModifiers, String>,
         ) {
             $({
-                gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, _mods, _tmod_vals,
+                gather_tmods!($struct_name, $tmod_enum_name, $opt, &self.$opt, $init, _mods, _tmod_vals,
                     [$dep_tracking_marker], [$($tmod),*]);
             })*
         }
@@ -681,10 +686,9 @@ fn build_options<O: Default>(
                         ),
                     }
                 }
-                if let Some(tmod) = *tmod
-                    && let Some(value) = value
-                {
-                    target_modifiers.insert(tmod, value.to_string());
+                if let Some(tmod) = *tmod {
+                    let v = value.map_or(String::new(), ToOwned::to_owned);
+                    target_modifiers.insert(tmod, v);
                 }
             }
             None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")),
@@ -1886,7 +1890,8 @@ pub mod parse {
     pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
         match v {
             Some("spec") => *slot = WasmCAbi::Spec,
-            Some("legacy") => *slot = WasmCAbi::Legacy,
+            // Explicitly setting the `-Z` flag suppresses the lint.
+            Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false },
             _ => return false,
         }
         true
@@ -2170,6 +2175,8 @@ options! {
         them only if an error has not been emitted"),
     ehcont_guard: bool = (false, parse_bool, [TRACKED],
         "generate Windows EHCont Guard tables"),
+    embed_metadata: bool = (true, parse_bool, [TRACKED],
+        "embed metadata in rlibs and dylibs (default: yes)"),
     embed_source: bool = (false, parse_bool, [TRACKED],
         "embed source text in DWARF debug sections (default: no)"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
@@ -2227,7 +2234,8 @@ options! {
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify extended properties for incr. comp. (default: no):
         - hashes of green query instances
-        - hash collisions of query keys"),
+        - hash collisions of query keys
+        - hash collisions when creating dep-nodes"),
     inline_llvm: bool = (true, parse_bool, [TRACKED],
         "enable LLVM inlining (default: yes)"),
     inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -2599,7 +2607,7 @@ written to standard error output)"),
         Requires `-Clto[=[fat,yes]]`"),
     wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
         "whether to build a wasi command or reactor"),
-    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy, parse_wasm_c_abi, [TRACKED],
+    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED],
         "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
     write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
         "whether long type names should be written to files instead of being printed in errors"),
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index b37a80274c0..a24919e434c 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -103,7 +103,7 @@ pub fn filename_for_input(
             OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
         }
         CrateType::Staticlib => {
-            let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix);
+            let (prefix, suffix) = sess.staticlib_components(false);
             OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
         }
         CrateType::Executable => {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 1c9adea281d..a87b1961a99 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -586,6 +586,14 @@ impl Session {
             .or(self.target.options.default_visibility)
             .unwrap_or(SymbolVisibility::Interposable)
     }
+
+    pub fn staticlib_components(&self, verbatim: bool) -> (&str, &str) {
+        if verbatim {
+            ("", "")
+        } else {
+            (&*self.target.staticlib_prefix, &*self.target.staticlib_suffix)
+        }
+    }
 }
 
 // JUSTIFICATION: defn of the suggested wrapper fns
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index fcede379b89..2243e831b66 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -149,14 +149,15 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
                 arg[a.len()..].to_string()
             };
             let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
-            if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
+            if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&option) {
                 excluded_cargo_defaults = true;
             } else {
                 result.push(a.to_string());
-                match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
-                    Some(s) => result.push(format!("{s}=[REDACTED]")),
-                    None => result.push(content),
-                }
+                result.push(if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&option) {
+                    format!("{option}=[REDACTED]")
+                } else {
+                    content
+                });
             }
         }
     }
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 8a2baaa42e2..4f3202b694c 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -118,7 +118,7 @@ pub fn edit_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<u
     // Check one isn't less than half the length of the other. If this is true then there is a
     // big difference in length.
     let big_len_diff = (n * 2) < m || (m * 2) < n;
-    let len_diff = if n < m { m - n } else { n - m };
+    let len_diff = m.abs_diff(n);
     let distance = edit_distance(a, b, limit + len_diff)?;
 
     // This is the crux, subtracting length difference means exact substring matches will now be 0
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 62027caa353..9959e98e3dd 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -27,9 +27,9 @@
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
 use std::collections::hash_set::Entry as SetEntry;
-use std::fmt;
 use std::hash::Hash;
 use std::sync::Arc;
+use std::{fmt, iter, mem};
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -57,7 +57,11 @@ pub struct SyntaxContext(u32);
 impl !Ord for SyntaxContext {}
 impl !PartialOrd for SyntaxContext {}
 
-#[derive(Debug, Encodable, Decodable, Clone)]
+/// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal.
+/// The other fields are only for caching.
+type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
+
+#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)]
 pub struct SyntaxContextData {
     outer_expn: ExpnId,
     outer_transparency: Transparency,
@@ -70,6 +74,46 @@ pub struct SyntaxContextData {
     dollar_crate_name: Symbol,
 }
 
+impl SyntaxContextData {
+    fn new(
+        (parent, outer_expn, outer_transparency): SyntaxContextKey,
+        opaque: SyntaxContext,
+        opaque_and_semitransparent: SyntaxContext,
+    ) -> SyntaxContextData {
+        SyntaxContextData {
+            outer_expn,
+            outer_transparency,
+            parent,
+            opaque,
+            opaque_and_semitransparent,
+            dollar_crate_name: kw::DollarCrate,
+        }
+    }
+
+    fn root() -> SyntaxContextData {
+        SyntaxContextData {
+            outer_expn: ExpnId::root(),
+            outer_transparency: Transparency::Opaque,
+            parent: SyntaxContext::root(),
+            opaque: SyntaxContext::root(),
+            opaque_and_semitransparent: SyntaxContext::root(),
+            dollar_crate_name: kw::DollarCrate,
+        }
+    }
+
+    fn decode_placeholder() -> SyntaxContextData {
+        SyntaxContextData { dollar_crate_name: kw::Empty, ..SyntaxContextData::root() }
+    }
+
+    fn is_decode_placeholder(&self) -> bool {
+        self.dollar_crate_name == kw::Empty
+    }
+
+    fn key(&self) -> SyntaxContextKey {
+        (self.parent, self.outer_expn, self.outer_transparency)
+    }
+}
+
 rustc_index::newtype_index! {
     /// A unique ID associated with a macro invocation and expansion.
     #[orderable]
@@ -342,7 +386,7 @@ pub(crate) struct HygieneData {
     foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
     expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
     syntax_context_data: Vec<SyntaxContextData>,
-    syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
+    syntax_context_map: FxHashMap<SyntaxContextKey, SyntaxContext>,
     /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
     /// This is used by `update_disambiguator` to keep track of which `ExpnData`s
     /// would have collisions without a disambiguator.
@@ -361,22 +405,16 @@ impl HygieneData {
             None,
         );
 
+        let root_ctxt_data = SyntaxContextData::root();
         HygieneData {
             local_expn_data: IndexVec::from_elem_n(Some(root_data), 1),
             local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1),
             foreign_expn_data: FxHashMap::default(),
             foreign_expn_hashes: FxHashMap::default(),
-            expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
+            expn_hash_to_expn_id: iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
                 .collect(),
-            syntax_context_data: vec![SyntaxContextData {
-                outer_expn: ExpnId::root(),
-                outer_transparency: Transparency::Opaque,
-                parent: SyntaxContext(0),
-                opaque: SyntaxContext(0),
-                opaque_and_semitransparent: SyntaxContext(0),
-                dollar_crate_name: kw::DollarCrate,
-            }],
-            syntax_context_map: FxHashMap::default(),
+            syntax_context_data: vec![root_ctxt_data],
+            syntax_context_map: iter::once((root_ctxt_data.key(), SyntaxContext(0))).collect(),
             expn_data_disambiguators: UnhashMap::default(),
         }
     }
@@ -425,23 +463,28 @@ impl HygieneData {
     }
 
     fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
+        debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
         self.syntax_context_data[ctxt.0 as usize].opaque
     }
 
     fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
+        debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
         self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
     }
 
     fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
+        debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
         self.syntax_context_data[ctxt.0 as usize].outer_expn
     }
 
     fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
+        debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
         let data = &self.syntax_context_data[ctxt.0 as usize];
         (data.outer_expn, data.outer_transparency)
     }
 
     fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
+        debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
         self.syntax_context_data[ctxt.0 as usize].parent
     }
 
@@ -515,7 +558,7 @@ impl HygieneData {
     ) -> SyntaxContext {
         assert_ne!(expn_id, ExpnId::root());
         if transparency == Transparency::Opaque {
-            return self.apply_mark_internal(ctxt, expn_id, transparency);
+            return self.alloc_ctxt(ctxt, expn_id, transparency);
         }
 
         let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
@@ -526,7 +569,7 @@ impl HygieneData {
         };
 
         if call_site_ctxt.is_root() {
-            return self.apply_mark_internal(ctxt, expn_id, transparency);
+            return self.alloc_ctxt(ctxt, expn_id, transparency);
         }
 
         // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
@@ -539,75 +582,60 @@ impl HygieneData {
         //
         // See the example at `test/ui/hygiene/legacy_interaction.rs`.
         for (expn_id, transparency) in self.marks(ctxt) {
-            call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
+            call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency);
         }
-        self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
+        self.alloc_ctxt(call_site_ctxt, expn_id, transparency)
     }
 
-    fn apply_mark_internal(
+    /// Allocate a new context with the given key, or retrieve it from cache if the given key
+    /// already exists. The auxiliary fields are calculated from the key.
+    fn alloc_ctxt(
         &mut self,
-        ctxt: SyntaxContext,
+        parent: SyntaxContext,
         expn_id: ExpnId,
         transparency: Transparency,
     ) -> SyntaxContext {
-        let syntax_context_data = &mut self.syntax_context_data;
-        let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
-        let mut opaque_and_semitransparent =
-            syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
-
-        if transparency >= Transparency::Opaque {
-            let parent = opaque;
-            opaque = *self
-                .syntax_context_map
-                .entry((parent, expn_id, transparency))
-                .or_insert_with(|| {
-                    let new_opaque = SyntaxContext(syntax_context_data.len() as u32);
-                    syntax_context_data.push(SyntaxContextData {
-                        outer_expn: expn_id,
-                        outer_transparency: transparency,
-                        parent,
-                        opaque: new_opaque,
-                        opaque_and_semitransparent: new_opaque,
-                        dollar_crate_name: kw::DollarCrate,
-                    });
-                    new_opaque
-                });
-        }
+        debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder());
 
-        if transparency >= Transparency::SemiTransparent {
-            let parent = opaque_and_semitransparent;
-            opaque_and_semitransparent = *self
-                .syntax_context_map
-                .entry((parent, expn_id, transparency))
-                .or_insert_with(|| {
-                    let new_opaque_and_semitransparent =
-                        SyntaxContext(syntax_context_data.len() as u32);
-                    syntax_context_data.push(SyntaxContextData {
-                        outer_expn: expn_id,
-                        outer_transparency: transparency,
-                        parent,
-                        opaque,
-                        opaque_and_semitransparent: new_opaque_and_semitransparent,
-                        dollar_crate_name: kw::DollarCrate,
-                    });
-                    new_opaque_and_semitransparent
-                });
+        // Look into the cache first.
+        let key = (parent, expn_id, transparency);
+        if let Some(ctxt) = self.syntax_context_map.get(&key) {
+            return *ctxt;
         }
 
-        let parent = ctxt;
-        *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
-            let new_opaque_and_semitransparent_and_transparent =
-                SyntaxContext(syntax_context_data.len() as u32);
-            syntax_context_data.push(SyntaxContextData {
-                outer_expn: expn_id,
-                outer_transparency: transparency,
-                parent,
-                opaque,
-                opaque_and_semitransparent,
-                dollar_crate_name: kw::DollarCrate,
-            });
-            new_opaque_and_semitransparent_and_transparent
-        })
+        // Reserve a new syntax context.
+        let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len());
+        self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
+        self.syntax_context_map.insert(key, ctxt);
+
+        // Opaque and semi-transparent versions of the parent. Note that they may be equal to the
+        // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
+        // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
+        // and semi-transparents.
+        let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
+        let parent_opaque_and_semitransparent =
+            self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
+
+        // Evaluate opaque and semi-transparent versions of the new syntax context.
+        let (opaque, opaque_and_semitransparent) = match transparency {
+            Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
+            Transparency::SemiTransparent => (
+                parent_opaque,
+                // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+                self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+            ),
+            Transparency::Opaque => (
+                // Will be the same as `ctxt` if the expn chain contains only opaques.
+                self.alloc_ctxt(parent_opaque, expn_id, transparency),
+                // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
+                self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+            ),
+        };
+
+        // Fill the full data, now that we have it.
+        self.syntax_context_data[ctxt.as_u32() as usize] =
+            SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
+        ctxt
     }
 }
 
@@ -626,25 +654,26 @@ pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
 
 pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
     // The new contexts that need updating are at the end of the list and have `$crate` as a name.
-    let (len, to_update) = HygieneData::with(|data| {
-        (
-            data.syntax_context_data.len(),
-            data.syntax_context_data
-                .iter()
-                .rev()
-                .take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate)
-                .count(),
-        )
+    // Also decoding placeholders can be encountered among both old and new contexts.
+    let mut to_update = vec![];
+    HygieneData::with(|data| {
+        for (idx, scdata) in data.syntax_context_data.iter().enumerate().rev() {
+            if scdata.dollar_crate_name == kw::DollarCrate {
+                to_update.push((idx, kw::DollarCrate));
+            } else if !scdata.is_decode_placeholder() {
+                break;
+            }
+        }
     });
     // The callback must be called from outside of the `HygieneData` lock,
     // since it will try to acquire it too.
-    let range_to_update = len - to_update..len;
-    let names: Vec<_> =
-        range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
+    for (idx, name) in &mut to_update {
+        *name = get_name(SyntaxContext::from_usize(*idx));
+    }
     HygieneData::with(|data| {
-        range_to_update.zip(names).for_each(|(idx, name)| {
+        for (idx, name) in to_update {
             data.syntax_context_data[idx].dollar_crate_name = name;
-        })
+        }
     })
 }
 
@@ -713,6 +742,10 @@ impl SyntaxContext {
         SyntaxContext(raw as u32)
     }
 
+    fn from_usize(raw: usize) -> SyntaxContext {
+        SyntaxContext(u32::try_from(raw).unwrap())
+    }
+
     /// Extend a syntax context with a given expansion and transparency.
     pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
         HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
@@ -893,7 +926,10 @@ impl SyntaxContext {
     }
 
     pub(crate) fn dollar_crate_name(self) -> Symbol {
-        HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
+        HygieneData::with(|data| {
+            debug_assert!(!data.syntax_context_data[self.0 as usize].is_decode_placeholder());
+            data.syntax_context_data[self.0 as usize].dollar_crate_name
+        })
     }
 
     pub fn edition(self) -> Edition {
@@ -1244,7 +1280,7 @@ impl HygieneEncodeContext {
 
             // Consume the current round of SyntaxContexts.
             // Drop the lock() temporary early
-            let latest_ctxts = { std::mem::take(&mut *self.latest_ctxts.lock()) };
+            let latest_ctxts = { mem::take(&mut *self.latest_ctxts.lock()) };
 
             // It's fine to iterate over a HashMap, because the serialization
             // of the table that we insert data into doesn't depend on insertion
@@ -1256,7 +1292,7 @@ impl HygieneEncodeContext {
                 }
             });
 
-            let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
+            let latest_expns = { mem::take(&mut *self.latest_expns.lock()) };
 
             // Same as above, this is fine as we are inserting into a order-independent hashset
             #[allow(rustc::potential_query_instability)]
@@ -1373,9 +1409,11 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
         return SyntaxContext::root();
     }
 
-    let ctxt = {
+    let pending_ctxt = {
         let mut inner = context.inner.lock();
 
+        // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
+        // raw ids from different crate metadatas.
         if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() {
             // This has already been decoded.
             return ctxt;
@@ -1383,40 +1421,36 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
 
         match inner.decoding.entry(raw_id) {
             Entry::Occupied(ctxt_entry) => {
+                let pending_ctxt = *ctxt_entry.get();
                 match context.local_in_progress.borrow_mut().entry(raw_id) {
-                    SetEntry::Occupied(..) => {
-                        // We're decoding this already on the current thread. Return here
-                        // and let the function higher up the stack finish decoding to handle
-                        // recursive cases.
-                        return *ctxt_entry.get();
-                    }
+                    // We're decoding this already on the current thread. Return here and let the
+                    // function higher up the stack finish decoding to handle recursive cases.
+                    // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok
+                    // during reminder of the decoding process, it's certainly not ok after the
+                    // top level decoding function returns.
+                    SetEntry::Occupied(..) => return pending_ctxt,
+                    // Some other thread is currently decoding this.
+                    // Race with it (alternatively we could wait here).
+                    // We cannot return this value, unlike in the recursive case above, because it
+                    // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code.
                     SetEntry::Vacant(entry) => {
                         entry.insert();
-
-                        // Some other thread is current decoding this. Race with it.
-                        *ctxt_entry.get()
+                        pending_ctxt
                     }
                 }
             }
             Entry::Vacant(entry) => {
-                // We are the first thread to start decoding. Mark the current thread as being progress.
+                // We are the first thread to start decoding. Mark the current thread as being
+                // progress.
                 context.local_in_progress.borrow_mut().insert(raw_id);
 
                 // Allocate and store SyntaxContext id *before* calling the decoder function,
                 // as the SyntaxContextData may reference itself.
                 let new_ctxt = HygieneData::with(|hygiene_data| {
-                    let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
                     // Push a dummy SyntaxContextData to ensure that nobody else can get the
-                    // same ID as us. This will be overwritten after call `decode_Data`
-                    hygiene_data.syntax_context_data.push(SyntaxContextData {
-                        outer_expn: ExpnId::root(),
-                        outer_transparency: Transparency::Transparent,
-                        parent: SyntaxContext::root(),
-                        opaque: SyntaxContext::root(),
-                        opaque_and_semitransparent: SyntaxContext::root(),
-                        dollar_crate_name: kw::Empty,
-                    });
-                    new_ctxt
+                    // same ID as us. This will be overwritten after call `decode_data`.
+                    hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder());
+                    SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1)
                 });
                 entry.insert(new_ctxt);
                 new_ctxt
@@ -1426,27 +1460,42 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
 
     // Don't try to decode data while holding the lock, since we need to
     // be able to recursively decode a SyntaxContext
-    let mut ctxt_data = decode_data(d, raw_id);
-    // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`
-    // We don't care what the encoding crate set this to - we want to resolve it
-    // from the perspective of the current compilation session
-    ctxt_data.dollar_crate_name = kw::DollarCrate;
-
-    // Overwrite the dummy data with our decoded SyntaxContextData
-    HygieneData::with(|hygiene_data| {
-        if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize)
-            && old.outer_expn == ctxt_data.outer_expn
-            && old.outer_transparency == ctxt_data.outer_transparency
-            && old.parent == ctxt_data.parent
-        {
-            ctxt_data = old.clone();
+    let ctxt_data = decode_data(d, raw_id);
+    let ctxt_key = ctxt_data.key();
+
+    let ctxt = HygieneData::with(|hygiene_data| {
+        match hygiene_data.syntax_context_map.get(&ctxt_key) {
+            // Ensure that syntax contexts are unique.
+            // If syntax contexts with the given key already exists, reuse it instead of
+            // using `pending_ctxt`.
+            // `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
+            // Hopefully its value isn't stored anywhere during decoding and its dummy data
+            // is never accessed later. The `is_decode_placeholder` asserts on all
+            // accesses to syntax context data attempt to ensure it.
+            Some(&ctxt) => ctxt,
+            // This is a completely new context.
+            // Overwrite its placeholder data with our decoded data.
+            None => {
+                let ctxt_data_ref =
+                    &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize];
+                let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data);
+                // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
+                // We don't care what the encoding crate set this to - we want to resolve it
+                // from the perspective of the current compilation session.
+                ctxt_data_ref.dollar_crate_name = kw::DollarCrate;
+                // Make sure nothing weird happened while `decode_data` was running.
+                if !prev_ctxt_data.is_decode_placeholder() {
+                    // Another thread may have already inserted the decoded data,
+                    // but the decoded data should match.
+                    assert_eq!(prev_ctxt_data, *ctxt_data_ref);
+                }
+                hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt);
+                pending_ctxt
+            }
         }
-
-        hygiene_data.syntax_context_data[ctxt.as_u32() as usize] = ctxt_data;
     });
 
     // Mark the context as completed
-
     context.local_in_progress.borrow_mut().remove(&raw_id);
 
     let mut inner = context.inner.lock();
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f19d4d9f362..9e6ba2e1b9c 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -876,7 +876,7 @@ impl Span {
         self.ctxt()
             .outer_expn_data()
             .allow_internal_unstable
-            .is_some_and(|features| features.iter().any(|&f| f == feature))
+            .is_some_and(|features| features.contains(&feature))
     }
 
     /// Checks if this span arises from a compiler desugaring of kind `kind`.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d83863b1f7a..bc853fe9079 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -26,13 +26,13 @@ symbols! {
     // documents (such as the Rust Reference) about whether it is a keyword
     // (e.g. `_`).
     //
-    // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*` predicates and
-    // `used_keywords`.
-    // But this should rarely be necessary if the keywords are kept in alphabetic order.
+    // If you modify this list, adjust any relevant `Symbol::{is,can_be}_*`
+    // predicates and `used_keywords`. Also consider adding new keywords to the
+    // `ui/parser/raw/raw-idents.rs` test.
     Keywords {
         // Special reserved identifiers used internally for elided lifetimes,
         // unnamed method parameters, crate root module, error recovery etc.
-        // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved`
+        // Matching predicates: `is_special`/`is_reserved`
         //
         // Notes about `kw::Empty`:
         // - Its use can blur the lines between "empty symbol" and "no symbol".
@@ -42,13 +42,16 @@ symbols! {
         //   present, it's better to use `sym::dummy` than `kw::Empty`, because
         //   it's clearer that it's intended as a dummy value, and more likely
         //   to be detected if it accidentally does get used.
+        // tidy-alphabetical-start
+        DollarCrate:        "$crate",
         Empty:              "",
         PathRoot:           "{{root}}",
-        DollarCrate:        "$crate",
         Underscore:         "_",
+        // tidy-alphabetical-end
 
         // Keywords that are used in stable Rust.
-        // Matching predicates: `is_any_keyword`, `is_used_keyword_always`/`is_reserved`
+        // Matching predicates: `is_used_keyword_always`/`is_reserved`
+        // tidy-alphabetical-start
         As:                 "as",
         Break:              "break",
         Const:              "const",
@@ -84,9 +87,11 @@ symbols! {
         Use:                "use",
         Where:              "where",
         While:              "while",
+        // tidy-alphabetical-end
 
         // Keywords that are used in unstable Rust or reserved for future use.
-        // Matching predicates: `is_any_keyword`, `is_unused_keyword_always`/`is_reserved`
+        // Matching predicates: `is_unused_keyword_always`/`is_reserved`
+        // tidy-alphabetical-start
         Abstract:           "abstract",
         Become:             "become",
         Box:                "box",
@@ -99,41 +104,48 @@ symbols! {
         Unsized:            "unsized",
         Virtual:            "virtual",
         Yield:              "yield",
+        // tidy-alphabetical-end
 
         // Edition-specific keywords that are used in stable Rust.
-        // Matching predicates: `is_any_keyword`, `is_used_keyword_conditional`/`is_reserved` (if
+        // Matching predicates: `is_used_keyword_conditional`/`is_reserved` (if
         // the edition suffices)
+        // tidy-alphabetical-start
         Async:              "async", // >= 2018 Edition only
         Await:              "await", // >= 2018 Edition only
         Dyn:                "dyn", // >= 2018 Edition only
+        // tidy-alphabetical-end
 
         // Edition-specific keywords that are used in unstable Rust or reserved for future use.
-        // Matching predicates: `is_any_keyword`, `is_unused_keyword_conditional`/`is_reserved` (if
+        // Matching predicates: `is_unused_keyword_conditional`/`is_reserved` (if
         // the edition suffices)
+        // tidy-alphabetical-start
         Gen:                "gen", // >= 2024 Edition only
         Try:                "try", // >= 2018 Edition only
-
-        // NOTE: When adding new keywords, consider adding them to the ui/parser/raw/raw-idents.rs test.
+        // tidy-alphabetical-end
 
         // "Lifetime keywords": regular keywords with a leading `'`.
-        // Matching predicates: `is_any_keyword`
-        UnderscoreLifetime: "'_",
+        // Matching predicates: none
+        // tidy-alphabetical-start
         StaticLifetime:     "'static",
+        UnderscoreLifetime: "'_",
+        // tidy-alphabetical-end
 
         // Weak keywords, have special meaning only in specific contexts.
-        // Matching predicates: `is_any_keyword`
+        // Matching predicates: `is_weak`
+        // tidy-alphabetical-start
         Auto:               "auto",
         Builtin:            "builtin",
         Catch:              "catch",
+        ContractEnsures:    "contract_ensures",
+        ContractRequires:   "contract_requires",
         Default:            "default",
         MacroRules:         "macro_rules",
         Raw:                "raw",
         Reuse:              "reuse",
-        ContractEnsures:  "contract_ensures",
-        ContractRequires: "contract_requires",
         Safe:               "safe",
         Union:              "union",
         Yeet:               "yeet",
+        // tidy-alphabetical-end
     }
 
     // Pre-interned symbols that can be referred to with `rustc_span::sym::*`.
@@ -611,6 +623,7 @@ symbols! {
         cfg_target_has_atomic_equal_alignment,
         cfg_target_thread_local,
         cfg_target_vendor,
+        cfg_trace: "<cfg>", // must not be a valid identifier
         cfg_ub_checks,
         cfg_version,
         cfi,
@@ -973,6 +986,7 @@ symbols! {
         field_init_shorthand,
         file,
         file_options,
+        flags,
         float,
         float_to_int_unchecked,
         floorf128,
@@ -1003,7 +1017,6 @@ symbols! {
         forbid,
         forget,
         format,
-        format_alignment,
         format_args,
         format_args_capture,
         format_args_macro,
@@ -1365,6 +1378,7 @@ symbols! {
         movbe_target_feature,
         move_ref_pattern,
         move_size_limit,
+        movrs_target_feature,
         mul,
         mul_assign,
         mul_with_overflow,
@@ -1376,6 +1390,7 @@ symbols! {
         naked,
         naked_asm,
         naked_functions,
+        naked_functions_target_feature,
         name,
         names,
         native_link_modifiers,
@@ -1557,6 +1572,7 @@ symbols! {
         pointer_like,
         poll,
         poll_next,
+        position,
         post_dash_lto: "post-lto",
         postfix_match,
         powerpc_target_feature,
@@ -1572,6 +1588,7 @@ symbols! {
         precise_capturing,
         precise_capturing_in_traits,
         precise_pointer_size_matching,
+        precision,
         pref_align_of,
         prefetch_read_data,
         prefetch_read_instruction,
@@ -1758,6 +1775,7 @@ symbols! {
         rustc_deallocator,
         rustc_def_path,
         rustc_default_body_unstable,
+        rustc_delayed_bug_from_inside_query,
         rustc_deny_explicit_impl,
         rustc_deprecated_safe_2024,
         rustc_diagnostic_item,
@@ -1774,7 +1792,6 @@ symbols! {
         rustc_dump_user_args,
         rustc_dump_vtable,
         rustc_effective_visibility,
-        rustc_error,
         rustc_evaluate_where_clauses,
         rustc_expected_cgu_reuse,
         rustc_force_inline,
@@ -1794,6 +1811,7 @@ symbols! {
         rustc_lint_opt_ty,
         rustc_lint_query_instability,
         rustc_lint_untracked_query_information,
+        rustc_macro_edition_2021,
         rustc_macro_transparency,
         rustc_main,
         rustc_mir,
@@ -2105,7 +2123,9 @@ symbols! {
         type_changing_struct_update,
         type_const,
         type_id,
+        type_ir_infer_ctxt_like,
         type_ir_inherent,
+        type_ir_interner,
         type_length_limit,
         type_macros,
         type_name,
@@ -2258,6 +2278,7 @@ symbols! {
         wasm_target_feature,
         where_clause_attrs,
         while_let,
+        width,
         windows,
         windows_subsystem,
         with_negative_coherence,
@@ -2676,11 +2697,6 @@ pub mod sym {
 }
 
 impl Symbol {
-    /// Don't use this unless you're doing something very loose and heuristic-y.
-    pub fn is_any_keyword(self) -> bool {
-        self >= kw::As && self <= kw::Yeet
-    }
-
     fn is_special(self) -> bool {
         self <= kw::Underscore
     }
@@ -2689,14 +2705,14 @@ impl Symbol {
         self >= kw::As && self <= kw::While
     }
 
-    fn is_used_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool {
-        (self >= kw::Async && self <= kw::Dyn) && edition() >= Edition::Edition2018
-    }
-
     fn is_unused_keyword_always(self) -> bool {
         self >= kw::Abstract && self <= kw::Yield
     }
 
+    fn is_used_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool {
+        (self >= kw::Async && self <= kw::Dyn) && edition() >= Edition::Edition2018
+    }
+
     fn is_unused_keyword_conditional(self, edition: impl Copy + FnOnce() -> Edition) -> bool {
         self == kw::Gen && edition().at_least_rust_2024()
             || self == kw::Try && edition().at_least_rust_2018()
@@ -2710,6 +2726,10 @@ impl Symbol {
             || self.is_unused_keyword_conditional(edition)
     }
 
+    pub fn is_weak(self) -> bool {
+        self >= kw::Auto && self <= kw::Yeet
+    }
+
     /// A keyword or reserved identifier that can be used as a path segment.
     pub fn is_path_segment_keyword(self) -> bool {
         self == kw::Super
@@ -2737,11 +2757,6 @@ impl Symbol {
 }
 
 impl Ident {
-    /// Don't use this unless you're doing something very loose and heuristic-y.
-    pub fn is_any_keyword(self) -> bool {
-        self.name.is_any_keyword()
-    }
-
     /// Returns `true` for reserved identifiers used internally for elided lifetimes,
     /// unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special(self) -> bool {
@@ -2791,7 +2806,7 @@ impl Ident {
 /// *Note:* Please update this if a new keyword is added beyond the current
 /// range.
 pub fn used_keywords(edition: impl Copy + FnOnce() -> Edition) -> Vec<Symbol> {
-    (kw::Empty.as_u32()..kw::Yeet.as_u32())
+    (kw::DollarCrate.as_u32()..kw::Yeet.as_u32())
         .filter_map(|kw| {
             let kw = Symbol::new(kw);
             if kw.is_used_keyword_always() || kw.is_used_keyword_conditional(edition) {
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 88754f1f15b..2802e891807 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
     loop {
         let key = tcx.def_key(ty_def_id);
         match key.disambiguated_data.data {
-            DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
+            DefPathData::TypeNs(_)
+            | DefPathData::ValueNs(_)
+            | DefPathData::Closure
+            | DefPathData::SyntheticCoroutineBody => {
                 instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
                 debug!(?instance_ty);
                 break;
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index d824a23279b..99d44bcd7eb 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             DefPathData::Ctor => 'c',
             DefPathData::AnonConst => 'k',
             DefPathData::OpaqueTy => 'i',
+            DefPathData::SyntheticCoroutineBody => 's',
 
             // These should never show up as `path_append` arguments.
             DefPathData::CrateRoot
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 6d0ee3c7ee5..a52b2b76bc1 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -705,7 +705,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "xtensa" => xtensa::compute_abi_info(cx, self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
             "wasm32" => {
-                if spec.os == "unknown" && cx.wasm_c_abi_opt() == WasmCAbi::Legacy {
+                if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) {
                     wasm::compute_wasm_abi_info(self)
                 } else {
                     wasm::compute_c_abi_info(cx, self)
diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs
index 364a6551131..881168c98c3 100644
--- a/compiler/rustc_target/src/callconv/wasm.rs
+++ b/compiler/rustc_target/src/callconv/wasm.rs
@@ -10,6 +10,9 @@ where
     if val.layout.is_aggregate() {
         if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
             let size = val.layout.size;
+            // This size check also catches over-aligned scalars as `size` will be rounded up to a
+            // multiple of the alignment, and the default alignment of all scalar types on wasm
+            // equals their size.
             if unit.size == size {
                 val.cast_to(unit);
                 return true;
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index 134405f3630..4b6de5e18f5 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -103,6 +103,12 @@ impl Target {
                     base.$key_name = Some(s);
                 }
             } );
+            ($key_name:ident, Option<StaticCow<str>>) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                if let Some(s) = obj.remove(&name).and_then(|b| Some(b.as_str()?.to_string())) {
+                    base.$key_name = Some(s.into());
+                }
+            } );
             ($key_name:ident, BinaryFormat) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 obj.remove(&name).and_then(|f| f.as_str().and_then(|s| {
@@ -623,6 +629,7 @@ impl Target {
         key!(stack_probes, StackProbeType)?;
         key!(min_global_align, Option<u64>);
         key!(default_codegen_units, Option<u64>);
+        key!(default_codegen_backend, Option<StaticCow<str>>);
         key!(trap_unreachable, bool);
         key!(requires_lto, bool);
         key!(singlethread, bool);
@@ -801,6 +808,7 @@ impl ToJson for Target {
         target_option_val!(stack_probes);
         target_option_val!(min_global_align);
         target_option_val!(default_codegen_units);
+        target_option_val!(default_codegen_backend);
         target_option_val!(trap_unreachable);
         target_option_val!(requires_lto);
         target_option_val!(singlethread);
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 1887134c575..7234d1dc63e 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2234,7 +2234,10 @@ pub enum WasmCAbi {
     /// Spec-compliant C ABI.
     Spec,
     /// Legacy ABI. Which is non-spec-compliant.
-    Legacy,
+    Legacy {
+        /// Indicates whether the `wasm_c_abi` lint should be emitted.
+        with_lint: bool,
+    },
 }
 
 pub trait HasWasmCAbiOpt {
@@ -3342,7 +3345,10 @@ impl Target {
                 );
             }
             "arm" => {
-                check!(self.llvm_floatabi.is_some(), "ARM targets must specify their float ABI",)
+                check!(
+                    self.llvm_floatabi.is_some(),
+                    "ARM targets must set `llvm-floatabi` to `hard` or `soft`",
+                )
             }
             _ => {}
         }
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
index dbe1540364a..860629b08e1 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
@@ -2,7 +2,7 @@ use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
-        llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
+        llvm_target: "armv5te-unknown-linux-gnueabi".into(),
         metadata: TargetMetadata {
             description: Some("Armv5TE Linux with uClibc".into()),
             tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 5d292bbf8ad..6a83835059e 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
     );
 
     Target {
-        llvm_target: "thumbv7a-vita-eabihf".into(),
+        llvm_target: "thumbv7a-sony-vita-eabihf".into(),
         metadata: TargetMetadata {
             description: Some(
                 "Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index 1300280e35b..71b3fbe00b2 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -23,6 +23,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions {
+            vendor: "openwrt".into(),
             abi: "abi64".into(),
             endian: Endian::Big,
             mcount: "_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
index 0955b3debea..c14bfbf46d2 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
@@ -4,7 +4,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
-        llvm_target: "mips-unknown-linux-uclibc".into(),
+        llvm_target: "mips-unknown-linux-gnu".into(),
         metadata: TargetMetadata {
             description: Some("MIPS Linux with uClibc".into()),
             tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
index 08c4347fe01..f0056799d66 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
@@ -2,7 +2,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
-        llvm_target: "mipsel-unknown-linux-uclibc".into(),
+        llvm_target: "mipsel-unknown-linux-gnu".into(),
         metadata: TargetMetadata {
             description: Some("MIPS (LE) Linux with uClibc".into()),
             tier: Some(3),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
index 8a4bc58e546..efc17d8d083 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             stack_probes: StackProbeType::Inline,
             ..base::vxworks::opts()
         },
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
index 6dda346aaaf..5b7feef70d0 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index ba10e3c6881..938b39b10c6 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index c8ef737b9e7..9f02ed4bcbe 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c,+zba,+zbb,+zbs,+v".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei,+zba,+zbb,+zbs,+v".into(),
             llvm_abiname: "lp64d".into(),
             supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
index 39aa70035e4..8d8c21952de 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv64".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             stack_probes: StackProbeType::Inline,
             ..base::vxworks::opts()
         },
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
index ecf65677531..e628095b88a 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             ..base::freebsd::opts()
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
index e260237ca77..c4466e13d14 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -4,7 +4,7 @@ pub(crate) fn target() -> Target {
     let mut base = base::fuchsia::opts();
     base.code_model = Some(CodeModel::Medium);
     base.cpu = "generic-rv64".into();
-    base.features = "+m,+a,+f,+d,+c".into();
+    base.features = "+m,+a,+f,+d,+c,+zicsr,+zifencei".into();
     base.llvm_abiname = "lp64d".into();
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
index 88b5dca284a..5c15bdd9f64 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         options: TargetOptions {
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             relocation_model: RelocModel::Pic,
             code_model: Some(CodeModel::Medium),
             tls_model: TlsModel::LocalExec,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
index 8ffb622511d..af2f42fa00a 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 33b08fdcb05..70c19952af0 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
index 2b647e36f18..1f359d1e7fe 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             mcount: "__mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index d6f0a5499b9..5a5aad93efb 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
             llvm_abiname: "lp64d".into(),
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
index bc6829897a4..e8abc926dd0 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
             llvm_abiname: "lp64d".into(),
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
index 75f508d8e93..85d7dfe7865 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
-            features: "+m,+a,+f,+d,+c".into(),
+            features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             ..base::openbsd::opts()
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index a034a9fb244..4107249dcf1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     base.panic_strategy = PanicStrategy::Abort;
 
     Target {
-        llvm_target: "x86_64-unknown-l4re-uclibc".into(),
+        llvm_target: "x86_64-unknown-l4re-gnu".into(),
         metadata: TargetMetadata {
             description: None,
             tier: Some(3),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index a96caf227f7..b4ec1879fed 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -380,11 +380,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("adx", Stable, &[]),
     ("aes", Stable, &["sse2"]),
+    ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
+    ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("avx", Stable, &["sse4.2"]),
     ("avx2", Stable, &["avx"]),
     ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
@@ -418,6 +423,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
     ("lzcnt", Stable, &[]),
     ("movbe", Stable, &[]),
+    ("movrs", Unstable(sym::movrs_target_feature), &[]),
     ("pclmulqdq", Stable, &["sse2"]),
     ("popcnt", Stable, &[]),
     ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
@@ -488,7 +494,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("c", Stable, &[]),
     ("d", Unstable(sym::riscv_target_feature), &["f"]),
     ("e", Unstable(sym::riscv_target_feature), &[]),
-    ("f", Unstable(sym::riscv_target_feature), &[]),
+    ("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
     (
         "forced-atomics",
         Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
@@ -497,7 +503,8 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("m", Stable, &[]),
     ("relax", Unstable(sym::riscv_target_feature), &[]),
     ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
-    ("v", Unstable(sym::riscv_target_feature), &[]),
+    ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
+    ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
     ("za128rs", Unstable(sym::riscv_target_feature), &[]),
     ("za64rs", Unstable(sym::riscv_target_feature), &[]),
     ("zaamo", Unstable(sym::riscv_target_feature), &[]),
@@ -516,19 +523,59 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
     ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
     ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
-    ("zfinx", Unstable(sym::riscv_target_feature), &[]),
+    ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
     ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
     ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
+    ("zicntr", Unstable(sym::riscv_target_feature), &["zicsr"]),
+    ("zicsr", Unstable(sym::riscv_target_feature), &[]),
+    ("zifencei", Unstable(sym::riscv_target_feature), &[]),
+    ("zihintpause", Unstable(sym::riscv_target_feature), &[]),
+    ("zihpm", Unstable(sym::riscv_target_feature), &["zicsr"]),
     ("zk", Stable, &["zkn", "zkr", "zkt"]),
     ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
     ("zknd", Stable, &[]),
     ("zkne", Stable, &[]),
     ("zknh", Stable, &[]),
-    ("zkr", Stable, &[]),
+    ("zkr", Stable, &["zicsr"]),
     ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
     ("zksed", Stable, &[]),
     ("zksh", Stable, &[]),
     ("zkt", Stable, &[]),
+    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
+    ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
+    ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
+    ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
+    ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
+    ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
+    ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
+    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zfhmin"]),
+    ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
+    ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]),
+    ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]),
+    ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
+    ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvknhb", Unstable(sym::riscv_target_feature), &["zve64x"]),
+    ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
+    ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
+    ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]),
+    ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]),
+    ("zvkt", Unstable(sym::riscv_target_feature), &[]),
+    ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]),
+    ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]),
+    ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]),
+    ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]),
+    ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]),
+    ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]),
+    ("zvl32b", Unstable(sym::riscv_target_feature), &[]),
+    ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]),
+    ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]),
+    ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]),
+    ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]),
+    ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]),
     // tidy-alphabetical-end
 ];
 
@@ -704,8 +751,20 @@ const ARM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(1
 const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")];
 const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")];
 const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")];
-const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
-    &[/*(64, "zvl64b"), */ (128, "v")];
+const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[
+    (32, "zvl32b"),
+    (64, "zvl64b"),
+    (128, "zvl128b"),
+    (256, "zvl256b"),
+    (512, "zvl512b"),
+    (1024, "zvl1024b"),
+    (2048, "zvl2048b"),
+    (4096, "zvl4096b"),
+    (8192, "zvl8192b"),
+    (16384, "zvl16384b"),
+    (32768, "zvl32768b"),
+    (65536, "zvl65536b"),
+];
 // Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
 const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/];
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 0bcb5f6f3b2..f45e3904212 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1051,7 +1051,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                             None?
                         }
                         let args = self.node_args_opt(expr.hir_id)?;
-                        let span = tcx.hir().span(segment.hir_id);
+                        let span = tcx.hir_span(segment.hir_id);
                         let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                         InsertableGenericArgs {
                             insert_span,
@@ -1110,7 +1110,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 if generics.has_impl_trait() {
                     return None;
                 }
-                let span = tcx.hir().span(segment.hir_id);
+                let span = tcx.hir_span(segment.hir_id);
                 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                 Some(InsertableGenericArgs {
                     insert_span,
@@ -1144,7 +1144,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                     if !segment.infer_args || generics.has_impl_trait() {
                         do yeet ();
                     }
-                    let span = tcx.hir().span(segment.hir_id);
+                    let span = tcx.hir_span(segment.hir_id);
                     let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
                     InsertableGenericArgs {
                         insert_span,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 083ce022238..3559c660ee2 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -365,7 +365,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 // obligation comes from the `impl`. Find that `impl` so that we can point
                 // at it in the suggestion.
                 let trait_did = trait_id.to_def_id();
-                tcx.hir_trait_impls(trait_did).iter().find_map(|&impl_did| {
+                tcx.local_trait_impls(trait_did).iter().find_map(|&impl_did| {
                     if let Node::Item(Item {
                         kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
                     }) = tcx.hir_node_by_def_id(impl_did)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index 00f053fa599..683b5b528c6 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
@@ -51,7 +51,6 @@ pub fn find_param_with_region<'tcx>(
         _ => return None, // not a free region
     };
 
-    let hir = &tcx.hir();
     let def_id = id.as_local()?;
 
     // FIXME: use def_kind
@@ -93,7 +92,7 @@ pub fn find_param_with_region<'tcx>(
             });
             found_anon_region.then(|| {
                 let ty_hir_id = fn_decl.inputs[index].hir_id;
-                let param_ty_span = hir.span(ty_hir_id);
+                let param_ty_span = tcx.hir_span(ty_hir_id);
                 let is_first = index == 0;
                 AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, kind, is_first }
             })
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 07a67cde3be..bc45fc11e9b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -14,6 +14,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, LangItem, Node};
 use rustc_infer::infer::{InferOk, TypeTrace};
+use rustc_infer::traits::solve::Goal;
 use rustc_middle::traits::SignatureMismatchData;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -930,7 +931,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             )) = arg.kind
             && let Node::Pat(pat) = self.tcx.hir_node(*hir_id)
             && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)
-            && preds.contains(&obligation.predicate)
+            && preds.contains(&obligation.as_goal())
         {
             return Err(*guar);
         }
@@ -1236,7 +1237,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
                 // Only suggest derive if this isn't a derived obligation,
                 // and the struct is local.
-                if let Some(span) = self.tcx.hir().span_if_local(def.did())
+                if let Some(span) = self.tcx.hir_span_if_local(def.did())
                     && obligation.cause.code().parent().is_none()
                 {
                     if ty.is_structural_eq_shallow(self.tcx) {
@@ -1292,6 +1293,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     fn can_match_trait(
         &self,
+        param_env: ty::ParamEnv<'tcx>,
         goal: ty::TraitPredicate<'tcx>,
         assumption: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
@@ -1306,11 +1308,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             assumption,
         );
 
-        self.can_eq(ty::ParamEnv::empty(), goal.trait_ref, trait_assumption.trait_ref)
+        self.can_eq(param_env, goal.trait_ref, trait_assumption.trait_ref)
     }
 
     fn can_match_projection(
         &self,
+        param_env: ty::ParamEnv<'tcx>,
         goal: ty::ProjectionPredicate<'tcx>,
         assumption: ty::PolyProjectionPredicate<'tcx>,
     ) -> bool {
@@ -1320,7 +1323,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             assumption,
         );
 
-        let param_env = ty::ParamEnv::empty();
         self.can_eq(param_env, goal.projection_term, assumption.projection_term)
             && self.can_eq(param_env, goal.term, assumption.term)
     }
@@ -1330,24 +1332,32 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn error_implies(
         &self,
-        cond: ty::Predicate<'tcx>,
-        error: ty::Predicate<'tcx>,
+        cond: Goal<'tcx, ty::Predicate<'tcx>>,
+        error: Goal<'tcx, ty::Predicate<'tcx>>,
     ) -> bool {
         if cond == error {
             return true;
         }
 
-        if let Some(error) = error.as_trait_clause() {
+        // FIXME: We could be smarter about this, i.e. if cond's param-env is a
+        // subset of error's param-env. This only matters when binders will carry
+        // predicates though, and obviously only matters for error reporting.
+        if cond.param_env != error.param_env {
+            return false;
+        }
+        let param_env = error.param_env;
+
+        if let Some(error) = error.predicate.as_trait_clause() {
             self.enter_forall(error, |error| {
-                elaborate(self.tcx, std::iter::once(cond))
+                elaborate(self.tcx, std::iter::once(cond.predicate))
                     .filter_map(|implied| implied.as_trait_clause())
-                    .any(|implied| self.can_match_trait(error, implied))
+                    .any(|implied| self.can_match_trait(param_env, error, implied))
             })
-        } else if let Some(error) = error.as_projection_clause() {
+        } else if let Some(error) = error.predicate.as_projection_clause() {
             self.enter_forall(error, |error| {
-                elaborate(self.tcx, std::iter::once(cond))
+                elaborate(self.tcx, std::iter::once(cond.predicate))
                     .filter_map(|implied| implied.as_projection_clause())
-                    .any(|implied| self.can_match_projection(error, implied))
+                    .any(|implied| self.can_match_projection(param_env, error, implied))
             })
         } else {
             false
@@ -2943,7 +2953,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         };
 
         let found_node = found_did.and_then(|did| self.tcx.hir_get_if_local(did));
-        let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
+        let found_span = found_did.and_then(|did| self.tcx.hir_span_if_local(did));
 
         if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
             // We check closures twice, with obligations flowing in different directions,
@@ -3030,7 +3040,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         node: Node<'_>,
     ) -> Option<(Span, Option<Span>, Vec<ArgKind>)> {
         let sm = self.tcx.sess.source_map();
-        let hir = self.tcx.hir();
         Some(match node {
             Node::Expr(&hir::Expr {
                 kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }),
@@ -3086,7 +3095,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     .collect::<Vec<ArgKind>>(),
             ),
             Node::Ctor(variant_data) => {
-                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
+                let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| self.tcx.hir_span(id));
                 (span, None, vec![ArgKind::empty(); variant_data.fields().len()])
             }
             _ => panic!("non-FnLike node found: {node:?}"),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 98df09b6f7b..8ff7030717a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -12,6 +12,7 @@ use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_cod
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{self as hir, AmbigArg, LangItem};
+use rustc_infer::traits::solve::Goal;
 use rustc_infer::traits::{
     DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
     PredicateObligation, SelectionError,
@@ -144,7 +145,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
+            goal: Goal<'tcx, ty::Predicate<'tcx>>,
             index: Option<usize>, // None if this is an old error
         }
 
@@ -152,15 +153,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             .reported_trait_errors
             .borrow()
             .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .0
-                        .iter()
-                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
-                        .collect(),
-                )
+            .map(|(&span, goals)| {
+                (span, goals.0.iter().map(|&goal| ErrorDescriptor { goal, index: None }).collect())
             })
             .collect();
 
@@ -186,10 +180,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 span = expn_data.call_site;
             }
 
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate,
-                index: Some(index),
-            });
+            error_map
+                .entry(span)
+                .or_default()
+                .push(ErrorDescriptor { goal: error.obligation.as_goal(), index: Some(index) });
         }
 
         // We do this in 2 passes because we want to display errors in order, though
@@ -210,9 +204,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             continue;
                         }
 
-                        if self.error_implies(error2.predicate, error.predicate)
+                        if self.error_implies(error2.goal, error.goal)
                             && !(error2.index >= error.index
-                                && self.error_implies(error.predicate, error2.predicate))
+                                && self.error_implies(error.goal, error2.goal))
                         {
                             info!("skipping {:?} (implied by {:?})", error, error2);
                             is_suppressed[index] = true;
@@ -243,7 +237,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         .entry(span)
                         .or_insert_with(|| (vec![], guar))
                         .0
-                        .push(error.obligation.predicate);
+                        .push(error.obligation.as_goal());
                 }
             }
         }
@@ -398,7 +392,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         );
 
         if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
-            if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) {
+            if let Some(span) = self.tcx.hir_span_if_local(trait_item_def_id) {
                 let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
                 err.span_label(span, format!("definition of `{item_name}` from trait"));
             }
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 dc8022b95c3..38fcba4ea62 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1193,7 +1193,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             // FIXME(compiler-errors): This is kind of a mess, but required for obligations
             // that come from a path expr to affect the *call* expr.
             c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _)
-                if self.tcx.hir().span(*hir_id).lo() == span.lo() =>
+                if self.tcx.hir_span(*hir_id).lo() == span.lo() =>
             {
                 c
             }
@@ -4481,7 +4481,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref);
 
         if self.predicate_must_hold_modulo_regions(&obligation) {
-            let arg_span = self.tcx.hir().span(*arg_hir_id);
+            let arg_span = self.tcx.hir_span(*arg_hir_id);
             err.multipart_suggestion_verbose(
                 format!("use a unary tuple instead"),
                 vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())],
@@ -4521,7 +4521,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     parent_code: _,
                 } = cause.code()
                 {
-                    let arg_span = self.tcx.hir().span(*arg_hir_id);
+                    let arg_span = self.tcx.hir_span(*arg_hir_id);
                     let mut sp: MultiSpan = arg_span.into();
 
                     sp.push_span_label(
@@ -4530,7 +4530,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         generic types that should be inferred from this argument",
                     );
                     sp.push_span_label(
-                        self.tcx.hir().span(*call_hir_id),
+                        self.tcx.hir_span(*call_hir_id),
                         "add turbofish arguments to this call to \
                         specify the types manually, even if it's redundant",
                     );
@@ -4939,7 +4939,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         .type_implements_trait(pred.def_id(), [rhs_ty, lhs_ty], param_env)
                         .must_apply_modulo_regions()
                 {
-                    let lhs_span = tcx.hir().span(lhs_hir_id);
+                    let lhs_span = tcx.hir_span(lhs_hir_id);
                     let sm = tcx.sess.source_map();
                     if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_span)
                         && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_span)
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7159397c4b1..b30390a9330 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -9,7 +9,7 @@ use rustc_errors::{
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
-use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
+use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
 use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
@@ -567,10 +567,14 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
 
             impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
                 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
-                    let make_suggestion = |ident: Ident| {
-                        if ident.name == kw::Empty && ident.span.is_empty() {
+                    let make_suggestion = |lifetime: &hir::Lifetime| {
+                        if lifetime.is_anon_in_path == IsAnonInPath::Yes
+                            && lifetime.ident.span.is_empty()
+                        {
                             format!("{}, ", self.suggestion_param_name)
-                        } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
+                        } else if lifetime.ident.name == kw::UnderscoreLifetime
+                            && lifetime.ident.span.is_empty()
+                        {
                             format!("{} ", self.suggestion_param_name)
                         } else {
                             self.suggestion_param_name.clone()
@@ -584,7 +588,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                                         matches!(
                                             arg,
                                             hir::GenericArg::Lifetime(lifetime)
-                                            if lifetime.ident.name == kw::Empty
+                                                if lifetime.is_anon_in_path == IsAnonInPath::Yes
                                         )
                                     }) {
                                         self.suggestions.push((
@@ -605,7 +609,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                                             {
                                                 self.suggestions.push((
                                                     lifetime.ident.span,
-                                                    make_suggestion(lifetime.ident),
+                                                    make_suggestion(lifetime),
                                                 ));
                                             }
                                         }
@@ -614,8 +618,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                             }
                         }
                         hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
-                            self.suggestions
-                                .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
+                            self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime)));
                         }
                         _ => {}
                     }
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index af5a60027ba..f2725411e13 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -96,7 +96,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     ) -> Option<Vec<Goal<'tcx, ty::Predicate<'tcx>>>> {
         crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID)
             .map(|obligations| {
-                obligations.into_iter().map(|obligation| obligation.into()).collect()
+                obligations.into_iter().map(|obligation| obligation.as_goal()).collect()
             })
     }
 
@@ -149,16 +149,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         self.0.instantiate_canonical_var(span, cv_info, universe_map)
     }
 
-    fn insert_hidden_type(
+    fn register_hidden_type_in_storage(
         &self,
-        opaque_type_key: ty::OpaqueTypeKey<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        hidden_ty: Ty<'tcx>,
-        goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) -> Result<(), NoSolution> {
-        self.0
-            .insert_hidden_type(opaque_type_key, DUMMY_SP, param_env, hidden_ty, goals)
-            .map_err(|_| NoSolution)
+        opaque_type_key: rustc_type_ir::OpaqueTypeKey<Self::Interner>,
+        hidden_ty: <Self::Interner as ty::Interner>::Ty,
+        span: <Self::Interner as ty::Interner>::Span,
+    ) -> Option<<Self::Interner as ty::Interner>::Ty> {
+        self.0.register_hidden_type_in_storage(
+            opaque_type_key,
+            ty::OpaqueHiddenType { span, ty: hidden_ty },
+        )
     }
 
     fn add_item_bounds_for_hidden_type(
@@ -172,15 +172,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals);
     }
 
-    fn inject_new_hidden_type_unchecked(
-        &self,
-        key: ty::OpaqueTypeKey<'tcx>,
-        hidden_ty: Ty<'tcx>,
-        span: Span,
-    ) {
-        self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { ty: hidden_ty, span })
-    }
-
     fn reset_opaque_types(&self) {
         let _ = self.take_opaque_types();
     }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 704ba6e501d..192e632a2d5 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -80,7 +80,7 @@ impl<'tcx> ObligationStorage<'tcx> {
             // change.
             // FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
             self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| {
-                let goal = o.clone().into();
+                let goal = o.as_goal();
                 let result = <&SolverDelegate<'tcx>>::from(infcx)
                     .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span)
                     .0;
@@ -161,7 +161,7 @@ where
 
             let mut has_changed = false;
             for obligation in self.obligations.unstalled_for_select() {
-                let goal = obligation.clone().into();
+                let goal = obligation.as_goal();
                 let result = <&SolverDelegate<'tcx>>::from(infcx)
                     .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
                     .0;
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 352ac7c1a4e..3a939df25e0 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _};
-use rustc_type_ir::solve::{Goal, NoSolution};
+use rustc_type_ir::solve::NoSolution;
 use tracing::{instrument, trace};
 
 use crate::solve::Certainty;
@@ -89,7 +89,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
     let (code, refine_obligation) = infcx.probe(|_| {
         match <&SolverDelegate<'tcx>>::from(infcx)
             .evaluate_root_goal(
-                root_obligation.clone().into(),
+                root_obligation.as_goal(),
                 GenerateProofTree::No,
                 root_obligation.cause.span,
             )
@@ -155,7 +155,7 @@ fn find_best_leaf_obligation<'tcx>(
         .fudge_inference_if_ok(|| {
             infcx
                 .visit_proof_tree(
-                    obligation.clone().into(),
+                    obligation.as_goal(),
                     &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
                 )
                 .break_value()
@@ -245,7 +245,7 @@ impl<'tcx> BestObligation<'tcx> {
         {
             let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
                 GoalSource::Misc,
-                Goal::new(infcx.tcx, obligation.param_env, obligation.predicate),
+                obligation.as_goal(),
                 self.span(),
             );
             // Skip nested goals that aren't the *reason* for our goal's failure.
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 4c7172c3278..bcc247ba53c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -625,7 +625,7 @@ fn compute_intercrate_ambiguity_causes<'tcx>(
     let mut causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>> = Default::default();
 
     for obligation in obligations {
-        search_ambiguity_causes(infcx, obligation.clone().into(), &mut causes);
+        search_ambiguity_causes(infcx, obligation.as_goal(), &mut causes);
     }
 
     causes
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index 78a45243983..fa6bbf1d6e5 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>(
     // create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
     // its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
     let param_env = {
-        let param_env = tcx.param_env(method.def_id);
+        // N.B. We generally want to emulate the construction of the `unnormalized_param_env`
+        // in the param-env query here. The fact that we don't just start with the clauses
+        // in the param-env of the method is because those are already normalized, and mixing
+        // normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
+        // will cause ambiguity that the user can't really avoid.
+        //
+        // We leave out certain complexities of the param-env query here. Specifically, we:
+        // 1. Do not add `~const` bounds since there are no `dyn const Trait`s.
+        // 2. Do not add RPITIT self projection bounds for defaulted methods, since we
+        //    are not constructing a param-env for "inside" of the body of the defaulted
+        //    method, so we don't really care about projecting to a specific RPIT type,
+        //    and because RPITITs are not dyn compatible (yet).
+        let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
 
         // Self: Unsize<U>
         let unsize_predicate =
-            ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx);
+            ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
+        predicates.push(unsize_predicate.upcast(tcx));
 
         // U: Trait<Arg1, ..., ArgN>
-        let trait_predicate = {
-            let trait_def_id = method.trait_container(tcx).unwrap();
-            let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
-                if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
-            });
-
-            ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
-        };
+        let trait_def_id = method.trait_container(tcx).unwrap();
+        let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
+            if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+        });
+        let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
+        predicates.push(trait_predicate.upcast(tcx));
 
         normalize_param_env_or_error(
             tcx,
-            ty::ParamEnv::new(tcx.mk_clauses_from_iter(
-                param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
-            )),
+            ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
             ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
         )
     };
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 3c127416cbf..defbafac20b 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -106,10 +106,6 @@ fn match_candidate<'tcx>(
 
     more_nested(selcx, &mut nested);
 
-    for nested in &mut nested {
-        nested.set_depth_from_parent(obligation.recursion_depth);
-    }
-
     Ok(nested)
 }
 
@@ -263,7 +259,7 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
                 .all_fields()
                 .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
                 .collect();
-            match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+            match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) {
                 // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
                 Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
                 // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
@@ -378,10 +374,6 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
                             }),
                     );
 
-                    for nested in &mut nested {
-                        nested.set_depth_from_parent(obligation.recursion_depth);
-                    }
-
                     Ok(nested)
                 }
                 _ => Err(EvaluationFailure::NoSolution),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e39f8e673db..e98a240a53f 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -225,9 +225,15 @@ struct FulfillProcessor<'a, 'tcx> {
     selcx: SelectionContext<'a, 'tcx>,
 }
 
-fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> {
+fn mk_pending<'tcx>(
+    parent: &PredicateObligation<'tcx>,
+    os: PredicateObligations<'tcx>,
+) -> PendingPredicateObligations<'tcx> {
     os.into_iter()
-        .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] })
+        .map(|mut o| {
+            o.set_depth_from_parent(parent.recursion_depth);
+            PendingPredicateObligation { obligation: o, stalled_on: vec![] }
+        })
         .collect()
 }
 
@@ -341,7 +347,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
             );
             if predicate != obligation.predicate {
                 obligations.push(obligation.with(infcx.tcx, predicate));
-                return ProcessResult::Changed(mk_pending(obligations));
+                return ProcessResult::Changed(mk_pending(obligation, obligations));
             }
         }
         let binder = obligation.predicate.kind();
@@ -385,7 +391,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     let mut obligations = PredicateObligations::with_capacity(1);
                     obligations.push(obligation.with(infcx.tcx, pred));
 
-                    ProcessResult::Changed(mk_pending(obligations))
+                    ProcessResult::Changed(mk_pending(obligation, obligations))
                 }
                 ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
                 ty::PredicateKind::NormalizesTo(..) => {
@@ -410,6 +416,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     let host_obligation = obligation.with(infcx.tcx, data);
 
                     self.process_host_obligation(
+                        obligation,
                         host_obligation,
                         &mut pending_obligation.stalled_on,
                     )
@@ -486,7 +493,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         // `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
                         // `lhs + rhs`.
                         ty::ConstKind::Expr(_) => {
-                            return ProcessResult::Changed(mk_pending(PredicateObligations::new()));
+                            return ProcessResult::Changed(mk_pending(
+                                obligation,
+                                PredicateObligations::new(),
+                            ));
                         }
                         ty::ConstKind::Placeholder(_) => {
                             bug!("placeholder const {:?} in old solver", ct)
@@ -503,7 +513,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ct_ty,
                         ty,
                     ) {
-                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(
+                            obligation,
+                            inf_ok.into_obligations(),
+                        )),
                         Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
                             SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
                         )),
@@ -537,7 +550,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()];
                             ProcessResult::Unchanged
                         }
-                        Some(os) => ProcessResult::Changed(mk_pending(os)),
+                        Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
                     }
                 }
 
@@ -553,11 +566,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
                             ProcessResult::Unchanged
                         }
-                        Ok(Ok(mut ok)) => {
-                            for subobligation in &mut ok.obligations {
-                                subobligation.set_depth_from_parent(obligation.recursion_depth);
-                            }
-                            ProcessResult::Changed(mk_pending(ok.obligations))
+                        Ok(Ok(ok)) => {
+                            ProcessResult::Changed(mk_pending(obligation, ok.obligations))
                         }
                         Ok(Err(err)) => {
                             let expected_found = if subtype.a_is_expected {
@@ -582,7 +592,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
                             ProcessResult::Unchanged
                         }
-                        Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
+                        Ok(Ok(ok)) => {
+                            ProcessResult::Changed(mk_pending(obligation, ok.obligations))
+                        }
                         Ok(Err(err)) => {
                             let expected_found = ExpectedFound::new(coerce.b, coerce.a);
                             ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
@@ -645,6 +657,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                     )
                                 {
                                     return ProcessResult::Changed(mk_pending(
+                                        obligation,
                                         new_obligations.into_obligations(),
                                     ));
                                 }
@@ -659,6 +672,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                     .eq(DefineOpaqueTypes::Yes, c1, c2)
                                 {
                                     return ProcessResult::Changed(mk_pending(
+                                        obligation,
                                         new_obligations.into_obligations(),
                                     ));
                                 }
@@ -704,9 +718,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 c1,
                                 c2,
                             ) {
-                                Ok(inf_ok) => {
-                                    ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
-                                }
+                                Ok(inf_ok) => ProcessResult::Changed(mk_pending(
+                                    obligation,
+                                    inf_ok.into_obligations(),
+                                )),
                                 Err(err) => {
                                     ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
                                         ExpectedFound::new(c1, c2),
@@ -790,7 +805,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
         match self.selcx.poly_select(&trait_obligation) {
             Ok(Some(impl_source)) => {
                 debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
-                ProcessResult::Changed(mk_pending(impl_source.nested_obligations()))
+                ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations()))
             }
             Ok(None) => {
                 debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth);
@@ -854,7 +869,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
         }
 
         match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
-            ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
+            ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)),
             ProjectAndUnifyResult::FailedNormalization => {
                 stalled_on.clear();
                 stalled_on.extend(args_infer_vars(
@@ -868,7 +883,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                 let mut obligations = PredicateObligations::with_capacity(1);
                 obligations.push(project_obligation.with(tcx, project_obligation.predicate));
 
-                ProcessResult::Changed(mk_pending(obligations))
+                ProcessResult::Changed(mk_pending(obligation, obligations))
             }
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                 ProcessResult::Error(FulfillmentErrorCode::Project(e))
@@ -878,11 +893,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
 
     fn process_host_obligation(
         &mut self,
+        obligation: &PredicateObligation<'tcx>,
         host_obligation: HostEffectObligation<'tcx>,
         stalled_on: &mut Vec<TyOrConstInferVar>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
-            Ok(nested) => ProcessResult::Changed(mk_pending(nested)),
+            Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)),
             Err(effects::EvaluationFailure::Ambiguous) => {
                 stalled_on.clear();
                 stalled_on.extend(args_infer_vars(
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index fc352499146..d15c9afef3a 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -16,7 +16,7 @@ use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
-use rustc_type_ir::{Interner, elaborate};
+use rustc_type_ir::elaborate;
 use tracing::{debug, instrument, trace};
 
 use super::SelectionCandidate::*;
@@ -86,10 +86,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // `Pointee` is automatically implemented for every type.
                 candidates.vec.push(BuiltinCandidate { has_nested: false });
             } else if tcx.is_lang_item(def_id, LangItem::Sized) {
-                // Sized is never implementable by end-users, it is
-                // always automatically computed.
-                let sized_conditions = self.sized_conditions(obligation);
-                self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
+                self.assemble_builtin_sized_candidate(obligation, &mut candidates);
             } else if tcx.is_lang_item(def_id, LangItem::Unsize) {
                 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
             } else if tcx.is_lang_item(def_id, LangItem::Destruct) {
@@ -802,7 +799,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::UnsafeBinder(_) => {
                     // Only consider auto impls of unsafe traits when there are
                     // no unsafe fields.
-                    if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
+                    if self.tcx().trait_def(def_id).safety.is_unsafe()
+                        && self_ty.has_unsafe_fields()
+                    {
                         return;
                     }
 
@@ -1059,6 +1058,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Assembles the trait which are built-in to the language itself:
     /// `Copy`, `Clone` and `Sized`.
     #[instrument(level = "debug", skip(self, candidates))]
+    fn assemble_builtin_sized_candidate(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        match self.sized_conditions(obligation) {
+            BuiltinImplConditions::Where(nested) => {
+                candidates
+                    .vec
+                    .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() });
+            }
+            BuiltinImplConditions::None => {}
+            BuiltinImplConditions::Ambiguous => {
+                candidates.ambiguous = true;
+            }
+        }
+    }
+
+    /// Assembles the trait which are built-in to the language itself:
+    /// e.g. `Copy` and `Clone`.
+    #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_builtin_bound_candidates(
         &mut self,
         conditions: BuiltinImplConditions<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4404324d5cd..2cb7d2d8931 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -39,7 +39,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PolyTraitObligation<'tcx>,
         candidate: SelectionCandidate<'tcx>,
     ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
-        let mut impl_src = match candidate {
+        Ok(match candidate {
+            SizedCandidate { has_nested } => {
+                let data = self.confirm_builtin_candidate(obligation, has_nested);
+                ImplSource::Builtin(BuiltinImplSource::Misc, data)
+            }
+
             BuiltinCandidate { has_nested } => {
                 let data = self.confirm_builtin_candidate(obligation, has_nested);
                 ImplSource::Builtin(BuiltinImplSource::Misc, data)
@@ -134,15 +139,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             BikeshedGuaranteedNoDropCandidate => {
                 self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
             }
-        };
-
-        // The obligations returned by confirmation are recursively evaluated
-        // so we need to make sure they have the correct depth.
-        for subobligation in impl_src.borrow_nested_obligations_mut() {
-            subobligation.set_depth_from_parent(obligation.recursion_depth);
-        }
-
-        Ok(impl_src)
+        })
     }
 
     fn confirm_projection_candidate(
@@ -266,9 +263,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             } else {
                 bug!("unexpected builtin trait {:?}", trait_def)
             };
-            let BuiltinImplConditions::Where(nested) = conditions else {
+            let BuiltinImplConditions::Where(types) = conditions else {
                 bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
             };
+            let types = self.infcx.enter_forall_and_leak_universe(types);
 
             let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
             self.collect_predicates_for_types(
@@ -276,7 +274,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 cause,
                 obligation.recursion_depth + 1,
                 trait_def,
-                nested,
+                types,
             )
         } else {
             PredicateObligations::new()
@@ -444,37 +442,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<PredicateObligations<'tcx>, SelectionError<'tcx>> {
-        debug!(?obligation, "confirm_auto_impl_candidate");
-
-        let self_ty = obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
-        let types = self.constituent_types_for_ty(self_ty)?;
-        Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
-    }
-
-    /// See `confirm_auto_impl_candidate`.
-    fn vtable_auto_impl(
-        &mut self,
-        obligation: &PolyTraitObligation<'tcx>,
-        trait_def_id: DefId,
-        nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
-    ) -> PredicateObligations<'tcx> {
-        debug!(?nested, "vtable_auto_impl");
         ensure_sufficient_stack(|| {
-            let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
-
             assert_eq!(obligation.predicate.polarity(), ty::PredicatePolarity::Positive);
 
+            let self_ty =
+                obligation.predicate.self_ty().map_bound(|ty| self.infcx.shallow_resolve(ty));
+
+            let types = self.constituent_types_for_ty(self_ty)?;
+            let types = self.infcx.enter_forall_and_leak_universe(types);
+
+            let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
             let obligations = self.collect_predicates_for_types(
                 obligation.param_env,
                 cause,
                 obligation.recursion_depth + 1,
-                trait_def_id,
-                nested,
+                obligation.predicate.def_id(),
+                types,
             );
 
-            debug!(?obligations, "vtable_auto_impl");
-
-            obligations
+            Ok(obligations)
         })
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e1adabbeaa6..0679dbf1296 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1801,17 +1801,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             return Some(candidates.pop().unwrap().candidate);
         }
 
-        // We prefer trivial builtin candidates, i.e. builtin impls without any nested
-        // requirements, over all others. This is a fix for #53123 and prevents winnowing
-        // from accidentally extending the lifetime of a variable.
-        let mut trivial_builtin = candidates
-            .iter()
-            .filter(|c| matches!(c.candidate, BuiltinCandidate { has_nested: false }));
-        if let Some(_trivial) = trivial_builtin.next() {
-            // There should only ever be a single trivial builtin candidate
+        // We prefer `Sized` candidates over everything.
+        let mut sized_candidates =
+            candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ }));
+        if let Some(sized_candidate) = sized_candidates.next() {
+            // There should only ever be a single sized candidate
             // as they would otherwise overlap.
-            debug_assert_eq!(trivial_builtin.next(), None);
-            return Some(BuiltinCandidate { has_nested: false });
+            debug_assert_eq!(sized_candidates.next(), None);
+            // Only prefer the built-in `Sized` candidate if its nested goals are certain.
+            // Otherwise, we may encounter failure later on if inference causes this candidate
+            // to not hold, but a where clause would've applied instead.
+            if sized_candidate.evaluation.must_apply_modulo_regions() {
+                return Some(sized_candidate.candidate.clone());
+            } else {
+                return None;
+            }
         }
 
         // Before we consider where-bounds, we have to deduplicate them here and also
@@ -1940,7 +1944,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             // Don't use impl candidates which overlap with other candidates.
             // This should pretty much only ever happen with malformed impls.
             if candidates.iter().all(|c| match c.candidate {
-                BuiltinCandidate { has_nested: _ }
+                SizedCandidate { has_nested: _ }
+                | BuiltinCandidate { has_nested: _ }
                 | TransmutabilityCandidate
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
@@ -2370,7 +2375,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         trait_def_id: DefId,
-        types: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
+        types: Vec<Ty<'tcx>>,
     ) -> PredicateObligations<'tcx> {
         // Because the types were potentially derived from
         // higher-ranked obligations they may reference late-bound
@@ -2387,13 +2392,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // 3. Re-bind the regions back to `for<'a> &'a i32 : Copy`
 
         types
-            .as_ref()
-            .skip_binder() // binder moved -\
-            .iter()
-            .flat_map(|ty| {
-                let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
-
-                let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty);
+            .into_iter()
+            .flat_map(|placeholder_ty| {
                 let Normalized { value: normalized_ty, mut obligations } =
                     ensure_sufficient_stack(|| {
                         normalize_with_depth(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 7334beb52c9..0017186c1b0 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -611,7 +611,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         // Types with no meaningful known layout.
-        ty::Param(_) => {
+        ty::Param(_) | ty::Placeholder(..) => {
             return Err(error(cx, LayoutError::TooGeneric(ty)));
         }
 
@@ -628,11 +628,7 @@ fn layout_of_uncached<'tcx>(
             return Err(error(cx, err));
         }
 
-        ty::Placeholder(..)
-        | ty::Bound(..)
-        | ty::CoroutineWitness(..)
-        | ty::Infer(_)
-        | ty::Error(_) => {
+        ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => {
             // `ty::Error` is handled at the top of this function.
             bug!("layout_of: unexpected type `{ty}`")
         }
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 81aa4a1f19e..6a2498242fe 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -111,18 +111,20 @@ bitflags::bitflags! {
 
         /// Does this value have parameters/placeholders/inference variables which could be
         /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 21;
+        const STILL_FURTHER_SPECIALIZABLE = TypeFlags::HAS_TY_PARAM.bits()
+                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits()
+                                          | TypeFlags::HAS_TY_INFER.bits()
+                                          | TypeFlags::HAS_CT_PARAM.bits()
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits()
+                                          | TypeFlags::HAS_CT_INFER.bits();
 
         /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 22;
+        const HAS_TY_FRESH                = 1 << 21;
 
         /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 23;
-
-        /// Does this have `Coroutine` or `CoroutineWitness`?
-        const HAS_TY_COROUTINE            = 1 << 24;
+        const HAS_CT_FRESH                = 1 << 22;
 
         /// Does this have any binders with bound vars (e.g. that need to be anonymized)?
-        const HAS_BINDER_VARS             = 1 << 25;
+        const HAS_BINDER_VARS             = 1 << 23;
     }
 }
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 26c49510696..e512e8fc838 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -102,6 +102,7 @@ impl<I: Interner> TypingMode<I> {
     }
 }
 
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
 pub trait InferCtxtLike: Sized {
     type Interner: Interner;
     fn cx(&self) -> Self::Interner;
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index e765cb66d00..8f86270d7dc 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -15,6 +15,7 @@ use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesDat
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{self as ty, search_graph};
 
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
 pub trait Interner:
     Sized
     + Copy
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 62912189509..4e2baca2785 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -6,6 +6,7 @@
     feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
 )]
 #![cfg_attr(feature = "nightly", allow(internal_features))]
+#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))]
 // tidy-alphabetical-end
 
 extern crate self as rustc_type_ir;
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 119b658a2bf..2285e0e75de 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -269,10 +269,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
     }
 
-    fn has_coroutines(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_COROUTINE)
-    }
-
     fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_ERROR)
     }
diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs
index 82555461d64..413b5152bb3 100644
--- a/compiler/stable_mir/src/mir.rs
+++ b/compiler/stable_mir/src/mir.rs
@@ -5,4 +5,4 @@ pub mod pretty;
 pub mod visit;
 
 pub use body::*;
-pub use visit::MirVisitor;
+pub use visit::{MirVisitor, MutMirVisitor};
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index f8b46f50a52..2a1c163de3c 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -77,6 +77,22 @@ impl Body {
         &self.locals[self.arg_count + 1..]
     }
 
+    /// Returns a mutable reference to the local that holds this function's return value.
+    pub(crate) fn ret_local_mut(&mut self) -> &mut LocalDecl {
+        &mut self.locals[RETURN_LOCAL]
+    }
+
+    /// Returns a mutable slice of locals corresponding to this function's arguments.
+    pub(crate) fn arg_locals_mut(&mut self) -> &mut [LocalDecl] {
+        &mut self.locals[1..][..self.arg_count]
+    }
+
+    /// Returns a mutable slice of inner locals for this function.
+    /// Inner locals are those that are neither the return local nor the argument locals.
+    pub(crate) fn inner_locals_mut(&mut self) -> &mut [LocalDecl] {
+        &mut self.locals[self.arg_count + 1..]
+    }
+
     /// Convenience function to get all the locals in this function.
     ///
     /// Locals are typically accessed via the more specific methods `ret_local`,
@@ -1041,8 +1057,7 @@ impl Place {
     /// In order to retrieve the correct type, the `locals` argument must match the list of all
     /// locals from the function body where this place originates from.
     pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
-        let start_ty = locals[self.local].ty;
-        self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?))
+        self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty))
     }
 }
 
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index d985a98fcbf..9d2368ba332 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -39,406 +39,486 @@ use crate::mir::*;
 use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst};
 use crate::{Error, Opaque, Span};
 
-pub trait MirVisitor {
-    fn visit_body(&mut self, body: &Body) {
-        self.super_body(body)
-    }
-
-    fn visit_basic_block(&mut self, bb: &BasicBlock) {
-        self.super_basic_block(bb)
-    }
-
-    fn visit_ret_decl(&mut self, local: Local, decl: &LocalDecl) {
-        self.super_ret_decl(local, decl)
-    }
-
-    fn visit_arg_decl(&mut self, local: Local, decl: &LocalDecl) {
-        self.super_arg_decl(local, decl)
-    }
-
-    fn visit_local_decl(&mut self, local: Local, decl: &LocalDecl) {
-        self.super_local_decl(local, decl)
-    }
-
-    fn visit_statement(&mut self, stmt: &Statement, location: Location) {
-        self.super_statement(stmt, location)
-    }
-
-    fn visit_terminator(&mut self, term: &Terminator, location: Location) {
-        self.super_terminator(term, location)
-    }
-
-    fn visit_span(&mut self, span: &Span) {
-        self.super_span(span)
-    }
+macro_rules! make_mir_visitor {
+    ($visitor_trait_name:ident, $($mutability:ident)?) => {
+        pub trait $visitor_trait_name {
+            fn visit_body(&mut self, body: &$($mutability)? Body) {
+                self.super_body(body)
+            }
 
-    fn visit_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) {
-        self.super_place(place, ptx, location)
-    }
+            fn visit_basic_block(&mut self, bb: &$($mutability)? BasicBlock) {
+                self.super_basic_block(bb)
+            }
 
-    fn visit_projection_elem(
-        &mut self,
-        place_ref: PlaceRef<'_>,
-        elem: &ProjectionElem,
-        ptx: PlaceContext,
-        location: Location,
-    ) {
-        let _ = place_ref;
-        self.super_projection_elem(elem, ptx, location);
-    }
+            fn visit_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                self.super_ret_decl(local, decl)
+            }
 
-    fn visit_local(&mut self, local: &Local, ptx: PlaceContext, location: Location) {
-        let _ = (local, ptx, location);
-    }
+            fn visit_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                self.super_arg_decl(local, decl)
+            }
 
-    fn visit_rvalue(&mut self, rvalue: &Rvalue, location: Location) {
-        self.super_rvalue(rvalue, location)
-    }
+            fn visit_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                self.super_local_decl(local, decl)
+            }
 
-    fn visit_operand(&mut self, operand: &Operand, location: Location) {
-        self.super_operand(operand, location)
-    }
+            fn visit_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) {
+                self.super_statement(stmt, location)
+            }
 
-    fn visit_user_type_projection(&mut self, projection: &UserTypeProjection) {
-        self.super_user_type_projection(projection)
-    }
+            fn visit_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) {
+                self.super_terminator(term, location)
+            }
 
-    fn visit_ty(&mut self, ty: &Ty, location: Location) {
-        let _ = location;
-        self.super_ty(ty)
-    }
+            fn visit_span(&mut self, span: &$($mutability)? Span) {
+                self.super_span(span)
+            }
 
-    fn visit_const_operand(&mut self, constant: &ConstOperand, location: Location) {
-        self.super_const_operand(constant, location)
-    }
+            fn visit_place(&mut self, place: &$($mutability)? Place, ptx: PlaceContext, location: Location) {
+                self.super_place(place, ptx, location)
+            }
 
-    fn visit_mir_const(&mut self, constant: &MirConst, location: Location) {
-        self.super_mir_const(constant, location)
-    }
+            visit_place_fns!($($mutability)?);
 
-    fn visit_ty_const(&mut self, constant: &TyConst, location: Location) {
-        let _ = location;
-        self.super_ty_const(constant)
-    }
+            fn visit_local(&mut self, local: &$($mutability)? Local, ptx: PlaceContext, location: Location) {
+                let _ = (local, ptx, location);
+            }
 
-    fn visit_region(&mut self, region: &Region, location: Location) {
-        let _ = location;
-        self.super_region(region)
-    }
+            fn visit_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) {
+                self.super_rvalue(rvalue, location)
+            }
 
-    fn visit_args(&mut self, args: &GenericArgs, location: Location) {
-        let _ = location;
-        self.super_args(args)
-    }
+            fn visit_operand(&mut self, operand: &$($mutability)? Operand, location: Location) {
+                self.super_operand(operand, location)
+            }
 
-    fn visit_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
-        self.super_assert_msg(msg, location)
-    }
+            fn visit_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) {
+                self.super_user_type_projection(projection)
+            }
 
-    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
-        self.super_var_debug_info(var_debug_info);
-    }
+            fn visit_ty(&mut self, ty: &$($mutability)? Ty, location: Location) {
+                let _ = location;
+                self.super_ty(ty)
+            }
 
-    fn super_body(&mut self, body: &Body) {
-        let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _, span } = body;
+            fn visit_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) {
+                self.super_const_operand(constant, location)
+            }
 
-        for bb in blocks {
-            self.visit_basic_block(bb);
-        }
+            fn visit_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) {
+                self.super_mir_const(constant, location)
+            }
 
-        self.visit_ret_decl(RETURN_LOCAL, body.ret_local());
+            fn visit_ty_const(&mut self, constant: &$($mutability)? TyConst, location: Location) {
+                let _ = location;
+                self.super_ty_const(constant)
+            }
 
-        for (idx, arg) in body.arg_locals().iter().enumerate() {
-            self.visit_arg_decl(idx + 1, arg)
-        }
+            fn visit_region(&mut self, region: &$($mutability)? Region, location: Location) {
+                let _ = location;
+                self.super_region(region)
+            }
 
-        let local_start = arg_count + 1;
-        for (idx, arg) in body.inner_locals().iter().enumerate() {
-            self.visit_local_decl(idx + local_start, arg)
-        }
+            fn visit_args(&mut self, args: &$($mutability)? GenericArgs, location: Location) {
+                let _ = location;
+                self.super_args(args)
+            }
 
-        for info in var_debug_info.iter() {
-            self.visit_var_debug_info(info);
-        }
+            fn visit_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) {
+                self.super_assert_msg(msg, location)
+            }
 
-        self.visit_span(span)
-    }
+            fn visit_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) {
+                self.super_var_debug_info(var_debug_info);
+            }
 
-    fn super_basic_block(&mut self, bb: &BasicBlock) {
-        let BasicBlock { statements, terminator } = bb;
-        for stmt in statements {
-            self.visit_statement(stmt, Location(stmt.span));
-        }
-        self.visit_terminator(terminator, Location(terminator.span));
-    }
+            fn super_body(&mut self, body: &$($mutability)? Body) {
+                super_body!(self, body, $($mutability)?);
+            }
 
-    fn super_local_decl(&mut self, local: Local, decl: &LocalDecl) {
-        let _ = local;
-        let LocalDecl { ty, span, .. } = decl;
-        self.visit_ty(ty, Location(*span));
-    }
+            fn super_basic_block(&mut self, bb: &$($mutability)? BasicBlock) {
+                let BasicBlock { statements, terminator } = bb;
+                for stmt in statements {
+                    self.visit_statement(stmt, Location(stmt.span));
+                }
+                self.visit_terminator(terminator, Location(terminator.span));
+            }
 
-    fn super_ret_decl(&mut self, local: Local, decl: &LocalDecl) {
-        self.super_local_decl(local, decl)
-    }
+            fn super_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                let _ = local;
+                let LocalDecl { ty, span, .. } = decl;
+                self.visit_ty(ty, Location(*span));
+            }
 
-    fn super_arg_decl(&mut self, local: Local, decl: &LocalDecl) {
-        self.super_local_decl(local, decl)
-    }
+            fn super_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                self.super_local_decl(local, decl)
+            }
 
-    fn super_statement(&mut self, stmt: &Statement, location: Location) {
-        let Statement { kind, span } = stmt;
-        self.visit_span(span);
-        match kind {
-            StatementKind::Assign(place, rvalue) => {
-                self.visit_place(place, PlaceContext::MUTATING, location);
-                self.visit_rvalue(rvalue, location);
-            }
-            StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => {
-                self.visit_place(place, PlaceContext::NON_MUTATING, location);
-            }
-            StatementKind::SetDiscriminant { place, .. }
-            | StatementKind::Deinit(place)
-            | StatementKind::Retag(_, place) => {
-                self.visit_place(place, PlaceContext::MUTATING, location);
-            }
-            StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
-                self.visit_local(local, PlaceContext::NON_USE, location);
-            }
-            StatementKind::AscribeUserType { place, projections, variance: _ } => {
-                self.visit_place(place, PlaceContext::NON_USE, location);
-                self.visit_user_type_projection(projections);
-            }
-            StatementKind::Coverage(coverage) => visit_opaque(coverage),
-            StatementKind::Intrinsic(intrisic) => match intrisic {
-                NonDivergingIntrinsic::Assume(operand) => {
-                    self.visit_operand(operand, location);
-                }
-                NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
-                    src,
-                    dst,
-                    count,
-                }) => {
-                    self.visit_operand(src, location);
-                    self.visit_operand(dst, location);
-                    self.visit_operand(count, location);
-                }
-            },
-            StatementKind::ConstEvalCounter | StatementKind::Nop => {}
-        }
-    }
+            fn super_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
+                self.super_local_decl(local, decl)
+            }
 
-    fn super_terminator(&mut self, term: &Terminator, location: Location) {
-        let Terminator { kind, span } = term;
-        self.visit_span(span);
-        match kind {
-            TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Abort
-            | TerminatorKind::Unreachable => {}
-            TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
-                self.visit_operand(cond, location);
-                self.visit_assert_msg(msg, location);
-            }
-            TerminatorKind::Drop { place, target: _, unwind: _ } => {
-                self.visit_place(place, PlaceContext::MUTATING, location);
-            }
-            TerminatorKind::Call { func, args, destination, target: _, unwind: _ } => {
-                self.visit_operand(func, location);
-                for arg in args {
-                    self.visit_operand(arg, location);
+            fn super_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) {
+                let Statement { kind, span } = stmt;
+                self.visit_span(span);
+                match kind {
+                    StatementKind::Assign(place, rvalue) => {
+                        self.visit_place(place, PlaceContext::MUTATING, location);
+                        self.visit_rvalue(rvalue, location);
+                    }
+                    StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => {
+                        self.visit_place(place, PlaceContext::NON_MUTATING, location);
+                    }
+                    StatementKind::SetDiscriminant { place, .. }
+                    | StatementKind::Deinit(place)
+                    | StatementKind::Retag(_, place) => {
+                        self.visit_place(place, PlaceContext::MUTATING, location);
+                    }
+                    StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
+                        self.visit_local(local, PlaceContext::NON_USE, location);
+                    }
+                    StatementKind::AscribeUserType { place, projections, variance: _ } => {
+                        self.visit_place(place, PlaceContext::NON_USE, location);
+                        self.visit_user_type_projection(projections);
+                    }
+                    StatementKind::Coverage(coverage) => visit_opaque(coverage),
+                    StatementKind::Intrinsic(intrisic) => match intrisic {
+                        NonDivergingIntrinsic::Assume(operand) => {
+                            self.visit_operand(operand, location);
+                        }
+                        NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                            src,
+                            dst,
+                            count,
+                        }) => {
+                            self.visit_operand(src, location);
+                            self.visit_operand(dst, location);
+                            self.visit_operand(count, location);
+                        }
+                    },
+                    StatementKind::ConstEvalCounter | StatementKind::Nop => {}
                 }
-                self.visit_place(destination, PlaceContext::MUTATING, location);
             }
-            TerminatorKind::InlineAsm { operands, .. } => {
-                for op in operands {
-                    let InlineAsmOperand { in_value, out_place, raw_rpr: _ } = op;
-                    if let Some(input) = in_value {
-                        self.visit_operand(input, location);
+
+            fn super_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) {
+                let Terminator { kind, span } = term;
+                self.visit_span(span);
+                match kind {
+                    TerminatorKind::Goto { .. }
+                    | TerminatorKind::Resume
+                    | TerminatorKind::Abort
+                    | TerminatorKind::Unreachable => {}
+                    TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
+                        self.visit_operand(cond, location);
+                        self.visit_assert_msg(msg, location);
+                    }
+                    TerminatorKind::Drop { place, target: _, unwind: _ } => {
+                        self.visit_place(place, PlaceContext::MUTATING, location);
+                    }
+                    TerminatorKind::Call { func, args, destination, target: _, unwind: _ } => {
+                        self.visit_operand(func, location);
+                        for arg in args {
+                            self.visit_operand(arg, location);
+                        }
+                        self.visit_place(destination, PlaceContext::MUTATING, location);
+                    }
+                    TerminatorKind::InlineAsm { operands, .. } => {
+                        for op in operands {
+                            let InlineAsmOperand { in_value, out_place, raw_rpr: _ } = op;
+                            if let Some(input) = in_value {
+                                self.visit_operand(input, location);
+                            }
+                            if let Some(output) = out_place {
+                                self.visit_place(output, PlaceContext::MUTATING, location);
+                            }
+                        }
                     }
-                    if let Some(output) = out_place {
-                        self.visit_place(output, PlaceContext::MUTATING, location);
+                    TerminatorKind::Return => {
+                        let $($mutability)? local = RETURN_LOCAL;
+                        self.visit_local(&$($mutability)? local, PlaceContext::NON_MUTATING, location);
+                    }
+                    TerminatorKind::SwitchInt { discr, targets: _ } => {
+                        self.visit_operand(discr, location);
                     }
                 }
             }
-            TerminatorKind::Return => {
-                let local = RETURN_LOCAL;
-                self.visit_local(&local, PlaceContext::NON_MUTATING, location);
-            }
-            TerminatorKind::SwitchInt { discr, targets: _ } => {
-                self.visit_operand(discr, location);
-            }
-        }
-    }
 
-    fn super_span(&mut self, span: &Span) {
-        let _ = span;
-    }
-
-    fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) {
-        let _ = location;
-        let _ = ptx;
-        self.visit_local(&place.local, ptx, location);
+            fn super_span(&mut self, span: &$($mutability)? Span) {
+                let _ = span;
+            }
 
-        for (idx, elem) in place.projection.iter().enumerate() {
-            let place_ref = PlaceRef { local: place.local, projection: &place.projection[..idx] };
-            self.visit_projection_elem(place_ref, elem, ptx, location);
-        }
-    }
+            fn super_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) {
+                match rvalue {
+                    Rvalue::AddressOf(mutability, place) => {
+                        let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut };
+                        self.visit_place(place, pcx, location);
+                    }
+                    Rvalue::Aggregate(_, operands) => {
+                        for op in operands {
+                            self.visit_operand(op, location);
+                        }
+                    }
+                    Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+                        self.visit_operand(lhs, location);
+                        self.visit_operand(rhs, location);
+                    }
+                    Rvalue::Cast(_, op, ty) => {
+                        self.visit_operand(op, location);
+                        self.visit_ty(ty, location);
+                    }
+                    Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => {
+                        self.visit_place(place, PlaceContext::NON_MUTATING, location);
+                    }
+                    Rvalue::Ref(region, kind, place) => {
+                        self.visit_region(region, location);
+                        let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) };
+                        self.visit_place(place, pcx, location);
+                    }
+                    Rvalue::Repeat(op, constant) => {
+                        self.visit_operand(op, location);
+                        self.visit_ty_const(constant, location);
+                    }
+                    Rvalue::ShallowInitBox(op, ty) => {
+                        self.visit_ty(ty, location);
+                        self.visit_operand(op, location)
+                    }
+                    Rvalue::ThreadLocalRef(_) => {}
+                    Rvalue::NullaryOp(_, ty) => {
+                        self.visit_ty(ty, location);
+                    }
+                    Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => {
+                        self.visit_operand(op, location);
+                    }
+                }
+            }
 
-    fn super_projection_elem(
-        &mut self,
-        elem: &ProjectionElem,
-        ptx: PlaceContext,
-        location: Location,
-    ) {
-        match elem {
-            ProjectionElem::Downcast(_idx) => {}
-            ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
-            | ProjectionElem::Deref
-            | ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
-            ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location),
-            ProjectionElem::Index(local) => self.visit_local(local, ptx, location),
-            ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => {
-                self.visit_ty(ty, location)
+            fn super_operand(&mut self, operand: &$($mutability)? Operand, location: Location) {
+                match operand {
+                    Operand::Copy(place) | Operand::Move(place) => {
+                        self.visit_place(place, PlaceContext::NON_MUTATING, location)
+                    }
+                    Operand::Constant(constant) => {
+                        self.visit_const_operand(constant, location);
+                    }
+                }
             }
-        }
-    }
 
-    fn super_rvalue(&mut self, rvalue: &Rvalue, location: Location) {
-        match rvalue {
-            Rvalue::AddressOf(mutability, place) => {
-                let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut };
-                self.visit_place(place, pcx, location);
+            fn super_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) {
+                // This is a no-op on mir::Visitor.
+                let _ = projection;
             }
-            Rvalue::Aggregate(_, operands) => {
-                for op in operands {
-                    self.visit_operand(op, location);
-                }
+
+            fn super_ty(&mut self, ty: &$($mutability)? Ty) {
+                let _ = ty;
             }
-            Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
-                self.visit_operand(lhs, location);
-                self.visit_operand(rhs, location);
+
+            fn super_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) {
+                let ConstOperand { span, user_ty: _, const_ } = constant;
+                self.visit_span(span);
+                self.visit_mir_const(const_, location);
             }
-            Rvalue::Cast(_, op, ty) => {
-                self.visit_operand(op, location);
+
+            fn super_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) {
+                let MirConst { kind: _, ty, id: _ } = constant;
                 self.visit_ty(ty, location);
             }
-            Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => {
-                self.visit_place(place, PlaceContext::NON_MUTATING, location);
-            }
-            Rvalue::Ref(region, kind, place) => {
-                self.visit_region(region, location);
-                let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) };
-                self.visit_place(place, pcx, location);
+
+            fn super_ty_const(&mut self, constant: &$($mutability)? TyConst) {
+                let _ = constant;
             }
-            Rvalue::Repeat(op, constant) => {
-                self.visit_operand(op, location);
-                self.visit_ty_const(constant, location);
+
+            fn super_region(&mut self, region: &$($mutability)? Region) {
+                let _ = region;
             }
-            Rvalue::ShallowInitBox(op, ty) => {
-                self.visit_ty(ty, location);
-                self.visit_operand(op, location)
+
+            fn super_args(&mut self, args: &$($mutability)? GenericArgs) {
+                let _ = args;
             }
-            Rvalue::ThreadLocalRef(_) => {}
-            Rvalue::NullaryOp(_, ty) => {
-                self.visit_ty(ty, location);
+
+            fn super_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) {
+                let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } =
+                    var_debug_info;
+                self.visit_span(&$($mutability)? source_info.span);
+                let location = Location(source_info.span);
+                if let Some(composite) = composite {
+                    self.visit_ty(&$($mutability)? composite.ty, location);
+                }
+                match value {
+                    VarDebugInfoContents::Place(place) => {
+                        self.visit_place(place, PlaceContext::NON_USE, location);
+                    }
+                    VarDebugInfoContents::Const(constant) => {
+                        self.visit_mir_const(&$($mutability)? constant.const_, location);
+                    }
+                }
             }
-            Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => {
-                self.visit_operand(op, location);
+
+            fn super_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) {
+                match msg {
+                    AssertMessage::BoundsCheck { len, index } => {
+                        self.visit_operand(len, location);
+                        self.visit_operand(index, location);
+                    }
+                    AssertMessage::Overflow(_, left, right) => {
+                        self.visit_operand(left, location);
+                        self.visit_operand(right, location);
+                    }
+                    AssertMessage::OverflowNeg(op)
+                    | AssertMessage::DivisionByZero(op)
+                    | AssertMessage::RemainderByZero(op) => {
+                        self.visit_operand(op, location);
+                    }
+                    AssertMessage::ResumedAfterReturn(_)
+                    | AssertMessage::ResumedAfterPanic(_)
+                    | AssertMessage::NullPointerDereference => {
+                        //nothing to visit
+                    }
+                    AssertMessage::MisalignedPointerDereference { required, found } => {
+                        self.visit_operand(required, location);
+                        self.visit_operand(found, location);
+                    }
+                }
             }
         }
-    }
+    };
+}
 
-    fn super_operand(&mut self, operand: &Operand, location: Location) {
-        match operand {
-            Operand::Copy(place) | Operand::Move(place) => {
-                self.visit_place(place, PlaceContext::NON_MUTATING, location)
-            }
-            Operand::Constant(constant) => {
-                self.visit_const_operand(constant, location);
-            }
+macro_rules! super_body {
+    ($self:ident, $body:ident, mut) => {
+        for bb in $body.blocks.iter_mut() {
+            $self.visit_basic_block(bb);
         }
-    }
 
-    fn super_user_type_projection(&mut self, projection: &UserTypeProjection) {
-        // This is a no-op on mir::Visitor.
-        let _ = projection;
-    }
+        $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local_mut());
 
-    fn super_ty(&mut self, ty: &Ty) {
-        let _ = ty;
-    }
+        for (idx, arg) in $body.arg_locals_mut().iter_mut().enumerate() {
+            $self.visit_arg_decl(idx + 1, arg)
+        }
 
-    fn super_const_operand(&mut self, constant: &ConstOperand, location: Location) {
-        let ConstOperand { span, user_ty: _, const_ } = constant;
-        self.visit_span(span);
-        self.visit_mir_const(const_, location);
-    }
+        let local_start = $body.arg_count + 1;
+        for (idx, arg) in $body.inner_locals_mut().iter_mut().enumerate() {
+            $self.visit_local_decl(idx + local_start, arg)
+        }
 
-    fn super_mir_const(&mut self, constant: &MirConst, location: Location) {
-        let MirConst { kind: _, ty, id: _ } = constant;
-        self.visit_ty(ty, location);
-    }
+        for info in $body.var_debug_info.iter_mut() {
+            $self.visit_var_debug_info(info);
+        }
 
-    fn super_ty_const(&mut self, constant: &TyConst) {
-        let _ = constant;
-    }
+        $self.visit_span(&mut $body.span)
+    };
 
-    fn super_region(&mut self, region: &Region) {
-        let _ = region;
-    }
+    ($self:ident, $body:ident, ) => {
+        let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _, span } = $body;
 
-    fn super_args(&mut self, args: &GenericArgs) {
-        let _ = args;
-    }
+        for bb in blocks {
+            $self.visit_basic_block(bb);
+        }
 
-    fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
-        let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } =
-            var_debug_info;
-        self.visit_span(&source_info.span);
-        let location = Location(source_info.span);
-        if let Some(composite) = composite {
-            self.visit_ty(&composite.ty, location);
+        $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local());
+
+        for (idx, arg) in $body.arg_locals().iter().enumerate() {
+            $self.visit_arg_decl(idx + 1, arg)
         }
-        match value {
-            VarDebugInfoContents::Place(place) => {
-                self.visit_place(place, PlaceContext::NON_USE, location);
-            }
-            VarDebugInfoContents::Const(constant) => {
-                self.visit_mir_const(&constant.const_, location);
-            }
+
+        let local_start = arg_count + 1;
+        for (idx, arg) in $body.inner_locals().iter().enumerate() {
+            $self.visit_local_decl(idx + local_start, arg)
         }
-    }
 
-    fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
-        match msg {
-            AssertMessage::BoundsCheck { len, index } => {
-                self.visit_operand(len, location);
-                self.visit_operand(index, location);
-            }
-            AssertMessage::Overflow(_, left, right) => {
-                self.visit_operand(left, location);
-                self.visit_operand(right, location);
+        for info in var_debug_info.iter() {
+            $self.visit_var_debug_info(info);
+        }
+
+        $self.visit_span(span)
+    };
+}
+
+macro_rules! visit_place_fns {
+    (mut) => {
+        fn super_place(&mut self, place: &mut Place, ptx: PlaceContext, location: Location) {
+            self.visit_local(&mut place.local, ptx, location);
+
+            for elem in place.projection.iter_mut() {
+                self.visit_projection_elem(elem, ptx, location);
             }
-            AssertMessage::OverflowNeg(op)
-            | AssertMessage::DivisionByZero(op)
-            | AssertMessage::RemainderByZero(op) => {
-                self.visit_operand(op, location);
+        }
+
+        // We don't have to replicate the `process_projection()` like we did in
+        // `rustc_middle::mir::visit.rs` here because the `projection` field in `Place`
+        // of Stable-MIR is not an immutable borrow, unlike in `Place` of MIR.
+        fn visit_projection_elem(
+            &mut self,
+            elem: &mut ProjectionElem,
+            ptx: PlaceContext,
+            location: Location,
+        ) {
+            self.super_projection_elem(elem, ptx, location)
+        }
+
+        fn super_projection_elem(
+            &mut self,
+            elem: &mut ProjectionElem,
+            ptx: PlaceContext,
+            location: Location,
+        ) {
+            match elem {
+                ProjectionElem::Deref => {}
+                ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location),
+                ProjectionElem::Index(local) => self.visit_local(local, ptx, location),
+                ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {}
+                ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
+                ProjectionElem::Downcast(_idx) => {}
+                ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location),
+                ProjectionElem::Subtype(ty) => self.visit_ty(ty, location),
             }
-            AssertMessage::ResumedAfterReturn(_)
-            | AssertMessage::ResumedAfterPanic(_)
-            | AssertMessage::NullPointerDereference => {
-                //nothing to visit
+        }
+    };
+
+    () => {
+        fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) {
+            self.visit_local(&place.local, ptx, location);
+
+            for (idx, elem) in place.projection.iter().enumerate() {
+                let place_ref =
+                    PlaceRef { local: place.local, projection: &place.projection[..idx] };
+                self.visit_projection_elem(place_ref, elem, ptx, location);
             }
-            AssertMessage::MisalignedPointerDereference { required, found } => {
-                self.visit_operand(required, location);
-                self.visit_operand(found, location);
+        }
+
+        fn visit_projection_elem<'a>(
+            &mut self,
+            place_ref: PlaceRef<'a>,
+            elem: &ProjectionElem,
+            ptx: PlaceContext,
+            location: Location,
+        ) {
+            let _ = place_ref;
+            self.super_projection_elem(elem, ptx, location);
+        }
+
+        fn super_projection_elem(
+            &mut self,
+            elem: &ProjectionElem,
+            ptx: PlaceContext,
+            location: Location,
+        ) {
+            match elem {
+                ProjectionElem::Deref => {}
+                ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location),
+                ProjectionElem::Index(local) => self.visit_local(local, ptx, location),
+                ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {}
+                ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
+                ProjectionElem::Downcast(_idx) => {}
+                ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location),
+                ProjectionElem::Subtype(ty) => self.visit_ty(ty, location),
             }
         }
-    }
+    };
 }
 
+make_mir_visitor!(MirVisitor,);
+make_mir_visitor!(MutMirVisitor, mut);
+
 /// This function is a no-op that gets used to ensure this visitor is kept up-to-date.
 ///
 /// The idea is that whenever we replace an Opaque type by a real type, the compiler will fail
@@ -483,7 +563,7 @@ pub struct PlaceRef<'a> {
 impl PlaceRef<'_> {
     /// Get the type of this place.
     pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
-        self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?))
+        self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty))
     }
 }
 
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 104e0a3d010..23d9d926eba 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -67,9 +67,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.151"
+version = "0.1.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abc30f1766d387c35f2405e586d3e7a88230dc728ff78cd1d0bc59ae0b63154b"
+checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -89,9 +89,9 @@ dependencies = [
 
 [[package]]
 name = "dlmalloc"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b5e0d321d61de16390ed273b647ce51605b575916d3c25e6ddf27a1e140035"
+checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
 dependencies = [
  "cfg-if",
  "compiler_builtins",
@@ -176,9 +176,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.3"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
 dependencies = [
  "adler2",
  "compiler_builtins",
@@ -223,9 +223,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.93"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
 dependencies = [
  "unicode-ident",
 ]
@@ -247,9 +247,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
@@ -287,12 +287,9 @@ dependencies = [
 
 [[package]]
 name = "rand_core"
-version = "0.9.0"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
-dependencies = [
- "zerocopy",
-]
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
 
 [[package]]
 name = "rand_xorshift"
@@ -382,9 +379,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.98"
+version = "2.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -413,9 +410,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.16"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-width"
@@ -540,18 +537,18 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "zerocopy"
-version = "0.8.17"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.8.17"
+version = "0.8.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/library/Cargo.toml b/library/Cargo.toml
index 4d5955593ff..026ba147008 100644
--- a/library/Cargo.toml
+++ b/library/Cargo.toml
@@ -38,8 +38,11 @@ adler2.debug = 0
 gimli.debug = 0
 gimli.opt-level = "s"
 miniz_oxide.debug = 0
+miniz_oxide.opt-level = "s"
+# `opt-level = "s"` for `object` led to a size regression when tried previously
 object.debug = 0
 rustc-demangle.debug = 0
+rustc-demangle.opt-level = "s"
 
 [patch.crates-io]
 # See comments in `library/rustc-std-workspace-core/README.md` for what's going on
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 8d0253bd29a..b729d5e116d 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -16,7 +16,7 @@ bench = false
 
 [dependencies]
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] }
 
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index e77caad6540..4644e37f809 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1149,9 +1149,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     ///
     /// [memory layout]: self#memory-layout
     #[unstable(feature = "allocator_api", issue = "32838")]
-    #[rustc_const_unstable(feature = "const_box", issue = "92521")]
     #[inline]
-    pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
+    pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
     }
 
@@ -1203,9 +1202,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// [memory layout]: self#memory-layout
     #[unstable(feature = "allocator_api", issue = "32838")]
     // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
-    #[rustc_const_unstable(feature = "const_box", issue = "92521")]
     #[inline]
-    pub const unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self {
+    pub unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Self {
         // SAFETY: guaranteed by the caller.
         unsafe { Box::from_raw_in(raw.as_ptr(), alloc) }
     }
@@ -1550,9 +1548,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This
     /// is so that there is no conflict with a method on the inner type.
     #[unstable(feature = "allocator_api", issue = "32838")]
-    #[rustc_const_unstable(feature = "const_box", issue = "92521")]
     #[inline]
-    pub const fn allocator(b: &Self) -> &A {
+    pub fn allocator(b: &Self) -> &A {
         &b.1
     }
 
@@ -1639,8 +1636,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
     /// let bar = Pin::from(foo);
     /// ```
     #[stable(feature = "box_into_pin", since = "1.63.0")]
-    #[rustc_const_unstable(feature = "const_box", issue = "92521")]
-    pub const fn into_pin(boxed: Self) -> Pin<Self>
+    pub fn into_pin(boxed: Self) -> Pin<Self>
     where
         A: 'static,
     {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index c62f8e5b70f..be581661f4c 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -20,7 +20,7 @@ use core::iter;
 use core::marker::{PhantomData, Unsize};
 use core::mem::{self, ManuallyDrop, align_of_val_raw};
 use core::num::NonZeroUsize;
-use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
+use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
 use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, NonNull};
@@ -4066,3 +4066,413 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
         core::error::Error::provide(&**self, req);
     }
 }
+
+/// A uniquely owned [`Arc`].
+///
+/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong
+/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
+/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`.
+///
+/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common
+/// use case is to have an object be mutable during its initialization phase but then have it become
+/// immutable and converted to a normal `Arc`.
+///
+/// This can be used as a flexible way to create cyclic data structures, as in the example below.
+///
+/// ```
+/// #![feature(unique_rc_arc)]
+/// use std::sync::{Arc, Weak, UniqueArc};
+///
+/// struct Gadget {
+///     me: Weak<Gadget>,
+/// }
+///
+/// fn create_gadget() -> Option<Arc<Gadget>> {
+///     let mut rc = UniqueArc::new(Gadget {
+///         me: Weak::new(),
+///     });
+///     rc.me = UniqueArc::downgrade(&rc);
+///     Some(UniqueArc::into_arc(rc))
+/// }
+///
+/// create_gadget().unwrap();
+/// ```
+///
+/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that
+/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the
+/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data,
+/// including fallible or async constructors.
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+pub struct UniqueArc<
+    T: ?Sized,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
+    ptr: NonNull<ArcInner<T>>,
+    // Define the ownership of `ArcInner<T>` for drop-check
+    _marker: PhantomData<ArcInner<T>>,
+    // Invariance is necessary for soundness: once other `Weak`
+    // references exist, we already have a form of shared mutability!
+    _marker2: PhantomData<*mut T>,
+    alloc: A,
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Send> Send for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<T: ?Sized + Sync + Send, A: Allocator + Sync> Sync for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "coerce_unsized", issue = "18598")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueArc<U, A>>
+    for UniqueArc<T, A>
+{
+}
+
+//#[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<UniqueArc<U>> for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Display, A: Allocator> fmt::Display for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + fmt::Debug, A: Allocator> fmt::Debug for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> fmt::Pointer for UniqueArc<T, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Pointer::fmt(&(&raw const **self), f)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::Borrow<T> for UniqueArc<T, A> {
+    fn borrow(&self) -> &T {
+        &**self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> borrow::BorrowMut<T> for UniqueArc<T, A> {
+    fn borrow_mut(&mut self) -> &mut T {
+        &mut **self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsRef<T> for UniqueArc<T, A> {
+    fn as_ref(&self) -> &T {
+        &**self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueArc<T, A> {
+    fn as_mut(&mut self) -> &mut T {
+        &mut **self
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueArc<T, A> {
+    /// Equality for two `UniqueArc`s.
+    ///
+    /// Two `UniqueArc`s are equal if their inner values are equal.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five == UniqueArc::new(5));
+    /// ```
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(&**self, &**other)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for UniqueArc<T, A> {
+    /// Partial comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `partial_cmp()` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    /// use std::cmp::Ordering;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6)));
+    /// ```
+    #[inline(always)]
+    fn partial_cmp(&self, other: &UniqueArc<T, A>) -> Option<Ordering> {
+        (**self).partial_cmp(&**other)
+    }
+
+    /// Less-than comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `<` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five < UniqueArc::new(6));
+    /// ```
+    #[inline(always)]
+    fn lt(&self, other: &UniqueArc<T, A>) -> bool {
+        **self < **other
+    }
+
+    /// 'Less than or equal to' comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `<=` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five <= UniqueArc::new(5));
+    /// ```
+    #[inline(always)]
+    fn le(&self, other: &UniqueArc<T, A>) -> bool {
+        **self <= **other
+    }
+
+    /// Greater-than comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `>` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five > UniqueArc::new(4));
+    /// ```
+    #[inline(always)]
+    fn gt(&self, other: &UniqueArc<T, A>) -> bool {
+        **self > **other
+    }
+
+    /// 'Greater than or equal to' comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `>=` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert!(five >= UniqueArc::new(5));
+    /// ```
+    #[inline(always)]
+    fn ge(&self, other: &UniqueArc<T, A>) -> bool {
+        **self >= **other
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Ord, A: Allocator> Ord for UniqueArc<T, A> {
+    /// Comparison for two `UniqueArc`s.
+    ///
+    /// The two are compared by calling `cmp()` on their inner values.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unique_rc_arc)]
+    /// use std::sync::UniqueArc;
+    /// use std::cmp::Ordering;
+    ///
+    /// let five = UniqueArc::new(5);
+    ///
+    /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6)));
+    /// ```
+    #[inline]
+    fn cmp(&self, other: &UniqueArc<T, A>) -> Ordering {
+        (**self).cmp(&**other)
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Eq, A: Allocator> Eq for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Hash, A: Allocator> Hash for UniqueArc<T, A> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        (**self).hash(state);
+    }
+}
+
+impl<T> UniqueArc<T, Global> {
+    /// Creates a new `UniqueArc`.
+    ///
+    /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+    /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+    /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+    /// point to the new [`Arc`].
+    #[cfg(not(no_global_oom_handling))]
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
+    pub fn new(value: T) -> Self {
+        Self::new_in(value, Global)
+    }
+}
+
+impl<T, A: Allocator> UniqueArc<T, A> {
+    /// Creates a new `UniqueArc` in the provided allocator.
+    ///
+    /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading
+    /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`].
+    /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will
+    /// point to the new [`Arc`].
+    #[cfg(not(no_global_oom_handling))]
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
+    // #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn new_in(data: T, alloc: A) -> Self {
+        let (ptr, alloc) = Box::into_unique(Box::new_in(
+            ArcInner {
+                strong: atomic::AtomicUsize::new(0),
+                // keep one weak reference so if all the weak pointers that are created are dropped
+                // the UniqueArc still stays valid.
+                weak: atomic::AtomicUsize::new(1),
+                data,
+            },
+            alloc,
+        ));
+        Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc }
+    }
+}
+
+impl<T: ?Sized, A: Allocator> UniqueArc<T, A> {
+    /// Converts the `UniqueArc` into a regular [`Arc`].
+    ///
+    /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that
+    /// is passed to `into_arc`.
+    ///
+    /// Any weak references created before this method is called can now be upgraded to strong
+    /// references.
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
+    pub fn into_arc(this: Self) -> Arc<T, A> {
+        let this = ManuallyDrop::new(this);
+
+        // Move the allocator out.
+        // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
+        // a `ManuallyDrop`.
+        let alloc: A = unsafe { ptr::read(&this.alloc) };
+
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        unsafe {
+            // Convert our weak reference into a strong reference
+            (*this.ptr.as_ptr()).strong.store(1, Release);
+            Arc::from_inner_in(this.ptr, alloc)
+        }
+    }
+}
+
+impl<T: ?Sized, A: Allocator + Clone> UniqueArc<T, A> {
+    /// Creates a new weak reference to the `UniqueArc`.
+    ///
+    /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted
+    /// to a [`Arc`] using [`UniqueArc::into_arc`].
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    #[must_use]
+    pub fn downgrade(this: &Self) -> Weak<T, A> {
+        // Using a relaxed ordering is alright here, as knowledge of the
+        // original reference prevents other threads from erroneously deleting
+        // the object or converting the object to a normal `Arc<T, A>`.
+        //
+        // Note that we don't need to test if the weak counter is locked because there
+        // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock
+        // the weak counter.
+        //
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) };
+
+        // See comments in Arc::clone() for why we do this (for mem::forget).
+        if old_size > MAX_REFCOUNT {
+            abort();
+        }
+
+        Weak { ptr: this.ptr, alloc: this.alloc.clone() }
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> Deref for UniqueArc<T, A> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        unsafe { &self.ptr.as_ref().data }
+    }
+}
+
+// #[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueArc<T> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized, A: Allocator> DerefMut for UniqueArc<T, A> {
+    fn deref_mut(&mut self) -> &mut T {
+        // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
+        // have unique ownership and therefore it's safe to make a mutable reference because
+        // `UniqueArc` owns the only strong reference to itself.
+        // We also need to be careful to only create a mutable reference to the `data` field,
+        // as a mutable reference to the entire `ArcInner` would assert uniqueness over the
+        // ref count fields too, invalidating any attempt by `Weak`s to access the ref count.
+        unsafe { &mut (*self.ptr.as_ptr()).data }
+    }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+// #[unstable(feature = "deref_pure_trait", issue = "87121")]
+unsafe impl<T: ?Sized, A: Allocator> DerefPure for UniqueArc<T, A> {}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc<T, A> {
+    fn drop(&mut self) {
+        // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0.
+        // SAFETY: This pointer was allocated at creation time so we know it is valid.
+        let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
+        unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
+    }
+}
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 3782f9e9519..633ef717e04 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -3360,10 +3360,6 @@ impl<T: Hash, A: Allocator> Hash for Vec<T, A> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(
-    message = "vector indices are of type `usize` or ranges of `usize`",
-    label = "vector indices are of type `usize` or ranges of `usize`"
-)]
 impl<T, I: SliceIndex<[T]>, A: Allocator> Index<I> for Vec<T, A> {
     type Output = I::Output;
 
@@ -3374,10 +3370,6 @@ impl<T, I: SliceIndex<[T]>, A: Allocator> Index<I> for Vec<T, A> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(
-    message = "vector indices are of type `usize` or ranges of `usize`",
-    label = "vector indices are of type `usize` or ranges of `usize`"
-)]
 impl<T, I: SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
     #[inline]
     fn index_mut(&mut self, index: I) -> &mut Self::Output {
diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs
index 0baa50f439b..00bdf527133 100644
--- a/library/alloctests/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
@@ -1,7 +1,7 @@
 use std::any::Any;
 use std::cell::{Cell, RefCell};
 use std::iter::TrustedLen;
-use std::sync::{Arc, Weak};
+use std::sync::{Arc, UniqueArc, Weak};
 
 #[test]
 fn uninhabited() {
@@ -263,9 +263,30 @@ fn make_mut_unsized() {
     assert_eq!(*other_data, [110, 20, 30]);
 }
 
+#[test]
+fn test_unique_arc_weak() {
+    let data = UniqueArc::new(32);
+
+    // Test that `Weak` downgraded from `UniqueArc` cannot be upgraded.
+    let weak = UniqueArc::downgrade(&data);
+    assert_eq!(weak.strong_count(), 0);
+    assert_eq!(weak.weak_count(), 0);
+    assert!(weak.upgrade().is_none());
+
+    // Test that `Weak` can now be upgraded after the `UniqueArc` being converted to `Arc`.
+    let strong = UniqueArc::into_arc(data);
+    assert_eq!(*strong, 32);
+    assert_eq!(weak.strong_count(), 1);
+    assert_eq!(weak.weak_count(), 1);
+    let upgraded = weak.upgrade().unwrap();
+    assert_eq!(*upgraded, 32);
+    assert_eq!(weak.strong_count(), 2);
+    assert_eq!(weak.weak_count(), 1);
+}
+
 #[allow(unused)]
 mod pin_coerce_unsized {
-    use alloc::sync::Arc;
+    use alloc::sync::{Arc, UniqueArc};
     use core::pin::Pin;
 
     pub trait MyTrait {}
@@ -275,4 +296,7 @@ mod pin_coerce_unsized {
     pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
         arg
     }
+    pub fn pin_unique_arc(arg: Pin<UniqueArc<String>>) -> Pin<UniqueArc<dyn MyTrait>> {
+        arg
+    }
 }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 1a320b316a4..e789601a409 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -495,7 +495,7 @@ impl<T> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "move_cell", since = "1.17.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_confusables("swap")]
     pub const fn replace(&self, val: T) -> T {
         // SAFETY: This can cause data races if called from a separate thread,
@@ -537,7 +537,7 @@ impl<T: Copy> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn get(&self) -> T {
         // SAFETY: This can cause data races if called from a separate thread,
         // but `Cell` is `!Sync` so this won't happen.
@@ -617,7 +617,7 @@ impl<T: ?Sized> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn get_mut(&mut self) -> &mut T {
         self.value.get_mut()
     }
@@ -637,7 +637,7 @@ impl<T: ?Sized> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "as_cell", since = "1.37.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn from_mut(t: &mut T) -> &Cell<T> {
         // SAFETY: `&mut` ensures unique access.
         unsafe { &*(t as *mut T as *const Cell<T>) }
@@ -695,7 +695,7 @@ impl<T> Cell<[T]> {
     /// assert_eq!(slice_cell.len(), 3);
     /// ```
     #[stable(feature = "as_cell", since = "1.37.0")]
-    #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
+    #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn as_slice_of_cells(&self) -> &[Cell<T>] {
         // SAFETY: `Cell<T>` has the same memory layout as `T`.
         unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 25bd17d5802..0dc2cc72e06 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,6 +29,7 @@ mod bytewise;
 pub(crate) use bytewise::BytewiseEq;
 
 use self::Ordering::*;
+use crate::ops::ControlFlow;
 
 /// Trait for comparisons using the equality operator.
 ///
@@ -1435,6 +1436,67 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     fn ge(&self, other: &Rhs) -> bool {
         self.partial_cmp(other).is_some_and(Ordering::is_ge)
     }
+
+    /// If `self == other`, returns `ControlFlow::Continue(())`.
+    /// Otherwise, returns `ControlFlow::Break(self < other)`.
+    ///
+    /// This is useful for chaining together calls when implementing a lexical
+    /// `PartialOrd::lt`, as it allows types (like primitives) which can cheaply
+    /// check `==` and `<` separately to do rather than needing to calculate
+    /// (then optimize out) the three-way `Ordering` result.
+    #[inline]
+    #[must_use]
+    // Added to improve the behaviour of tuples; not necessarily stabilization-track.
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_lt(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_lt)
+    }
+
+    /// Same as `__chaining_lt`, but for `<=` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_le)
+    }
+
+    /// Same as `__chaining_lt`, but for `>` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_gt)
+    }
+
+    /// Same as `__chaining_lt`, but for `>=` instead of `<`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
+    #[doc(hidden)]
+    fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {
+        default_chaining_impl(self, other, Ordering::is_ge)
+    }
+}
+
+fn default_chaining_impl<T: ?Sized, U: ?Sized>(
+    lhs: &T,
+    rhs: &U,
+    p: impl FnOnce(Ordering) -> bool,
+) -> ControlFlow<bool>
+where
+    T: PartialOrd<U>,
+{
+    // It's important that this only call `partial_cmp` once, not call `eq` then
+    // one of the relational operators.  We don't want to `bcmp`-then-`memcp` a
+    // `String`, for example, or similarly for other data structures (#108157).
+    match <T as PartialOrd<U>>::partial_cmp(lhs, rhs) {
+        Some(Equal) => ControlFlow::Continue(()),
+        Some(c) => ControlFlow::Break(p(c)),
+        None => ControlFlow::Break(false),
+    }
 }
 
 /// Derive macro generating an impl of the trait [`PartialOrd`].
@@ -1741,15 +1803,16 @@ where
 mod impls {
     use crate::cmp::Ordering::{self, Equal, Greater, Less};
     use crate::hint::unreachable_unchecked;
+    use crate::ops::ControlFlow::{self, Break, Continue};
 
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialEq for $t {
                 #[inline]
-                fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
+                fn eq(&self, other: &Self) -> bool { *self == *other }
                 #[inline]
-                fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
+                fn ne(&self, other: &Self) -> bool { *self != *other }
             }
         )*)
     }
@@ -1779,12 +1842,51 @@ mod impls {
 
     eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
+    #[rustfmt::skip]
+    macro_rules! partial_ord_methods_primitive_impl {
+        () => {
+            #[inline(always)]
+            fn lt(&self, other: &Self) -> bool { *self <  *other }
+            #[inline(always)]
+            fn le(&self, other: &Self) -> bool { *self <= *other }
+            #[inline(always)]
+            fn gt(&self, other: &Self) -> bool { *self >  *other }
+            #[inline(always)]
+            fn ge(&self, other: &Self) -> bool { *self >= *other }
+
+            // These implementations are the same for `Ord` or `PartialOrd` types
+            // because if either is NAN the `==` test will fail so we end up in
+            // the `Break` case and the comparison will correctly return `false`.
+
+            #[inline]
+            fn __chaining_lt(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs < rhs) }
+            }
+            #[inline]
+            fn __chaining_le(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) }
+            }
+            #[inline]
+            fn __chaining_gt(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs > rhs) }
+            }
+            #[inline]
+            fn __chaining_ge(&self, other: &Self) -> ControlFlow<bool> {
+                let (lhs, rhs) = (*self, *other);
+                if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) }
+            }
+        };
+    }
+
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialOrd for $t {
                 #[inline]
-                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                     match (*self <= *other, *self >= *other) {
                         (false, false) => None,
                         (false, true) => Some(Greater),
@@ -1792,14 +1894,8 @@ mod impls {
                         (true, true) => Some(Equal),
                     }
                 }
-                #[inline(always)]
-                fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
-                #[inline(always)]
-                fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
-                #[inline(always)]
-                fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
-                #[inline(always)]
-                fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
+
+                partial_ord_methods_primitive_impl!();
             }
         )*)
     }
@@ -1818,6 +1914,8 @@ mod impls {
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
             Some(self.cmp(other))
         }
+
+        partial_ord_methods_primitive_impl!();
     }
 
     partial_ord_impl! { f16 f32 f64 f128 }
@@ -1827,23 +1925,17 @@ mod impls {
             #[stable(feature = "rust1", since = "1.0.0")]
             impl PartialOrd for $t {
                 #[inline]
-                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                     Some(crate::intrinsics::three_way_compare(*self, *other))
                 }
-                #[inline(always)]
-                fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
-                #[inline(always)]
-                fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
-                #[inline(always)]
-                fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
-                #[inline(always)]
-                fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
+
+                partial_ord_methods_primitive_impl!();
             }
 
             #[stable(feature = "rust1", since = "1.0.0")]
             impl Ord for $t {
                 #[inline]
-                fn cmp(&self, other: &$t) -> Ordering {
+                fn cmp(&self, other: &Self) -> Ordering {
                     crate::intrinsics::three_way_compare(*self, *other)
                 }
             }
diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs
index 0a70eb4da55..351bf9f8314 100644
--- a/library/core/src/ffi/primitives.rs
+++ b/library/core/src/ffi/primitives.rs
@@ -35,7 +35,7 @@ type_alias! { "c_float.md", c_float = f32; }
 type_alias! { "c_double.md", c_double = f64; }
 
 mod c_char_definition {
-    cfg_if! {
+    crate::cfg_match! {
         // These are the targets on which c_char is unsigned. Usually the
         // signedness is the same for all target_os values on a given architecture
         // but there are some exceptions (see isSignedCharDefault() in clang).
@@ -105,7 +105,7 @@ mod c_char_definition {
         //   architecture defaults). As we only have a target for userspace apps so there are no
         //   special cases for L4Re below.
         //   https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
-        if #[cfg(all(
+        all(
             not(windows),
             not(target_vendor = "apple"),
             not(target_os = "vita"),
@@ -122,24 +122,27 @@ mod c_char_definition {
                 target_arch = "s390x",
                 target_arch = "xtensa",
             )
-        ))] {
+        ) => {
             pub(super) type c_char = u8;
-        } else {
-            // On every other target, c_char is signed.
+        }
+        // On every other target, c_char is signed.
+        _ => {
             pub(super) type c_char = i8;
         }
     }
 }
 
 mod c_long_definition {
-    cfg_if! {
-        if #[cfg(any(
+    crate::cfg_match! {
+        any(
             all(target_pointer_width = "64", not(windows)),
             // wasm32 Linux ABI uses 64-bit long
-            all(target_arch = "wasm32", target_os = "linux")))] {
+            all(target_arch = "wasm32", target_os = "linux")
+        ) => {
             pub(super) type c_long = i64;
             pub(super) type c_ulong = u64;
-        } else {
+        }
+        _ => {
             // The minimal size of `long` in the C standard is 32 bits
             pub(super) type c_long = i32;
             pub(super) type c_ulong = u32;
@@ -169,11 +172,12 @@ pub type c_ptrdiff_t = isize;
 pub type c_ssize_t = isize;
 
 mod c_int_definition {
-    cfg_if! {
-        if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] {
+    crate::cfg_match! {
+        any(target_arch = "avr", target_arch = "msp430") => {
             pub(super) type c_int = i16;
             pub(super) type c_uint = u16;
-        } else {
+        }
+        _ => {
             pub(super) type c_int = i32;
             pub(super) type c_uint = u32;
         }
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 4a43c12be9a..870ad9df4fd 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -86,7 +86,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
         let min_precision = 0;
@@ -162,7 +162,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         // 1 integral digit + `precision` fractional digits = `precision + 1` total digits
         float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
     } else {
@@ -180,7 +180,7 @@ where
         true => flt2dec::Sign::MinusPlus,
     };
 
-    if let Some(precision) = fmt.options.precision {
+    if let Some(precision) = fmt.options.get_precision() {
         // this behavior of {:.PREC?} predates exponential formatting for {:?}
         float_to_decimal_common_exact(fmt, num, sign, precision)
     } else {
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 48f36044471..30fd2d7815f 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -33,19 +33,6 @@ pub enum Alignment {
     Center,
 }
 
-#[doc(hidden)]
-#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")]
-impl From<rt::Alignment> for Option<Alignment> {
-    fn from(value: rt::Alignment) -> Self {
-        match value {
-            rt::Alignment::Left => Some(Alignment::Left),
-            rt::Alignment::Right => Some(Alignment::Right),
-            rt::Alignment::Center => Some(Alignment::Center),
-            rt::Alignment::Unknown => None,
-        }
-    }
-}
-
 #[stable(feature = "debug_builders", since = "1.2.0")]
 pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 #[unstable(feature = "debug_closure_helpers", issue = "117729")]
@@ -291,11 +278,52 @@ pub enum DebugAsHex {
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "formatting_options", issue = "118117")]
 pub struct FormattingOptions {
+    /// Flags, with the following bit fields:
+    ///
+    /// ```text
+    ///   31  30  29  28  27  26  25  24  23  22  21  20                              0
+    /// ┌───┬───────┬───┬───┬───┬───┬───┬───┬───┬───┬──────────────────────────────────┐
+    /// │ 1 │ align │ p │ w │ X?│ x?│'0'│ # │ - │ + │               fill               │
+    /// └───┴───────┴───┴───┴───┴───┴───┴───┴───┴───┴──────────────────────────────────┘
+    ///   │     │     │   │  └─┬───────────────────┘ └─┬──────────────────────────────┘
+    ///   │     │     │   │    │                       └─ The fill character (21 bits char).
+    ///   │     │     │   │    └─ The debug upper/lower hex, zero pad, alternate, and plus/minus flags.
+    ///   │     │     │   └─ Whether a width is set. (The value is stored separately.)
+    ///   │     │     └─ Whether a precision is set. (The value is stored separately.)
+    ///   │     ├─ 0: Align left. (<)
+    ///   │     ├─ 1: Align right. (>)
+    ///   │     ├─ 2: Align center. (^)
+    ///   │     └─ 3: Alignment not set. (default)
+    ///   └─ Always set.
+    ///      This makes it possible to distinguish formatting flags from
+    ///      a &str size when stored in (the upper bits of) the same field.
+    ///      (fmt::Arguments will make use of this property in the future.)
+    /// ```
+    // Note: This could use a special niche type with range 0x8000_0000..=0xfdd0ffff.
+    // It's unclear if that's useful, though.
     flags: u32,
-    fill: char,
-    align: Option<Alignment>,
-    width: Option<u16>,
-    precision: Option<u16>,
+    /// Width if width flag (bit 27) above is set. Otherwise, always 0.
+    width: u16,
+    /// Precision if precision flag (bit 28) above is set. Otherwise, always 0.
+    precision: u16,
+}
+
+// This needs to match with compiler/rustc_ast_lowering/src/format.rs.
+mod flags {
+    pub(super) const SIGN_PLUS_FLAG: u32 = 1 << 21;
+    pub(super) const SIGN_MINUS_FLAG: u32 = 1 << 22;
+    pub(super) const ALTERNATE_FLAG: u32 = 1 << 23;
+    pub(super) const SIGN_AWARE_ZERO_PAD_FLAG: u32 = 1 << 24;
+    pub(super) const DEBUG_LOWER_HEX_FLAG: u32 = 1 << 25;
+    pub(super) const DEBUG_UPPER_HEX_FLAG: u32 = 1 << 26;
+    pub(super) const WIDTH_FLAG: u32 = 1 << 27;
+    pub(super) const PRECISION_FLAG: u32 = 1 << 28;
+    pub(super) const ALIGN_BITS: u32 = 0b11 << 29;
+    pub(super) const ALIGN_LEFT: u32 = 0 << 29;
+    pub(super) const ALIGN_RIGHT: u32 = 1 << 29;
+    pub(super) const ALIGN_CENTER: u32 = 2 << 29;
+    pub(super) const ALIGN_UNKNOWN: u32 = 3 << 29;
+    pub(super) const ALWAYS_SET: u32 = 1 << 31;
 }
 
 impl FormattingOptions {
@@ -311,7 +339,11 @@ impl FormattingOptions {
     /// - no [`DebugAsHex`] output mode.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn new() -> Self {
-        Self { flags: 0, fill: ' ', align: None, width: None, precision: None }
+        Self {
+            flags: ' ' as u32 | flags::ALIGN_UNKNOWN | flags::ALWAYS_SET,
+            width: 0,
+            precision: 0,
+        }
     }
 
     /// Sets or removes the sign (the `+` or the `-` flag).
@@ -324,13 +356,12 @@ impl FormattingOptions {
     /// - `-`: Currently not used
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
-        self.flags =
-            self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32);
-        match sign {
-            None => {}
-            Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32,
-            Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32,
-        }
+        let sign = match sign {
+            None => 0,
+            Some(Sign::Plus) => flags::SIGN_PLUS_FLAG,
+            Some(Sign::Minus) => flags::SIGN_MINUS_FLAG,
+        };
+        self.flags = self.flags & !(flags::SIGN_PLUS_FLAG | flags::SIGN_MINUS_FLAG) | sign;
         self
     }
     /// Sets or unsets the `0` flag.
@@ -339,9 +370,9 @@ impl FormattingOptions {
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
         if sign_aware_zero_pad {
-            self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32
+            self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG;
         } else {
-            self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32)
+            self.flags &= !flags::SIGN_AWARE_ZERO_PAD_FLAG;
         }
         self
     }
@@ -356,9 +387,9 @@ impl FormattingOptions {
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn alternate(&mut self, alternate: bool) -> &mut Self {
         if alternate {
-            self.flags |= 1 << rt::Flag::Alternate as u32
+            self.flags |= flags::ALTERNATE_FLAG;
         } else {
-            self.flags &= !(1 << rt::Flag::Alternate as u32)
+            self.flags &= !flags::ALTERNATE_FLAG;
         }
         self
     }
@@ -370,7 +401,7 @@ impl FormattingOptions {
     /// printed around it.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn fill(&mut self, fill: char) -> &mut Self {
-        self.fill = fill;
+        self.flags = self.flags & (u32::MAX << 21) | fill as u32;
         self
     }
     /// Sets or removes the alignment.
@@ -379,7 +410,13 @@ impl FormattingOptions {
     /// positioned if it is smaller than the width of the formatter.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
-        self.align = align;
+        let align: u32 = match align {
+            Some(Alignment::Left) => flags::ALIGN_LEFT,
+            Some(Alignment::Right) => flags::ALIGN_RIGHT,
+            Some(Alignment::Center) => flags::ALIGN_CENTER,
+            None => flags::ALIGN_UNKNOWN,
+        };
+        self.flags = self.flags & !flags::ALIGN_BITS | align;
         self
     }
     /// Sets or removes the width.
@@ -390,7 +427,13 @@ impl FormattingOptions {
     /// will be used to take up the required space.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn width(&mut self, width: Option<u16>) -> &mut Self {
-        self.width = width;
+        if let Some(width) = width {
+            self.flags |= flags::WIDTH_FLAG;
+            self.width = width;
+        } else {
+            self.flags &= !flags::WIDTH_FLAG;
+            self.width = 0;
+        }
         self
     }
     /// Sets or removes the precision.
@@ -404,77 +447,85 @@ impl FormattingOptions {
     /// decimal point should be printed.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
-        self.precision = precision;
+        if let Some(precision) = precision {
+            self.flags |= flags::PRECISION_FLAG;
+            self.precision = precision;
+        } else {
+            self.flags &= !flags::PRECISION_FLAG;
+            self.precision = 0;
+        }
         self
     }
     /// Specifies whether the [`Debug`] trait should use lower-/upper-case
     /// hexadecimal or normal integers
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
-        self.flags = self.flags
-            & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32);
-        match debug_as_hex {
-            None => {}
-            Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32,
-            Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32,
-        }
+        let debug_as_hex = match debug_as_hex {
+            None => 0,
+            Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG,
+            Some(DebugAsHex::Upper) => flags::DEBUG_UPPER_HEX_FLAG,
+        };
+        self.flags = self.flags & !(flags::DEBUG_LOWER_HEX_FLAG | flags::DEBUG_UPPER_HEX_FLAG)
+            | debug_as_hex;
         self
     }
 
     /// Returns the current sign (the `+` or the `-` flag).
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_sign(&self) -> Option<Sign> {
-        const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32;
-        const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32;
-        match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) {
-            SIGN_PLUS_BITFIELD => Some(Sign::Plus),
-            SIGN_MINUS_BITFIELD => Some(Sign::Minus),
-            0 => None,
-            _ => panic!("Invalid sign bits set in flags"),
+        if self.flags & flags::SIGN_PLUS_FLAG != 0 {
+            Some(Sign::Plus)
+        } else if self.flags & flags::SIGN_MINUS_FLAG != 0 {
+            Some(Sign::Minus)
+        } else {
+            None
         }
     }
     /// Returns the current `0` flag.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_sign_aware_zero_pad(&self) -> bool {
-        self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+        self.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0
     }
     /// Returns the current `#` flag.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_alternate(&self) -> bool {
-        self.flags & (1 << rt::Flag::Alternate as u32) != 0
+        self.flags & flags::ALTERNATE_FLAG != 0
     }
     /// Returns the current fill character.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_fill(&self) -> char {
-        self.fill
+        // SAFETY: We only ever put a valid `char` in the lower 21 bits of the flags field.
+        unsafe { char::from_u32_unchecked(self.flags & 0x1FFFFF) }
     }
     /// Returns the current alignment.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_align(&self) -> Option<Alignment> {
-        self.align
+        match self.flags & flags::ALIGN_BITS {
+            flags::ALIGN_LEFT => Some(Alignment::Left),
+            flags::ALIGN_RIGHT => Some(Alignment::Right),
+            flags::ALIGN_CENTER => Some(Alignment::Center),
+            _ => None,
+        }
     }
     /// Returns the current width.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_width(&self) -> Option<u16> {
-        self.width
+        if self.flags & flags::WIDTH_FLAG != 0 { Some(self.width) } else { None }
     }
     /// Returns the current precision.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_precision(&self) -> Option<u16> {
-        self.precision
+        if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None }
     }
     /// Returns the current precision.
     #[unstable(feature = "formatting_options", issue = "118117")]
     pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> {
-        const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32;
-        const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32;
-        match self.flags
-            & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32))
-        {
-            DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper),
-            DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower),
-            0 => None,
-            _ => panic!("Invalid hex debug bits set in flags"),
+        if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 {
+            Some(DebugAsHex::Lower)
+        } else if self.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 {
+            Some(DebugAsHex::Upper)
+        } else {
+            None
         }
     }
 
@@ -485,27 +536,6 @@ impl FormattingOptions {
     pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
         Formatter { options: self, buf: write }
     }
-
-    #[doc(hidden)]
-    #[unstable(
-        feature = "fmt_internals",
-        reason = "internal routines only exposed for testing",
-        issue = "none"
-    )]
-    /// Flags for formatting
-    pub fn flags(&mut self, flags: u32) {
-        self.flags = flags
-    }
-    #[doc(hidden)]
-    #[unstable(
-        feature = "fmt_internals",
-        reason = "internal routines only exposed for testing",
-        issue = "none"
-    )]
-    /// Flags for formatting
-    pub fn get_flags(&self) -> u32 {
-        self.flags
-    }
 }
 
 #[unstable(feature = "formatting_options", issue = "118117")]
@@ -1479,15 +1509,25 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
 }
 
 unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
-    fmt.options.fill = arg.fill;
-    fmt.options.align = arg.align.into();
-    fmt.options.flags = arg.flags;
-    // SAFETY: arg and args come from the same Arguments,
-    // which guarantees the indexes are always within bounds.
-    unsafe {
-        fmt.options.width = getcount(args, &arg.width);
-        fmt.options.precision = getcount(args, &arg.precision);
-    }
+    let (width, precision) =
+        // SAFETY: arg and args come from the same Arguments,
+        // which guarantees the indexes are always within bounds.
+        unsafe { (getcount(args, &arg.width), getcount(args, &arg.precision)) };
+
+    #[cfg(bootstrap)]
+    let options =
+        *FormattingOptions { flags: flags::ALWAYS_SET | arg.flags << 21, width: 0, precision: 0 }
+            .align(match arg.align {
+                rt::Alignment::Left => Some(Alignment::Left),
+                rt::Alignment::Right => Some(Alignment::Right),
+                rt::Alignment::Center => Some(Alignment::Center),
+                rt::Alignment::Unknown => None,
+            })
+            .fill(arg.fill)
+            .width(width)
+            .precision(precision);
+    #[cfg(not(bootstrap))]
+    let options = FormattingOptions { flags: arg.flags, width, precision };
 
     // Extract the correct argument
     debug_assert!(arg.position < args.len());
@@ -1495,17 +1535,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
     // which guarantees its index is always within bounds.
     let value = unsafe { args.get_unchecked(arg.position) };
 
+    // Set all the formatting options.
+    fmt.options = options;
+
     // Then actually do some printing
     // SAFETY: this is a placeholder argument.
     unsafe { value.fmt(fmt) }
 }
 
+#[cfg(bootstrap)]
 unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
     match *cnt {
-        #[cfg(bootstrap)]
         rt::Count::Is(n) => Some(n as u16),
-        #[cfg(not(bootstrap))]
-        rt::Count::Is(n) => Some(n),
         rt::Count::Implied => None,
         rt::Count::Param(i) => {
             debug_assert!(i < args.len());
@@ -1516,6 +1557,20 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
     }
 }
 
+#[cfg(not(bootstrap))]
+unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> u16 {
+    match *cnt {
+        rt::Count::Is(n) => n,
+        rt::Count::Implied => 0,
+        rt::Count::Param(i) => {
+            debug_assert!(i < args.len());
+            // SAFETY: cnt and args come from the same Arguments,
+            // which guarantees this index is always within bounds.
+            unsafe { args.get_unchecked(i).as_u16().unwrap_unchecked() }
+        }
+    }
+}
+
 /// Padding after the end of something. Returned by `Formatter::padding`.
 #[must_use = "don't forget to write the post padding"]
 pub(crate) struct PostPadding {
@@ -1629,40 +1684,28 @@ impl<'a> Formatter<'a> {
         }
 
         // The `width` field is more of a `min-width` parameter at this point.
-        match self.options.width {
-            // If there's no minimum length requirements then we can just
-            // write the bytes.
-            None => {
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)
-            }
-            // Check if we're over the minimum width, if so then we can also
-            // just write the bytes.
-            Some(min) if width >= usize::from(min) => {
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)
-            }
+        let min = self.options.width;
+        if width >= usize::from(min) {
+            // We're over the minimum width, so then we can just write the bytes.
+            write_prefix(self, sign, prefix)?;
+            self.buf.write_str(buf)
+        } else if self.sign_aware_zero_pad() {
             // The sign and prefix goes before the padding if the fill character
             // is zero
-            Some(min) if self.sign_aware_zero_pad() => {
-                let old_fill = crate::mem::replace(&mut self.options.fill, '0');
-                let old_align =
-                    crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
-                write_prefix(self, sign, prefix)?;
-                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
-                self.buf.write_str(buf)?;
-                post_padding.write(self)?;
-                self.options.fill = old_fill;
-                self.options.align = old_align;
-                Ok(())
-            }
+            let old_options = self.options;
+            self.options.fill('0').align(Some(Alignment::Right));
+            write_prefix(self, sign, prefix)?;
+            let post_padding = self.padding(min - width as u16, Alignment::Right)?;
+            self.buf.write_str(buf)?;
+            post_padding.write(self)?;
+            self.options = old_options;
+            Ok(())
+        } else {
             // Otherwise, the sign and prefix goes after the padding
-            Some(min) => {
-                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
-                write_prefix(self, sign, prefix)?;
-                self.buf.write_str(buf)?;
-                post_padding.write(self)
-            }
+            let post_padding = self.padding(min - width as u16, Alignment::Right)?;
+            write_prefix(self, sign, prefix)?;
+            self.buf.write_str(buf)?;
+            post_padding.write(self)
         }
     }
 
@@ -1698,13 +1741,13 @@ impl<'a> Formatter<'a> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pad(&mut self, s: &str) -> Result {
         // Make sure there's a fast path up front.
-        if self.options.width.is_none() && self.options.precision.is_none() {
+        if self.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 {
             return self.buf.write_str(s);
         }
 
         // The `precision` field can be interpreted as a maximum width for the
         // string being formatted.
-        let (s, char_count) = if let Some(max_char_count) = self.options.precision {
+        let (s, char_count) = if let Some(max_char_count) = self.options.get_precision() {
             let mut iter = s.char_indices();
             let remaining = match iter.advance_by(usize::from(max_char_count)) {
                 Ok(()) => 0,
@@ -1720,12 +1763,11 @@ impl<'a> Formatter<'a> {
         };
 
         // The `width` field is more of a minimum width parameter at this point.
-        if let Some(width) = self.options.width
-            && char_count < usize::from(width)
-        {
+        if char_count < usize::from(self.options.width) {
             // If we're under the minimum width, then fill up the minimum width
             // with the specified string + some alignment.
-            let post_padding = self.padding(width - char_count as u16, Alignment::Left)?;
+            let post_padding =
+                self.padding(self.options.width - char_count as u16, Alignment::Left)?;
             self.buf.write_str(s)?;
             post_padding.write(self)
         } else {
@@ -1744,19 +1786,20 @@ impl<'a> Formatter<'a> {
         padding: u16,
         default: Alignment,
     ) -> result::Result<PostPadding, Error> {
-        let align = self.align().unwrap_or(default);
+        let align = self.options.get_align().unwrap_or(default);
+        let fill = self.options.get_fill();
 
-        let (pre_pad, post_pad) = match align {
-            Alignment::Left => (0, padding),
-            Alignment::Right => (padding, 0),
-            Alignment::Center => (padding / 2, (padding + 1) / 2),
+        let padding_left = match align {
+            Alignment::Left => 0,
+            Alignment::Right => padding,
+            Alignment::Center => padding / 2,
         };
 
-        for _ in 0..pre_pad {
-            self.buf.write_char(self.options.fill)?;
+        for _ in 0..padding_left {
+            self.buf.write_char(fill)?;
         }
 
-        Ok(PostPadding::new(self.options.fill, post_pad))
+        Ok(PostPadding::new(fill, padding - padding_left))
     }
 
     /// Takes the formatted parts and applies the padding.
@@ -1768,12 +1811,16 @@ impl<'a> Formatter<'a> {
     ///
     /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
     unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        if let Some(mut width) = self.options.width {
+        if self.options.width == 0 {
+            // this is the common case and we take a shortcut
+            // SAFETY: Per the precondition.
+            unsafe { self.write_formatted_parts(formatted) }
+        } else {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
             let mut formatted = formatted.clone();
-            let old_fill = self.options.fill;
-            let old_align = self.options.align;
+            let mut width = self.options.width;
+            let old_options = self.options;
             if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = formatted.sign;
@@ -1782,8 +1829,7 @@ impl<'a> Formatter<'a> {
                 // remove the sign from the formatted parts
                 formatted.sign = "";
                 width = width.saturating_sub(sign.len() as u16);
-                self.options.fill = '0';
-                self.options.align = Some(Alignment::Right);
+                self.options.fill('0').align(Some(Alignment::Right));
             }
 
             // remaining parts go through the ordinary padding process.
@@ -1800,13 +1846,8 @@ impl<'a> Formatter<'a> {
                 }
                 post_padding.write(self)
             };
-            self.options.fill = old_fill;
-            self.options.align = old_align;
+            self.options = old_options;
             ret
-        } else {
-            // this is the common case and we take a shortcut
-            // SAFETY: Per the precondition.
-            unsafe { self.write_formatted_parts(formatted) }
         }
     }
 
@@ -1927,7 +1968,9 @@ impl<'a> Formatter<'a> {
                 or `sign_aware_zero_pad` methods instead"
     )]
     pub fn flags(&self) -> u32 {
-        self.options.flags
+        // Extract the debug upper/lower hex, zero pad, alternate, and plus/minus flags
+        // to stay compatible with older versions of Rust.
+        self.options.flags >> 21 & 0x3F
     }
 
     /// Returns the character used as 'fill' whenever there is alignment.
@@ -1960,7 +2003,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn fill(&self) -> char {
-        self.options.fill
+        self.options.get_fill()
     }
 
     /// Returns a flag indicating what form of alignment was requested.
@@ -1995,7 +2038,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags_align", since = "1.28.0")]
     pub fn align(&self) -> Option<Alignment> {
-        self.options.align
+        self.options.get_align()
     }
 
     /// Returns the optionally specified integer width that the output should be.
@@ -2025,7 +2068,11 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> {
-        self.options.width.map(|x| x as usize)
+        if self.options.flags & flags::WIDTH_FLAG == 0 {
+            None
+        } else {
+            Some(self.options.width as usize)
+        }
     }
 
     /// Returns the optionally specified precision for numeric types.
@@ -2056,7 +2103,11 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> {
-        self.options.precision.map(|x| x as usize)
+        if self.options.flags & flags::PRECISION_FLAG == 0 {
+            None
+        } else {
+            Some(self.options.precision as usize)
+        }
     }
 
     /// Determines if the `+` flag was specified.
@@ -2088,7 +2139,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_plus(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0
+        self.options.flags & flags::SIGN_PLUS_FLAG != 0
     }
 
     /// Determines if the `-` flag was specified.
@@ -2117,7 +2168,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_minus(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0
+        self.options.flags & flags::SIGN_MINUS_FLAG != 0
     }
 
     /// Determines if the `#` flag was specified.
@@ -2145,7 +2196,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn alternate(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::Alternate as u32) != 0
+        self.options.flags & flags::ALTERNATE_FLAG != 0
     }
 
     /// Determines if the `0` flag was specified.
@@ -2171,17 +2222,16 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn sign_aware_zero_pad(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
+        self.options.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0
     }
 
     // FIXME: Decide what public API we want for these two flags.
     // https://github.com/rust-lang/rust/issues/48584
     fn debug_lower_hex(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
+        self.options.flags & flags::DEBUG_LOWER_HEX_FLAG != 0
     }
-
     fn debug_upper_hex(&self) -> bool {
-        self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
+        self.options.flags & flags::DEBUG_UPPER_HEX_FLAG != 0
     }
 
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
@@ -2761,7 +2811,7 @@ impl Debug for char {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Display for char {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        if f.options.width.is_none() && f.options.precision.is_none() {
+        if f.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 {
             f.write_char(*self)
         } else {
             f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8]))
@@ -2792,26 +2842,24 @@ impl<T: ?Sized> Pointer for *const T {
 ///
 /// [problematic]: https://github.com/rust-lang/rust/issues/95489
 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result {
-    let old_width = f.options.width;
-    let old_flags = f.options.flags;
+    let old_options = f.options;
 
     // The alternate flag is already treated by LowerHex as being special-
     // it denotes whether to prefix with 0x. We use it to work out whether
     // or not to zero extend, and then unconditionally set it to get the
     // prefix.
-    if f.alternate() {
-        f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
+    if f.options.get_alternate() {
+        f.options.sign_aware_zero_pad(true);
 
-        if f.options.width.is_none() {
-            f.options.width = Some((usize::BITS / 4) as u16 + 2);
+        if f.options.get_width().is_none() {
+            f.options.width(Some((usize::BITS / 4) as u16 + 2));
         }
     }
-    f.options.flags |= 1 << (rt::Flag::Alternate as u32);
+    f.options.alternate(true);
 
     let ret = LowerHex::fmt(&ptr_addr, f);
 
-    f.options.width = old_width;
-    f.options.flags = old_flags;
+    f.options = old_options;
 
     ret
 }
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 080fc6ddfc9..0b04ebccae2 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -11,13 +11,16 @@ use crate::ptr::NonNull;
 #[derive(Copy, Clone)]
 pub struct Placeholder {
     pub position: usize,
+    #[cfg(bootstrap)]
     pub fill: char,
+    #[cfg(bootstrap)]
     pub align: Alignment,
     pub flags: u32,
     pub precision: Count,
     pub width: Count,
 }
 
+#[cfg(bootstrap)]
 impl Placeholder {
     #[inline]
     pub const fn new(
@@ -32,6 +35,7 @@ impl Placeholder {
     }
 }
 
+#[cfg(bootstrap)]
 #[lang = "format_alignment"]
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum Alignment {
@@ -58,17 +62,6 @@ pub enum Count {
     Implied,
 }
 
-// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs.
-#[derive(Copy, Clone)]
-pub(super) enum Flag {
-    SignPlus,
-    SignMinus,
-    Alternate,
-    SignAwareZeroPad,
-    DebugLowerHex,
-    DebugUpperHex,
-}
-
 #[derive(Copy, Clone)]
 enum ArgumentType<'a> {
     Placeholder {
diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs
index fe4fa80263c..2aaefba2468 100644
--- a/library/core/src/internal_macros.rs
+++ b/library/core/src/internal_macros.rs
@@ -120,80 +120,3 @@ macro_rules! impl_fn_for_zst {
         )+
     }
 }
-
-/// A macro for defining `#[cfg]` if-else statements.
-///
-/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
-/// of `#[cfg]` cases, emitting the implementation which matches first.
-///
-/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to
-/// rewrite each clause multiple times.
-///
-/// # Example
-///
-/// ```ignore(cannot-test-this-because-non-exported-macro)
-/// cfg_if! {
-///     if #[cfg(unix)] {
-///         fn foo() { /* unix specific functionality */ }
-///     } else if #[cfg(target_pointer_width = "32")] {
-///         fn foo() { /* non-unix, 32-bit functionality */ }
-///     } else {
-///         fn foo() { /* fallback implementation */ }
-///     }
-/// }
-///
-/// # fn main() {}
-/// ```
-// This is a copy of `cfg_if!` from the `cfg_if` crate.
-// The recursive invocations should use $crate if this is ever exported.
-macro_rules! cfg_if {
-    // match if/else chains with a final `else`
-    (
-        $(
-            if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
-        ) else+
-        else { $( $e_tokens:tt )* }
-    ) => {
-        cfg_if! {
-            @__items () ;
-            $(
-                (( $i_meta ) ( $( $i_tokens )* )) ,
-            )+
-            (() ( $( $e_tokens )* )) ,
-        }
-    };
-
-    // Internal and recursive macro to emit all the items
-    //
-    // Collects all the previous cfgs in a list at the beginning, so they can be
-    // negated. After the semicolon is all the remaining items.
-    (@__items ( $( $_:meta , )* ) ; ) => {};
-    (
-        @__items ( $( $no:meta , )* ) ;
-        (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
-        $( $rest:tt , )*
-    ) => {
-        // Emit all items within one block, applying an appropriate #[cfg]. The
-        // #[cfg] will require all `$yes` matchers specified and must also negate
-        // all previous matchers.
-        #[cfg(all(
-            $( $yes , )?
-            not(any( $( $no ),* ))
-        ))]
-        cfg_if! { @__identity $( $tokens )* }
-
-        // Recurse to emit all other items in `$rest`, and when we do so add all
-        // our `$yes` matchers to the list of `$no` matchers as future emissions
-        // will have to negate everything we just matched as well.
-        cfg_if! {
-            @__items ( $( $no , )* $( $yes , )? ) ;
-            $( $rest , )*
-        }
-    };
-
-    // Internal macro to make __apply work out right for different match types,
-    // because of how macros match/expand stuff.
-    (@__identity $( $tokens:tt )* ) => {
-        $( $tokens )*
-    };
-}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index cf03c07b6a5..81e59a1f349 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3002,6 +3002,7 @@ pub const fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discrimina
 
 /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
 /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
+/// Returns `1` if unwinding occurred and `catch_fn` was called; returns `0` otherwise.
 ///
 /// `catch_fn` must not unwind.
 ///
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 9b9353b800a..a820045521b 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -172,61 +172,6 @@ where
     }
 }
 
-/// Marker trait for iterators/iterables which have a statically known upper
-/// bound of the number of items they can produce.
-///
-/// # Safety
-///
-/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`.
-/// Used in specializations.  Implementations must not be conditional on lifetimes or
-/// user-implementable traits.
-#[rustc_specialization_trait]
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe trait BoundedSize {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(1);
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Option<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for option::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, U> BoundedSize for Result<T, U> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for result::IntoIter<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for Once<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T> BoundedSize for OnceWith<T> {}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for [T; N] {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<T, const N: usize> BoundedSize for array::IntoIter<T, N> {
-    const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N);
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for Filter<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, P> BoundedSize for FilterMap<I, P> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize, F> BoundedSize for Map<I, F> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Copied<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: BoundedSize> BoundedSize for Cloned<I> {
-    const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND;
-}
-
 /// An iterator that flattens one level of nesting in an iterator of things
 /// that can be turned into iterators.
 ///
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index cc089c617c0..ada37b9af4c 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -1,7 +1,8 @@
 use crate::fmt;
 use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
-use crate::mem::{self, MaybeUninit};
+use crate::mem::MaybeUninit;
 use crate::num::NonZero;
+use crate::ops::{NeverShortCircuit, Try};
 
 /// Creates a new iterator that repeats a single element a given number of times.
 ///
@@ -95,10 +96,10 @@ impl<A> RepeatN<A> {
     fn take_element(&mut self) -> Option<A> {
         if self.count > 0 {
             self.count = 0;
-            let element = mem::replace(&mut self.element, MaybeUninit::uninit());
             // SAFETY: We just set count to zero so it won't be dropped again,
             // and it used to be non-zero so it hasn't already been dropped.
-            unsafe { Some(element.assume_init()) }
+            let element = unsafe { self.element.assume_init_read() };
+            Some(element)
         } else {
             None
         }
@@ -169,6 +170,39 @@ impl<A: Clone> Iterator for RepeatN<A> {
         }
     }
 
+    fn try_fold<B, F, R>(&mut self, mut acc: B, mut f: F) -> R
+    where
+        F: FnMut(B, A) -> R,
+        R: Try<Output = B>,
+    {
+        if self.count > 0 {
+            while self.count > 1 {
+                self.count -= 1;
+                // SAFETY: the count was larger than 1, so the element is
+                // initialized and hasn't been dropped.
+                acc = f(acc, unsafe { self.element.assume_init_ref().clone() })?;
+            }
+
+            // We could just set the count to zero directly, but doing it this
+            // way should make it easier for the optimizer to fold this tail
+            // into the loop when `clone()` is equivalent to copying.
+            self.count -= 1;
+            // SAFETY: we just set the count to zero from one, so the element
+            // is still initialized, has not been dropped yet and will not be
+            // accessed by future calls.
+            f(acc, unsafe { self.element.assume_init_read() })
+        } else {
+            try { acc }
+        }
+    }
+
+    fn fold<B, F>(mut self, init: B, f: F) -> B
+    where
+        F: FnMut(B, A) -> B,
+    {
+        self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
+    }
+
     #[inline]
     fn last(mut self) -> Option<A> {
         self.take_element()
@@ -203,6 +237,23 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     fn nth_back(&mut self, n: usize) -> Option<A> {
         self.nth(n)
     }
+
+    #[inline]
+    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+    where
+        F: FnMut(B, A) -> R,
+        R: Try<Output = B>,
+    {
+        self.try_fold(init, f)
+    }
+
+    #[inline]
+    fn rfold<B, F>(self, init: B, f: F) -> B
+    where
+        F: FnMut(B, A) -> B,
+    {
+        self.fold(init, f)
+    }
 }
 
 #[stable(feature = "iter_repeat_n", since = "1.82.0")]
@@ -220,7 +271,7 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
             // SAFETY: the check above ensured that the count used to be non-zero,
             // so element hasn't been dropped yet, and we just lowered the count to
             // zero so it won't be dropped later, and thus it's okay to take it here.
-            unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() }
+            unsafe { self.element.assume_init_read() }
         } else {
             // SAFETY: the count is non-zero, so it must have not been dropped yet.
             let element = unsafe { self.element.assume_init_ref() };
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index 5b7d95c2f65..12e2b8b393a 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -10,7 +10,7 @@ use crate::num::Wrapping;
 /// [`sum()`]: Iterator::sum
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
     message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
     label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
 )]
@@ -31,7 +31,7 @@ pub trait Sum<A = Self>: Sized {
 /// [`product()`]: Iterator::product
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
-#[rustc_on_unimplemented(
+#[diagnostic::on_unimplemented(
     message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
     label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
 )]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e1ca69edcbb..dc06aa4c38d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -100,6 +100,7 @@
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
+#![feature(cfg_match)]
 #![feature(closure_track_caller)]
 #![feature(const_carrying_mul_add)]
 #![feature(const_eval_select)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index fa0d882181a..5f200b31d1a 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1744,7 +1744,7 @@ pub(crate) mod builtin {
     }
 
     /// Provide a list of type aliases and other opaque-type-containing type definitions.
-    /// This list will be used in the body of the item it is applied to to define opaque
+    /// This list will be used in the body of the item it is applied to define opaque
     /// types' hidden types.
     /// Can only be applied to things that have bodies.
     #[unstable(
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 7aa5ed60d04..2f027be6928 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1623,6 +1623,8 @@ impl Ipv6Addr {
             // IANA says N/A.
             || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _])
             || self.is_documentation()
+            // Segment Routing (SRv6) SIDs (`5f00::/16`)
+            || matches!(self.segments(), [0x5f00, ..])
             || self.is_unique_local()
             || self.is_unicast_link_local())
     }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 79d864e1b19..53373584d55 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -14,7 +14,7 @@
 use crate::convert::FloatToInt;
 use crate::num::FpCategory;
 use crate::panic::const_assert;
-use crate::{intrinsics, mem};
+use crate::{cfg_match, intrinsics, mem};
 
 /// The radix or base of the internal representation of `f32`.
 /// Use [`f32::RADIX`] instead.
@@ -996,21 +996,22 @@ impl f32 {
     #[stable(feature = "num_midpoint", since = "1.85.0")]
     #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
     pub const fn midpoint(self, other: f32) -> f32 {
-        cfg_if! {
+        cfg_match! {
             // Allow faster implementation that have known good 64-bit float
             // implementations. Falling back to the branchy code on targets that don't
             // have 64-bit hardware floats or buggy implementations.
             // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114
-            if #[cfg(any(
-                    target_arch = "x86_64",
-                    target_arch = "aarch64",
-                    all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"),
-                    all(target_arch = "arm", target_feature = "vfp2"),
-                    target_arch = "wasm32",
-                    target_arch = "wasm64",
-                ))] {
+            any(
+                target_arch = "x86_64",
+                target_arch = "aarch64",
+                all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"),
+                all(target_arch = "arm", target_feature = "vfp2"),
+                target_arch = "wasm32",
+                target_arch = "wasm64",
+            ) => {
                 ((self as f64 + other as f64) / 2.0) as f32
-            } else {
+            }
+            _ => {
                 const LO: f32 = f32::MIN_POSITIVE * 2.;
                 const HI: f32 = f32::MAX / 2.;
 
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 7fcd19f67ee..bc097bf198d 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1943,6 +1943,7 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
 #[stable(feature = "pin_macro", since = "1.68.0")]
 #[rustc_macro_transparency = "semitransparent"]
 #[allow_internal_unstable(unsafe_pin_internals)]
+#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)]
 pub macro pin($value:expr $(,)?) {
     // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
     // review such a hypothetical macro (that any user-code could define):
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 89c856fe107..ba4c849837e 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -127,15 +127,13 @@ mod prim_bool {}
 /// [`Result<String, !>`] which we can unpack like this:
 ///
 /// ```
-/// #![feature(exhaustive_patterns)]
 /// use std::str::FromStr;
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
-/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
-/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
-/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain
-/// enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively
+/// match on [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behavior
+/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`.
 ///
 /// ## Infinite loops
 ///
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 7d0839aff3f..71a84aff246 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -386,7 +386,8 @@ impl<T: ?Sized> *const T {
     /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
     ///   [allocated object], and the entire memory range between `self` and the result must be in
     ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space.
+    ///   of the address space. Note that "range" here refers to a half-open range as usual in Rust,
+    ///   i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
     ///
     /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
     /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs
index 3358c03d30a..c4808b1065d 100644
--- a/library/core/src/slice/sort/select.rs
+++ b/library/core/src/slice/sort/select.rs
@@ -6,6 +6,7 @@
 //! for pivot selection. Using this as a fallback ensures O(n) worst case running time with
 //! better performance than one would get using heapsort as fallback.
 
+use crate::cfg_match;
 use crate::mem::{self, SizedTypeProperties};
 #[cfg(not(feature = "optimize_for_size"))]
 use crate::slice::sort::shared::pivot::choose_pivot;
@@ -41,10 +42,11 @@ where
         let min_idx = min_index(v, &mut is_less).unwrap();
         v.swap(min_idx, index);
     } else {
-        cfg_if! {
-            if #[cfg(feature = "optimize_for_size")] {
+        cfg_match! {
+            feature = "optimize_for_size" => {
                 median_of_medians(v, &mut is_less, index);
-            } else {
+            }
+            _ => {
                 partition_at_index_loop(v, index, None, &mut is_less);
             }
         }
diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs
index 090367cdaba..a36e5f7801d 100644
--- a/library/core/src/slice/sort/stable/mod.rs
+++ b/library/core/src/slice/sort/stable/mod.rs
@@ -2,12 +2,12 @@
 
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::cmp;
-use crate::intrinsics;
 use crate::mem::{MaybeUninit, SizedTypeProperties};
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::smallsort::{
     SMALL_SORT_GENERAL_SCRATCH_LEN, StableSmallSortTypeImpl, insertion_sort_shift_left,
 };
+use crate::{cfg_match, intrinsics};
 
 pub(crate) mod merge;
 
@@ -39,17 +39,18 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
         return;
     }
 
-    cfg_if! {
-        if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
+    cfg_match! {
+        any(feature = "optimize_for_size", target_pointer_width = "16") => {
             // Unlike driftsort, mergesort only requires len / 2,
             // not len - len / 2.
             let alloc_len = len / 2;
 
-            cfg_if! {
-                if #[cfg(target_pointer_width = "16")] {
+            cfg_match! {
+                target_pointer_width = "16" => {
                     let mut heap_buf = BufT::with_capacity(alloc_len);
                     let scratch = heap_buf.as_uninit_slice_mut();
-                } else {
+                }
+                _ => {
                     // For small inputs 4KiB of stack storage suffices, which allows us to avoid
                     // calling the (de-)allocator. Benchmarks showed this was quite beneficial.
                     let mut stack_buf = AlignedStorage::<T, 4096>::new();
@@ -65,7 +66,8 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool, BufT: BufGuard<T>>(v: &mut [T], is_less
             }
 
             tiny::mergesort(v, scratch, is_less);
-        } else {
+        }
+        _ => {
             // More advanced sorting methods than insertion sort are faster if called in
             // a hot loop for small inputs, but for general-purpose code the small
             // binary size of insertion sort is more important. The instruction cache in
diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs
index 2eb653c4601..b6c2e05a06a 100644
--- a/library/core/src/slice/sort/unstable/mod.rs
+++ b/library/core/src/slice/sort/unstable/mod.rs
@@ -1,11 +1,11 @@
 //! This module contains the entry points for `slice::sort_unstable`.
 
-use crate::intrinsics;
 use crate::mem::SizedTypeProperties;
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::find_existing_run;
 #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))]
 use crate::slice::sort::shared::smallsort::insertion_sort_shift_left;
+use crate::{cfg_match, intrinsics};
 
 pub(crate) mod heapsort;
 pub(crate) mod quicksort;
@@ -30,10 +30,11 @@ pub fn sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) {
         return;
     }
 
-    cfg_if! {
-        if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] {
+    cfg_match! {
+        any(feature = "optimize_for_size", target_pointer_width = "16") => {
             heapsort::heapsort(v, is_less);
-        } else {
+        }
+        _ => {
             // More advanced sorting methods than insertion sort are faster if called in
             // a hot loop for small inputs, but for general-purpose code the small
             // binary size of insertion sort is more important. The instruction cache in
diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs
index 68a16118716..7e6cfb55990 100644
--- a/library/core/src/slice/sort/unstable/quicksort.rs
+++ b/library/core/src/slice/sort/unstable/quicksort.rs
@@ -9,7 +9,7 @@ use crate::slice::sort::shared::pivot::choose_pivot;
 use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl;
 #[cfg(not(feature = "optimize_for_size"))]
 use crate::slice::sort::unstable::heapsort;
-use crate::{intrinsics, ptr};
+use crate::{cfg_match, intrinsics, ptr};
 
 /// Sorts `v` recursively.
 ///
@@ -142,10 +142,11 @@ const fn inst_partition<T, F: FnMut(&T, &T) -> bool>() -> fn(&mut [T], &T, &mut
     if size_of::<T>() <= MAX_BRANCHLESS_PARTITION_SIZE {
         // Specialize for types that are relatively cheap to copy, where branchless optimizations
         // have large leverage e.g. `u64` and `String`.
-        cfg_if! {
-            if #[cfg(feature = "optimize_for_size")] {
+        cfg_match! {
+            feature = "optimize_for_size" => {
                 partition_lomuto_branchless_simple::<T, F>
-            } else {
+            }
+            _ => {
                 partition_lomuto_branchless_cyclic::<T, F>
             }
         }
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 88bee622031..9b1b13e7129 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -469,6 +469,7 @@ impl AtomicBool {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
@@ -1389,6 +1390,7 @@ impl<T> AtomicPtr<T> {
     ///
     /// [valid]: crate::ptr#safety
     /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+    #[inline]
     #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
@@ -2525,6 +2527,7 @@ macro_rules! atomic_int {
             ///
             /// [valid]: crate::ptr#safety
             /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+            #[inline]
             #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
             #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")]
             pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 206b5b9e2c2..d754bb90343 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -2,6 +2,7 @@
 
 use crate::cmp::Ordering::{self, *};
 use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
+use crate::ops::ControlFlow::{Break, Continue};
 
 // Recursive macro for implementing n-ary tuple functions and operations
 //
@@ -80,19 +81,19 @@ macro_rules! tuple_impls {
                 }
                 #[inline]
                 fn lt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(lt, __chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn le(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(le, __chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn ge(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(ge, __chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
                 #[inline]
                 fn gt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+                    lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
                 }
             }
         }
@@ -171,15 +172,16 @@ macro_rules! maybe_tuple_doc {
 // `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1,
 // a2, b2, a3, b3)` (and similarly for `lexical_cmp`)
 //
-// `$ne_rel` is only used to determine the result after checking that they're
-// not equal, so `lt` and `le` can both just use `Less`.
+// `$chain_rel` is the chaining method from `PartialOrd` to use for all but the
+// final value, to produce better results for simple primitives.
 macro_rules! lexical_ord {
-    ($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
-        let c = PartialOrd::partial_cmp(&$a, &$b);
-        if c != Some(Equal) { c == Some($ne_rel) }
-        else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) }
+    ($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
+        match PartialOrd::$chain_rel(&$a, &$b) {
+            Break(val) => val,
+            Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+),
+        }
     }};
-    ($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => {
+    ($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => {
         // Use the specific method for the last element
         PartialOrd::$rel(&$a, &$b)
     };
diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs
index 3f082a90770..d9060fe903d 100644
--- a/library/coretests/tests/fmt/mod.rs
+++ b/library/coretests/tests/fmt/mod.rs
@@ -81,6 +81,7 @@ fn formatting_options_ctor() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn formatting_options_flags() {
     use core::fmt::*;
     for sign in [None, Some(Sign::Plus), Some(Sign::Minus)] {
@@ -98,6 +99,25 @@ fn formatting_options_flags() {
                     assert_eq!(formatting_options.get_alternate(), alternate);
                     assert_eq!(formatting_options.get_sign_aware_zero_pad(), sign_aware_zero_pad);
                     assert_eq!(formatting_options.get_debug_as_hex(), debug_as_hex);
+
+                    let mut output = String::new();
+                    let fmt = Formatter::new(&mut output, formatting_options);
+                    assert_eq!(fmt.options(), formatting_options);
+
+                    assert_eq!(fmt.sign_minus(), sign == Some(Sign::Minus));
+                    assert_eq!(fmt.sign_plus(), sign == Some(Sign::Plus));
+                    assert_eq!(fmt.alternate(), alternate);
+                    assert_eq!(fmt.sign_aware_zero_pad(), sign_aware_zero_pad);
+
+                    // The flags method is deprecated.
+                    // This checks compatibility with older versions of Rust.
+                    assert_eq!(fmt.flags() & 1 != 0, sign == Some(Sign::Plus));
+                    assert_eq!(fmt.flags() & 2 != 0, sign == Some(Sign::Minus));
+                    assert_eq!(fmt.flags() & 4 != 0, alternate);
+                    assert_eq!(fmt.flags() & 8 != 0, sign_aware_zero_pad);
+                    assert_eq!(fmt.flags() & 16 != 0, debug_as_hex == Some(DebugAsHex::Lower));
+                    assert_eq!(fmt.flags() & 32 != 0, debug_as_hex == Some(DebugAsHex::Upper));
+                    assert_eq!(fmt.flags() & 0xFFFF_FFC0, 0);
                 }
             }
         }
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 79022fec8a2..7ad154796f6 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -39,7 +39,6 @@
 #![feature(generic_assert_internals)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
-#![feature(inline_const_pat)]
 #![feature(int_roundings)]
 #![feature(ip)]
 #![feature(ip_from)]
@@ -95,16 +94,17 @@
 
 /// Version of `assert_matches` that ignores fancy runtime printing in const context and uses structural equality.
 macro_rules! assert_eq_const_safe {
-    ($left:expr, $right:expr) => {
-        assert_eq_const_safe!($left, $right, concat!(stringify!($left), " == ", stringify!($right)));
+    ($t:ty: $left:expr, $right:expr) => {
+        assert_eq_const_safe!($t: $left, $right, concat!(stringify!($left), " == ", stringify!($right)));
     };
-    ($left:expr, $right:expr$(, $($arg:tt)+)?) => {
+    ($t:ty: $left:expr, $right:expr$(, $($arg:tt)+)?) => {
         {
             fn runtime() {
                 assert_eq!($left, $right, $($($arg)*),*);
             }
             const fn compiletime() {
-                assert!(matches!($left, const { $right }));
+                const PAT: $t = $right;
+                assert!(matches!($left, PAT), $($($arg)*),*);
             }
             core::intrinsics::const_eval_select((), compiletime, runtime)
         }
diff --git a/library/coretests/tests/net/ip_addr.rs b/library/coretests/tests/net/ip_addr.rs
index f01b43282ec..3fec59d67b7 100644
--- a/library/coretests/tests/net/ip_addr.rs
+++ b/library/coretests/tests/net/ip_addr.rs
@@ -689,6 +689,8 @@ fn ipv6_properties() {
 
     check!("2002::", &[0x20, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
 
+    check!("5f00::", &[0x5f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
     check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
 
     check!(
diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs
index bbf19d2b444..0d9fb9e797e 100644
--- a/library/coretests/tests/num/int_macros.rs
+++ b/library/coretests/tests/num/int_macros.rs
@@ -1,5 +1,6 @@
 macro_rules! int_module {
     ($T:ident, $U:ident) => {
+        use core::num::ParseIntError;
         use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
         use core::$T::*;
 
@@ -32,20 +33,20 @@ macro_rules! int_module {
         test_runtime_and_compiletime! {
 
             fn test_rem_euclid() {
-                assert_eq_const_safe!((-1 as $T).rem_euclid(MIN), MAX);
+                assert_eq_const_safe!($T: (-1 as $T).rem_euclid(MIN), MAX);
             }
 
             fn test_abs() {
-                assert_eq_const_safe!((1 as $T).abs(), 1 as $T);
-                assert_eq_const_safe!((0 as $T).abs(), 0 as $T);
-                assert_eq_const_safe!((-1 as $T).abs(), 1 as $T);
+                assert_eq_const_safe!($T: (1 as $T).abs(), 1 as $T);
+                assert_eq_const_safe!($T: (0 as $T).abs(), 0 as $T);
+                assert_eq_const_safe!($T: (-1 as $T).abs(), 1 as $T);
             }
 
             fn test_signum() {
-                assert_eq_const_safe!((1 as $T).signum(), 1 as $T);
-                assert_eq_const_safe!((0 as $T).signum(), 0 as $T);
-                assert_eq_const_safe!((-0 as $T).signum(), 0 as $T);
-                assert_eq_const_safe!((-1 as $T).signum(), -1 as $T);
+                assert_eq_const_safe!($T: (1 as $T).signum(), 1 as $T);
+                assert_eq_const_safe!($T: (0 as $T).signum(), 0 as $T);
+                assert_eq_const_safe!($T: (-0 as $T).signum(), 0 as $T);
+                assert_eq_const_safe!($T: (-1 as $T).signum(), -1 as $T);
             }
 
             fn test_is_positive() {
@@ -72,123 +73,123 @@ macro_rules! int_module {
 
         test_runtime_and_compiletime! {
             fn test_count_ones() {
-                assert_eq_const_safe!(A.count_ones(), 3);
-                assert_eq_const_safe!(B.count_ones(), 2);
-                assert_eq_const_safe!(C.count_ones(), 5);
+                assert_eq_const_safe!(u32: A.count_ones(), 3);
+                assert_eq_const_safe!(u32: B.count_ones(), 2);
+                assert_eq_const_safe!(u32: C.count_ones(), 5);
             }
 
             fn test_count_zeros() {
-                assert_eq_const_safe!(A.count_zeros(), $T::BITS - 3);
-                assert_eq_const_safe!(B.count_zeros(), $T::BITS - 2);
-                assert_eq_const_safe!(C.count_zeros(), $T::BITS - 5);
+                assert_eq_const_safe!(u32: A.count_zeros(), $T::BITS - 3);
+                assert_eq_const_safe!(u32: B.count_zeros(), $T::BITS - 2);
+                assert_eq_const_safe!(u32: C.count_zeros(), $T::BITS - 5);
             }
 
             fn test_leading_trailing_ones() {
                 const A: $T = 0b0101_1111;
-                assert_eq_const_safe!(A.trailing_ones(), 5);
-                assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7);
+                assert_eq_const_safe!(u32: A.trailing_ones(), 5);
+                assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7);
 
-                assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5);
+                assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5);
 
-                assert_eq_const_safe!(_1.leading_ones(), $T::BITS);
-                assert_eq_const_safe!(_1.trailing_ones(), $T::BITS);
+                assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS);
+                assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS);
 
-                assert_eq_const_safe!((_1 << 1).trailing_ones(), 0);
-                assert_eq_const_safe!(MAX.leading_ones(), 0);
+                assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0);
+                assert_eq_const_safe!(u32: MAX.leading_ones(), 0);
 
-                assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1);
-                assert_eq_const_safe!(MAX.trailing_ones(), $T::BITS - 1);
+                assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1);
+                assert_eq_const_safe!(u32: MAX.trailing_ones(), $T::BITS - 1);
 
-                assert_eq_const_safe!(_0.leading_ones(), 0);
-                assert_eq_const_safe!(_0.trailing_ones(), 0);
+                assert_eq_const_safe!(u32: _0.leading_ones(), 0);
+                assert_eq_const_safe!(u32: _0.trailing_ones(), 0);
 
                 const X: $T = 0b0010_1100;
-                assert_eq_const_safe!(X.leading_ones(), 0);
-                assert_eq_const_safe!(X.trailing_ones(), 0);
+                assert_eq_const_safe!(u32: X.leading_ones(), 0);
+                assert_eq_const_safe!(u32: X.trailing_ones(), 0);
             }
 
             fn test_rotate() {
-                assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
-                assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
-                assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+                assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+                assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+                assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C);
 
                 // Rotating these should make no difference
                 //
                 // We test using 124 bits because to ensure that overlong bit shifts do
                 // not cause undefined behavior. See #10183.
-                assert_eq_const_safe!(_0.rotate_left(124), _0);
-                assert_eq_const_safe!(_1.rotate_left(124), _1);
-                assert_eq_const_safe!(_0.rotate_right(124), _0);
-                assert_eq_const_safe!(_1.rotate_right(124), _1);
+                assert_eq_const_safe!($T: _0.rotate_left(124), _0);
+                assert_eq_const_safe!($T: _1.rotate_left(124), _1);
+                assert_eq_const_safe!($T: _0.rotate_right(124), _0);
+                assert_eq_const_safe!($T: _1.rotate_right(124), _1);
 
                 // Rotating by 0 should have no effect
-                assert_eq_const_safe!(A.rotate_left(0), A);
-                assert_eq_const_safe!(B.rotate_left(0), B);
-                assert_eq_const_safe!(C.rotate_left(0), C);
+                assert_eq_const_safe!($T: A.rotate_left(0), A);
+                assert_eq_const_safe!($T: B.rotate_left(0), B);
+                assert_eq_const_safe!($T: C.rotate_left(0), C);
                 // Rotating by a multiple of word size should also have no effect
-                assert_eq_const_safe!(A.rotate_left(128), A);
-                assert_eq_const_safe!(B.rotate_left(128), B);
-                assert_eq_const_safe!(C.rotate_left(128), C);
+                assert_eq_const_safe!($T: A.rotate_left(128), A);
+                assert_eq_const_safe!($T: B.rotate_left(128), B);
+                assert_eq_const_safe!($T: C.rotate_left(128), C);
             }
 
             fn test_swap_bytes() {
-                assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A);
-                assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B);
-                assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C);
+                assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A);
+                assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B);
+                assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C);
 
                 // Swapping these should make no difference
-                assert_eq_const_safe!(_0.swap_bytes(), _0);
-                assert_eq_const_safe!(_1.swap_bytes(), _1);
+                assert_eq_const_safe!($T: _0.swap_bytes(), _0);
+                assert_eq_const_safe!($T: _1.swap_bytes(), _1);
             }
 
             fn test_le() {
-                assert_eq_const_safe!($T::from_le(A.to_le()), A);
-                assert_eq_const_safe!($T::from_le(B.to_le()), B);
-                assert_eq_const_safe!($T::from_le(C.to_le()), C);
-                assert_eq_const_safe!($T::from_le(_0), _0);
-                assert_eq_const_safe!($T::from_le(_1), _1);
-                assert_eq_const_safe!(_0.to_le(), _0);
-                assert_eq_const_safe!(_1.to_le(), _1);
+                assert_eq_const_safe!($T: $T::from_le(A.to_le()), A);
+                assert_eq_const_safe!($T: $T::from_le(B.to_le()), B);
+                assert_eq_const_safe!($T: $T::from_le(C.to_le()), C);
+                assert_eq_const_safe!($T: $T::from_le(_0), _0);
+                assert_eq_const_safe!($T: $T::from_le(_1), _1);
+                assert_eq_const_safe!($T: _0.to_le(), _0);
+                assert_eq_const_safe!($T: _1.to_le(), _1);
             }
 
             fn test_be() {
-                assert_eq_const_safe!($T::from_be(A.to_be()), A);
-                assert_eq_const_safe!($T::from_be(B.to_be()), B);
-                assert_eq_const_safe!($T::from_be(C.to_be()), C);
-                assert_eq_const_safe!($T::from_be(_0), _0);
-                assert_eq_const_safe!($T::from_be(_1), _1);
-                assert_eq_const_safe!(_0.to_be(), _0);
-                assert_eq_const_safe!(_1.to_be(), _1);
+                assert_eq_const_safe!($T: $T::from_be(A.to_be()), A);
+                assert_eq_const_safe!($T: $T::from_be(B.to_be()), B);
+                assert_eq_const_safe!($T: $T::from_be(C.to_be()), C);
+                assert_eq_const_safe!($T: $T::from_be(_0), _0);
+                assert_eq_const_safe!($T: $T::from_be(_1), _1);
+                assert_eq_const_safe!($T: _0.to_be(), _0);
+                assert_eq_const_safe!($T: _1.to_be(), _1);
             }
 
             fn test_signed_checked_div() {
-                assert_eq_const_safe!((10 as $T).checked_div(2), Some(5));
-                assert_eq_const_safe!((5 as $T).checked_div(0), None);
-                assert_eq_const_safe!(isize::MIN.checked_div(-1), None);
+                assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5));
+                assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None);
+                assert_eq_const_safe!(Option<$T>: $T::MIN.checked_div(-1), None);
             }
 
             fn test_saturating_abs() {
-                assert_eq_const_safe!((0 as $T).saturating_abs(), 0);
-                assert_eq_const_safe!((123 as $T).saturating_abs(), 123);
-                assert_eq_const_safe!((-123 as $T).saturating_abs(), 123);
-                assert_eq_const_safe!((MAX - 2).saturating_abs(), MAX - 2);
-                assert_eq_const_safe!((MAX - 1).saturating_abs(), MAX - 1);
-                assert_eq_const_safe!(MAX.saturating_abs(), MAX);
-                assert_eq_const_safe!((MIN + 2).saturating_abs(), MAX - 1);
-                assert_eq_const_safe!((MIN + 1).saturating_abs(), MAX);
-                assert_eq_const_safe!(MIN.saturating_abs(), MAX);
+                assert_eq_const_safe!($T: (0 as $T).saturating_abs(), 0);
+                assert_eq_const_safe!($T: (123 as $T).saturating_abs(), 123);
+                assert_eq_const_safe!($T: (-123 as $T).saturating_abs(), 123);
+                assert_eq_const_safe!($T: (MAX - 2).saturating_abs(), MAX - 2);
+                assert_eq_const_safe!($T: (MAX - 1).saturating_abs(), MAX - 1);
+                assert_eq_const_safe!($T: MAX.saturating_abs(), MAX);
+                assert_eq_const_safe!($T: (MIN + 2).saturating_abs(), MAX - 1);
+                assert_eq_const_safe!($T: (MIN + 1).saturating_abs(), MAX);
+                assert_eq_const_safe!($T: MIN.saturating_abs(), MAX);
             }
 
             fn test_saturating_neg() {
-                assert_eq_const_safe!((0 as $T).saturating_neg(), 0);
-                assert_eq_const_safe!((123 as $T).saturating_neg(), -123);
-                assert_eq_const_safe!((-123 as $T).saturating_neg(), 123);
-                assert_eq_const_safe!((MAX - 2).saturating_neg(), MIN + 3);
-                assert_eq_const_safe!((MAX - 1).saturating_neg(), MIN + 2);
-                assert_eq_const_safe!(MAX.saturating_neg(), MIN + 1);
-                assert_eq_const_safe!((MIN + 2).saturating_neg(), MAX - 1);
-                assert_eq_const_safe!((MIN + 1).saturating_neg(), MAX);
-                assert_eq_const_safe!(MIN.saturating_neg(), MAX);
+                assert_eq_const_safe!($T: (0 as $T).saturating_neg(), 0);
+                assert_eq_const_safe!($T: (123 as $T).saturating_neg(), -123);
+                assert_eq_const_safe!($T: (-123 as $T).saturating_neg(), 123);
+                assert_eq_const_safe!($T: (MAX - 2).saturating_neg(), MIN + 3);
+                assert_eq_const_safe!($T: (MAX - 1).saturating_neg(), MIN + 2);
+                assert_eq_const_safe!($T: MAX.saturating_neg(), MIN + 1);
+                assert_eq_const_safe!($T: (MIN + 2).saturating_neg(), MAX - 1);
+                assert_eq_const_safe!($T: (MIN + 1).saturating_neg(), MAX);
+                assert_eq_const_safe!($T: MIN.saturating_neg(), MAX);
             }
         }
 
@@ -250,23 +251,23 @@ macro_rules! int_module {
 
         test_runtime_and_compiletime! {
             fn test_from_str_radix() {
-                assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T));
-                assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T));
-                assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T));
-                assert_eq_const_safe!(i32::from_str_radix("123", 16), Ok(291 as i32));
-                assert_eq_const_safe!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
-                assert_eq_const_safe!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
-                assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T));
-                assert_eq_const_safe!($T::from_str_radix("Z", 36), Ok(35 as $T));
-
-                assert_eq_const_safe!($T::from_str_radix("-123", 10), Ok(-123 as $T));
-                assert_eq_const_safe!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
-                assert_eq_const_safe!($T::from_str_radix("-123", 8), Ok(-83 as $T));
-                assert_eq_const_safe!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
-                assert_eq_const_safe!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
-                assert_eq_const_safe!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
-                assert_eq_const_safe!($T::from_str_radix("-z", 36), Ok(-35 as $T));
-                assert_eq_const_safe!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("123", 16), Ok(291 as i32));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("ffff", 16), Ok(65535 as i32));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("Z", 36), Ok(35 as $T));
+
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 10), Ok(-123 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-1001", 2), Ok(-9 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 8), Ok(-83 as $T));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-123", 16), Ok(-291 as i32));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
+                assert_eq_const_safe!(Result<i32, ParseIntError>: i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-z", 36), Ok(-35 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-Z", 36), Ok(-35 as $T));
 
                 assert!($T::from_str_radix("Z", 35).is_err());
                 assert!($T::from_str_radix("-9", 2).is_err());
@@ -277,16 +278,16 @@ macro_rules! int_module {
             fn test_pow() {
                 {
                     const R: $T = 2;
-                    assert_eq_const_safe!(R.pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
-                    assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
-                    assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
-                    assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
-                    assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+                    assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
                 }
 
                 {
@@ -295,221 +296,227 @@ macro_rules! int_module {
                     // if itest::MAX == 2^j-1, then itest is a `j` bit int,
                     // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
                     // thussaturating_pow the overflowing result is exactly 1.
-                    assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T);
-                    assert_eq_const_safe!(R.checked_pow(2), None);
-                    assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true));
-                    assert_eq_const_safe!(R.saturating_pow(2), MAX);
+                    assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T);
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None);
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true));
+                    assert_eq_const_safe!($T: R.saturating_pow(2), MAX);
                 }
 
                 {
                     // test for negative exponent.
                     const R: $T = -2;
-                    assert_eq_const_safe!(R.pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.pow(3), -8 as $T);
-                    assert_eq_const_safe!(R.pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(3), -8 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
-                    assert_eq_const_safe!(R.checked_pow(3), Some(-8 as $T));
-                    assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
-                    assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
-                    assert_eq_const_safe!(R.overflowing_pow(3), (-8 as $T, false));
-                    assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
-                    assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.saturating_pow(3), -8 as $T);
-                    assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.pow(3), -8 as $T);
+                    assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(3), -8 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(3), Some(-8 as $T));
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(3), (-8 as $T, false));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+                    assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.saturating_pow(3), -8 as $T);
+                    assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
                 }
             }
 
             fn test_div_floor() {
                 const A: $T = 8;
                 const B: $T = 3;
-                assert_eq_const_safe!(A.div_floor(B), 2);
-                assert_eq_const_safe!(A.div_floor(-B), -3);
-                assert_eq_const_safe!((-A).div_floor(B), -3);
-                assert_eq_const_safe!((-A).div_floor(-B), 2);
+                assert_eq_const_safe!($T: A.div_floor(B), 2);
+                assert_eq_const_safe!($T: A.div_floor(-B), -3);
+                assert_eq_const_safe!($T: (-A).div_floor(B), -3);
+                assert_eq_const_safe!($T: (-A).div_floor(-B), 2);
             }
 
             fn test_div_ceil() {
                 const A: $T = 8;
                 const B: $T = 3;
-                assert_eq_const_safe!(A.div_ceil(B), 3);
-                assert_eq_const_safe!(A.div_ceil(-B), -2);
-                assert_eq_const_safe!((-A).div_ceil(B), -2);
-                assert_eq_const_safe!((-A).div_ceil(-B), 3);
+                assert_eq_const_safe!($T: A.div_ceil(B), 3);
+                assert_eq_const_safe!($T: A.div_ceil(-B), -2);
+                assert_eq_const_safe!($T: (-A).div_ceil(B), -2);
+                assert_eq_const_safe!($T: (-A).div_ceil(-B), 3);
             }
 
             fn test_next_multiple_of() {
-                assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16);
-                assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24);
-                assert_eq_const_safe!((16 as $T).next_multiple_of(-8), 16);
-                assert_eq_const_safe!((23 as $T).next_multiple_of(-8), 16);
-                assert_eq_const_safe!((-16 as $T).next_multiple_of(8), -16);
-                assert_eq_const_safe!((-23 as $T).next_multiple_of(8), -16);
-                assert_eq_const_safe!((-16 as $T).next_multiple_of(-8), -16);
-                assert_eq_const_safe!((-23 as $T).next_multiple_of(-8), -24);
-                assert_eq_const_safe!(MIN.next_multiple_of(-1), MIN);
+                assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16);
+                assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24);
+                assert_eq_const_safe!($T: (16 as $T).next_multiple_of(-8), 16);
+                assert_eq_const_safe!($T: (23 as $T).next_multiple_of(-8), 16);
+                assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(8), -16);
+                assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(8), -16);
+                assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(-8), -16);
+                assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(-8), -24);
+                assert_eq_const_safe!($T: MIN.next_multiple_of(-1), MIN);
             }
 
             fn test_checked_next_multiple_of() {
-                assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16));
-                assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24));
-                assert_eq_const_safe!((16 as $T).checked_next_multiple_of(-8), Some(16));
-                assert_eq_const_safe!((23 as $T).checked_next_multiple_of(-8), Some(16));
-                assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(8), Some(-16));
-                assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(8), Some(-16));
-                assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(-8), Some(-16));
-                assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(-8), Some(-24));
-                assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None);
-                assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None);
-                assert_eq_const_safe!(MIN.checked_next_multiple_of(-3), None);
-                assert_eq_const_safe!(MIN.checked_next_multiple_of(-1), Some(MIN));
+                assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16));
+                assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24));
+                assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(-8), Some(16));
+                assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(-8), Some(16));
+                assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(8), Some(-16));
+                assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(8), Some(-16));
+                assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(-8), Some(-16));
+                assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(-8), Some(-24));
+                assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None);
+                assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None);
+                assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-3), None);
+                assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-1), Some(MIN));
             }
 
             fn test_carrying_add() {
-                assert_eq_const_safe!(MAX.carrying_add(1, false), (MIN, true));
-                assert_eq_const_safe!(MAX.carrying_add(0, true), (MIN, true));
-                assert_eq_const_safe!(MAX.carrying_add(1, true), (MIN + 1, true));
-                assert_eq_const_safe!(MAX.carrying_add(-1, false), (MAX - 1, false));
-                assert_eq_const_safe!(MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow
-                assert_eq_const_safe!(MIN.carrying_add(-1, false), (MAX, true));
-                assert_eq_const_safe!(MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow
-                assert_eq_const_safe!((0 as $T).carrying_add(MAX, true), (MIN, true));
-                assert_eq_const_safe!((0 as $T).carrying_add(MIN, true), (MIN + 1, false));
+                assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, false), (MIN, true));
+                assert_eq_const_safe!(($T, bool): MAX.carrying_add(0, true), (MIN, true));
+                assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, true), (MIN + 1, true));
+                assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, false), (MAX - 1, false));
+                assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow
+                assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, false), (MAX, true));
+                assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow
+                assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MAX, true), (MIN, true));
+                assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MIN, true), (MIN + 1, false));
             }
 
             fn test_borrowing_sub() {
-                assert_eq_const_safe!(MIN.borrowing_sub(1, false), (MAX, true));
-                assert_eq_const_safe!(MIN.borrowing_sub(0, true), (MAX, true));
-                assert_eq_const_safe!(MIN.borrowing_sub(1, true), (MAX - 1, true));
-                assert_eq_const_safe!(MIN.borrowing_sub(-1, false), (MIN + 1, false));
-                assert_eq_const_safe!(MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow
-                assert_eq_const_safe!(MAX.borrowing_sub(-1, false), (MIN, true));
-                assert_eq_const_safe!(MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow
-                assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, false), (MIN, true));
-                assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, true), (MAX, false));
+                assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, false), (MAX, true));
+                assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(0, true), (MAX, true));
+                assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, true), (MAX - 1, true));
+                assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, false), (MIN + 1, false));
+                assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow
+                assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, false), (MIN, true));
+                assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow
+                assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, false), (MIN, true));
+                assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, true), (MAX, false));
             }
 
             fn test_widening_mul() {
-                assert_eq_const_safe!(MAX.widening_mul(MAX), (1, MAX / 2));
-                assert_eq_const_safe!(MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
-                assert_eq_const_safe!(MIN.widening_mul(MIN), (0, MAX / 2 + 1));
+                assert_eq_const_safe!(($U, $T): MAX.widening_mul(MAX), (1, MAX / 2));
+                assert_eq_const_safe!(($U, $T): MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
+                assert_eq_const_safe!(($U, $T): MIN.widening_mul(MIN), (0, MAX / 2 + 1));
             }
 
             fn test_carrying_mul() {
-                assert_eq_const_safe!(MAX.carrying_mul(MAX, 0), (1, MAX / 2));
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, 0), (1, MAX / 2));
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul(MAX, MAX),
                     (UMAX / 2 + 1, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul(MAX, MIN),
                     (UMAX / 2 + 2, MAX / 2 - 1)
                 );
-                assert_eq_const_safe!(MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2));
-                assert_eq_const_safe!(MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2));
-                assert_eq_const_safe!(MIN.carrying_mul(MAX, MIN), (0, MIN / 2));
-                assert_eq_const_safe!(MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1));
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2));
+                assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2));
+                assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MIN), (0, MIN / 2));
+                assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1));
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul(MIN, MAX),
                     (UMAX / 2, MAX / 2 + 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul(MIN, MIN),
                     (UMAX / 2 + 1, MAX / 2)
                 );
             }
 
             fn test_carrying_mul_add() {
-                assert_eq_const_safe!(MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2));
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2));
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul_add(MAX, MAX, 0),
                     (UMAX / 2 + 1, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul_add(MAX, MIN, 0),
                     (UMAX / 2 + 2, MAX / 2 - 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul_add(MAX, MAX, MAX),
                     (UMAX, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul_add(MAX, MAX, MIN),
                     (0, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MAX.carrying_mul_add(MAX, MIN, MIN),
                     (1, MAX / 2 - 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MAX, 0, 0),
                     (MIN as $U, MIN / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MAX, MAX, 0),
                     (UMAX, MIN / 2)
                 );
-                assert_eq_const_safe!(MIN.carrying_mul_add(MAX, MIN, 0), (0, MIN / 2));
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
+                    MIN.carrying_mul_add(MAX, MIN, 0),
+                    (0, MIN / 2)
+                );
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MAX, MAX, MAX),
                     (UMAX / 2 - 1, MIN / 2 + 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MAX, MAX, MIN),
                     (UMAX / 2, MIN / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MAX, MIN, MIN),
                     (UMAX / 2 + 1, MIN / 2 - 1)
                 );
-                assert_eq_const_safe!(MIN.carrying_mul_add(MIN, 0, 0), (0, MAX / 2 + 1));
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
+                    MIN.carrying_mul_add(MIN, 0, 0),
+                    (0, MAX / 2 + 1)
+                );
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MIN, MAX, 0),
                     (UMAX / 2, MAX / 2 + 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MIN, MIN, 0),
                     (UMAX / 2 + 1, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MIN, MAX, MAX),
                     (UMAX - 1, MAX / 2 + 1)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MIN, MAX, MIN),
                     (UMAX, MAX / 2)
                 );
-                assert_eq_const_safe!(
+                assert_eq_const_safe!(($U, $T):
                     MIN.carrying_mul_add(MIN, MIN, MIN),
                     (0, MAX / 2)
                 );
             }
 
             fn test_midpoint() {
-                assert_eq_const_safe!(<$T>::midpoint(1, 3), 2);
-                assert_eq_const_safe!(<$T>::midpoint(3, 1), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2);
 
-                assert_eq_const_safe!(<$T>::midpoint(0, 0), 0);
-                assert_eq_const_safe!(<$T>::midpoint(0, 2), 1);
-                assert_eq_const_safe!(<$T>::midpoint(2, 0), 1);
-                assert_eq_const_safe!(<$T>::midpoint(2, 2), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0);
+                assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1);
+                assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1);
+                assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2);
 
-                assert_eq_const_safe!(<$T>::midpoint(1, 4), 2);
-                assert_eq_const_safe!(<$T>::midpoint(4, 1), 2);
-                assert_eq_const_safe!(<$T>::midpoint(3, 4), 3);
-                assert_eq_const_safe!(<$T>::midpoint(4, 3), 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3);
 
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), 0);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), 0);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), 0);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), 0);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
 
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
             }
         }
 
@@ -526,154 +533,154 @@ macro_rules! int_module {
         test_runtime_and_compiletime! {
             fn test_unbounded_shl() {
                 // <$T>::MIN
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // <$T>::MAX
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 1
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // -1
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, 1), (-1 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, 3), (-1 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, 5), (-1 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 1), (-1 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 3), (-1 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 5), (-1 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 8
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 17
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
             }
 
             fn test_unbounded_shr() {
                 // <$T>::MIN
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1);
 
                 // <$T>::MAX
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 1
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // -1
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, 1), (-1 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, 3), (-1 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, 5), (-1 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1);
-                assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 1), (-1 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 3), (-1 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 5), (-1 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1);
 
                 // 8
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 17
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
             }
         }
     };
diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs
index d09eb97b17e..2e35e8bf534 100644
--- a/library/coretests/tests/num/uint_macros.rs
+++ b/library/coretests/tests/num/uint_macros.rs
@@ -1,5 +1,6 @@
 macro_rules! uint_module {
     ($T:ident) => {
+        use core::num::ParseIntError;
         use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
         use core::$T::*;
 
@@ -49,95 +50,95 @@ macro_rules! uint_module {
 
             fn test_leading_trailing_ones() {
                 const A: $T = 0b0101_1111;
-                assert_eq_const_safe!(A.trailing_ones(), 5);
-                assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7);
+                assert_eq_const_safe!(u32: A.trailing_ones(), 5);
+                assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7);
 
-                assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5);
+                assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5);
 
-                assert_eq_const_safe!(_1.leading_ones(), $T::BITS);
-                assert_eq_const_safe!(_1.trailing_ones(), $T::BITS);
+                assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS);
+                assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS);
 
-                assert_eq_const_safe!((_1 << 1).trailing_ones(), 0);
-                assert_eq_const_safe!((_1 >> 1).leading_ones(), 0);
+                assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0);
+                assert_eq_const_safe!(u32: (_1 >> 1).leading_ones(), 0);
 
-                assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1);
-                assert_eq_const_safe!((_1 >> 1).trailing_ones(), $T::BITS - 1);
+                assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1);
+                assert_eq_const_safe!(u32: (_1 >> 1).trailing_ones(), $T::BITS - 1);
 
-                assert_eq_const_safe!(_0.leading_ones(), 0);
-                assert_eq_const_safe!(_0.trailing_ones(), 0);
+                assert_eq_const_safe!(u32: _0.leading_ones(), 0);
+                assert_eq_const_safe!(u32: _0.trailing_ones(), 0);
 
                 const X: $T = 0b0010_1100;
-                assert_eq_const_safe!(X.leading_ones(), 0);
-                assert_eq_const_safe!(X.trailing_ones(), 0);
+                assert_eq_const_safe!(u32: X.leading_ones(), 0);
+                assert_eq_const_safe!(u32: X.trailing_ones(), 0);
             }
 
             fn test_rotate() {
-                assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
-                assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
-                assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);
+                assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A);
+                assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);
+                assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C);
 
                 // Rotating these should make no difference
                 //
                 // We test using 124 bits because to ensure that overlong bit shifts do
                 // not cause undefined behavior. See #10183.
-                assert_eq_const_safe!(_0.rotate_left(124), _0);
-                assert_eq_const_safe!(_1.rotate_left(124), _1);
-                assert_eq_const_safe!(_0.rotate_right(124), _0);
-                assert_eq_const_safe!(_1.rotate_right(124), _1);
+                assert_eq_const_safe!($T: _0.rotate_left(124), _0);
+                assert_eq_const_safe!($T: _1.rotate_left(124), _1);
+                assert_eq_const_safe!($T: _0.rotate_right(124), _0);
+                assert_eq_const_safe!($T: _1.rotate_right(124), _1);
 
                 // Rotating by 0 should have no effect
-                assert_eq_const_safe!(A.rotate_left(0), A);
-                assert_eq_const_safe!(B.rotate_left(0), B);
-                assert_eq_const_safe!(C.rotate_left(0), C);
+                assert_eq_const_safe!($T: A.rotate_left(0), A);
+                assert_eq_const_safe!($T: B.rotate_left(0), B);
+                assert_eq_const_safe!($T: C.rotate_left(0), C);
                 // Rotating by a multiple of word size should also have no effect
-                assert_eq_const_safe!(A.rotate_left(128), A);
-                assert_eq_const_safe!(B.rotate_left(128), B);
-                assert_eq_const_safe!(C.rotate_left(128), C);
+                assert_eq_const_safe!($T: A.rotate_left(128), A);
+                assert_eq_const_safe!($T: B.rotate_left(128), B);
+                assert_eq_const_safe!($T: C.rotate_left(128), C);
             }
 
             fn test_swap_bytes() {
-                assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A);
-                assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B);
-                assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C);
+                assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A);
+                assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B);
+                assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C);
 
                 // Swapping these should make no difference
-                assert_eq_const_safe!(_0.swap_bytes(), _0);
-                assert_eq_const_safe!(_1.swap_bytes(), _1);
+                assert_eq_const_safe!($T: _0.swap_bytes(), _0);
+                assert_eq_const_safe!($T: _1.swap_bytes(), _1);
             }
 
             fn test_reverse_bits() {
-                assert_eq_const_safe!(A.reverse_bits().reverse_bits(), A);
-                assert_eq_const_safe!(B.reverse_bits().reverse_bits(), B);
-                assert_eq_const_safe!(C.reverse_bits().reverse_bits(), C);
+                assert_eq_const_safe!($T: A.reverse_bits().reverse_bits(), A);
+                assert_eq_const_safe!($T: B.reverse_bits().reverse_bits(), B);
+                assert_eq_const_safe!($T: C.reverse_bits().reverse_bits(), C);
 
                 // Swapping these should make no difference
-                assert_eq_const_safe!(_0.reverse_bits(), _0);
-                assert_eq_const_safe!(_1.reverse_bits(), _1);
+                assert_eq_const_safe!($T: _0.reverse_bits(), _0);
+                assert_eq_const_safe!($T: _1.reverse_bits(), _1);
             }
 
             fn test_le() {
-                assert_eq_const_safe!($T::from_le(A.to_le()), A);
-                assert_eq_const_safe!($T::from_le(B.to_le()), B);
-                assert_eq_const_safe!($T::from_le(C.to_le()), C);
-                assert_eq_const_safe!($T::from_le(_0), _0);
-                assert_eq_const_safe!($T::from_le(_1), _1);
-                assert_eq_const_safe!(_0.to_le(), _0);
-                assert_eq_const_safe!(_1.to_le(), _1);
+                assert_eq_const_safe!($T: $T::from_le(A.to_le()), A);
+                assert_eq_const_safe!($T: $T::from_le(B.to_le()), B);
+                assert_eq_const_safe!($T: $T::from_le(C.to_le()), C);
+                assert_eq_const_safe!($T: $T::from_le(_0), _0);
+                assert_eq_const_safe!($T: $T::from_le(_1), _1);
+                assert_eq_const_safe!($T: _0.to_le(), _0);
+                assert_eq_const_safe!($T: _1.to_le(), _1);
             }
 
             fn test_be() {
-                assert_eq_const_safe!($T::from_be(A.to_be()), A);
-                assert_eq_const_safe!($T::from_be(B.to_be()), B);
-                assert_eq_const_safe!($T::from_be(C.to_be()), C);
-                assert_eq_const_safe!($T::from_be(_0), _0);
-                assert_eq_const_safe!($T::from_be(_1), _1);
-                assert_eq_const_safe!(_0.to_be(), _0);
-                assert_eq_const_safe!(_1.to_be(), _1);
+                assert_eq_const_safe!($T: $T::from_be(A.to_be()), A);
+                assert_eq_const_safe!($T: $T::from_be(B.to_be()), B);
+                assert_eq_const_safe!($T: $T::from_be(C.to_be()), C);
+                assert_eq_const_safe!($T: $T::from_be(_0), _0);
+                assert_eq_const_safe!($T: $T::from_be(_1), _1);
+                assert_eq_const_safe!($T: _0.to_be(), _0);
+                assert_eq_const_safe!($T: _1.to_be(), _1);
             }
 
             fn test_unsigned_checked_div() {
-                assert_eq_const_safe!((10 as $T).checked_div(2), Some(5));
-                assert_eq_const_safe!((5 as $T).checked_div(0), None);
+                assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5));
+                assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None);
             }
         }
 
@@ -194,12 +195,12 @@ macro_rules! uint_module {
 
         test_runtime_and_compiletime! {
             fn test_parse_bytes() {
-                assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T));
-                assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T));
-                assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T));
-                assert_eq_const_safe!(u16::from_str_radix("123", 16), Ok(291 as u16));
-                assert_eq_const_safe!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
-                assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T));
+                assert_eq_const_safe!(Result<u16, ParseIntError>: u16::from_str_radix("123", 16), Ok(291 as u16));
+                assert_eq_const_safe!(Result<u16, ParseIntError>: u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+                assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T));
 
                 assert!($T::from_str_radix("Z", 10).is_err());
                 assert!($T::from_str_radix("_", 2).is_err());
@@ -208,16 +209,16 @@ macro_rules! uint_module {
             fn test_pow() {
                 {
                     const R: $T = 2;
-                    assert_eq_const_safe!(R.pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T);
-                    assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T));
-                    assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T));
-                    assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false));
-                    assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false));
-                    assert_eq_const_safe!(R.saturating_pow(2), 4 as $T);
-                    assert_eq_const_safe!(R.saturating_pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.pow(0), 1 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T);
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T));
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false));
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false));
+                    assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T);
+                    assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T);
                 }
 
                 {
@@ -226,20 +227,20 @@ macro_rules! uint_module {
                     // if itest::MAX == 2^j-1, then itest is a `j` bit int,
                     // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
                     // thussaturating_pow the overflowing result is exactly 1.
-                    assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T);
-                    assert_eq_const_safe!(R.checked_pow(2), None);
-                    assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true));
-                    assert_eq_const_safe!(R.saturating_pow(2), MAX);
+                    assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T);
+                    assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None);
+                    assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true));
+                    assert_eq_const_safe!($T: R.saturating_pow(2), MAX);
                 }
             }
 
             fn test_isqrt() {
-                assert_eq_const_safe!((0 as $T).isqrt(), 0 as $T);
-                assert_eq_const_safe!((1 as $T).isqrt(), 1 as $T);
-                assert_eq_const_safe!((2 as $T).isqrt(), 1 as $T);
-                assert_eq_const_safe!((99 as $T).isqrt(), 9 as $T);
-                assert_eq_const_safe!((100 as $T).isqrt(), 10 as $T);
-                assert_eq_const_safe!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1);
+                assert_eq_const_safe!($T: (0 as $T).isqrt(), 0 as $T);
+                assert_eq_const_safe!($T: (1 as $T).isqrt(), 1 as $T);
+                assert_eq_const_safe!($T: (2 as $T).isqrt(), 1 as $T);
+                assert_eq_const_safe!($T: (99 as $T).isqrt(), 9 as $T);
+                assert_eq_const_safe!($T: (100 as $T).isqrt(), 10 as $T);
+                assert_eq_const_safe!($T: $T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1);
             }
         }
 
@@ -264,24 +265,24 @@ macro_rules! uint_module {
 
         test_runtime_and_compiletime! {
             fn test_div_floor() {
-                assert_eq_const_safe!((8 as $T).div_floor(3), 2);
+                assert_eq_const_safe!($T: (8 as $T).div_floor(3), 2);
             }
 
             fn test_div_ceil() {
-                assert_eq_const_safe!((8 as $T).div_ceil(3), 3);
+                assert_eq_const_safe!($T: (8 as $T).div_ceil(3), 3);
             }
 
             fn test_next_multiple_of() {
-                assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16);
-                assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24);
-                assert_eq_const_safe!(MAX.next_multiple_of(1), MAX);
+                assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16);
+                assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24);
+                assert_eq_const_safe!($T: MAX.next_multiple_of(1), MAX);
             }
 
             fn test_checked_next_multiple_of() {
-                assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16));
-                assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24));
-                assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None);
-                assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None);
+                assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16));
+                assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24));
+                assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None);
+                assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None);
             }
 
             fn test_is_next_multiple_of() {
@@ -292,63 +293,63 @@ macro_rules! uint_module {
             }
 
             fn test_carrying_add() {
-                assert_eq_const_safe!($T::MAX.carrying_add(1, false), (0, true));
-                assert_eq_const_safe!($T::MAX.carrying_add(0, true), (0, true));
-                assert_eq_const_safe!($T::MAX.carrying_add(1, true), (1, true));
+                assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, false), (0, true));
+                assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(0, true), (0, true));
+                assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, true), (1, true));
 
-                assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false));
-                assert_eq_const_safe!($T::MIN.carrying_add(0, true), (1, false));
-                assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, true), (0, true));
+                assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, false), ($T::MAX, false));
+                assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add(0, true), (1, false));
+                assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, true), (0, true));
             }
 
             fn test_borrowing_sub() {
-                assert_eq_const_safe!($T::MIN.borrowing_sub(1, false), ($T::MAX, true));
-                assert_eq_const_safe!($T::MIN.borrowing_sub(0, true), ($T::MAX, true));
-                assert_eq_const_safe!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
+                assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, false), ($T::MAX, true));
+                assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(0, true), ($T::MAX, true));
+                assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true));
 
-                assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, false), (0, false));
-                assert_eq_const_safe!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
-                assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
+                assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, false), (0, false));
+                assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
+                assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
             }
 
             fn test_widening_mul() {
-                assert_eq_const_safe!($T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
+                assert_eq_const_safe!(($T, $T): $T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
             }
 
             fn test_carrying_mul() {
-                assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
-                assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));
+                assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
+                assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));
             }
 
             fn test_carrying_mul_add() {
-                assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1));
-                assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX));
-                assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX));
+                assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1));
+                assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX));
+                assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX));
             }
 
             fn test_midpoint() {
-                assert_eq_const_safe!(<$T>::midpoint(1, 3), 2);
-                assert_eq_const_safe!(<$T>::midpoint(3, 1), 2);
-
-                assert_eq_const_safe!(<$T>::midpoint(0, 0), 0);
-                assert_eq_const_safe!(<$T>::midpoint(0, 2), 1);
-                assert_eq_const_safe!(<$T>::midpoint(2, 0), 1);
-                assert_eq_const_safe!(<$T>::midpoint(2, 2), 2);
-
-                assert_eq_const_safe!(<$T>::midpoint(1, 4), 2);
-                assert_eq_const_safe!(<$T>::midpoint(4, 1), 2);
-                assert_eq_const_safe!(<$T>::midpoint(3, 4), 3);
-                assert_eq_const_safe!(<$T>::midpoint(4, 3), 3);
-
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
-
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
-                assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2);
+
+                assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0);
+                assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1);
+                assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1);
+                assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2);
+
+                assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3);
+
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+                assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
             }
         }
 
@@ -365,154 +366,154 @@ macro_rules! uint_module {
         test_runtime_and_compiletime! {
             fn test_unbounded_shl() {
                 // <$T>::MIN
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // <$T>::MAX
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 1
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // !0
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, 1), (!0 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, 3), (!0 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, 5), (!0 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 1), (!0 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 3), (!0 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 5), (!0 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 8
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 17
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5));
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0);
             }
 
             fn test_unbounded_shr() {
                 // <$T>::MIN
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // <$T>::MAX
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 1
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // !0
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, 1), (!0 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, 3), (!0 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, 5), (!0 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 1), (!0 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 3), (!0 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 5), (!0 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 8
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0);
 
                 // 17
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5));
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
-                assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5));
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0);
+                assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0);
             }
         }
     };
diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs
index 43542397a61..3174c91a649 100644
--- a/library/coretests/tests/pin_macro.rs
+++ b/library/coretests/tests/pin_macro.rs
@@ -30,3 +30,31 @@ fn unsize_coercion() {
     let dyn_obj: Pin<&mut dyn Send> = pin!([PhantomPinned; 2]);
     stuff(dyn_obj);
 }
+
+#[test]
+fn rust_2024_expr() {
+    // Check that we accept a Rust 2024 $expr.
+    std::pin::pin!(const { 1 });
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn temp_lifetime() {
+    // Check that temporary lifetimes work as in Rust 2021.
+    // Regression test for https://github.com/rust-lang/rust/issues/138596
+    match std::pin::pin!(foo(&mut 0)) {
+        _ => {}
+    }
+    async fn foo(_: &mut usize) {}
+}
+
+#[test]
+fn transitive_extension() {
+    async fn temporary() {}
+
+    // `pin!` witnessed in the wild being used like this, even if it yields
+    // a `Pin<&mut &mut impl Unpin>`; it does work because `pin!`
+    // happens to transitively extend the lifespan of `temporary()`.
+    let p = pin!(&mut temporary());
+    let _use = p;
+}
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 03c3e697cfe..52cc8fba043 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
 
 use std::hash::Hash;
 use std::ops::{Bound, Range};
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 9d9601b79a7..176da603d58 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.151" }
+compiler_builtins = { version = "=0.1.152" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index f9a360585e8..801baf3d990 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -665,6 +665,7 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
+    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -673,7 +674,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[unstable(feature = "file_lock", issue = "130994")]
     pub fn lock(&self) -> io::Result<()> {
         self.inner.lock()
     }
@@ -717,6 +718,7 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
+    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -725,7 +727,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[unstable(feature = "file_lock", issue = "130994")]
     pub fn lock_shared(&self) -> io::Result<()> {
         self.inner.lock_shared()
     }
@@ -774,6 +776,7 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
+    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -782,7 +785,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[unstable(feature = "file_lock", issue = "130994")]
     pub fn try_lock(&self) -> io::Result<bool> {
         self.inner.try_lock()
     }
@@ -830,6 +833,7 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
+    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -838,7 +842,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[unstable(feature = "file_lock", issue = "130994")]
     pub fn try_lock_shared(&self) -> io::Result<bool> {
         self.inner.try_lock_shared()
     }
@@ -866,6 +870,7 @@ impl File {
     /// # Examples
     ///
     /// ```no_run
+    /// #![feature(file_lock)]
     /// use std::fs::File;
     ///
     /// fn main() -> std::io::Result<()> {
@@ -875,7 +880,7 @@ impl File {
     ///     Ok(())
     /// }
     /// ```
-    #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")]
+    #[unstable(feature = "file_lock", issue = "130994")]
     pub fn unlock(&self) -> io::Result<()> {
         self.inner.unlock()
     }
@@ -1343,6 +1348,9 @@ impl Seek for Arc<File> {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         (&**self).seek(pos)
     }
+    fn stream_position(&mut self) -> io::Result<u64> {
+        (&**self).stream_position()
+    }
 }
 
 impl OpenOptions {
@@ -2362,7 +2370,7 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
 #[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
-    fs_imp::unlink(path.as_ref())
+    fs_imp::remove_file(path.as_ref())
 }
 
 /// Given a path, queries the file system to get information about a file,
@@ -2401,7 +2409,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
 #[doc(alias = "stat")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
-    fs_imp::stat(path.as_ref()).map(Metadata)
+    fs_imp::metadata(path.as_ref()).map(Metadata)
 }
 
 /// Queries the metadata about a file without following symlinks.
@@ -2436,7 +2444,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
 #[doc(alias = "lstat")]
 #[stable(feature = "symlink_metadata", since = "1.1.0")]
 pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
-    fs_imp::lstat(path.as_ref()).map(Metadata)
+    fs_imp::symlink_metadata(path.as_ref()).map(Metadata)
 }
 
 /// Renames a file or directory to a new name, replacing the original file if
@@ -2590,7 +2598,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 #[doc(alias = "CreateHardLink", alias = "linkat")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
-    fs_imp::link(original.as_ref(), link.as_ref())
+    fs_imp::hard_link(original.as_ref(), link.as_ref())
 }
 
 /// Creates a new symbolic link on the filesystem.
@@ -2656,7 +2664,7 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Re
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
-    fs_imp::readlink(path.as_ref())
+    fs_imp::read_link(path.as_ref())
 }
 
 /// Returns the canonical, absolute form of a path with all intermediate
@@ -2832,7 +2840,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 #[doc(alias = "rmdir", alias = "RemoveDirectory")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
-    fs_imp::rmdir(path.as_ref())
+    fs_imp::remove_dir(path.as_ref())
 }
 
 /// Removes a directory at this path, after removing all its contents. Use
@@ -2959,7 +2967,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 #[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
-    fs_imp::readdir(path.as_ref()).map(ReadDir)
+    fs_imp::read_dir(path.as_ref()).map(ReadDir)
 }
 
 /// Changes the permissions found on a file or a directory.
@@ -2995,7 +3003,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
 #[doc(alias = "chmod", alias = "SetFileAttributes")]
 #[stable(feature = "set_permissions", since = "1.1.0")]
 pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
-    fs_imp::set_perm(path.as_ref(), perm.0)
+    fs_imp::set_permissions(path.as_ref(), perm.0)
 }
 
 impl DirBuilder {
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 6dd18e4f4c8..4712e58980c 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1719,6 +1719,23 @@ fn test_eq_direntry_metadata() {
     }
 }
 
+/// Test that windows file type equality is not affected by attributes unrelated
+/// to the file type.
+#[test]
+#[cfg(target_os = "windows")]
+fn test_eq_windows_file_type() {
+    let tmpdir = tmpdir();
+    let file1 = File::create(tmpdir.join("file1")).unwrap();
+    let file2 = File::create(tmpdir.join("file2")).unwrap();
+    assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type());
+
+    // Change the readonly attribute of one file.
+    let mut perms = file1.metadata().unwrap().permissions();
+    perms.set_readonly(true);
+    file1.set_permissions(perms).unwrap();
+    assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type());
+}
+
 /// Regression test for https://github.com/rust-lang/rust/issues/50619.
 #[test]
 #[cfg(target_os = "linux")]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 6579b6887aa..314cbb45d49 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2989,11 +2989,11 @@ impl<T: Read> Read for Take<T> {
             return Ok(());
         }
 
-        if self.limit <= buf.capacity() as u64 {
-            // if we just use an as cast to convert, limit may wrap around on a 32 bit target
-            let limit = cmp::min(self.limit, usize::MAX as u64) as usize;
+        if self.limit < buf.capacity() as u64 {
+            // The condition above guarantees that `self.limit` fits in `usize`.
+            let limit = self.limit as usize;
 
-            let extra_init = cmp::min(limit as usize, buf.init_ref().len());
+            let extra_init = cmp::min(limit, buf.init_ref().len());
 
             // SAFETY: no uninit data is written to ibuf
             let ibuf = unsafe { &mut buf.as_mut()[..limit] };
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index ce46241f8e8..8fc16331339 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -97,15 +97,15 @@ const fn stderr_raw() -> StderrRaw {
 
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        handle_ebadf(self.0.read(buf), 0)
+        handle_ebadf(self.0.read(buf), || Ok(0))
     }
 
     fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
-        handle_ebadf(self.0.read_buf(buf), ())
+        handle_ebadf(self.0.read_buf(buf), || Ok(()))
     }
 
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        handle_ebadf(self.0.read_vectored(bufs), 0)
+        handle_ebadf(self.0.read_vectored(bufs), || Ok(0))
     }
 
     #[inline]
@@ -113,23 +113,37 @@ impl Read for StdinRaw {
         self.0.is_read_vectored()
     }
 
+    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+        if buf.is_empty() {
+            return Ok(());
+        }
+        handle_ebadf(self.0.read_exact(buf), || Err(io::Error::READ_EXACT_EOF))
+    }
+
+    fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
+        if buf.capacity() == 0 {
+            return Ok(());
+        }
+        handle_ebadf(self.0.read_buf_exact(buf), || Err(io::Error::READ_EXACT_EOF))
+    }
+
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        handle_ebadf(self.0.read_to_end(buf), 0)
+        handle_ebadf(self.0.read_to_end(buf), || Ok(0))
     }
 
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        handle_ebadf(self.0.read_to_string(buf), 0)
+        handle_ebadf(self.0.read_to_string(buf), || Ok(0))
     }
 }
 
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        handle_ebadf(self.0.write(buf), buf.len())
+        handle_ebadf(self.0.write(buf), || Ok(buf.len()))
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = || bufs.iter().map(|b| b.len()).sum();
-        handle_ebadf_lazy(self.0.write_vectored(bufs), total)
+        let total = || Ok(bufs.iter().map(|b| b.len()).sum());
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -138,30 +152,30 @@ impl Write for StdoutRaw {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        handle_ebadf(self.0.flush(), ())
+        handle_ebadf(self.0.flush(), || Ok(()))
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        handle_ebadf(self.0.write_all(buf), ())
+        handle_ebadf(self.0.write_all(buf), || Ok(()))
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        handle_ebadf(self.0.write_all_vectored(bufs), ())
+        handle_ebadf(self.0.write_all_vectored(bufs), || Ok(()))
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        handle_ebadf(self.0.write_fmt(fmt), ())
+        handle_ebadf(self.0.write_fmt(fmt), || Ok(()))
     }
 }
 
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        handle_ebadf(self.0.write(buf), buf.len())
+        handle_ebadf(self.0.write(buf), || Ok(buf.len()))
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = || bufs.iter().map(|b| b.len()).sum();
-        handle_ebadf_lazy(self.0.write_vectored(bufs), total)
+        let total = || Ok(bufs.iter().map(|b| b.len()).sum());
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -170,32 +184,25 @@ impl Write for StderrRaw {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        handle_ebadf(self.0.flush(), ())
+        handle_ebadf(self.0.flush(), || Ok(()))
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        handle_ebadf(self.0.write_all(buf), ())
+        handle_ebadf(self.0.write_all(buf), || Ok(()))
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        handle_ebadf(self.0.write_all_vectored(bufs), ())
+        handle_ebadf(self.0.write_all_vectored(bufs), || Ok(()))
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        handle_ebadf(self.0.write_fmt(fmt), ())
-    }
-}
-
-fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
-    match r {
-        Err(ref e) if stdio::is_ebadf(e) => Ok(default),
-        r => r,
+        handle_ebadf(self.0.write_fmt(fmt), || Ok(()))
     }
 }
 
-fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> {
+fn handle_ebadf<T>(r: io::Result<T>, default: impl FnOnce() -> io::Result<T>) -> io::Result<T> {
     match r {
-        Err(ref e) if stdio::is_ebadf(e) => Ok(default()),
+        Err(ref e) if stdio::is_ebadf(e) => default(),
         r => r,
     }
 }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ad005833ad5..9dcedaa13f6 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -297,6 +297,7 @@
 #![feature(extended_varargs_abi_support)]
 #![feature(f128)]
 #![feature(f16)]
+#![feature(ffi_const)]
 #![feature(formatting_options)]
 #![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index a7b5cdf4ec0..03003037b29 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -315,12 +315,8 @@ fn read_buf() {
         let mut buf = BorrowedBuf::from(buf.as_mut_slice());
         t!(s.read_buf(buf.unfilled()));
         assert_eq!(buf.filled(), &[1, 2, 3, 4]);
-
-        // FIXME: sgx uses default_read_buf that initializes the buffer.
-        if cfg!(not(target_env = "sgx")) {
-            // TcpStream::read_buf should omit buffer initialization.
-            assert_eq!(buf.init_len(), 4);
-        }
+        // TcpStream::read_buf should omit buffer initialization.
+        assert_eq!(buf.init_len(), 4);
 
         t.join().ok().expect("thread panicked");
     })
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 2dcbfc96618..be73e7dee9c 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -15,9 +15,8 @@ use crate::mem::ManuallyDrop;
     target_os = "trusty"
 )))]
 use crate::sys::cvt;
-use crate::sys_common::FromInner;
 #[cfg(not(target_os = "trusty"))]
-use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, io};
 
 type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
@@ -507,6 +506,7 @@ impl<'a> AsFd for io::StderrLock<'a> {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for io::PipeReader {
     fn as_fd(&self) -> BorrowedFd<'_> {
         self.0.as_fd()
@@ -514,6 +514,7 @@ impl AsFd for io::PipeReader {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl From<io::PipeReader> for OwnedFd {
     fn from(pipe: io::PipeReader) -> Self {
         pipe.0.into_inner()
@@ -521,6 +522,7 @@ impl From<io::PipeReader> for OwnedFd {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl AsFd for io::PipeWriter {
     fn as_fd(&self) -> BorrowedFd<'_> {
         self.0.as_fd()
@@ -528,6 +530,7 @@ impl AsFd for io::PipeWriter {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl From<io::PipeWriter> for OwnedFd {
     fn from(pipe: io::PipeWriter) -> Self {
         pipe.0.into_inner()
@@ -535,6 +538,7 @@ impl From<io::PipeWriter> for OwnedFd {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for io::PipeReader {
     fn from(owned_fd: OwnedFd) -> Self {
         Self(FromInner::from_inner(owned_fd))
@@ -542,6 +546,7 @@ impl From<OwnedFd> for io::PipeReader {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl From<OwnedFd> for io::PipeWriter {
     fn from(owned_fd: OwnedFd) -> Self {
         Self(FromInner::from_inner(owned_fd))
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 596b21a5204..c800c1489ad 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -18,9 +18,8 @@ use crate::os::unix::io::AsFd;
 use crate::os::unix::io::OwnedFd;
 #[cfg(target_os = "wasi")]
 use crate::os::wasi::io::OwnedFd;
-use crate::sys_common::FromInner;
 #[cfg(not(target_os = "trusty"))]
-use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -287,6 +286,7 @@ impl<T: AsRawFd> AsRawFd for Box<T> {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl AsRawFd for io::PipeReader {
     fn as_raw_fd(&self) -> RawFd {
         self.0.as_raw_fd()
@@ -294,6 +294,7 @@ impl AsRawFd for io::PipeReader {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl FromRawFd for io::PipeReader {
     unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
         Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
@@ -301,6 +302,7 @@ impl FromRawFd for io::PipeReader {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl IntoRawFd for io::PipeReader {
     fn into_raw_fd(self) -> RawFd {
         self.0.into_raw_fd()
@@ -308,6 +310,7 @@ impl IntoRawFd for io::PipeReader {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl AsRawFd for io::PipeWriter {
     fn as_raw_fd(&self) -> RawFd {
         self.0.as_raw_fd()
@@ -315,6 +318,7 @@ impl AsRawFd for io::PipeWriter {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl FromRawFd for io::PipeWriter {
     unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
         Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
@@ -322,6 +326,7 @@ impl FromRawFd for io::PipeWriter {
 }
 
 #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")]
+#[cfg(not(target_os = "trusty"))]
 impl IntoRawFd for io::PipeWriter {
     fn into_raw_fd(self) -> RawFd {
         self.0.into_raw_fd()
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index f81ce8e1a1a..3b765a9537b 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1836,7 +1836,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
 /// # if cfg!(unix) {
 /// use std::process::{Command, ExitStatusError};
 ///
-/// fn run(cmd: &str) -> Result<(),ExitStatusError> {
+/// fn run(cmd: &str) -> Result<(), ExitStatusError> {
 ///     Command::new(cmd).status().unwrap().exit_ok()?;
 ///     Ok(())
 /// }
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 5b50a3c6ccf..e67b4f6f22f 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -176,6 +176,8 @@ pub use core::sync::Exclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::sync::atomic;
 
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+pub use alloc_crate::sync::UniqueArc;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::sync::{Arc, Weak};
 
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index c2e19eb393a..3b176d0d16c 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -1,28 +1,115 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
+use crate::io;
+use crate::path::{Path, PathBuf};
+
 pub mod common;
 
 cfg_if::cfg_if! {
     if #[cfg(target_family = "unix")] {
         mod unix;
-        pub use unix::*;
+        use unix as imp;
+        pub use unix::{chown, fchown, lchown};
+        #[cfg(not(target_os = "fuchsia"))]
+        pub use unix::chroot;
+        pub(crate) use unix::debug_assert_fd_is_open;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        pub(crate) use unix::CachedFileMetadata;
+        use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
     } else if #[cfg(target_os = "windows")] {
         mod windows;
-        pub use windows::*;
+        use windows as imp;
+        pub use windows::{symlink_inner, junction_point};
     } else if #[cfg(target_os = "hermit")] {
         mod hermit;
-        pub use hermit::*;
+        use hermit as imp;
     } else if #[cfg(target_os = "solid_asp3")] {
         mod solid;
-        pub use solid::*;
+        use solid as imp;
     } else if #[cfg(target_os = "uefi")] {
         mod uefi;
-        pub use uefi::*;
+        use uefi as imp;
     } else if #[cfg(target_os = "wasi")] {
         mod wasi;
-        pub use wasi::*;
+        use wasi as imp;
     } else {
         mod unsupported;
-        pub use unsupported::*;
+        use unsupported as imp;
     }
 }
+
+// FIXME: Replace this with platform-specific path conversion functions.
+#[cfg(not(target_family = "unix"))]
+#[inline]
+pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
+    f(path)
+}
+
+pub use imp::{
+    DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
+    ReadDir,
+};
+
+pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
+    // FIXME: use with_native_path
+    imp::readdir(path)
+}
+
+pub fn remove_file(path: &Path) -> io::Result<()> {
+    with_native_path(path, &imp::unlink)
+}
+
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+    with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
+}
+
+pub fn remove_dir(path: &Path) -> io::Result<()> {
+    with_native_path(path, &imp::rmdir)
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    // FIXME: use with_native_path
+    imp::remove_dir_all(path)
+}
+
+pub fn read_link(path: &Path) -> io::Result<PathBuf> {
+    with_native_path(path, &imp::readlink)
+}
+
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    with_native_path(original, &|original| {
+        with_native_path(link, &|link| imp::symlink(original, link))
+    })
+}
+
+pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
+    with_native_path(original, &|original| {
+        with_native_path(link, &|link| imp::link(original, link))
+    })
+}
+
+pub fn metadata(path: &Path) -> io::Result<FileAttr> {
+    with_native_path(path, &imp::stat)
+}
+
+pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
+    with_native_path(path, &imp::lstat)
+}
+
+pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
+    with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
+}
+
+pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
+    with_native_path(path, &imp::canonicalize)
+}
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    // FIXME: use with_native_path
+    imp::copy(from, to)
+}
+
+pub fn exists(path: &Path) -> io::Result<bool> {
+    // FIXME: use with_native_path
+    imp::exists(path)
+}
diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs
index defc1681d38..d6ae86bd3d2 100644
--- a/library/std/src/sys/fs/uefi.rs
+++ b/library/std/src/sys/fs/uefi.rs
@@ -1,3 +1,5 @@
+use r_efi::protocols::file;
+
 use crate::ffi::OsString;
 use crate::fmt;
 use crate::hash::Hash;
@@ -22,7 +24,12 @@ pub struct ReadDir(!);
 pub struct DirEntry(!);
 
 #[derive(Clone, Debug)]
-pub struct OpenOptions {}
+pub struct OpenOptions {
+    mode: u64,
+    append: bool,
+    truncate: bool,
+    create_new: bool,
+}
 
 #[derive(Copy, Clone, Debug, Default)]
 pub struct FileTimes {}
@@ -36,7 +43,7 @@ pub struct FilePermissions(bool);
 pub struct FileType(bool);
 
 #[derive(Debug)]
-pub struct DirBuilder {}
+pub struct DirBuilder;
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
@@ -141,15 +148,58 @@ impl DirEntry {
 
 impl OpenOptions {
     pub fn new() -> OpenOptions {
-        OpenOptions {}
+        OpenOptions { mode: 0, append: false, create_new: false, truncate: false }
+    }
+
+    pub fn read(&mut self, read: bool) {
+        if read {
+            self.mode |= file::MODE_READ;
+        } else {
+            self.mode &= !file::MODE_READ;
+        }
+    }
+
+    pub fn write(&mut self, write: bool) {
+        if write {
+            // Valid Combinations: Read, Read/Write, Read/Write/Create
+            self.read(true);
+            self.mode |= file::MODE_WRITE;
+        } else {
+            self.mode &= !file::MODE_WRITE;
+        }
+    }
+
+    pub fn append(&mut self, append: bool) {
+        // Docs state that `.write(true).append(true)` has the same effect as `.append(true)`
+        if append {
+            self.write(true);
+        }
+        self.append = append;
+    }
+
+    pub fn truncate(&mut self, truncate: bool) {
+        self.truncate = truncate;
+    }
+
+    pub fn create(&mut self, create: bool) {
+        if create {
+            self.mode |= file::MODE_CREATE;
+        } else {
+            self.mode &= !file::MODE_CREATE;
+        }
     }
 
-    pub fn read(&mut self, _read: bool) {}
-    pub fn write(&mut self, _write: bool) {}
-    pub fn append(&mut self, _append: bool) {}
-    pub fn truncate(&mut self, _truncate: bool) {}
-    pub fn create(&mut self, _create: bool) {}
-    pub fn create_new(&mut self, _create_new: bool) {}
+    pub fn create_new(&mut self, create_new: bool) {
+        self.create_new = create_new;
+    }
+
+    #[expect(dead_code)]
+    const fn is_mode_valid(&self) -> bool {
+        // Valid Combinations: Read, Read/Write, Read/Write/Create
+        self.mode == file::MODE_READ
+            || self.mode == (file::MODE_READ | file::MODE_WRITE)
+            || self.mode == (file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE)
+    }
 }
 
 impl File {
@@ -248,11 +298,11 @@ impl File {
 
 impl DirBuilder {
     pub fn new() -> DirBuilder {
-        DirBuilder {}
+        DirBuilder
     }
 
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        uefi_fs::mkdir(p)
     }
 }
 
@@ -311,12 +361,12 @@ pub fn stat(_p: &Path) -> io::Result<FileAttr> {
     unsupported()
 }
 
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    stat(p)
 }
 
-pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    crate::path::absolute(p)
 }
 
 pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
@@ -452,4 +502,30 @@ mod uefi_fs {
             }
         }
     }
+
+    /// An implementation of mkdir to allow creating new directory without having to open the
+    /// volume twice (once for checking and once for creating)
+    pub(crate) fn mkdir(path: &Path) -> io::Result<()> {
+        let absolute = crate::path::absolute(path)?;
+
+        let p = helpers::OwnedDevicePath::from_text(absolute.as_os_str())?;
+        let (vol, mut path_remaining) = File::open_volume_from_device_path(p.borrow())?;
+
+        // Check if file exists
+        match vol.open(&mut path_remaining, file::MODE_READ, 0) {
+            Ok(_) => {
+                return Err(io::Error::new(io::ErrorKind::AlreadyExists, "Path already exists"));
+            }
+            Err(e) if e.kind() == io::ErrorKind::NotFound => {}
+            Err(e) => return Err(e),
+        }
+
+        let _ = vol.open(
+            &mut path_remaining,
+            file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE,
+            file::DIRECTORY,
+        )?;
+
+        Ok(())
+    }
 }
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 7c3ed8029f7..87865be0387 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -155,15 +155,15 @@ cfg_has_statx! {{
         enum STATX_STATE{ Unknown = 0, Present, Unavailable }
         static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8);
 
-        syscall! {
+        syscall!(
             fn statx(
                 fd: c_int,
                 pathname: *const c_char,
                 flags: c_int,
                 mask: libc::c_uint,
-                statxbuf: *mut libc::statx
-            ) -> c_int
-        }
+                statxbuf: *mut libc::statx,
+            ) -> c_int;
+        );
 
         let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed);
         if statx_availability == STATX_STATE::Unavailable as u8 {
@@ -926,7 +926,7 @@ impl DirEntry {
         miri
     ))]
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        lstat(&self.path())
+        run_path_with_cstr(&self.path(), &lstat)
     }
 
     #[cfg(any(
@@ -1540,7 +1540,9 @@ impl File {
                 let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
                 // futimens requires Android API level 19
                 cvt(unsafe {
-                    weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
+                    weak!(
+                        fn futimens(fd: c_int, times: *const libc::timespec) -> c_int;
+                    );
                     match futimens.get() {
                         Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
                         None => return Err(io::const_error!(
@@ -1556,7 +1558,9 @@ impl File {
                     use crate::sys::{time::__timespec64, weak::weak};
 
                     // Added in glibc 2.34
-                    weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int);
+                    weak!(
+                        fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int;
+                    );
 
                     if let Some(futimens64) = __futimens64.get() {
                         let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64())
@@ -1653,7 +1657,7 @@ impl fmt::Debug for File {
         fn get_path(fd: c_int) -> Option<PathBuf> {
             let mut p = PathBuf::from("/proc/self/fd");
             p.push(&fd.to_string());
-            readlink(&p).ok()
+            run_path_with_cstr(&p, &readlink).ok()
         }
 
         #[cfg(any(target_vendor = "apple", target_os = "netbsd"))]
@@ -1671,7 +1675,7 @@ impl fmt::Debug for File {
                         // fallback to procfs as last resort
                         let mut p = PathBuf::from("/proc/self/fd");
                         p.push(&fd.to_string());
-                        return readlink(&p).ok();
+                        return run_path_with_cstr(&p, &readlink).ok()
                     } else {
                         return None;
                     }
@@ -1826,127 +1830,106 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
     }
 }
 
-pub fn unlink(p: &Path) -> io::Result<()> {
-    run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()))
+pub fn unlink(p: &CStr) -> io::Result<()> {
+    cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())
 }
 
-pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    run_path_with_cstr(old, &|old| {
-        run_path_with_cstr(new, &|new| {
-            cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
-        })
-    })
+pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> {
+    cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
 }
 
-pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
-    run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()))
+pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> {
+    cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())
 }
 
-pub fn rmdir(p: &Path) -> io::Result<()> {
-    run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()))
+pub fn rmdir(p: &CStr) -> io::Result<()> {
+    cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())
 }
 
-pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    run_path_with_cstr(p, &|c_path| {
-        let p = c_path.as_ptr();
+pub fn readlink(c_path: &CStr) -> io::Result<PathBuf> {
+    let p = c_path.as_ptr();
 
-        let mut buf = Vec::with_capacity(256);
+    let mut buf = Vec::with_capacity(256);
 
-        loop {
-            let buf_read =
-                cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })?
-                    as usize;
-
-            unsafe {
-                buf.set_len(buf_read);
-            }
+    loop {
+        let buf_read =
+            cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
 
-            if buf_read != buf.capacity() {
-                buf.shrink_to_fit();
+        unsafe {
+            buf.set_len(buf_read);
+        }
 
-                return Ok(PathBuf::from(OsString::from_vec(buf)));
-            }
+        if buf_read != buf.capacity() {
+            buf.shrink_to_fit();
 
-            // Trigger the internal buffer resizing logic of `Vec` by requiring
-            // more space than the current capacity. The length is guaranteed to be
-            // the same as the capacity due to the if statement above.
-            buf.reserve(1);
+            return Ok(PathBuf::from(OsString::from_vec(buf)));
         }
-    })
+
+        // Trigger the internal buffer resizing logic of `Vec` by requiring
+        // more space than the current capacity. The length is guaranteed to be
+        // the same as the capacity due to the if statement above.
+        buf.reserve(1);
+    }
 }
 
-pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
-    run_path_with_cstr(original, &|original| {
-        run_path_with_cstr(link, &|link| {
-            cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
-        })
-    })
+pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> {
+    cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
 }
 
-pub fn link(original: &Path, link: &Path) -> io::Result<()> {
-    run_path_with_cstr(original, &|original| {
-        run_path_with_cstr(link, &|link| {
-            cfg_if::cfg_if! {
-                if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
-                    // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
-                    // it implementation-defined whether `link` follows symlinks, so rely on the
-                    // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
-                    // Android has `linkat` on newer versions, but we happen to know `link`
-                    // always has the correct behavior, so it's here as well.
-                    cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
-                } else {
-                    // Where we can, use `linkat` instead of `link`; see the comment above
-                    // this one for details on why.
-                    cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
-                }
-            }
-            Ok(())
-        })
-    })
+pub fn link(original: &CStr, link: &CStr) -> io::Result<()> {
+    cfg_if::cfg_if! {
+        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
+            // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
+            // it implementation-defined whether `link` follows symlinks, so rely on the
+            // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
+            // Android has `linkat` on newer versions, but we happen to know `link`
+            // always has the correct behavior, so it's here as well.
+            cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+        } else {
+            // Where we can, use `linkat` instead of `link`; see the comment above
+            // this one for details on why.
+            cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+        }
+    }
+    Ok(())
 }
 
-pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    run_path_with_cstr(p, &|p| {
-        cfg_has_statx! {
-            if let Some(ret) = unsafe { try_statx(
-                libc::AT_FDCWD,
-                p.as_ptr(),
-                libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
-            ) } {
-                return ret;
-            }
+pub fn stat(p: &CStr) -> io::Result<FileAttr> {
+    cfg_has_statx! {
+        if let Some(ret) = unsafe { try_statx(
+            libc::AT_FDCWD,
+            p.as_ptr(),
+            libc::AT_STATX_SYNC_AS_STAT,
+            libc::STATX_BASIC_STATS | libc::STATX_BTIME,
+        ) } {
+            return ret;
         }
+    }
 
-        let mut stat: stat64 = unsafe { mem::zeroed() };
-        cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
-        Ok(FileAttr::from_stat64(stat))
-    })
+    let mut stat: stat64 = unsafe { mem::zeroed() };
+    cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
+    Ok(FileAttr::from_stat64(stat))
 }
 
-pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    run_path_with_cstr(p, &|p| {
-        cfg_has_statx! {
-            if let Some(ret) = unsafe { try_statx(
-                libc::AT_FDCWD,
-                p.as_ptr(),
-                libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
-                libc::STATX_BASIC_STATS | libc::STATX_BTIME,
-            ) } {
-                return ret;
-            }
+pub fn lstat(p: &CStr) -> io::Result<FileAttr> {
+    cfg_has_statx! {
+        if let Some(ret) = unsafe { try_statx(
+            libc::AT_FDCWD,
+            p.as_ptr(),
+            libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
+            libc::STATX_BASIC_STATS | libc::STATX_BTIME,
+        ) } {
+            return ret;
         }
+    }
 
-        let mut stat: stat64 = unsafe { mem::zeroed() };
-        cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
-        Ok(FileAttr::from_stat64(stat))
-    })
+    let mut stat: stat64 = unsafe { mem::zeroed() };
+    cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
+    Ok(FileAttr::from_stat64(stat))
 }
 
-pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
-    let r = run_path_with_cstr(p, &|path| unsafe {
-        Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
-    })?;
+pub fn canonicalize(path: &CStr) -> io::Result<PathBuf> {
+    let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) };
     if r.is_null() {
         return Err(io::Error::last_os_error());
     }
@@ -2324,19 +2307,19 @@ mod remove_dir_impl {
         Ok(())
     }
 
-    fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
+    fn remove_dir_all_modern(p: &CStr) -> io::Result<()> {
         // We cannot just call remove_dir_all_recursive() here because that would not delete a passed
         // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
         // into symlinks.
         let attr = lstat(p)?;
         if attr.file_type().is_symlink() {
-            crate::fs::remove_file(p)
+            super::unlink(p)
         } else {
-            run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p))
+            remove_dir_all_recursive(None, &p)
         }
     }
 
     pub fn remove_dir_all(p: &Path) -> io::Result<()> {
-        remove_dir_all_modern(p)
+        run_path_with_cstr(p, &remove_dir_all_modern)
     }
 }
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs
index 362e64abf1a..15727c99683 100644
--- a/library/std/src/sys/fs/windows.rs
+++ b/library/std/src/sys/fs/windows.rs
@@ -41,8 +41,8 @@ pub struct FileAttr {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType {
-    attributes: u32,
-    reparse_tag: u32,
+    is_directory: bool,
+    is_symlink: bool,
 }
 
 pub struct ReadDir {
@@ -547,7 +547,7 @@ impl File {
             ))?;
             attr.file_size = info.AllocationSize as u64;
             attr.number_of_links = Some(info.NumberOfLinks);
-            if attr.file_type().is_reparse_point() {
+            if attr.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
                 let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
                 cvt(c::GetFileInformationByHandleEx(
                     self.handle.as_raw_handle(),
@@ -1111,32 +1111,29 @@ impl FileTimes {
 }
 
 impl FileType {
-    fn new(attrs: u32, reparse_tag: u32) -> FileType {
-        FileType { attributes: attrs, reparse_tag }
+    fn new(attributes: u32, reparse_tag: u32) -> FileType {
+        let is_directory = attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0;
+        let is_symlink = {
+            let is_reparse_point = attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0;
+            let is_reparse_tag_name_surrogate = reparse_tag & 0x20000000 != 0;
+            is_reparse_point && is_reparse_tag_name_surrogate
+        };
+        FileType { is_directory, is_symlink }
     }
     pub fn is_dir(&self) -> bool {
-        !self.is_symlink() && self.is_directory()
+        !self.is_symlink && self.is_directory
     }
     pub fn is_file(&self) -> bool {
-        !self.is_symlink() && !self.is_directory()
+        !self.is_symlink && !self.is_directory
     }
     pub fn is_symlink(&self) -> bool {
-        self.is_reparse_point() && self.is_reparse_tag_name_surrogate()
+        self.is_symlink
     }
     pub fn is_symlink_dir(&self) -> bool {
-        self.is_symlink() && self.is_directory()
+        self.is_symlink && self.is_directory
     }
     pub fn is_symlink_file(&self) -> bool {
-        self.is_symlink() && !self.is_directory()
-    }
-    fn is_directory(&self) -> bool {
-        self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0
-    }
-    fn is_reparse_point(&self) -> bool {
-        self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
-    }
-    fn is_reparse_tag_name_surrogate(&self) -> bool {
-        self.reparse_tag & 0x20000000 != 0
+        self.is_symlink && !self.is_directory
     }
 }
 
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 09677b9d642..f0cfb9b2773 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -17,6 +17,7 @@ pub mod io;
 pub mod net;
 pub mod os_str;
 pub mod path;
+pub mod process;
 pub mod random;
 pub mod stdio;
 pub mod sync;
diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs
index 283b1fe9a33..e8aea8b706a 100644
--- a/library/std/src/sys/net/connection/xous/tcpstream.rs
+++ b/library/std/src/sys/net/connection/xous/tcpstream.rs
@@ -324,7 +324,7 @@ impl TcpStream {
                 }
                 Ok(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.local_port, 0, 0)))
             }
-            _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "tnternal error")),
+            _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "internal error")),
         }
     }
 
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 608245bd430..67eab96fa40 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -25,8 +25,6 @@ pub mod futex;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub mod thread;
 pub mod time;
 
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index bb419c2530e..fe43cfd2caf 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -16,8 +16,6 @@ mod libunwind_integration;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub mod thread;
 pub mod thread_parking;
 pub mod time;
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index e4a61fdcfe3..22052a168fd 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -25,8 +25,6 @@ pub(crate) mod error;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub use self::itron::{thread, thread_parking};
 pub mod time;
 
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 41b25121592..c1921a2f40d 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -14,8 +14,6 @@ pub mod env;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub mod thread;
 #[allow(non_upper_case_globals)]
 #[path = "../unix/time.rs"]
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
index 7034b643d8e..5295d3fdc91 100644
--- a/library/std/src/sys/pal/trusty/mod.rs
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -11,8 +11,6 @@ pub mod env;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 #[path = "../unsupported/thread.rs"]
 pub mod thread;
 #[path = "../unsupported/time.rs"]
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 2faa733f23f..309022bcccf 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -120,39 +120,6 @@ pub(crate) fn open_protocol<T>(
     }
 }
 
-pub(crate) fn create_event(
-    signal: u32,
-    tpl: efi::Tpl,
-    handler: Option<efi::EventNotify>,
-    context: *mut crate::ffi::c_void,
-) -> io::Result<NonNull<crate::ffi::c_void>> {
-    let boot_services: NonNull<efi::BootServices> =
-        boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
-    let mut event: r_efi::efi::Event = crate::ptr::null_mut();
-    let r = unsafe {
-        let create_event = (*boot_services.as_ptr()).create_event;
-        (create_event)(signal, tpl, handler, context, &mut event)
-    };
-    if r.is_error() {
-        Err(crate::io::Error::from_raw_os_error(r.as_usize()))
-    } else {
-        NonNull::new(event).ok_or(const_error!(io::ErrorKind::Other, "null protocol"))
-    }
-}
-
-/// # SAFETY
-/// - The supplied event must be valid
-pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result<()> {
-    let boot_services: NonNull<efi::BootServices> =
-        boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
-    let r = unsafe {
-        let close_event = (*boot_services.as_ptr()).close_event;
-        (close_event)(evt.as_ptr())
-    };
-
-    if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
-}
-
 /// Gets the Protocol for current system handle.
 ///
 /// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so.
@@ -735,3 +702,56 @@ impl Drop for ServiceProtocol {
         }
     }
 }
+
+#[repr(transparent)]
+pub(crate) struct OwnedEvent(NonNull<crate::ffi::c_void>);
+
+impl OwnedEvent {
+    pub(crate) fn new(
+        signal: u32,
+        tpl: efi::Tpl,
+        handler: Option<efi::EventNotify>,
+        context: Option<NonNull<crate::ffi::c_void>>,
+    ) -> io::Result<Self> {
+        let boot_services: NonNull<efi::BootServices> =
+            boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
+        let mut event: r_efi::efi::Event = crate::ptr::null_mut();
+        let context = context.map(NonNull::as_ptr).unwrap_or(crate::ptr::null_mut());
+
+        let r = unsafe {
+            let create_event = (*boot_services.as_ptr()).create_event;
+            (create_event)(signal, tpl, handler, context, &mut event)
+        };
+
+        if r.is_error() {
+            Err(crate::io::Error::from_raw_os_error(r.as_usize()))
+        } else {
+            NonNull::new(event)
+                .ok_or(const_error!(io::ErrorKind::Other, "failed to create event"))
+                .map(Self)
+        }
+    }
+
+    pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void {
+        let r = self.0.as_ptr();
+        crate::mem::forget(self);
+        r
+    }
+
+    /// SAFETY: Assumes that ptr is a non-null valid UEFI event
+    pub(crate) unsafe fn from_raw(ptr: *mut crate::ffi::c_void) -> Self {
+        Self(unsafe { NonNull::new_unchecked(ptr) })
+    }
+}
+
+impl Drop for OwnedEvent {
+    fn drop(&mut self) {
+        if let Some(boot_services) = boot_services() {
+            let bt: NonNull<r_efi::efi::BootServices> = boot_services.cast();
+            unsafe {
+                let close_event = (*bt.as_ptr()).close_event;
+                (close_event)(self.0.as_ptr())
+            };
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 714dc392688..9760a23084a 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -19,7 +19,6 @@ pub mod helpers;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-pub mod process;
 pub mod thread;
 pub mod time;
 
@@ -47,17 +46,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
     unsafe { uefi::env::init_globals(image_handle, system_table) };
 
     // Register exit boot services handler
-    match helpers::create_event(
+    match helpers::OwnedEvent::new(
         r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES,
         r_efi::efi::TPL_NOTIFY,
         Some(exit_boot_service_handler),
-        crate::ptr::null_mut(),
+        None,
     ) {
         Ok(x) => {
             if EXIT_BOOT_SERVICE_EVENT
                 .compare_exchange(
                     crate::ptr::null_mut(),
-                    x.as_ptr(),
+                    x.into_raw(),
                     Ordering::Release,
                     Ordering::Acquire,
                 )
@@ -77,7 +76,7 @@ pub unsafe fn cleanup() {
     if let Some(exit_boot_service_event) =
         NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire))
     {
-        let _ = unsafe { helpers::close_event(exit_boot_service_event) };
+        let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) };
     }
 }
 
@@ -143,7 +142,7 @@ pub fn abort_internal() -> ! {
     if let Some(exit_boot_service_event) =
         NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
     {
-        let _ = unsafe { helpers::close_event(exit_boot_service_event) };
+        let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) };
     }
 
     if let (Some(boot_services), Some(handle)) =
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index f03c440e30e..2ec8d01c13f 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -232,14 +232,14 @@ impl FileDesc {
     // implementation if `preadv` is not available.
     #[cfg(all(target_os = "android", target_pointer_width = "64"))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::syscall! {
+        super::weak::syscall!(
             fn preadv(
                 fd: libc::c_int,
                 iovec: *const libc::iovec,
                 n_iovec: libc::c_int,
-                offset: off64_t
-            ) -> isize
-        }
+                offset: off64_t,
+            ) -> isize;
+        );
 
         let ret = cvt(unsafe {
             preadv(
@@ -257,7 +257,14 @@ impl FileDesc {
     // and its metadata from LLVM IR.
     #[no_sanitize(cfi)]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+        super::weak::weak!(
+            fn preadv64(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t,
+            ) -> isize;
+        );
 
         match preadv64.get() {
             Some(preadv) => {
@@ -286,7 +293,14 @@ impl FileDesc {
     // use "weak" linking.
     #[cfg(target_vendor = "apple")]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+        super::weak::weak!(
+            fn preadv(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t,
+            ) -> isize;
+        );
 
         match preadv.get() {
             Some(preadv) => {
@@ -428,14 +442,14 @@ impl FileDesc {
     // implementation if `pwritev` is not available.
     #[cfg(all(target_os = "android", target_pointer_width = "64"))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::syscall! {
+        super::weak::syscall!(
             fn pwritev(
                 fd: libc::c_int,
                 iovec: *const libc::iovec,
                 n_iovec: libc::c_int,
-                offset: off64_t
-            ) -> isize
-        }
+                offset: off64_t,
+            ) -> isize;
+        );
 
         let ret = cvt(unsafe {
             pwritev(
@@ -450,7 +464,14 @@ impl FileDesc {
 
     #[cfg(all(target_os = "android", target_pointer_width = "32"))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+        super::weak::weak!(
+            fn pwritev64(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t,
+            ) -> isize;
+        );
 
         match pwritev64.get() {
             Some(pwritev) => {
@@ -479,7 +500,14 @@ impl FileDesc {
     // use "weak" linking.
     #[cfg(target_vendor = "apple")]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
-        super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+        super::weak::weak!(
+            fn pwritev(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t,
+            ) -> isize;
+        );
 
         match pwritev.get() {
             Some(pwritev) => {
diff --git a/library/std/src/sys/pal/unix/process/zircon.rs b/library/std/src/sys/pal/unix/fuchsia.rs
index 7932bd26d76..7932bd26d76 100644
--- a/library/std/src/sys/pal/unix/process/zircon.rs
+++ b/library/std/src/sys/pal/unix/fuchsia.rs
diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index bbf29f32523..d42a7e2a7fc 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
         _ => true,
     };
 
-    syscall! {
+    syscall!(
         fn copy_file_range(
             fd_in: libc::c_int,
             off_in: *mut libc::loff_t,
             fd_out: libc::c_int,
             off_out: *mut libc::loff_t,
             len: libc::size_t,
-            flags: libc::c_uint
-        ) -> libc::ssize_t
-    }
+            flags: libc::c_uint,
+        ) -> libc::ssize_t;
+    );
 
     fn probe_copy_file_range_support() -> u8 {
         // In some cases, we cannot determine availability from the first
@@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
     // Android builds use feature level 14, but the libc wrapper for splice is
     // gated on feature level 21+, so we have to invoke the syscall directly.
     #[cfg(target_os = "android")]
-    syscall! {
+    syscall!(
         fn splice(
             srcfd: libc::c_int,
             src_offset: *const i64,
             dstfd: libc::c_int,
             dst_offset: *const i64,
             len: libc::size_t,
-            flags: libc::c_int
-        ) -> libc::ssize_t
-    }
+            flags: libc::c_int,
+        ) -> libc::ssize_t;
+    );
 
     #[cfg(target_os = "linux")]
     use libc::splice;
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index e2e537b7bd3..413fda1d8d8 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -9,6 +9,8 @@ pub mod weak;
 pub mod args;
 pub mod env;
 pub mod fd;
+#[cfg(target_os = "fuchsia")]
+pub mod fuchsia;
 pub mod futex;
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub mod kernel_copy;
@@ -16,7 +18,6 @@ pub mod kernel_copy;
 pub mod linux;
 pub mod os;
 pub mod pipe;
-pub mod process;
 pub mod stack_overflow;
 pub mod sync;
 pub mod thread;
@@ -419,7 +420,7 @@ cfg_if::cfg_if! {
 }
 
 #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))]
-mod unsupported {
+pub mod unsupported {
     use crate::io;
 
     pub fn unsupported<T>() -> io::Result<T> {
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 30282fbf655..f47421c6705 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -59,11 +59,14 @@ unsafe extern "C" {
     #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
     #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
     #[cfg_attr(target_os = "aix", link_name = "_Errno")]
+    // SAFETY: this will always return the same pointer on a given thread.
+    #[unsafe(ffi_const)]
     fn errno_location() -> *mut c_int;
 }
 
 /// Returns the platform-specific value of errno
 #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
+#[inline]
 pub fn errno() -> i32 {
     unsafe { (*errno_location()) as i32 }
 }
@@ -72,16 +75,19 @@ pub fn errno() -> i32 {
 // needed for readdir and syscall!
 #[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))]
 #[allow(dead_code)] // but not all target cfgs actually end up using it
+#[inline]
 pub fn set_errno(e: i32) {
     unsafe { *errno_location() = e as c_int }
 }
 
 #[cfg(target_os = "vxworks")]
+#[inline]
 pub fn errno() -> i32 {
     unsafe { libc::errnoGet() }
 }
 
 #[cfg(target_os = "rtems")]
+#[inline]
 pub fn errno() -> i32 {
     unsafe extern "C" {
         #[thread_local]
@@ -92,6 +98,7 @@ pub fn errno() -> i32 {
 }
 
 #[cfg(target_os = "dragonfly")]
+#[inline]
 pub fn errno() -> i32 {
     unsafe extern "C" {
         #[thread_local]
@@ -103,6 +110,7 @@ pub fn errno() -> i32 {
 
 #[cfg(target_os = "dragonfly")]
 #[allow(dead_code)]
+#[inline]
 pub fn set_errno(e: i32) {
     unsafe extern "C" {
         #[thread_local]
diff --git a/library/std/src/sys/pal/unix/process/mod.rs b/library/std/src/sys/pal/unix/process/mod.rs
deleted file mode 100644
index 2751d51c44d..00000000000
--- a/library/std/src/sys/pal/unix/process/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes};
-pub use self::process_inner::{ExitStatus, ExitStatusError, Process};
-pub use crate::ffi::OsString as EnvKey;
-
-#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))]
-mod process_common;
-
-#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))]
-mod process_unsupported;
-
-cfg_if::cfg_if! {
-    if #[cfg(target_os = "fuchsia")] {
-        #[path = "process_fuchsia.rs"]
-        mod process_inner;
-        mod zircon;
-    } else if #[cfg(target_os = "vxworks")] {
-        #[path = "process_vxworks.rs"]
-        mod process_inner;
-    } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] {
-        mod process_inner {
-            pub use super::process_unsupported::*;
-        }
-    } else {
-        #[path = "process_unix.rs"]
-        mod process_inner;
-    }
-}
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 0ecccdc8812..34b3948e3f6 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -424,18 +424,32 @@ mod imp {
 
         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);
+            dlsym!(
+                fn sysctlbyname(
+                    name: *const libc::c_char,
+                    oldp: *mut libc::c_void,
+                    oldlenp: *mut libc::size_t,
+                    newp: *const libc::c_void,
+                    newlen: libc::size_t,
+                ) -> libc::c_int;
+            );
             let mut guard: usize = 0;
             let mut size = size_of_val(&guard);
             let oid = c"security.bsd.stack_guard_page";
             match sysctlbyname.get() {
-                Some(fcn) if unsafe {
-                    fcn(oid.as_ptr(),
-                        (&raw mut guard).cast(),
-                        &raw mut size,
-                        ptr::null_mut(),
-                        0) == 0
-                } => guard,
+                Some(fcn)
+                    if unsafe {
+                        fcn(
+                            oid.as_ptr(),
+                            (&raw mut guard).cast(),
+                            &raw mut size,
+                            ptr::null_mut(),
+                            0,
+                        ) == 0
+                    } =>
+                {
+                    guard
+                }
                 _ => 1,
             }
         });
@@ -585,6 +599,7 @@ mod imp {
     target_os = "openbsd",
     target_os = "solaris",
     target_os = "illumos",
+    target_os = "cygwin",
 )))]
 mod imp {
     pub unsafe fn init() {}
@@ -597,3 +612,89 @@ mod imp {
 
     pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
 }
+
+#[cfg(target_os = "cygwin")]
+mod imp {
+    mod c {
+        pub type PVECTORED_EXCEPTION_HANDLER =
+            Option<unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32>;
+        pub type NTSTATUS = i32;
+        pub type BOOL = i32;
+
+        unsafe extern "system" {
+            pub fn AddVectoredExceptionHandler(
+                first: u32,
+                handler: PVECTORED_EXCEPTION_HANDLER,
+            ) -> *mut core::ffi::c_void;
+            pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL;
+        }
+
+        pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _;
+        pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32;
+
+        #[repr(C)]
+        #[derive(Clone, Copy)]
+        pub struct EXCEPTION_POINTERS {
+            pub ExceptionRecord: *mut EXCEPTION_RECORD,
+            // We don't need this field here
+            // pub Context: *mut CONTEXT,
+        }
+        #[repr(C)]
+        #[derive(Clone, Copy)]
+        pub struct EXCEPTION_RECORD {
+            pub ExceptionCode: NTSTATUS,
+            pub ExceptionFlags: u32,
+            pub ExceptionRecord: *mut EXCEPTION_RECORD,
+            pub ExceptionAddress: *mut core::ffi::c_void,
+            pub NumberParameters: u32,
+            pub ExceptionInformation: [usize; 15],
+        }
+    }
+
+    /// Reserve stack space for use in stack overflow exceptions.
+    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;
+
+            if code == c::EXCEPTION_STACK_OVERFLOW {
+                crate::thread::with_current_name(|name| {
+                    let name = name.unwrap_or("<unknown>");
+                    rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+                });
+            }
+            c::EXCEPTION_CONTINUE_SEARCH
+        }
+    }
+
+    pub unsafe 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();
+    }
+
+    pub unsafe fn cleanup() {}
+
+    pub unsafe fn make_handler(main_thread: bool) -> super::Handler {
+        if !main_thread {
+            reserve_stack();
+        }
+        super::Handler::null()
+    }
+
+    pub unsafe fn drop_handler(_data: *mut libc::c_void) {}
+}
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index bffe2536299..9078dd1c231 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -143,8 +143,8 @@ impl Thread {
     pub fn set_name(name: &CStr) {
         unsafe {
             cfg_if::cfg_if! {
-                if #[cfg(target_os = "linux")] {
-                    // Linux limits the allowed length of the name.
+                if #[cfg(any(target_os = "linux", target_os = "cygwin"))] {
+                    // Linux and Cygwin limits the allowed length of the name.
                     const TASK_COMM_LEN: usize = 16;
                     let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
                 } else {
@@ -193,11 +193,12 @@ impl Thread {
     // and its metadata from LLVM IR.
     #[no_sanitize(cfi)]
     pub fn set_name(name: &CStr) {
-        weak! {
+        weak!(
             fn pthread_setname_np(
-                libc::pthread_t, *const libc::c_char
-            ) -> libc::c_int
-        }
+                thread: libc::pthread_t,
+                name: *const libc::c_char,
+            ) -> libc::c_int;
+        );
 
         if let Some(f) = pthread_setname_np.get() {
             #[cfg(target_os = "nto")]
@@ -346,6 +347,7 @@ impl Drop for Thread {
     target_os = "solaris",
     target_os = "illumos",
     target_os = "vxworks",
+    target_os = "cygwin",
     target_vendor = "apple",
 ))]
 fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
@@ -761,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
     // We shouldn't really be using such an internal symbol, but there's currently
     // no other way to account for the TLS size.
-    dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t);
+    dlsym!(
+        fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t;
+    );
 
     match __pthread_get_minstack.get() {
         None => libc::PTHREAD_STACK_MIN,
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index c0a3044660b..b8469b1681f 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -123,7 +123,12 @@ impl Timespec {
 
             // __clock_gettime64 was added to 32-bit arches in glibc 2.34,
             // and it handles both vDSO calls and ENOSYS fallbacks itself.
-            weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int);
+            weak!(
+                fn __clock_gettime64(
+                    clockid: libc::clockid_t,
+                    tp: *mut __timespec64,
+                ) -> libc::c_int;
+            );
 
             if let Some(clock_gettime64) = __clock_gettime64.get() {
                 let mut t = MaybeUninit::uninit();
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index ce3f66a8374..e7f4e005cc4 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -29,7 +29,7 @@ use crate::{mem, ptr};
 // We can use true weak linkage on ELF targets.
 #[cfg(all(unix, not(target_vendor = "apple")))]
 pub(crate) macro weak {
-    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+    (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
         let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
             unsafe extern "C" {
                 #[linkage = "extern_weak"]
@@ -62,10 +62,16 @@ impl<F: Copy> ExternWeak<F> {
 }
 
 pub(crate) macro dlsym {
-    (fn $name:ident($($t:ty),*) -> $ret:ty) => (
-         dlsym!(fn $name($($t),*) -> $ret, stringify!($name));
+    (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
+         dlsym!(
+            #[link_name = stringify!($name)]
+            fn $name($($param : $t),*) -> $ret;
+        );
     ),
-    (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => (
+    (
+        #[link_name = $sym:expr]
+        fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
+    ) => (
         static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
             DlsymWeak::new(concat!($sym, '\0'));
         let $name = &DLSYM;
@@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {
 
 #[cfg(not(any(target_os = "linux", target_os = "android")))]
 pub(crate) macro syscall {
-    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+    (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
         // FIXME(#115199): Rust currently omits weak function definitions
         // and its metadata from LLVM IR.
         #[no_sanitize(cfi)]
-        unsafe fn $name($($arg_name: $t),*) -> $ret {
-            weak! { fn $name($($t),*) -> $ret }
+        unsafe fn $name($($param: $t),*) -> $ret {
+            weak!(fn $name($($param: $t),*) -> $ret;);
 
             if let Some(fun) = $name.get() {
-                fun($($arg_name),*)
+                fun($($param),*)
             } else {
                 super::os::set_errno(libc::ENOSYS);
                 -1
@@ -162,16 +168,18 @@ pub(crate) macro syscall {
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub(crate) macro syscall {
-    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
-        unsafe fn $name($($arg_name:$t),*) -> $ret {
-            weak! { fn $name($($t),*) -> $ret }
+    (
+        fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
+    ) => (
+        unsafe fn $name($($param: $t),*) -> $ret {
+            weak!(fn $name($($param: $t),*) -> $ret;);
 
             // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
             // interposition, but if it's not found just use a raw syscall.
             if let Some(fun) = $name.get() {
-                fun($($arg_name),*)
+                fun($($param),*)
             } else {
-                libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
+                libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
             }
         }
     )
@@ -179,9 +187,9 @@ pub(crate) macro syscall {
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub(crate) macro raw_syscall {
-    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
-        unsafe fn $name($($arg_name:$t),*) -> $ret {
-            libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
+    (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
+        unsafe fn $name($($param: $t),*) -> $ret {
+            libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret
         }
     )
 }
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index bcea699f3b2..38838b915b5 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -4,7 +4,6 @@ pub mod args;
 pub mod env;
 pub mod os;
 pub mod pipe;
-pub mod process;
 pub mod thread;
 pub mod time;
 
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index c89832857dd..cdd613f76b6 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -23,8 +23,6 @@ pub mod futex;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub mod thread;
 pub mod time;
 
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index c85b03d4a89..cc569bb3daf 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -67,7 +67,7 @@ cfg_if::cfg_if! {
     }
 }
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs
index 3008ba88753..6ac28f1bf4f 100644
--- a/library/std/src/sys/pal/wasip2/mod.rs
+++ b/library/std/src/sys/pal/wasip2/mod.rs
@@ -20,8 +20,6 @@ pub mod futex;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 #[path = "../wasi/thread.rs"]
 pub mod thread;
 #[path = "../wasi/time.rs"]
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index afdb159fe6f..dd5aff391fd 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -6,7 +6,7 @@ use crate::time::Duration;
 
 pub struct Thread(!);
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
+pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
 
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs
index 175fe75357f..8d39b70d039 100644
--- a/library/std/src/sys/pal/wasm/mod.rs
+++ b/library/std/src/sys/pal/wasm/mod.rs
@@ -23,8 +23,6 @@ pub mod env;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs
index 3447a0157e4..d973743639a 100644
--- a/library/std/src/sys/pal/windows/args.rs
+++ b/library/std/src/sys/pal/windows/args.rs
@@ -6,13 +6,13 @@
 #[cfg(test)]
 mod tests;
 
+use super::ensure_no_nuls;
 use super::os::current_exe;
 use crate::ffi::{OsStr, OsString};
 use crate::num::NonZero;
 use crate::os::windows::prelude::*;
 use crate::path::{Path, PathBuf};
 use crate::sys::path::get_long_path;
-use crate::sys::process::ensure_no_nuls;
 use crate::sys::{c, to_u16s};
 use crate::sys_common::AsInner;
 use crate::sys_common::wstr::WStrUnits;
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 6eb68f3a3bc..bdf0cc2c59c 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -22,7 +22,6 @@ pub mod futex;
 pub mod handle;
 pub mod os;
 pub mod pipe;
-pub mod process;
 pub mod thread;
 pub mod time;
 cfg_if::cfg_if! {
@@ -287,6 +286,14 @@ pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
     }
 }
 
+pub fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> crate::io::Result<T> {
+    if s.as_ref().encode_wide().any(|b| b == 0) {
+        Err(crate::io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data"))
+    } else {
+        Ok(s)
+    }
+}
+
 pub trait IsZero {
     fn is_zero(&self) -> bool;
 }
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index 8521cf4162f..c7852464922 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -74,7 +74,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
         let ours;
         let mut name;
         let mut tries = 0;
-        let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
         loop {
             tries += 1;
             name = format!(
@@ -96,7 +95,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
                 c::PIPE_TYPE_BYTE
                     | c::PIPE_READMODE_BYTE
                     | c::PIPE_WAIT
-                    | reject_remote_clients_flag,
+                    | c::PIPE_REJECT_REMOTE_CLIENTS,
                 1,
                 PIPE_BUFFER_CAPACITY,
                 PIPE_BUFFER_CAPACITY,
@@ -112,30 +111,15 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
             //
             // Don't try again too much though as this could also perhaps be a
             // legit error.
-            // If `ERROR_INVALID_PARAMETER` is returned, this probably means we're
-            // running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is
-            // not supported, so we continue retrying without it. This implies
-            // reduced security on Windows versions older than Vista by allowing
-            // connections to this pipe from remote machines.
-            // Proper fix would increase the number of FFI imports and introduce
-            // significant amount of Windows XP specific code with no clean
-            // testing strategy
-            // For more info, see https://github.com/rust-lang/rust/pull/37677.
             if handle == c::INVALID_HANDLE_VALUE {
                 let error = api::get_last_error();
-                if tries < 10 {
-                    if error == WinError::ACCESS_DENIED {
-                        continue;
-                    } else if reject_remote_clients_flag != 0
-                        && error == WinError::INVALID_PARAMETER
-                    {
-                        reject_remote_clients_flag = 0;
-                        tries -= 1;
-                        continue;
-                    }
+                if tries < 10 && error == WinError::ACCESS_DENIED {
+                    continue;
+                } else {
+                    return Err(io::Error::from_raw_os_error(error.code as i32));
                 }
-                return Err(io::Error::from_raw_os_error(error.code as i32));
             }
+
             ours = Handle::from_raw_handle(handle);
             break;
         }
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 7d823012ad1..58926e2beb1 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -6,8 +6,6 @@ pub mod env;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 pub mod thread;
 pub mod time;
 
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index 499e2787201..4659dad16e8 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -17,8 +17,6 @@ pub mod env;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
 #[path = "../unsupported/thread.rs"]
 pub mod thread;
 #[path = "../unsupported/time.rs"]
diff --git a/library/std/src/sys/process/mod.rs b/library/std/src/sys/process/mod.rs
new file mode 100644
index 00000000000..92cfac7f47c
--- /dev/null
+++ b/library/std/src/sys/process/mod.rs
@@ -0,0 +1,19 @@
+cfg_if::cfg_if! {
+    if #[cfg(target_family = "unix")] {
+        mod unix;
+        use unix as imp;
+    } else if #[cfg(target_os = "windows")] {
+        mod windows;
+        use windows as imp;
+    } else if #[cfg(target_os = "uefi")] {
+        mod uefi;
+        use uefi as imp;
+    } else {
+        mod unsupported;
+        use unsupported as imp;
+    }
+}
+
+pub use imp::{
+    Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes,
+};
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/process/uefi.rs
index 1203d51e531..b46418ae9bb 100644
--- a/library/std/src/sys/pal/uefi/process.rs
+++ b/library/std/src/sys/process/uefi.rs
@@ -1,12 +1,13 @@
 use r_efi::protocols::simple_text_output;
 
-use super::helpers;
 use crate::collections::BTreeMap;
 pub use crate::ffi::OsString as EnvKey;
 use crate::ffi::{OsStr, OsString};
 use crate::num::{NonZero, NonZeroI32};
 use crate::path::Path;
 use crate::sys::fs::File;
+use crate::sys::pal::helpers;
+use crate::sys::pal::os::error_string;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::unsupported;
 use crate::sys_common::process::{CommandEnv, CommandEnvs};
@@ -225,7 +226,7 @@ impl ExitStatus {
 
 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());
+        let err_str = error_string(self.0.as_usize());
         write!(f, "{}", err_str)
     }
 }
@@ -241,7 +242,7 @@ 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());
+        let err_str = error_string(self.0.as_usize());
         write!(f, "{}", err_str)
     }
 }
@@ -335,7 +336,6 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
 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_error};
     use crate::mem::MaybeUninit;
@@ -343,7 +343,7 @@ mod uefi_command_internal {
     use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
     use crate::ptr::NonNull;
     use crate::slice;
-    use crate::sys::pal::uefi::helpers::OwnedTable;
+    use crate::sys::pal::helpers::{self, OwnedTable};
     use crate::sys_common::wstr::WStrUnits;
 
     pub struct Image {
diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/process/unix/common.rs
index a1c747c8df4..8bc17f31491 100644
--- a/library/std/src/sys/pal/unix/process/process_common.rs
+++ b/library/std/src/sys/process/unix/common.rs
@@ -54,7 +54,7 @@ cfg_if::cfg_if! {
 
             let bit = (signum - 1) as usize;
             if set.is_null() || bit >= (8 * size_of::<sigset_t>()) {
-                crate::sys::pal::unix::os::set_errno(libc::EINVAL);
+                crate::sys::pal::os::set_errno(libc::EINVAL);
                 return -1;
             }
             let raw = slice::from_raw_parts_mut(
diff --git a/library/std/src/sys/pal/unix/process/process_common/tests.rs b/library/std/src/sys/process/unix/common/tests.rs
index e5c8dd6e341..e5c8dd6e341 100644
--- a/library/std/src/sys/pal/unix/process/process_common/tests.rs
+++ b/library/std/src/sys/process/unix/common/tests.rs
diff --git a/library/std/src/sys/pal/unix/process/process_fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs
index 05c9ace470e..0de32ecffd4 100644
--- a/library/std/src/sys/pal/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/process/unix/fuchsia.rs
@@ -1,8 +1,8 @@
 use libc::{c_int, size_t};
 
+use super::common::*;
 use crate::num::NonZero;
-use crate::sys::process::process_common::*;
-use crate::sys::process::zircon::{Handle, zx_handle_t};
+use crate::sys::pal::fuchsia::*;
 use crate::{fmt, io, mem, ptr};
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -58,8 +58,6 @@ impl Command {
         stdio: ChildPipes,
         maybe_envp: Option<&CStringArray>,
     ) -> io::Result<zx_handle_t> {
-        use crate::sys::process::zircon::*;
-
         let envp = match maybe_envp {
             // None means to clone the current environment, which is done in the
             // flags below.
@@ -152,8 +150,6 @@ impl Process {
     }
 
     pub fn kill(&mut self) -> io::Result<()> {
-        use crate::sys::process::zircon::*;
-
         unsafe {
             zx_cvt(zx_task_kill(self.handle.raw()))?;
         }
@@ -162,8 +158,6 @@ impl Process {
     }
 
     pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        use crate::sys::process::zircon::*;
-
         let mut proc_info: zx_info_process_t = Default::default();
         let mut actual: size_t = 0;
         let mut avail: size_t = 0;
@@ -194,8 +188,6 @@ impl Process {
     }
 
     pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        use crate::sys::process::zircon::*;
-
         let mut proc_info: zx_info_process_t = Default::default();
         let mut actual: size_t = 0;
         let mut avail: size_t = 0;
@@ -251,7 +243,7 @@ impl ExitStatus {
         None
     }
 
-    // FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al.
+    // FIXME: The actually-Unix implementation in unix.rs uses WSTOPSIG, WCOREDUMP et al.
     // I infer from the implementation of `success`, `code` and `signal` above that these are not
     // available on Fuchsia.
     //
diff --git a/library/std/src/sys/process/unix/mod.rs b/library/std/src/sys/process/unix/mod.rs
new file mode 100644
index 00000000000..2e8b38f7de1
--- /dev/null
+++ b/library/std/src/sys/process/unix/mod.rs
@@ -0,0 +1,23 @@
+#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))]
+mod common;
+
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "fuchsia")] {
+        mod fuchsia;
+        use fuchsia as imp;
+    } else if #[cfg(target_os = "vxworks")] {
+        mod vxworks;
+        use vxworks as imp;
+    } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] {
+        mod unsupported;
+        use unsupported as imp;
+    } else {
+        mod unix;
+        use unix as imp;
+    }
+}
+
+pub use imp::{ExitStatus, ExitStatusError, Process};
+
+pub use self::common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes};
+pub use crate::ffi::OsString as EnvKey;
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/process/unix/unix.rs
index f19512233d8..191a09c8da9 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -10,12 +10,12 @@ use libc::{c_int, pid_t};
 )))]
 use libc::{gid_t, uid_t};
 
+use super::common::*;
 use crate::io::{self, Error, ErrorKind};
 use crate::num::NonZero;
 use crate::sys::cvt;
 #[cfg(target_os = "linux")]
-use crate::sys::pal::unix::linux::pidfd::PidFd;
-use crate::sys::process::process_common::*;
+use crate::sys::pal::linux::pidfd::PidFd;
 use crate::{fmt, mem, sys};
 
 cfg_if::cfg_if! {
@@ -461,18 +461,20 @@ impl Command {
             if #[cfg(target_os = "linux")] {
                 use crate::sys::weak::weak;
 
-                weak! {
+                weak!(
                     fn pidfd_spawnp(
-                        *mut libc::c_int,
-                        *const libc::c_char,
-                        *const libc::posix_spawn_file_actions_t,
-                        *const libc::posix_spawnattr_t,
-                        *const *mut libc::c_char,
-                        *const *mut libc::c_char
-                    ) -> libc::c_int
-                }
+                        pidfd: *mut libc::c_int,
+                        path: *const libc::c_char,
+                        file_actions: *const libc::posix_spawn_file_actions_t,
+                        attrp: *const libc::posix_spawnattr_t,
+                        argv: *const *mut libc::c_char,
+                        envp: *const *mut libc::c_char,
+                    ) -> libc::c_int;
+                );
 
-                weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int }
+                weak!(
+                    fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int;
+                );
 
                 static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0);
                 const UNKNOWN: u8 = 0;
@@ -593,19 +595,19 @@ impl Command {
             // https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html.
             // The _np version is more widely available, though, so try that first.
 
-            weak! {
+            weak!(
                 fn posix_spawn_file_actions_addchdir_np(
-                    *mut libc::posix_spawn_file_actions_t,
-                    *const libc::c_char
-                ) -> libc::c_int
-            }
+                    file_actions: *mut libc::posix_spawn_file_actions_t,
+                    path: *const libc::c_char,
+                ) -> libc::c_int;
+            );
 
-            weak! {
+            weak!(
                 fn posix_spawn_file_actions_addchdir(
-                    *mut libc::posix_spawn_file_actions_t,
-                    *const libc::c_char
-                ) -> libc::c_int
-            }
+                    file_actions: *mut libc::posix_spawn_file_actions_t,
+                    path: *const libc::c_char,
+                ) -> libc::c_int;
+            );
 
             posix_spawn_file_actions_addchdir_np
                 .get()
@@ -1051,7 +1053,7 @@ impl ExitStatus {
         // true on all actual versions of Unix, is widely assumed, and is specified in SuS
         // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
         // true for a platform pretending to be Unix, the tests (our doctests, and also
-        // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
+        // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
         match NonZero::try_from(self.0) {
             /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)),
             /* was zero, couldn't convert */ Err(_) => Ok(()),
@@ -1232,10 +1234,9 @@ impl ExitStatusError {
 
 #[cfg(target_os = "linux")]
 mod linux_child_ext {
-
+    use crate::io::ErrorKind;
     use crate::os::linux::process as os;
-    use crate::sys::pal::unix::ErrorKind;
-    use crate::sys::pal::unix::linux::pidfd as imp;
+    use crate::sys::pal::linux::pidfd as imp;
     use crate::sys_common::FromInner;
     use crate::{io, mem};
 
@@ -1261,10 +1262,9 @@ mod linux_child_ext {
 }
 
 #[cfg(test)]
-#[path = "process_unix/tests.rs"]
 mod tests;
 
-// See [`process_unsupported_wait_status::compare_with_linux`];
+// See [`unsupported_wait_status::compare_with_linux`];
 #[cfg(all(test, target_os = "linux"))]
-#[path = "process_unsupported/wait_status.rs"]
-mod process_unsupported_wait_status;
+#[path = "unsupported/wait_status.rs"]
+mod unsupported_wait_status;
diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs
index f4d6ac6b4e3..f4d6ac6b4e3 100644
--- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs
+++ b/library/std/src/sys/process/unix/unix/tests.rs
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/process/unix/unsupported.rs
index c58548835ff..78d270923cf 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/process/unix/unsupported.rs
@@ -1,9 +1,9 @@
 use libc::{c_int, pid_t};
 
+use super::common::*;
 use crate::io;
 use crate::num::NonZero;
-use crate::sys::pal::unix::unsupported::*;
-use crate::sys::process::process_common::*;
+use crate::sys::pal::unsupported::*;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs b/library/std/src/sys/process/unix/unsupported/wait_status.rs
index f04036bde49..f348d557e4b 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs
+++ b/library/std/src/sys/process/unix/unsupported/wait_status.rs
@@ -7,7 +7,7 @@ use crate::ffi::c_int;
 use crate::fmt;
 use crate::num::NonZero;
 
-/// Emulated wait status for use by `process_unsupported.rs`
+/// Emulated wait status for use by `unsupported.rs`
 ///
 /// Uses the "traditional unix" encoding.  For use on platfors which are `#[cfg(unix)]`
 /// but do not actually support subprocesses at all.
@@ -48,7 +48,7 @@ impl ExitStatus {
         // true on all actual versions of Unix, is widely assumed, and is specified in SuS
         // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
         // true for a platform pretending to be Unix, the tests (our doctests, and also
-        // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
+        // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
         match NonZero::try_from(self.wait_status) {
             /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)),
             /* was zero, couldn't convert */ Err(_) => Ok(()),
@@ -79,5 +79,6 @@ impl ExitStatus {
 }
 
 #[cfg(test)]
-#[path = "wait_status/tests.rs"] // needed because of strange layout of process_unsupported
+#[path = "wait_status/tests.rs"]
+// needed because this module is also imported through #[path] for testing purposes
 mod tests;
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs
index 5132eab10a1..0d9232fac5e 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs
+++ b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs
@@ -1,4 +1,4 @@
-// Note that tests in this file are run on Linux as well as on platforms using process_unsupported
+// Note that tests in this file are run on Linux as well as on platforms using unsupported
 
 // Test that our emulation exactly matches Linux
 //
diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs
index e2c1b6a0326..5f1727789a1 100644
--- a/library/std/src/sys/pal/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/process/unix/vxworks.rs
@@ -1,11 +1,11 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 use libc::{self, RTP_ID, c_char, c_int};
 
+use super::common::*;
 use crate::io::{self, ErrorKind};
 use crate::num::NonZero;
 use crate::sys::cvt;
-use crate::sys::pal::unix::thread;
-use crate::sys::process::process_common::*;
+use crate::sys::pal::thread;
 use crate::{fmt, sys};
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -200,7 +200,7 @@ impl ExitStatus {
         // true on all actual versions of Unix, is widely assumed, and is specified in SuS
         // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
         // true for a platform pretending to be Unix, the tests (our doctests, and also
-        // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
+        // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
         match NonZero::try_from(self.0) {
             Ok(failure) => Err(ExitStatusError(failure)),
             Err(_) => Ok(()),
diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/process/unsupported.rs
index fee81744f09..fee81744f09 100644
--- a/library/std/src/sys/pal/unsupported/process.rs
+++ b/library/std/src/sys/process/unsupported.rs
diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/process/windows.rs
index 50e4baba607..06c15e08f3f 100644
--- a/library/std/src/sys/pal/windows/process.rs
+++ b/library/std/src/sys/process/windows.rs
@@ -5,11 +5,10 @@ mod tests;
 
 use core::ffi::c_void;
 
-use super::api::{self, WinError};
 use crate::collections::BTreeMap;
 use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX};
 use crate::ffi::{OsStr, OsString};
-use crate::io::{self, Error, ErrorKind};
+use crate::io::{self, Error};
 use crate::num::NonZero;
 use crate::os::windows::ffi::{OsStrExt, OsStringExt};
 use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle};
@@ -20,6 +19,8 @@ use crate::sys::args::{self, Arg};
 use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS};
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::handle::Handle;
+use crate::sys::pal::api::{self, WinError};
+use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
 use crate::sys::pipe::{self, AnonPipe};
 use crate::sys::{cvt, path, stdio};
 use crate::sys_common::IntoInner;
@@ -142,14 +143,6 @@ impl AsRef<OsStr> for EnvKey {
     }
 }
 
-pub(crate) fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> io::Result<T> {
-    if s.as_ref().encode_wide().any(|b| b == 0) {
-        Err(io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data"))
-    } else {
-        Ok(s)
-    }
-}
-
 pub struct Command {
     program: OsString,
     args: Vec<Arg>,
@@ -279,7 +272,7 @@ impl Command {
         let is_batch_file = if path::is_verbatim(&program) {
             has_bat_extension(&program[..program.len() - 1])
         } else {
-            super::fill_utf16_buf(
+            fill_utf16_buf(
                 |buffer, size| unsafe {
                     // resolve the path so we can test the final file name.
                     c::GetFullPathNameW(program.as_ptr(), size, buffer, ptr::null_mut())
@@ -521,7 +514,7 @@ where
     // 3 & 4. System paths
     // SAFETY: This uses `fill_utf16_buf` to safely call the OS functions.
     unsafe {
-        if let Ok(Some(path)) = super::fill_utf16_buf(
+        if let Ok(Some(path)) = fill_utf16_buf(
             |buf, size| c::GetSystemDirectoryW(buf, size),
             |buf| exists(PathBuf::from(OsString::from_wide(buf))),
         ) {
@@ -529,7 +522,7 @@ where
         }
         #[cfg(not(target_vendor = "uwp"))]
         {
-            if let Ok(Some(path)) = super::fill_utf16_buf(
+            if let Ok(Some(path)) = fill_utf16_buf(
                 |buf, size| c::GetWindowsDirectoryW(buf, size),
                 |buf| exists(PathBuf::from(OsString::from_wide(buf))),
             ) {
@@ -851,10 +844,8 @@ fn make_command_line(argv0: &OsStr, args: &[Arg], force_quotes: bool) -> io::Res
 
 // Get `cmd.exe` for use with bat scripts, encoded as a UTF-16 string.
 fn command_prompt() -> io::Result<Vec<u16>> {
-    let mut system: Vec<u16> = super::fill_utf16_buf(
-        |buf, size| unsafe { c::GetSystemDirectoryW(buf, size) },
-        |buf| buf.into(),
-    )?;
+    let mut system: Vec<u16> =
+        fill_utf16_buf(|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) }, |buf| buf.into())?;
     system.extend("\\cmd.exe".encode_utf16().chain([0]));
     Ok(system)
 }
diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/process/windows/tests.rs
index 1377e12162f..1377e12162f 100644
--- a/library/std/src/sys/pal/windows/process/tests.rs
+++ b/library/std/src/sys/process/windows/tests.rs
diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs
index e3cb79285cd..c0591ec0c15 100644
--- a/library/std/src/sys/random/linux.rs
+++ b/library/std/src/sys/random/linux.rs
@@ -73,13 +73,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) {
     // A weak symbol allows interposition, e.g. for perf measurements that want to
     // disable randomness for consistency. Otherwise, we'll try a raw syscall.
     // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28)
-    syscall! {
+    syscall!(
         fn getrandom(
             buffer: *mut libc::c_void,
             length: libc::size_t,
-            flags: libc::c_uint
-        ) -> libc::ssize_t
-    }
+            flags: libc::c_uint,
+        ) -> libc::ssize_t;
+    );
 
     static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true);
     static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true);
diff --git a/library/std/src/sys/random/trusty.rs b/library/std/src/sys/random/trusty.rs
index da6ca3eea24..e4db24695f8 100644
--- a/library/std/src/sys/random/trusty.rs
+++ b/library/std/src/sys/random/trusty.rs
@@ -1,4 +1,4 @@
-extern "C" {
+unsafe extern "C" {
     fn trusty_rng_secure_rand(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t);
 }
 
diff --git a/library/std/src/sys/stdio/sgx.rs b/library/std/src/sys/stdio/sgx.rs
index 1894c098d18..2cf47f49192 100644
--- a/library/std/src/sys/stdio/sgx.rs
+++ b/library/std/src/sys/stdio/sgx.rs
@@ -3,9 +3,9 @@ use fortanix_sgx_abi as abi;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::sys::fd::FileDesc;
 
-pub struct Stdin(());
-pub struct Stdout(());
-pub struct Stderr(());
+pub struct Stdin;
+pub struct Stdout;
+pub struct Stderr;
 
 fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
     let fd = FileDesc::new(fd);
@@ -16,7 +16,7 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
 
 impl Stdin {
     pub const fn new() -> Stdin {
-        Stdin(())
+        Stdin
     }
 }
 
@@ -41,7 +41,7 @@ impl io::Read for Stdin {
 
 impl Stdout {
     pub const fn new() -> Stdout {
-        Stdout(())
+        Stdout
     }
 }
 
@@ -66,7 +66,7 @@ impl io::Write for Stdout {
 
 impl Stderr {
     pub const fn new() -> Stderr {
-        Stderr(())
+        Stderr
     }
 }
 
diff --git a/library/std/src/sys/stdio/solid.rs b/library/std/src/sys/stdio/solid.rs
index a2ff4bb212f..55daf0b54b9 100644
--- a/library/std/src/sys/stdio/solid.rs
+++ b/library/std/src/sys/stdio/solid.rs
@@ -1,22 +1,13 @@
+#[expect(dead_code)]
+#[path = "unsupported.rs"]
+mod unsupported_stdio;
+
 use crate::io;
 use crate::sys::pal::abi;
 
-pub struct Stdin;
+pub type Stdin = unsupported_stdio::Stdin;
 pub struct Stdout;
-pub struct Stderr;
-struct PanicOutput;
-
-impl Stdin {
-    pub const fn new() -> Stdin {
-        Stdin
-    }
-}
-
-impl io::Read for Stdin {
-    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-        Ok(0)
-    }
-}
+pub type Stderr = Stdout;
 
 impl Stdout {
     pub const fn new() -> Stdout {
@@ -35,46 +26,12 @@ impl io::Write for Stdout {
     }
 }
 
-impl Stderr {
-    pub const fn new() -> Stderr {
-        Stderr
-    }
-}
-
-impl io::Write for Stderr {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) };
-        Ok(buf.len())
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-impl PanicOutput {
-    pub const fn new() -> PanicOutput {
-        PanicOutput
-    }
-}
-
-impl io::Write for PanicOutput {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) };
-        Ok(buf.len())
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
 
 pub fn is_ebadf(_err: &io::Error) -> bool {
     true
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Some(PanicOutput::new())
+    Some(Stderr::new())
 }
diff --git a/library/std/src/sys/stdio/teeos.rs b/library/std/src/sys/stdio/teeos.rs
index 67e251812da..27b3292bf8f 100644
--- a/library/std/src/sys/stdio/teeos.rs
+++ b/library/std/src/sys/stdio/teeos.rs
@@ -1,12 +1,16 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
+#[expect(dead_code)]
+#[path = "unsupported.rs"]
+mod unsupported_stdio;
+
 use core::arch::asm;
 
 use crate::io;
 
-pub struct Stdin;
+pub type Stdin = unsupported_stdio::Stdin;
 pub struct Stdout;
-pub struct Stderr;
+pub type Stderr = Stdout;
 
 const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2;
 
@@ -25,27 +29,6 @@ unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 {
     ret as i32
 }
 
-fn print_buf(s: &[u8]) -> io::Result<usize> {
-    // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`.
-    const MAX_LEN: usize = 512;
-    let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() };
-    let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) };
-
-    if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) }
-}
-
-impl Stdin {
-    pub const fn new() -> Stdin {
-        Stdin
-    }
-}
-
-impl io::Read for Stdin {
-    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-        Ok(0)
-    }
-}
-
 impl Stdout {
     pub const fn new() -> Stdout {
         Stdout
@@ -54,23 +37,13 @@ impl Stdout {
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        print_buf(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
+        // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`.
+        const MAX_LEN: usize = 512;
+        let len = buf.len().min(MAX_LEN);
+        let result =
+            unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, buf.as_ptr() as u64, len as u64) };
 
-impl Stderr {
-    pub const fn new() -> Stderr {
-        Stderr
-    }
-}
-
-impl io::Write for Stderr {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        print_buf(buf)
+        if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) }
     }
 
     fn flush(&mut self) -> io::Result<()> {
@@ -78,7 +51,7 @@ impl io::Write for Stderr {
     }
 }
 
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
 
 pub fn is_ebadf(err: &io::Error) -> bool {
     err.raw_os_error() == Some(libc::EBADF as i32)
diff --git a/library/std/src/sys/stdio/unix.rs b/library/std/src/sys/stdio/unix.rs
index 08a06e0da9f..8535e3539e9 100644
--- a/library/std/src/sys/stdio/unix.rs
+++ b/library/std/src/sys/stdio/unix.rs
@@ -11,13 +11,13 @@ use crate::os::hermit::io::FromRawFd;
 use crate::os::unix::io::FromRawFd;
 use crate::sys::fd::FileDesc;
 
-pub struct Stdin(());
-pub struct Stdout(());
-pub struct Stderr(());
+pub struct Stdin;
+pub struct Stdout;
+pub struct Stderr;
 
 impl Stdin {
     pub const fn new() -> Stdin {
-        Stdin(())
+        Stdin
     }
 }
 
@@ -42,7 +42,7 @@ impl io::Read for Stdin {
 
 impl Stdout {
     pub const fn new() -> Stdout {
-        Stdout(())
+        Stdout
     }
 }
 
@@ -68,7 +68,7 @@ impl io::Write for Stdout {
 
 impl Stderr {
     pub const fn new() -> Stderr {
-        Stderr(())
+        Stderr
     }
 }
 
diff --git a/library/std/src/sys/stdio/unsupported.rs b/library/std/src/sys/stdio/unsupported.rs
index b5e3f5be988..177264f5c10 100644
--- a/library/std/src/sys/stdio/unsupported.rs
+++ b/library/std/src/sys/stdio/unsupported.rs
@@ -1,8 +1,8 @@
-use crate::io;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 
 pub struct Stdin;
 pub struct Stdout;
-pub struct Stderr;
+pub type Stderr = Stdout;
 
 impl Stdin {
     pub const fn new() -> Stdin {
@@ -11,9 +11,47 @@ impl Stdin {
 }
 
 impl io::Read for Stdin {
+    #[inline]
     fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
         Ok(0)
     }
+
+    #[inline]
+    fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        Ok(())
+    }
+
+    #[inline]
+    fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        Ok(0)
+    }
+
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        // Do not force `Chain<Empty, T>` or `Chain<T, Empty>` to use vectored
+        // reads, unless the other reader is vectored.
+        false
+    }
+
+    #[inline]
+    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+        if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
+    }
+
+    #[inline]
+    fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
+    }
+
+    #[inline]
+    fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
+        Ok(0)
+    }
+
+    #[inline]
+    fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
+        Ok(0)
+    }
 }
 
 impl Stdout {
@@ -23,26 +61,35 @@ impl Stdout {
 }
 
 impl io::Write for Stdout {
+    #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         Ok(buf.len())
     }
 
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let total_len = bufs.iter().map(|b| b.len()).sum();
+        Ok(total_len)
     }
-}
 
-impl Stderr {
-    pub const fn new() -> Stderr {
-        Stderr
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
     }
-}
 
-impl io::Write for Stderr {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        Ok(buf.len())
+    #[inline]
+    fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
+        Ok(())
     }
 
+    #[inline]
+    fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
+        Ok(())
+    }
+
+    // Keep the default write_fmt so the `fmt::Arguments` are still evaluated.
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/stdio/xous.rs b/library/std/src/sys/stdio/xous.rs
index 71736145221..a92167642b7 100644
--- a/library/std/src/sys/stdio/xous.rs
+++ b/library/std/src/sys/stdio/xous.rs
@@ -1,27 +1,18 @@
-use crate::io;
-
-pub struct Stdin;
-pub struct Stdout {}
-pub struct Stderr;
+#[expect(dead_code)]
+#[path = "unsupported.rs"]
+mod unsupported_stdio;
 
+use crate::io;
 use crate::os::xous::ffi::{Connection, lend, try_lend, try_scalar};
 use crate::os::xous::services::{LogLend, LogScalar, log_server, try_connect};
 
-impl Stdin {
-    pub const fn new() -> Stdin {
-        Stdin
-    }
-}
-
-impl io::Read for Stdin {
-    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-        Ok(0)
-    }
-}
+pub type Stdin = unsupported_stdio::Stdin;
+pub struct Stdout;
+pub struct Stderr;
 
 impl Stdout {
     pub const fn new() -> Stdout {
-        Stdout {}
+        Stdout
     }
 }
 
@@ -73,7 +64,7 @@ impl io::Write for Stderr {
     }
 }
 
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
 
 pub fn is_ebadf(_err: &io::Error) -> bool {
     true
diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs
index 99b5ad9cb9f..98f471ad54b 100644
--- a/library/std/src/thread/spawnhook.rs
+++ b/library/std/src/thread/spawnhook.rs
@@ -113,18 +113,23 @@ where
 pub(super) fn run_spawn_hooks(thread: &Thread) -> ChildSpawnHooks {
     // Get a snapshot of the spawn hooks.
     // (Increments the refcount to the first node.)
-    let hooks = SPAWN_HOOKS.with(|hooks| {
+    if let Ok(hooks) = SPAWN_HOOKS.try_with(|hooks| {
         let snapshot = hooks.take();
         hooks.set(snapshot.clone());
         snapshot
-    });
-    // Iterate over the hooks, run them, and collect the results in a vector.
-    let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref())
-        .map(|hook| (hook.hook)(thread))
-        .collect();
-    // Pass on the snapshot of the hooks and the results to the new thread,
-    // which will then run SpawnHookResults::run().
-    ChildSpawnHooks { hooks, to_run }
+    }) {
+        // Iterate over the hooks, run them, and collect the results in a vector.
+        let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref())
+            .map(|hook| (hook.hook)(thread))
+            .collect();
+        // Pass on the snapshot of the hooks and the results to the new thread,
+        // which will then run SpawnHookResults::run().
+        ChildSpawnHooks { hooks, to_run }
+    } else {
+        // TLS has been destroyed. Skip running the hooks.
+        // See https://github.com/rust-lang/rust/issues/138696
+        ChildSpawnHooks::default()
+    }
 }
 
 /// The results of running the spawn hooks.
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 06c347af181..59ec48a57d1 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -108,6 +108,7 @@ fn test_is_finished() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_join_panic() {
     match thread::spawn(move || panic!()).join() {
         result::Result::Err(_) => (),
@@ -210,6 +211,7 @@ fn test_simple_newsched_spawn() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_try_panic_message_string_literal() {
     match thread::spawn(move || {
         panic!("static string");
@@ -226,6 +228,7 @@ fn test_try_panic_message_string_literal() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_try_panic_any_message_owned_str() {
     match thread::spawn(move || {
         panic_any("owned string".to_string());
@@ -242,6 +245,7 @@ fn test_try_panic_any_message_owned_str() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_try_panic_any_message_any() {
     match thread::spawn(move || {
         panic_any(Box::new(413u16) as Box<dyn Any + Send>);
@@ -260,6 +264,7 @@ fn test_try_panic_any_message_any() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_try_panic_any_message_unit_struct() {
     struct Juju;
 
diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs
index 74c62720107..88fb448d1eb 100644
--- a/library/std/tests/sync/mutex.rs
+++ b/library/std/tests/sync/mutex.rs
@@ -118,6 +118,7 @@ fn test_into_inner_drop() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_into_inner_poison() {
     let m = new_poisoned_mutex(NonCopy(10));
 
@@ -135,6 +136,7 @@ fn test_get_cloned() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_get_cloned_poison() {
     let m = new_poisoned_mutex(Cloneable(10));
 
@@ -152,6 +154,7 @@ fn test_get_mut() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_get_mut_poison() {
     let mut m = new_poisoned_mutex(NonCopy(10));
 
@@ -179,6 +182,7 @@ fn test_set() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_set_poison() {
     fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
     where
@@ -217,6 +221,7 @@ fn test_replace() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_replace_poison() {
     fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
     where
@@ -261,6 +266,7 @@ fn test_mutex_arc_condvar() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_arc_condvar_poison() {
     let packet = Packet(Arc::new((Mutex::new(1), Condvar::new())));
     let packet2 = Packet(packet.0.clone());
@@ -290,6 +296,7 @@ fn test_arc_condvar_poison() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_mutex_arc_poison() {
     let arc = Arc::new(Mutex::new(1));
     assert!(!arc.is_poisoned());
@@ -304,6 +311,7 @@ fn test_mutex_arc_poison() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_mutex_arc_poison_mapped() {
     let arc = Arc::new(Mutex::new(1));
     assert!(!arc.is_poisoned());
@@ -335,6 +343,7 @@ fn test_mutex_arc_nested() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_mutex_arc_access_in_unwind() {
     let arc = Arc::new(Mutex::new(1));
     let arc2 = arc.clone();
@@ -381,6 +390,7 @@ fn test_mapping_mapped_guard() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn panic_while_mapping_unlocked_poison() {
     let lock = Mutex::new(());
 
diff --git a/library/std/tests/sync/once.rs b/library/std/tests/sync/once.rs
index a3ffc73fe06..1b43831df3a 100644
--- a/library/std/tests/sync/once.rs
+++ b/library/std/tests/sync/once.rs
@@ -52,6 +52,7 @@ fn stampede_once() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn poison_bad() {
     static O: Once = Once::new();
 
@@ -80,6 +81,7 @@ fn poison_bad() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn wait_for_force_to_finish() {
     static O: Once = Once::new();
 
@@ -137,6 +139,7 @@ fn wait() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn wait_on_poisoned() {
     let once = Once::new();
 
@@ -145,6 +148,7 @@ fn wait_on_poisoned() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn wait_force_on_poisoned() {
     let once = Once::new();
 
diff --git a/library/std/tests/sync/once_lock.rs b/library/std/tests/sync/once_lock.rs
index ac9aaa8892e..922fd7da3d4 100644
--- a/library/std/tests/sync/once_lock.rs
+++ b/library/std/tests/sync/once_lock.rs
@@ -77,8 +77,10 @@ fn get_or_try_init() {
     let cell: OnceLock<String> = OnceLock::new();
     assert!(cell.get().is_none());
 
-    let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
-    assert!(res.is_err());
+    if cfg!(panic = "unwind") {
+        let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
+        assert!(res.is_err());
+    }
     assert!(cell.get().is_none());
 
     assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs
index 49f260648c6..d2c784aefcf 100644
--- a/library/std/tests/sync/rwlock.rs
+++ b/library/std/tests/sync/rwlock.rs
@@ -73,6 +73,7 @@ fn frob() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_poison_wr() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -85,6 +86,7 @@ fn test_rw_arc_poison_wr() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_poison_mapped_w_r() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -98,6 +100,7 @@ fn test_rw_arc_poison_mapped_w_r() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_poison_ww() {
     let arc = Arc::new(RwLock::new(1));
     assert!(!arc.is_poisoned());
@@ -112,6 +115,7 @@ fn test_rw_arc_poison_ww() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_poison_mapped_w_w() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -126,6 +130,7 @@ fn test_rw_arc_poison_mapped_w_w() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_no_poison_rr() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -139,6 +144,7 @@ fn test_rw_arc_no_poison_rr() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_no_poison_mapped_r_r() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -153,6 +159,7 @@ fn test_rw_arc_no_poison_mapped_r_r() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_no_poison_rw() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -166,6 +173,7 @@ fn test_rw_arc_no_poison_rw() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_no_poison_mapped_r_w() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -218,6 +226,7 @@ fn test_rw_arc() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_rw_arc_access_in_unwind() {
     let arc = Arc::new(RwLock::new(1));
     let arc2 = arc.clone();
@@ -316,6 +325,7 @@ fn test_into_inner_drop() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_into_inner_poison() {
     let m = new_poisoned_rwlock(NonCopy(10));
 
@@ -333,6 +343,7 @@ fn test_get_cloned() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_get_cloned_poison() {
     let m = new_poisoned_rwlock(Cloneable(10));
 
@@ -350,6 +361,7 @@ fn test_get_mut() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_get_mut_poison() {
     let mut m = new_poisoned_rwlock(NonCopy(10));
 
@@ -377,6 +389,7 @@ fn test_set() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_set_poison() {
     fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
     where
@@ -415,6 +428,7 @@ fn test_replace() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_replace_poison() {
     fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T)
     where
@@ -482,6 +496,7 @@ fn test_mapping_mapped_guard() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn panic_while_mapping_read_unlocked_no_poison() {
     let lock = RwLock::new(());
 
@@ -551,6 +566,7 @@ fn panic_while_mapping_read_unlocked_no_poison() {
 }
 
 #[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn panic_while_mapping_write_unlocked_poison() {
     let lock = RwLock::new(());
 
diff --git a/rustfmt.toml b/rustfmt.toml
index 8feeb60ca12..c884a33729c 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -49,7 +49,6 @@ 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",
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 890e64e2bab..17ee4d610f9 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -88,9 +88,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.1.22"
+version = "1.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
 dependencies = [
  "shlex",
 ]
@@ -150,9 +150,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
 
 [[package]]
 name = "cmake"
-version = "0.1.48"
+version = "0.1.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a"
+checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
 dependencies = [
  "cc",
 ]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index d3e2b9e05e9..23aa87a7407 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -32,10 +32,8 @@ test = false
 # Most of the time updating these dependencies requires modifications to the
 # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
 # otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
-#
-# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
-cc = "=1.1.22"
-cmake = "=0.1.48"
+cc = "=1.2.17"
+cmake = "=0.1.54"
 
 build_helper = { path = "../build_helper" }
 clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 68400ba0ea0..140f601253c 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1162,6 +1162,30 @@ class RustBuild(object):
         config = self.get_toml("build")
         return config or default_build_triple(self.verbose)
 
+    def is_git_repository(self, repo_path):
+        return os.path.isdir(os.path.join(repo_path, ".git"))
+
+    def get_latest_commit(self):
+        repo_path = self.rust_root
+        author_email = self.stage0_data.get("git_merge_commit_email")
+        if not self.is_git_repository(repo_path):
+            return "<commit>"
+        cmd = [
+            "git",
+            "-C",
+            repo_path,
+            "rev-list",
+            "--author",
+            author_email,
+            "-n1",
+            "HEAD",
+        ]
+        try:
+            commit = subprocess.check_output(cmd, universal_newlines=True).strip()
+            return commit or "<commit>"
+        except subprocess.CalledProcessError:
+            return "<commit>"
+
     def check_vendored_status(self):
         """Check that vendoring is configured properly"""
         # keep this consistent with the equivalent check in bootstrap:
@@ -1174,7 +1198,8 @@ class RustBuild(object):
                 eprint("      use vendored sources by default.")
 
         cargo_dir = os.path.join(self.rust_root, ".cargo")
-        url = "https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz"
+        commit = self.get_latest_commit()
+        url = f"https://ci-artifacts.rust-lang.org/rustc-builds/{commit}/rustc-nightly-src.tar.xz"
         if self.use_vendored_sources:
             vendor_dir = os.path.join(self.rust_root, "vendor")
             if not os.path.exists(vendor_dir):
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index f6afe096724..0d4d6e0ff54 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -250,6 +250,11 @@ v(
     "mips64el-unknown-linux-muslabi64 install directory",
 )
 v(
+    "musl-root-powerpc64",
+    "target.powerpc64-unknown-linux-musl.musl-root",
+    "powerpc64-unknown-linux-musl install directory",
+)
+v(
     "musl-root-powerpc64le",
     "target.powerpc64le-unknown-linux-musl.musl-root",
     "powerpc64le-unknown-linux-musl install directory",
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index d2c0d380fb4..e157ff233bb 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/134740
+Last change is for: https://github.com/rust-lang/rust/pull/138784
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 443131dc7f3..cbfe00a757c 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -11,8 +11,8 @@ use std::str::FromStr;
 use std::{env, process};
 
 use bootstrap::{
-    Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids,
-    human_readable_changes, t,
+    Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug,
+    find_recent_config_change_ids, human_readable_changes, t,
 };
 #[cfg(feature = "tracing")]
 use tracing::instrument;
@@ -155,50 +155,52 @@ fn check_version(config: &Config) -> Option<String> {
     let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
     let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");
 
-    if let Some(mut id) = config.change_id {
-        if id == latest_change_id {
-            return None;
+    let mut id = match config.change_id {
+        Some(ChangeId::Id(id)) if id == latest_change_id => return None,
+        Some(ChangeId::Ignore) => return None,
+        Some(ChangeId::Id(id)) => id,
+        None => {
+            msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
+            msg.push_str("NOTE: to silence this warning, ");
+            msg.push_str(&format!(
+                "add `change-id = {latest_change_id}` or change-id = \"ignore\" at the top of `bootstrap.toml`"
+            ));
+            return Some(msg);
         }
+    };
 
-        // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
-        // then use the one from the bootstrap.toml. This way we never show the same warnings
-        // more than once.
-        if let Ok(t) = fs::read_to_string(&warned_id_path) {
-            let last_warned_id = usize::from_str(&t)
-                .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
-
-            // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
-            // Otherwise, we may retrieve all the changes if it's not the highest value.
-            // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
-            if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
-                id = last_warned_id;
-            }
-        };
+    // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
+    // then use the one from the bootstrap.toml. This way we never show the same warnings
+    // more than once.
+    if let Ok(t) = fs::read_to_string(&warned_id_path) {
+        let last_warned_id = usize::from_str(&t)
+            .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));
+
+        // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
+        // Otherwise, we may retrieve all the changes if it's not the highest value.
+        // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
+        if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
+            id = last_warned_id;
+        }
+    };
 
-        let changes = find_recent_config_change_ids(id);
+    let changes = find_recent_config_change_ids(id);
 
-        if changes.is_empty() {
-            return None;
-        }
+    if changes.is_empty() {
+        return None;
+    }
 
-        msg.push_str("There have been changes to x.py since you last updated:\n");
-        msg.push_str(&human_readable_changes(&changes));
+    msg.push_str("There have been changes to x.py since you last updated:\n");
+    msg.push_str(&human_readable_changes(changes));
 
-        msg.push_str("NOTE: to silence this warning, ");
-        msg.push_str(&format!(
-            "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead"
-        ));
+    msg.push_str("NOTE: to silence this warning, ");
+    msg.push_str(&format!(
+        "update `bootstrap.toml` to use `change-id = {latest_change_id}` or change-id = \"ignore\" instead"
+    ));
 
-        if io::stdout().is_terminal() {
-            t!(fs::write(warned_id_path, latest_change_id.to_string()));
-        }
-    } else {
-        msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
-        msg.push_str("NOTE: to silence this warning, ");
-        msg.push_str(&format!(
-            "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`"
-        ));
-    };
+    if io::stdout().is_terminal() {
+        t!(fs::write(warned_id_path, latest_change_id.to_string()));
+    }
 
     Some(msg)
 }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 846b4de8142..18b5d4426b1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -33,7 +33,7 @@ use crate::utils::exec::command;
 use crate::utils::helpers::{
     exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
 };
-use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
+use crate::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
 
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Std {
@@ -321,7 +321,7 @@ fn copy_and_stamp(
     dependency_type: DependencyType,
 ) {
     let target = libdir.join(name);
-    builder.copy_link(&sourcedir.join(name), &target);
+    builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
 
     target_deps.push((target, dependency_type));
 }
@@ -330,7 +330,7 @@ fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &
     let libunwind_path = builder.ensure(llvm::Libunwind { target });
     let libunwind_source = libunwind_path.join("libunwind.a");
     let libunwind_target = libdir.join("libunwind.a");
-    builder.copy_link(&libunwind_source, &libunwind_target);
+    builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
     libunwind_target
 }
 
@@ -401,7 +401,7 @@ fn copy_self_contained_objects(
             for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
                 let src = crt_path.join(obj);
                 let target = libdir_self_contained.join(obj);
-                builder.copy_link(&src, &target);
+                builder.copy_link(&src, &target, FileType::NativeLibrary);
                 target_deps.push((target, DependencyType::TargetSelfContained));
             }
         } else {
@@ -443,9 +443,9 @@ fn copy_self_contained_objects(
     } else if target.is_windows_gnu() {
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
             let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
-            let target = libdir_self_contained.join(obj);
-            builder.copy_link(&src, &target);
-            target_deps.push((target, DependencyType::TargetSelfContained));
+            let dst = libdir_self_contained.join(obj);
+            builder.copy_link(&src, &dst, FileType::NativeLibrary);
+            target_deps.push((dst, DependencyType::TargetSelfContained));
         }
     }
 
@@ -790,8 +790,11 @@ impl Step for StdLink {
                     let file = t!(file);
                     let path = file.path();
                     if path.is_file() {
-                        builder
-                            .copy_link(&path, &sysroot.join("lib").join(path.file_name().unwrap()));
+                        builder.copy_link(
+                            &path,
+                            &sysroot.join("lib").join(path.file_name().unwrap()),
+                            FileType::Regular,
+                        );
                     }
                 }
             }
@@ -829,7 +832,7 @@ fn copy_sanitizers(
 
     for runtime in &runtimes {
         let dst = libdir.join(&runtime.name);
-        builder.copy_link(&runtime.path, &dst);
+        builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
 
         // The `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` are also supported for
         // sanitizers, but they share a sanitizer runtime with `${arch}-apple-darwin`, so we do
@@ -934,9 +937,9 @@ impl Step for StartupObjects {
                     .run(builder);
             }
 
-            let target = sysroot_dir.join((*file).to_string() + ".o");
-            builder.copy_link(dst_file, &target);
-            target_deps.push((target, DependencyType::Target));
+            let obj = sysroot_dir.join((*file).to_string() + ".o");
+            builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
+            target_deps.push((obj, DependencyType::Target));
         }
 
         target_deps
@@ -952,7 +955,7 @@ fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, conte
         if src.is_dir() {
             t!(fs::create_dir_all(dst));
         } else {
-            builder.copy_link(&src, &dst);
+            builder.copy_link(&src, &dst, FileType::Regular);
         }
     }
 }
@@ -1707,7 +1710,7 @@ fn copy_codegen_backends_to_sysroot(
             let dot = filename.find('.').unwrap();
             format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
         };
-        builder.copy_link(file, &dst.join(target_filename));
+        builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
     }
 }
 
@@ -2011,7 +2014,11 @@ impl Step for Assemble {
                         extra_features: vec![],
                     });
                 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
-                builder.copy_link(&llvm_bitcode_linker.tool_path, &libdir_bin.join(tool_exe));
+                builder.copy_link(
+                    &llvm_bitcode_linker.tool_path,
+                    &libdir_bin.join(tool_exe),
+                    FileType::Executable,
+                );
             }
         };
 
@@ -2072,8 +2079,8 @@ impl Step for Assemble {
                 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
             let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
             let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
-            builder.copy_link(&src_lib, &dst_lib);
-            builder.copy_link(&src_lib, &target_dst_lib);
+            builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
+            builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
         }
 
         // Build the libraries for this compiler to link to (i.e., the libraries
@@ -2168,7 +2175,7 @@ impl Step for Assemble {
             };
 
             if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
-                builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
+                builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
             }
         }
 
@@ -2196,7 +2203,11 @@ impl Step for Assemble {
             // See <https://github.com/rust-lang/rust/issues/132719>.
             let src_exe = exe("llvm-objcopy", target_compiler.host);
             let dst_exe = exe("rust-objcopy", target_compiler.host);
-            builder.copy_link(&libdir_bin.join(src_exe), &libdir_bin.join(dst_exe));
+            builder.copy_link(
+                &libdir_bin.join(src_exe),
+                &libdir_bin.join(dst_exe),
+                FileType::Executable,
+            );
         }
 
         // In addition to `rust-lld` also install `wasm-component-ld` when
@@ -2212,6 +2223,7 @@ impl Step for Assemble {
             builder.copy_link(
                 &wasm_component.tool_path,
                 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
+                FileType::Executable,
             );
         }
 
@@ -2234,7 +2246,7 @@ impl Step for Assemble {
         t!(fs::create_dir_all(bindir));
         let compiler = builder.rustc(target_compiler);
         debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
-        builder.copy_link(&rustc, &compiler);
+        builder.copy_link(&rustc, &compiler, FileType::Executable);
 
         target_compiler
     }
@@ -2260,7 +2272,7 @@ pub fn add_to_sysroot(
             DependencyType::Target => sysroot_dst,
             DependencyType::TargetSelfContained => self_contained_dst,
         };
-        builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
+        builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 39f9680cb2f..83f71aeed72 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -32,7 +32,7 @@ use crate::utils::helpers::{
     exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
 };
 use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
-use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode, trace};
+use crate::{Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
 
 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
     format!("{}-{}", component, builder.rust_package_vers())
@@ -81,7 +81,7 @@ impl Step for Docs {
         let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
         tarball.set_product_name("Rust Documentation");
         tarball.add_bulk_dir(builder.doc_out(host), dest);
-        tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, 0o644);
+        tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
         Some(tarball.generate())
     }
 }
@@ -418,7 +418,7 @@ impl Step for Rustc {
                 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
             {
                 let rustdoc = builder.rustdoc(compiler);
-                builder.install(&rustdoc, &image.join("bin"), 0o755);
+                builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
             }
 
             if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
@@ -432,7 +432,8 @@ impl Step for Rustc {
                 },
                 builder.kind,
             ) {
-                builder.install(&ra_proc_macro_srv.tool_path, &image.join("libexec"), 0o755);
+                let dst = image.join("libexec");
+                builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
             }
 
             let libdir_relative = builder.libdir_relative(compiler);
@@ -444,7 +445,7 @@ impl Step for Rustc {
                     if is_dylib(&entry.path()) {
                         // Don't use custom libdir here because ^lib/ will be resolved again
                         // with installer
-                        builder.install(&entry.path(), &image.join("lib"), 0o644);
+                        builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
                     }
                 }
             }
@@ -463,7 +464,11 @@ impl Step for Rustc {
             if builder.config.lld_enabled {
                 let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let rust_lld = exe("rust-lld", compiler.host);
-                builder.copy_link(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
+                builder.copy_link(
+                    &src_dir.join(&rust_lld),
+                    &dst_dir.join(&rust_lld),
+                    FileType::Executable,
+                );
                 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
                 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&self_contained_lld_dst_dir));
@@ -472,6 +477,7 @@ impl Step for Rustc {
                     builder.copy_link(
                         &self_contained_lld_src_dir.join(&exe_name),
                         &self_contained_lld_dst_dir.join(&exe_name),
+                        FileType::Executable,
                     );
                 }
             }
@@ -480,13 +486,17 @@ impl Step for Rustc {
                 let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let llvm_objcopy = exe("llvm-objcopy", compiler.host);
                 let rust_objcopy = exe("rust-objcopy", compiler.host);
-                builder.copy_link(&src_dir.join(&llvm_objcopy), &dst_dir.join(&rust_objcopy));
+                builder.copy_link(
+                    &src_dir.join(&llvm_objcopy),
+                    &dst_dir.join(&rust_objcopy),
+                    FileType::Executable,
+                );
             }
 
             if builder.tool_enabled("wasm-component-ld") {
                 let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let ld = exe("wasm-component-ld", compiler.host);
-                builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
+                builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
             }
 
             // Man pages
@@ -511,15 +521,19 @@ impl Step for Rustc {
             // HTML copyright files
             let file_list = builder.ensure(super::run::GenerateCopyright);
             for file in file_list {
-                builder.install(&file, &image.join("share/doc/rust"), 0o644);
+                builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
             }
 
             // README
-            builder.install(&builder.src.join("README.md"), &image.join("share/doc/rust"), 0o644);
+            builder.install(
+                &builder.src.join("README.md"),
+                &image.join("share/doc/rust"),
+                FileType::Regular,
+            );
 
             // The REUSE-managed license files
             let license = |path: &Path| {
-                builder.install(path, &image.join("share/doc/rust/licenses"), 0o644);
+                builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
             };
             for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
                 license(&entry.path());
@@ -548,14 +562,14 @@ impl Step for DebuggerScripts {
         let dst = sysroot.join("lib/rustlib/etc");
         t!(fs::create_dir_all(&dst));
         let cp_debugger_script = |file: &str| {
-            builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
+            builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
         };
         if host.contains("windows-msvc") {
             // windbg debugger scripts
             builder.install(
                 &builder.src.join("src/etc/rust-windbg.cmd"),
                 &sysroot.join("bin"),
-                0o755,
+                FileType::Script,
             );
 
             cp_debugger_script("natvis/intrinsic.natvis");
@@ -567,15 +581,27 @@ impl Step for DebuggerScripts {
         cp_debugger_script("rust_types.py");
 
         // gdb debugger scripts
-        builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
-        builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
+        builder.install(
+            &builder.src.join("src/etc/rust-gdb"),
+            &sysroot.join("bin"),
+            FileType::Script,
+        );
+        builder.install(
+            &builder.src.join("src/etc/rust-gdbgui"),
+            &sysroot.join("bin"),
+            FileType::Script,
+        );
 
         cp_debugger_script("gdb_load_rust_pretty_printers.py");
         cp_debugger_script("gdb_lookup.py");
         cp_debugger_script("gdb_providers.py");
 
         // lldb debugger scripts
-        builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
+        builder.install(
+            &builder.src.join("src/etc/rust-lldb"),
+            &sysroot.join("bin"),
+            FileType::Script,
+        );
 
         cp_debugger_script("lldb_lookup.py");
         cp_debugger_script("lldb_providers.py");
@@ -640,9 +666,13 @@ fn copy_target_libs(
     t!(fs::create_dir_all(&self_contained_dst));
     for (path, dependency_type) in builder.read_stamp_file(stamp) {
         if dependency_type == DependencyType::TargetSelfContained {
-            builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
+            builder.copy_link(
+                &path,
+                &self_contained_dst.join(path.file_name().unwrap()),
+                FileType::NativeLibrary,
+            );
         } else if dependency_type == DependencyType::Target || builder.is_builder_target(target) {
-            builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
+            builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
         }
     }
 }
@@ -750,7 +780,11 @@ impl Step for RustcDev {
             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
         );
         for file in src_files {
-            tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
+            tarball.add_file(
+                builder.src.join(file),
+                "lib/rustlib/rustc-src/rust",
+                FileType::Regular,
+            );
         }
 
         Some(tarball.generate())
@@ -1045,7 +1079,11 @@ impl Step for PlainSourceTarball {
 
         // Copy the files normally
         for item in &src_files {
-            builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item));
+            builder.copy_link(
+                &builder.src.join(item),
+                &plain_dst_src.join(item),
+                FileType::Regular,
+            );
         }
 
         // Create the version file
@@ -1147,9 +1185,14 @@ impl Step for Cargo {
         let mut tarball = Tarball::new(builder, "cargo", &target.triple);
         tarball.set_overlay(OverlayKind::Cargo);
 
-        tarball.add_file(cargo.tool_path, "bin", 0o755);
-        tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
-        tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
+        tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
+        tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
+        tarball.add_renamed_file(
+            etc.join("cargo.bashcomp.sh"),
+            "etc/bash_completion.d",
+            "cargo",
+            FileType::Regular,
+        );
         tarball.add_dir(etc.join("man"), "share/man/man1");
         tarball.add_legal_and_readme_to("share/doc/cargo");
 
@@ -1193,7 +1236,7 @@ impl Step for RustAnalyzer {
         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
         tarball.set_overlay(OverlayKind::RustAnalyzer);
         tarball.is_preview(true);
-        tarball.add_file(rust_analyzer.tool_path, "bin", 0o755);
+        tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
         tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
         Some(tarball.generate())
     }
@@ -1239,8 +1282,8 @@ impl Step for Clippy {
         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
         tarball.set_overlay(OverlayKind::Clippy);
         tarball.is_preview(true);
-        tarball.add_file(clippy.tool_path, "bin", 0o755);
-        tarball.add_file(cargoclippy.tool_path, "bin", 0o755);
+        tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
+        tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
         tarball.add_legal_and_readme_to("share/doc/clippy");
         Some(tarball.generate())
     }
@@ -1289,8 +1332,8 @@ impl Step for Miri {
         let mut tarball = Tarball::new(builder, "miri", &target.triple);
         tarball.set_overlay(OverlayKind::Miri);
         tarball.is_preview(true);
-        tarball.add_file(miri.tool_path, "bin", 0o755);
-        tarball.add_file(cargomiri.tool_path, "bin", 0o755);
+        tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
+        tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
         tarball.add_legal_and_readme_to("share/doc/miri");
         Some(tarball.generate())
     }
@@ -1374,7 +1417,11 @@ impl Step for CodegenBackend {
         for backend in fs::read_dir(&backends_src).unwrap() {
             let file_name = backend.unwrap().file_name();
             if file_name.to_str().unwrap().contains(&backend_name) {
-                tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644);
+                tarball.add_file(
+                    backends_src.join(file_name),
+                    &backends_dst,
+                    FileType::NativeLibrary,
+                );
                 found_backend = true;
             }
         }
@@ -1420,8 +1467,8 @@ impl Step for Rustfmt {
         let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
         tarball.set_overlay(OverlayKind::Rustfmt);
         tarball.is_preview(true);
-        tarball.add_file(rustfmt.tool_path, "bin", 0o755);
-        tarball.add_file(cargofmt.tool_path, "bin", 0o755);
+        tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
+        tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
         tarball.add_legal_and_readme_to("share/doc/rustfmt");
         Some(tarball.generate())
     }
@@ -1578,27 +1625,33 @@ impl Step for Extended {
                     &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
                     &pkg.join(name),
                 );
-                builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
+                builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
                 pkgbuild(name);
             };
             prepare("rustc");
             prepare("cargo");
             prepare("rust-std");
             prepare("rust-analysis");
-            prepare("clippy");
-            prepare("rust-analyzer");
-            for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] {
+
+            for tool in &[
+                "clippy",
+                "rustfmt",
+                "rust-analyzer",
+                "rust-docs",
+                "miri",
+                "rustc-codegen-cranelift",
+            ] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
             }
             // create an 'uninstall' package
-            builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
+            builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
             pkgbuild("uninstall");
 
             builder.create_dir(&pkg.join("res"));
             builder.create(&pkg.join("res/LICENSE.txt"), &license);
-            builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
+            builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
             let mut cmd = command("productbuild");
             cmd.arg("--distribution")
                 .arg(xform(&etc.join("pkg/Distribution.xml")))
@@ -1627,6 +1680,8 @@ impl Step for Extended {
                     "rust-analyzer-preview".to_string()
                 } else if name == "clippy" {
                     "clippy-preview".to_string()
+                } else if name == "rustfmt" {
+                    "rustfmt-preview".to_string()
                 } else if name == "miri" {
                     "miri-preview".to_string()
                 } else if name == "rustc-codegen-cranelift" {
@@ -1646,7 +1701,7 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-analysis");
             prepare("rust-std");
-            for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] {
+            for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1655,7 +1710,7 @@ impl Step for Extended {
                 prepare("rust-mingw");
             }
 
-            builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
+            builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
 
             // Generate msi installer
             let wix_path = env::var_os("WIX")
@@ -1764,6 +1819,24 @@ impl Step for Extended {
                     .arg(etc.join("msi/remove-duplicates.xsl"))
                     .run(builder);
             }
+            if built_tools.contains("rustfmt") {
+                command(&heat)
+                    .current_dir(&exe)
+                    .arg("dir")
+                    .arg("rustfmt")
+                    .args(heat_flags)
+                    .arg("-cg")
+                    .arg("RustFmtGroup")
+                    .arg("-dr")
+                    .arg("RustFmt")
+                    .arg("-var")
+                    .arg("var.RustFmtDir")
+                    .arg("-out")
+                    .arg(exe.join("RustFmtGroup.wxs"))
+                    .arg("-t")
+                    .arg(etc.join("msi/remove-duplicates.xsl"))
+                    .run(builder);
+            }
             if built_tools.contains("miri") {
                 command(&heat)
                     .current_dir(&exe)
@@ -1830,11 +1903,14 @@ impl Step for Extended {
                     .arg("-out")
                     .arg(&output)
                     .arg(input);
-                add_env(builder, &mut cmd, target);
+                add_env(builder, &mut cmd, target, &built_tools);
 
                 if built_tools.contains("clippy") {
                     cmd.arg("-dClippyDir=clippy");
                 }
+                if built_tools.contains("rustfmt") {
+                    cmd.arg("-dRustFmtDir=rustfmt");
+                }
                 if built_tools.contains("rust-docs") {
                     cmd.arg("-dDocsDir=rust-docs");
                 }
@@ -1861,6 +1937,9 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 candle("ClippyGroup.wxs".as_ref());
             }
+            if built_tools.contains("rustfmt") {
+                candle("RustFmtGroup.wxs".as_ref());
+            }
             if built_tools.contains("miri") {
                 candle("MiriGroup.wxs".as_ref());
             }
@@ -1874,8 +1953,8 @@ impl Step for Extended {
             }
 
             builder.create(&exe.join("LICENSE.rtf"), &rtf);
-            builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
-            builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
+            builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
+            builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
 
             builder.info(&format!("building `msi` installer with {light:?}"));
             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
@@ -1899,6 +1978,9 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 cmd.arg("ClippyGroup.wixobj");
             }
+            if built_tools.contains("rustfmt") {
+                cmd.arg("RustFmtGroup.wixobj");
+            }
             if built_tools.contains("miri") {
                 cmd.arg("MiriGroup.wixobj");
             }
@@ -1925,7 +2007,12 @@ impl Step for Extended {
     }
 }
 
-fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSelection) {
+fn add_env(
+    builder: &Builder<'_>,
+    cmd: &mut BootstrapCommand,
+    target: TargetSelection,
+    built_tools: &HashSet<&'static str>,
+) {
     let mut parts = builder.version.split('.');
     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
         .env("CFG_RELEASE_NUM", &builder.version)
@@ -1946,6 +2033,15 @@ fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSele
     } else {
         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
     }
+
+    // ensure these variables are defined
+    let mut define_optional_tool = |tool_name: &str, env_name: &str| {
+        cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
+    };
+    define_optional_tool("rustfmt", "CFG_RUSTFMT");
+    define_optional_tool("clippy", "CFG_CLIPPY");
+    define_optional_tool("miri", "CFG_MIRI");
+    define_optional_tool("rust-analyzer", "CFG_RA");
 }
 
 fn install_llvm_file(
@@ -1961,13 +2057,13 @@ fn install_llvm_file(
     if source.is_symlink() {
         // If we have a symlink like libLLVM-18.so -> libLLVM.so.18.1, install the target of the
         // symlink, which is what will actually get loaded at runtime.
-        builder.install(&t!(fs::canonicalize(source)), destination, 0o644);
+        builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
 
         let full_dest = destination.join(source.file_name().unwrap());
         if install_symlink {
             // For download-ci-llvm, also install the symlink, to match what LLVM does. Using a
             // symlink is fine here, as this is not a rustup component.
-            builder.copy_link(source, &full_dest);
+            builder.copy_link(source, &full_dest, FileType::NativeLibrary);
         } else {
             // Otherwise, replace the symlink with an equivalent linker script. This is used when
             // projects like miri link against librustc_driver.so. We don't use a symlink, as
@@ -1984,7 +2080,7 @@ fn install_llvm_file(
             }
         }
     } else {
-        builder.install(source, destination, 0o644);
+        builder.install(source, destination, FileType::NativeLibrary);
     }
 }
 
@@ -2036,7 +2132,7 @@ fn maybe_install_llvm(
         let src_libdir = builder.llvm_out(target).join("lib");
         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
         if llvm_dylib_path.exists() {
-            builder.install(&llvm_dylib_path, dst_libdir, 0o644);
+            builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
         }
         !builder.config.dry_run()
     } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
@@ -2186,7 +2282,7 @@ impl Step for LlvmTools {
             let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
             for tool in tools_to_install(&builder.paths) {
                 let exe = src_bindir.join(exe(tool, target));
-                tarball.add_file(&exe, &dst_bindir, 0o755);
+                tarball.add_file(&exe, &dst_bindir, FileType::Executable);
             }
         }
 
@@ -2241,7 +2337,7 @@ impl Step for LlvmBitcodeLinker {
         tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
         tarball.is_preview(true);
 
-        tarball.add_file(llbc_linker.tool_path, self_contained_bin_dir, 0o755);
+        tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
 
         Some(tarball.generate())
     }
@@ -2302,7 +2398,7 @@ impl Step for RustDev {
                 let entry = t!(entry);
                 if entry.file_type().is_file() && !entry.path_is_symlink() {
                     let name = entry.file_name().to_str().unwrap();
-                    tarball.add_file(src_bindir.join(name), "bin", 0o755);
+                    tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
                 }
             }
         }
@@ -2314,11 +2410,11 @@ impl Step for RustDev {
             // We don't build LLD on some platforms, so only add it if it exists
             let lld_path = lld_out.join("bin").join(exe("lld", target));
             if lld_path.exists() {
-                tarball.add_file(lld_path, "bin", 0o755);
+                tarball.add_file(&lld_path, "bin", FileType::Executable);
             }
         }
 
-        tarball.add_file(builder.llvm_filecheck(target), "bin", 0o755);
+        tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
 
         // Copy the include directory as well; needed mostly to build
         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
@@ -2379,7 +2475,11 @@ impl Step for Bootstrap {
 
         let bootstrap_outdir = &builder.bootstrap_out;
         for file in &["bootstrap", "rustc", "rustdoc"] {
-            tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755);
+            tarball.add_file(
+                bootstrap_outdir.join(exe(file, target)),
+                "bootstrap/bin",
+                FileType::Executable,
+            );
         }
 
         Some(tarball.generate())
@@ -2412,7 +2512,7 @@ impl Step for BuildManifest {
         let build_manifest = builder.tool_exe(Tool::BuildManifest);
 
         let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
-        tarball.add_file(build_manifest, "bin", 0o755);
+        tarball.add_file(&build_manifest, "bin", FileType::Executable);
         tarball.generate()
     }
 }
@@ -2444,15 +2544,15 @@ impl Step for ReproducibleArtifacts {
         let mut added_anything = false;
         let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
         if let Some(path) = builder.config.rust_profile_use.as_ref() {
-            tarball.add_file(path, ".", 0o644);
+            tarball.add_file(path, ".", FileType::Regular);
             added_anything = true;
         }
         if let Some(path) = builder.config.llvm_profile_use.as_ref() {
-            tarball.add_file(path, ".", 0o644);
+            tarball.add_file(path, ".", FileType::Regular);
             added_anything = true;
         }
         for profile in &builder.config.reproducible_artifacts {
-            tarball.add_file(profile, ".", 0o644);
+            tarball.add_file(profile, ".", FileType::Regular);
             added_anything = true;
         }
         if added_anything { Some(tarball.generate()) } else { None }
@@ -2481,7 +2581,7 @@ impl Step for Gcc {
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let tarball = Tarball::new(builder, "gcc", &self.target.triple);
         let output = builder.ensure(super::gcc::Gcc { target: self.target });
-        tarball.add_file(output.libgccjit, "lib", 0o644);
+        tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
         tarball.generate()
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index a8da4146100..7fccf85a0ea 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -11,7 +11,6 @@ use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 use std::{env, fs, mem};
 
-use crate::Mode;
 use crate::core::build_steps::compile;
 use crate::core::build_steps::tool::{self, SourceType, Tool, prepare_tool_cargo};
 use crate::core::builder::{
@@ -19,6 +18,7 @@ use crate::core::builder::{
 };
 use crate::core::config::{Config, TargetSelection};
 use crate::helpers::{submodule_path_of, symlink_dir, t, up_to_date};
+use crate::{FileType, Mode};
 
 macro_rules! book {
     ($($name:ident, $path:expr, $book_name:expr, $lang:expr ;)+) => {
@@ -546,6 +546,7 @@ impl Step for SharedAssets {
         builder.copy_link(
             &builder.src.join("src").join("doc").join("rust.css"),
             &out.join("rust.css"),
+            FileType::Regular,
         );
 
         SharedAssetsPaths { version_info }
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 840841b0939..b1a97bde97b 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -31,7 +31,7 @@ fn rustfmt(
     // Avoid the submodule config paths from coming into play. We only allow a single global config
     // for the workspace for now.
     cmd.arg("--config-path").arg(src.canonicalize().unwrap());
-    cmd.arg("--edition").arg("2021");
+    cmd.arg("--edition").arg("2024");
     cmd.arg("--unstable-features");
     cmd.arg("--skip-children");
     if check {
@@ -93,7 +93,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, Str
         return Ok(None);
     }
 
-    get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"])
+    get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]).map(Some)
 }
 
 #[derive(serde_derive::Deserialize)]
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index b88a5f2bbf1..48bb5cb8e87 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -273,7 +273,7 @@ fn detect_gcc_sha(config: &crate::Config, is_git: bool) -> String {
         get_closest_merge_commit(
             Some(&config.src),
             &config.git_config(),
-            &[config.src.join("src/gcc"), config.src.join("src/bootstrap/download-ci-gcc-stamp")],
+            &["src/gcc", "src/bootstrap/download-ci-gcc-stamp"],
         )
         .unwrap()
     } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 0ae5256a18f..e21804fa3c0 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -14,7 +14,6 @@ use std::path::{Path, PathBuf};
 use std::sync::OnceLock;
 use std::{env, fs};
 
-use build_helper::ci::CiEnv;
 use build_helper::git::get_closest_merge_commit;
 #[cfg(feature = "tracing")]
 use tracing::instrument;
@@ -174,20 +173,19 @@ pub fn prebuilt_llvm_config(
     LlvmBuildStatus::ShouldBuild(Meta { stamp, res, out_dir, root: root.into() })
 }
 
+/// Paths whose changes invalidate LLVM downloads.
+pub const LLVM_INVALIDATION_PATHS: &[&str] = &[
+    "src/llvm-project",
+    "src/bootstrap/download-ci-llvm-stamp",
+    // the LLVM shared object file is named `LLVM-<LLVM-version>-rust-{version}-nightly`
+    "src/version",
+];
+
 /// 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 {
-        get_closest_merge_commit(
-            Some(&config.src),
-            &config.git_config(),
-            &[
-                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()
+        get_closest_merge_commit(Some(&config.src), &config.git_config(), LLVM_INVALIDATION_PATHS)
+            .unwrap()
     } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
         info.sha.trim().to_owned()
     } else {
@@ -207,10 +205,9 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
 
 /// Returns whether the CI-found LLVM is currently usable.
 ///
-/// This checks both the build triple platform to confirm we're usable at all,
-/// and then verifies if the current HEAD matches the detected LLVM SHA head,
-/// in which case LLVM is indicated as not available.
-pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
+/// This checks the build triple platform to confirm we're usable at all, and if LLVM
+/// with/without assertions is available.
+pub(crate) fn is_ci_llvm_available_for_target(config: &Config, asserts: bool) -> bool {
     // This is currently all tier 1 targets and tier 2 targets with host tools
     // (since others may not have CI artifacts)
     // https://doc.rust-lang.org/rustc/platform-support.html#tier-1
@@ -255,41 +252,9 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
         return false;
     }
 
-    if is_ci_llvm_modified(config) {
-        eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
-        return false;
-    }
-
     true
 }
 
-/// Returns true if we're running in CI with modified LLVM (and thus can't download it)
-pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool {
-    // If not running in a CI environment, return false.
-    if !config.is_running_on_ci {
-        return false;
-    }
-
-    // In rust-lang/rust managed CI, assert the existence of the LLVM submodule.
-    if CiEnv::is_rust_lang_managed_ci_job() {
-        assert!(
-            config.in_tree_llvm_info.is_managed_git_subrepository(),
-            "LLVM submodule must be fetched in rust-lang/rust managed CI builders."
-        );
-    }
-    // If LLVM submodule isn't present, skip the change check as it won't work.
-    else if !config.in_tree_llvm_info.is_managed_git_subrepository() {
-        return false;
-    }
-
-    let llvm_sha = detect_llvm_sha(config, true);
-    let head_sha = crate::output(
-        helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut(),
-    );
-    let head_sha = head_sha.trim();
-    llvm_sha == head_sha
-}
-
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Llvm {
     pub target: TargetSelection,
@@ -420,9 +385,6 @@ impl Step for Llvm {
             || target.contains("apple-watchos")
             || target.contains("apple-visionos")
         {
-            // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error.
-            cfg.define("CMAKE_OSX_SYSROOT", "/");
-            cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", "");
             // Prevent cmake from adding -bundle to CFLAGS automatically, which leads to a compiler error because "-bitcode_bundle" also gets added.
             cfg.define("LLVM_ENABLE_PLUGINS", "OFF");
             // Zlib fails to link properly, leading to a compiler error.
@@ -479,7 +441,6 @@ impl Step for Llvm {
 
         if helpers::forcing_clang_based_tests() {
             enabled_llvm_projects.push("clang");
-            enabled_llvm_projects.push("compiler-rt");
         }
 
         if builder.config.llvm_polly {
@@ -502,6 +463,10 @@ impl Step for Llvm {
 
         let mut enabled_llvm_runtimes = Vec::new();
 
+        if helpers::forcing_clang_based_tests() {
+            enabled_llvm_runtimes.push("compiler-rt");
+        }
+
         if builder.config.llvm_offload {
             enabled_llvm_runtimes.push("offload");
             //FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp.
@@ -677,10 +642,17 @@ fn configure_cmake(
     if !builder.is_builder_target(target) {
         cfg.define("CMAKE_CROSSCOMPILING", "True");
 
+        // NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us.
+        // But it currently determines this based on the `CARGO_CFG_TARGET_OS` environment variable,
+        // which isn't set when compiling outside `build.rs` (like bootstrap is).
+        //
+        // So for now, we define `CMAKE_SYSTEM_NAME` ourselves, to panicking in `cmake-rs`.
         if target.contains("netbsd") {
             cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
         } else if target.contains("dragonfly") {
             cfg.define("CMAKE_SYSTEM_NAME", "DragonFly");
+        } else if target.contains("openbsd") {
+            cfg.define("CMAKE_SYSTEM_NAME", "OpenBSD");
         } else if target.contains("freebsd") {
             cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
         } else if target.is_windows() {
@@ -691,10 +663,27 @@ fn configure_cmake(
             cfg.define("CMAKE_SYSTEM_NAME", "SunOS");
         } else if target.contains("linux") {
             cfg.define("CMAKE_SYSTEM_NAME", "Linux");
+        } else if target.contains("darwin") {
+            // macOS
+            cfg.define("CMAKE_SYSTEM_NAME", "Darwin");
+        } else if target.contains("ios") {
+            cfg.define("CMAKE_SYSTEM_NAME", "iOS");
+        } else if target.contains("tvos") {
+            cfg.define("CMAKE_SYSTEM_NAME", "tvOS");
+        } else if target.contains("visionos") {
+            cfg.define("CMAKE_SYSTEM_NAME", "visionOS");
+        } else if target.contains("watchos") {
+            cfg.define("CMAKE_SYSTEM_NAME", "watchOS");
+        } else if target.contains("none") {
+            // "none" should be the last branch
+            cfg.define("CMAKE_SYSTEM_NAME", "Generic");
         } else {
             builder.info(&format!(
                 "could not determine CMAKE_SYSTEM_NAME from the target `{target}`, build may fail",
             ));
+            // Fallback, set `CMAKE_SYSTEM_NAME` anyhow to avoid the logic `cmake-rs` tries, and
+            // to avoid CMAKE_SYSTEM_NAME being inferred from the host.
+            cfg.define("CMAKE_SYSTEM_NAME", "Generic");
         }
 
         // When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in
@@ -704,7 +693,19 @@ fn configure_cmake(
         // CMakeFiles (and then only in tests), and so far no issues have been
         // reported, the system version is currently left unset.
 
-        if target.contains("darwin") {
+        if target.contains("apple") {
+            if !target.contains("darwin") {
+                // FIXME(madsmtm): compiler-rt's CMake setup is kinda weird, it seems like they do
+                // version testing etc. for macOS (i.e. Darwin), even while building for iOS?
+                //
+                // So for now we set it to "Darwin" on all Apple platforms.
+                cfg.define("CMAKE_SYSTEM_NAME", "Darwin");
+
+                // These two defines prevent CMake from automatically trying to add a MacOSX sysroot, which leads to a compiler error.
+                cfg.define("CMAKE_OSX_SYSROOT", "/");
+                cfg.define("CMAKE_OSX_DEPLOYMENT_TARGET", "");
+            }
+
             // Make sure that CMake does not build universal binaries on macOS.
             // Explicitly specify the one single target architecture.
             if target.starts_with("aarch64") {
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index aaf6712102c..cd57e06ae04 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -26,7 +26,7 @@ use crate::core::config::{DebuginfoLevel, RustcLto, TargetSelection};
 use crate::utils::channel::GitInfo;
 use crate::utils::exec::{BootstrapCommand, command};
 use crate::utils::helpers::{add_dylib_path, exe, t};
-use crate::{Compiler, Kind, Mode, gha};
+use crate::{Compiler, FileType, Kind, Mode, gha};
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub enum SourceType {
@@ -353,7 +353,7 @@ fn copy_link_tool_bin(
 ) -> PathBuf {
     let cargo_out = builder.cargo_out(compiler, mode, target).join(exe(name, target));
     let bin = builder.tools_dir(compiler).join(exe(name, target));
-    builder.copy_link(&cargo_out, &bin);
+    builder.copy_link(&cargo_out, &bin, FileType::Executable);
     bin
 }
 
@@ -696,7 +696,7 @@ impl Step for Rustdoc {
                     .join(exe("rustdoc", target_compiler.host));
 
                 let bin_rustdoc = bin_rustdoc();
-                builder.copy_link(&precompiled_rustdoc, &bin_rustdoc);
+                builder.copy_link(&precompiled_rustdoc, &bin_rustdoc, FileType::Executable);
 
                 return ToolBuildResult {
                     tool_path: bin_rustdoc,
@@ -743,7 +743,7 @@ impl Step for Rustdoc {
                 compile::strip_debug(builder, target, &tool_path);
             }
             let bin_rustdoc = bin_rustdoc();
-            builder.copy_link(&tool_path, &bin_rustdoc);
+            builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable);
             ToolBuildResult { tool_path: bin_rustdoc, build_compiler, target_compiler }
         } else {
             ToolBuildResult { tool_path, build_compiler, target_compiler }
@@ -846,13 +846,20 @@ impl Step for LldWrapper {
         let src_exe = exe("lld", target);
         let dst_exe = exe("rust-lld", target);
 
-        builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
+        builder.copy_link(
+            &lld_install.join("bin").join(src_exe),
+            &libdir_bin.join(dst_exe),
+            FileType::Executable,
+        );
         let self_contained_lld_dir = libdir_bin.join("gcc-ld");
         t!(fs::create_dir_all(&self_contained_lld_dir));
 
         for name in crate::LLD_FILE_NAMES {
-            builder
-                .copy_link(&tool_result.tool_path, &self_contained_lld_dir.join(exe(name, target)));
+            builder.copy_link(
+                &tool_result.tool_path,
+                &self_contained_lld_dir.join(exe(name, target)),
+                FileType::Executable,
+            );
         }
 
         tool_result
@@ -949,8 +956,11 @@ impl Step for RustAnalyzerProcMacroSrv {
         // so that r-a can use it.
         let libexec_path = builder.sysroot(self.compiler).join("libexec");
         t!(fs::create_dir_all(&libexec_path));
-        builder
-            .copy_link(&tool_result.tool_path, &libexec_path.join("rust-analyzer-proc-macro-srv"));
+        builder.copy_link(
+            &tool_result.tool_path,
+            &libexec_path.join("rust-analyzer-proc-macro-srv"),
+            FileType::Executable,
+        );
 
         Some(tool_result)
     }
@@ -1007,7 +1017,7 @@ impl Step for LlvmBitcodeLinker {
             t!(fs::create_dir_all(&bindir_self_contained));
             let bin_destination = bindir_self_contained
                 .join(exe("llvm-bitcode-linker", tool_result.target_compiler.host));
-            builder.copy_link(&tool_result.tool_path, &bin_destination);
+            builder.copy_link(&tool_result.tool_path, &bin_destination, FileType::Executable);
             ToolBuildResult {
                 tool_path: bin_destination,
                 build_compiler: tool_result.build_compiler,
@@ -1189,7 +1199,7 @@ fn run_tool_build_step(
 
         for add_bin in add_bins_to_sysroot {
             let bin_destination = bindir.join(exe(add_bin, target_compiler.host));
-            builder.copy_link(&tool_path, &bin_destination);
+            builder.copy_link(&tool_path, &bin_destination, FileType::Executable);
         }
 
         // Return a path into the bin dir.
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index b7a51a33dbd..fd3b28e4e6a 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -1074,7 +1074,7 @@ fn test_prebuilt_llvm_config_path_resolution() {
     let config = configure(
         r#"
             [llvm]
-            download-ci-llvm = true
+            download-ci-llvm = "if-unchanged"
         "#,
     );
 
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 2b8c1f49afb..1712be7f947 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -23,6 +23,7 @@ use tracing::{instrument, span};
 
 use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
 use crate::core::build_steps::llvm;
+use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
 pub use crate::core::config::flags::Subcommand;
 use crate::core::config::flags::{Color, Flags, Warnings};
 use crate::core::download::is_download_ci_available;
@@ -192,7 +193,7 @@ pub enum GccCiMode {
 /// `bootstrap.example.toml`.
 #[derive(Default, Clone)]
 pub struct Config {
-    pub change_id: Option<usize>,
+    pub change_id: Option<ChangeId>,
     pub bypass_bootstrap_lock: bool,
     pub ccache: Option<String>,
     /// Call Build::ninja() instead of this.
@@ -699,14 +700,36 @@ pub(crate) struct TomlConfig {
     profile: Option<String>,
 }
 
+/// This enum is used for deserializing change IDs from TOML, allowing both numeric values and the string `"ignore"`.
+#[derive(Clone, Debug, PartialEq)]
+pub enum ChangeId {
+    Ignore,
+    Id(usize),
+}
+
 /// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type
 /// for the "change-id" field to parse it even if other fields are invalid. This ensures
 /// that if deserialization fails due to other fields, we can still provide the changelogs
 /// to allow developers to potentially find the reason for the failure in the logs..
 #[derive(Deserialize, Default)]
 pub(crate) struct ChangeIdWrapper {
-    #[serde(alias = "change-id")]
-    pub(crate) inner: Option<usize>,
+    #[serde(alias = "change-id", default, deserialize_with = "deserialize_change_id")]
+    pub(crate) inner: Option<ChangeId>,
+}
+
+fn deserialize_change_id<'de, D: Deserializer<'de>>(
+    deserializer: D,
+) -> Result<Option<ChangeId>, D::Error> {
+    let value = toml::Value::deserialize(deserializer)?;
+    Ok(match value {
+        toml::Value::String(s) if s == "ignore" => Some(ChangeId::Ignore),
+        toml::Value::Integer(i) => Some(ChangeId::Id(i as usize)),
+        _ => {
+            return Err(serde::de::Error::custom(
+                "expected \"ignore\" or an integer for change-id",
+            ));
+        }
+    })
 }
 
 /// Describes how to handle conflicts in merging two [`TomlConfig`]
@@ -1350,14 +1373,15 @@ impl Config {
         toml::from_str(&contents)
             .and_then(|table: toml::Value| TomlConfig::deserialize(table))
             .inspect_err(|_| {
-                if let Ok(Some(changes)) = toml::from_str(&contents)
-                    .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
-                    .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
+                if let Ok(ChangeIdWrapper { inner: Some(ChangeId::Id(id)) }) =
+                    toml::from_str::<toml::Value>(&contents)
+                        .and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
                 {
+                    let changes = crate::find_recent_config_change_ids(id);
                     if !changes.is_empty() {
                         println!(
                             "WARNING: There have been changes to x.py since you last updated:\n{}",
-                            crate::human_readable_changes(&changes)
+                            crate::human_readable_changes(changes)
                         );
                     }
                 }
@@ -1428,52 +1452,56 @@ impl Config {
 
         // Infer the rest of the configuration.
 
-        // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
-        // running on a completely different machine from where it was compiled.
-        let mut cmd = helpers::git(None);
-        // NOTE: we cannot support running from outside the repository because the only other path we have available
-        // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.
-        // We still support running outside the repository if we find we aren't in a git directory.
-
-        // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,
-        // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap
-        // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
-        cmd.arg("rev-parse").arg("--show-cdup");
-        // Discard stderr because we expect this to fail when building from a tarball.
-        let output = cmd
-            .as_command_mut()
-            .stderr(std::process::Stdio::null())
-            .output()
-            .ok()
-            .and_then(|output| if output.status.success() { Some(output) } else { None });
-        if let Some(output) = output {
-            let git_root_relative = String::from_utf8(output.stdout).unwrap();
-            // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
-            // and to resolve any relative components.
-            let git_root = env::current_dir()
-                .unwrap()
-                .join(PathBuf::from(git_root_relative.trim()))
-                .canonicalize()
-                .unwrap();
-            let s = git_root.to_str().unwrap();
-
-            // Bootstrap is quite bad at handling /? in front of paths
-            let git_root = match s.strip_prefix("\\\\?\\") {
-                Some(p) => PathBuf::from(p),
-                None => git_root,
-            };
-            // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
-            // for example, the build directory is inside of another unrelated git directory.
-            // In that case keep the original `CARGO_MANIFEST_DIR` handling.
-            //
-            // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
-            // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
-            if git_root.join("src").join("stage0").exists() {
-                config.src = git_root;
-            }
+        if let Some(src) = flags.src {
+            config.src = src
         } else {
-            // We're building from a tarball, not git sources.
-            // We don't support pre-downloaded bootstrap in this case.
+            // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
+            // running on a completely different machine from where it was compiled.
+            let mut cmd = helpers::git(None);
+            // NOTE: we cannot support running from outside the repository because the only other path we have available
+            // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.
+            // We still support running outside the repository if we find we aren't in a git directory.
+
+            // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,
+            // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap
+            // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
+            cmd.arg("rev-parse").arg("--show-cdup");
+            // Discard stderr because we expect this to fail when building from a tarball.
+            let output = cmd
+                .as_command_mut()
+                .stderr(std::process::Stdio::null())
+                .output()
+                .ok()
+                .and_then(|output| if output.status.success() { Some(output) } else { None });
+            if let Some(output) = output {
+                let git_root_relative = String::from_utf8(output.stdout).unwrap();
+                // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
+                // and to resolve any relative components.
+                let git_root = env::current_dir()
+                    .unwrap()
+                    .join(PathBuf::from(git_root_relative.trim()))
+                    .canonicalize()
+                    .unwrap();
+                let s = git_root.to_str().unwrap();
+
+                // Bootstrap is quite bad at handling /? in front of paths
+                let git_root = match s.strip_prefix("\\\\?\\") {
+                    Some(p) => PathBuf::from(p),
+                    None => git_root,
+                };
+                // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
+                // for example, the build directory is inside of another unrelated git directory.
+                // In that case keep the original `CARGO_MANIFEST_DIR` handling.
+                //
+                // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
+                // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
+                if git_root.join("src").join("stage0").exists() {
+                    config.src = git_root;
+                }
+            } else {
+                // We're building from a tarball, not git sources.
+                // We don't support pre-downloaded bootstrap in this case.
+            }
         }
 
         if cfg!(test) {
@@ -3096,7 +3124,14 @@ impl Config {
         download_ci_llvm: Option<StringOrBool>,
         asserts: bool,
     ) -> bool {
-        let download_ci_llvm = download_ci_llvm.unwrap_or(StringOrBool::Bool(true));
+        // We don't ever want to use `true` on CI, as we should not
+        // download upstream artifacts if there are any local modifications.
+        let default = if self.is_running_on_ci {
+            StringOrBool::String("if-unchanged".to_string())
+        } else {
+            StringOrBool::Bool(true)
+        };
+        let download_ci_llvm = download_ci_llvm.unwrap_or(default);
 
         let if_unchanged = || {
             if self.rust_info.is_from_tarball() {
@@ -3109,13 +3144,13 @@ impl Config {
             #[cfg(not(test))]
             self.update_submodule("src/llvm-project");
 
-            // Check for untracked changes in `src/llvm-project`.
+            // Check for untracked changes in `src/llvm-project` and other important places.
             let has_changes = self
-                .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
+                .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
                 .is_none();
 
             // Return false if there are untracked changes, otherwise check if CI LLVM is available.
-            if has_changes { false } else { llvm::is_ci_llvm_available(self, asserts) }
+            if has_changes { false } else { llvm::is_ci_llvm_available_for_target(self, asserts) }
         };
 
         match download_ci_llvm {
@@ -3126,8 +3161,15 @@ impl Config {
                     );
                 }
 
+                if b && self.is_running_on_ci {
+                    // On CI, we must always rebuild LLVM if there were any modifications to it
+                    panic!(
+                        "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead."
+                    );
+                }
+
                 // If download-ci-llvm=true we also want to check that CI llvm is available
-                b && llvm::is_ci_llvm_available(self, asserts)
+                b && llvm::is_ci_llvm_available_for_target(self, asserts)
             }
             StringOrBool::String(s) if s == "if-unchanged" => if_unchanged(),
             StringOrBool::String(other) => {
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index fb2c52966eb..d8002ba8467 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -10,8 +10,10 @@ use serde::Deserialize;
 
 use super::flags::Flags;
 use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
+use crate::ChangeId;
 use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
 use crate::core::build_steps::llvm;
+use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
 use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
 
 pub(crate) fn parse(config: &str) -> Config {
@@ -23,25 +25,13 @@ pub(crate) fn parse(config: &str) -> Config {
 
 #[test]
 fn download_ci_llvm() {
-    let config = parse("");
-    let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions);
-    if is_available {
-        assert!(config.llvm_from_ci);
-    }
-
-    let config = parse("llvm.download-ci-llvm = true");
-    let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions);
-    if is_available {
-        assert!(config.llvm_from_ci);
-    }
-
     let config = parse("llvm.download-ci-llvm = false");
     assert!(!config.llvm_from_ci);
 
     let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
-    if if_unchanged_config.llvm_from_ci {
+    if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci {
         let has_changes = if_unchanged_config
-            .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true)
+            .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
             .is_none();
 
         assert!(
@@ -162,7 +152,7 @@ runner = "x86_64-runner"
             )
         },
     );
-    assert_eq!(config.change_id, Some(1), "setting top-level value");
+    assert_eq!(config.change_id, Some(ChangeId::Id(1)), "setting top-level value");
     assert_eq!(
         config.rust_lto,
         crate::core::config::RustcLto::Fat,
@@ -302,7 +292,7 @@ fn parse_change_id_with_unknown_field() {
     "#;
 
     let change_id_wrapper: ChangeIdWrapper = toml::from_str(config).unwrap();
-    assert_eq!(change_id_wrapper.inner, Some(3461));
+    assert_eq!(change_id_wrapper.inner, Some(ChangeId::Id(3461)));
 }
 
 #[test]
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 1fba17dcf30..843d474f92d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -15,6 +15,7 @@
 //!
 //! More documentation can be found in each respective module below, and you can
 //! also check out the `src/bootstrap/README.md` file for more information.
+#![cfg_attr(test, allow(unused))]
 
 use std::cell::{Cell, RefCell};
 use std::collections::{BTreeSet, HashMap, HashSet};
@@ -36,14 +37,16 @@ use crate::core::builder;
 use crate::core::builder::Kind;
 use crate::core::config::{DryRun, LldMode, LlvmLibunwind, Target, TargetSelection, flags};
 use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode, command};
-use crate::utils::helpers::{self, dir_is_empty, exe, libdir, output, set_file_times, symlink_dir};
+use crate::utils::helpers::{
+    self, dir_is_empty, exe, libdir, output, set_file_times, split_debuginfo, symlink_dir,
+};
 
 mod core;
 mod utils;
 
 pub use core::builder::PathSet;
-pub use core::config::Config;
 pub use core::config::flags::{Flags, Subcommand};
+pub use core::config::{ChangeId, Config};
 
 #[cfg(feature = "tracing")]
 use tracing::{instrument, span};
@@ -274,6 +277,35 @@ pub enum CLang {
     Cxx,
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum FileType {
+    /// An executable binary file (like a `.exe`).
+    Executable,
+    /// A native, binary library file (like a `.so`, `.dll`, `.a`, `.lib` or `.o`).
+    NativeLibrary,
+    /// An executable (non-binary) script file (like a `.py` or `.sh`).
+    Script,
+    /// Any other regular file that is non-executable.
+    Regular,
+}
+
+impl FileType {
+    /// Get Unix permissions appropriate for this file type.
+    pub fn perms(self) -> u32 {
+        match self {
+            FileType::Executable | FileType::Script => 0o755,
+            FileType::Regular | FileType::NativeLibrary => 0o644,
+        }
+    }
+
+    pub fn could_have_split_debuginfo(self) -> bool {
+        match self {
+            FileType::Executable | FileType::NativeLibrary => true,
+            FileType::Script | FileType::Regular => false,
+        }
+    }
+}
+
 macro_rules! forward {
     ( $( $fn:ident( $($param:ident: $ty:ty),* ) $( -> $ret:ty)? ),+ $(,)? ) => {
         impl Build {
@@ -1744,8 +1776,18 @@ Executed at: {executed_at}"#,
     /// Attempts to use hard links if possible, falling back to copying.
     /// You can neither rely on this being a copy nor it being a link,
     /// so do not write to dst.
-    pub fn copy_link(&self, src: &Path, dst: &Path) {
+    pub fn copy_link(&self, src: &Path, dst: &Path, file_type: FileType) {
         self.copy_link_internal(src, dst, false);
+
+        if file_type.could_have_split_debuginfo() {
+            if let Some(dbg_file) = split_debuginfo(src) {
+                self.copy_link_internal(
+                    &dbg_file,
+                    &dst.with_extension(dbg_file.extension().unwrap()),
+                    false,
+                );
+            }
+        }
     }
 
     fn copy_link_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
@@ -1808,7 +1850,7 @@ Executed at: {executed_at}"#,
                 t!(fs::create_dir_all(&dst));
                 self.cp_link_r(&path, &dst);
             } else {
-                self.copy_link(&path, &dst);
+                self.copy_link(&path, &dst, FileType::Regular);
             }
         }
     }
@@ -1844,7 +1886,7 @@ Executed at: {executed_at}"#,
                     self.cp_link_filtered_recurse(&path, &dst, &relative, filter);
                 } else {
                     let _ = fs::remove_file(&dst);
-                    self.copy_link(&path, &dst);
+                    self.copy_link(&path, &dst, FileType::Regular);
                 }
             }
         }
@@ -1853,10 +1895,10 @@ Executed at: {executed_at}"#,
     fn copy_link_to_folder(&self, src: &Path, dest_folder: &Path) {
         let file_name = src.file_name().unwrap();
         let dest = dest_folder.join(file_name);
-        self.copy_link(src, &dest);
+        self.copy_link(src, &dest, FileType::Regular);
     }
 
-    fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
+    fn install(&self, src: &Path, dstdir: &Path, file_type: FileType) {
         if self.config.dry_run() {
             return;
         }
@@ -1866,8 +1908,16 @@ Executed at: {executed_at}"#,
         if !src.exists() {
             panic!("ERROR: File \"{}\" not found!", src.display());
         }
+
         self.copy_link_internal(src, &dst, true);
-        chmod(&dst, perms);
+        chmod(&dst, file_type.perms());
+
+        // If this file can have debuginfo, look for split debuginfo and install it too.
+        if file_type.could_have_split_debuginfo() {
+            if let Some(dbg_file) = split_debuginfo(src) {
+                self.install(&dbg_file, dstdir, FileType::Regular);
+            }
+        }
     }
 
     fn read(&self, path: &Path) -> String {
diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs
index c97529cbe9e..b4a1b52dd23 100644
--- a/src/bootstrap/src/utils/cc_detect/tests.rs
+++ b/src/bootstrap/src/utils/cc_detect/tests.rs
@@ -264,7 +264,7 @@ fn test_find_target_without_config() {
 fn test_find() {
     let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
     let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu");
-    let target2 = TargetSelection::from_user("arm-linux-androideabi");
+    let target2 = TargetSelection::from_user("x86_64-unknown-openbsd");
     build.targets.push(target1.clone());
     build.hosts.push(target2.clone());
     find(&build);
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 1a101b02f70..244391739f3 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -35,29 +35,25 @@ impl Display for ChangeSeverity {
     }
 }
 
-pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
-    if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) {
+pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo] {
+    if let Some(index) =
+        CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id)
+    {
+        // Skip the current_id and IDs before it
+        &CONFIG_CHANGE_HISTORY[index + 1..]
+    } else {
         // If the current change-id is greater than the most recent one, return
         // an empty list (it may be due to switching from a recent branch to an
         // older one); otherwise, return the full list (assuming the user provided
         // the incorrect change-id by accident).
         if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
             if current_id > config.change_id {
-                return Vec::new();
+                return &[];
             }
         }
 
-        return CONFIG_CHANGE_HISTORY.to_vec();
+        CONFIG_CHANGE_HISTORY
     }
-
-    let index =
-        CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
-
-    CONFIG_CHANGE_HISTORY
-        .iter()
-        .skip(index + 1) // Skip the current_id and IDs before it
-        .cloned()
-        .collect()
 }
 
 pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
@@ -390,4 +386,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "The default configuration filename has changed from `config.toml` to `bootstrap.toml`. `config.toml` is deprecated but remains supported for backward compatibility.",
     },
+    ChangeInfo {
+        change_id: 138986,
+        severity: ChangeSeverity::Info,
+        summary: "You can now use `change-id = \"ignore\"` to suppress `change-id ` warnings in the console.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 89d93a29acb..f8e4d4e0471 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -52,6 +52,23 @@ pub fn exe(name: &str, target: TargetSelection) -> String {
     crate::utils::shared_helpers::exe(name, &target.triple)
 }
 
+/// Returns the path to the split debug info for the specified file if it exists.
+pub fn split_debuginfo(name: impl Into<PathBuf>) -> Option<PathBuf> {
+    // FIXME: only msvc is currently supported
+
+    let path = name.into();
+    let pdb = path.with_extension("pdb");
+    if pdb.exists() {
+        return Some(pdb);
+    }
+
+    // pdbs get named with '-' replaced by '_'
+    let file_name = pdb.file_name()?.to_str()?.replace("-", "_");
+
+    let pdb: PathBuf = [path.parent()?, Path::new(&file_name)].into_iter().collect();
+    pdb.exists().then_some(pdb)
+}
+
 /// Returns `true` if the file name given looks like a dynamic library.
 pub fn is_dylib(path: &Path) -> bool {
     path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| {
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 885fff9c32c..862c4449624 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -9,9 +9,10 @@ use std::fs::File;
 use std::io::BufWriter;
 use std::time::{Duration, Instant, SystemTime};
 
+use build_helper::ci::CiEnv;
 use build_helper::metrics::{
-    JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test,
-    TestOutcome, TestSuite, TestSuiteMetadata,
+    CiMetadata, JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats,
+    Test, TestOutcome, TestSuite, TestSuiteMetadata,
 };
 use sysinfo::{CpuRefreshKind, RefreshKind, System};
 
@@ -217,7 +218,12 @@ impl BuildMetrics {
             children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(),
         });
 
-        let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations };
+        let json = JsonRoot {
+            format_version: CURRENT_FORMAT_VERSION,
+            system_stats,
+            invocations,
+            ci_metadata: get_ci_metadata(CiEnv::current()),
+        };
 
         t!(std::fs::create_dir_all(dest.parent().unwrap()));
         let mut file = BufWriter::new(t!(File::create(&dest)));
@@ -245,6 +251,16 @@ impl BuildMetrics {
     }
 }
 
+fn get_ci_metadata(ci_env: CiEnv) -> Option<CiMetadata> {
+    if ci_env != CiEnv::GitHubActions {
+        return None;
+    }
+    let workflow_run_id =
+        std::env::var("GITHUB_WORKFLOW_RUN_ID").ok().and_then(|id| id.parse::<u64>().ok())?;
+    let repository = std::env::var("GITHUB_REPOSITORY").ok()?;
+    Some(CiMetadata { workflow_run_id, repository })
+}
+
 struct MetricsState {
     finished_steps: Vec<StepMetrics>,
     running_steps: Vec<StepMetrics>,
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
index 34bf6bb7013..dbfd6f47dc6 100644
--- a/src/bootstrap/src/utils/proc_macro_deps.rs
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -6,18 +6,25 @@ pub static CRATES: &[&str] = &[
     "annotate-snippets",
     "anstyle",
     "basic-toml",
+    "block-buffer",
     "bumpalo",
+    "cfg-if",
+    "cpufeatures",
+    "crypto-common",
     "darling",
     "darling_core",
     "derive_builder_core",
+    "digest",
     "fluent-bundle",
     "fluent-langneg",
     "fluent-syntax",
     "fnv",
+    "generic-array",
     "heck",
     "ident_case",
     "intl-memoizer",
     "intl_pluralrules",
+    "libc",
     "log",
     "memchr",
     "mime",
@@ -25,12 +32,17 @@ pub static CRATES: &[&str] = &[
     "minimal-lexical",
     "nom",
     "num-conv",
+    "once_cell",
+    "pest",
+    "pest_generator",
+    "pest_meta",
     "proc-macro2",
     "quote",
     "rinja_parser",
     "rustc-hash",
     "self_cell",
     "serde",
+    "sha2",
     "smallvec",
     "stable_deref_trait",
     "strsim",
@@ -40,12 +52,15 @@ pub static CRATES: &[&str] = &[
     "time-core",
     "tinystr",
     "type-map",
+    "typenum",
+    "ucd-trie",
     "unic-langid",
     "unic-langid-impl",
     "unic-langid-macros",
     "unicase",
     "unicode-ident",
     "unicode-width",
+    "version_check",
     "wasm-bindgen-backend",
     "wasm-bindgen-macro-support",
     "wasm-bindgen-shared",
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index f1678bacc97..7b77b212934 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -7,6 +7,7 @@
 
 use std::path::{Path, PathBuf};
 
+use crate::FileType;
 use crate::core::build_steps::dist::distdir;
 use crate::core::builder::{Builder, Kind};
 use crate::core::config::BUILDER_CONFIG_FILENAME;
@@ -182,7 +183,12 @@ impl<'a> Tarball<'a> {
         &self.image_dir
     }
 
-    pub(crate) fn add_file(&self, src: impl AsRef<Path>, destdir: impl AsRef<Path>, perms: u32) {
+    pub(crate) fn add_file(
+        &self,
+        src: impl AsRef<Path>,
+        destdir: impl AsRef<Path>,
+        file_type: FileType,
+    ) {
         // create_dir_all fails to create `foo/bar/.`, so when the destination is "." this simply
         // uses the base directory as the destination directory.
         let destdir = if destdir.as_ref() == Path::new(".") {
@@ -192,7 +198,7 @@ impl<'a> Tarball<'a> {
         };
 
         t!(std::fs::create_dir_all(&destdir));
-        self.builder.install(src.as_ref(), &destdir, perms);
+        self.builder.install(src.as_ref(), &destdir, file_type);
     }
 
     pub(crate) fn add_renamed_file(
@@ -200,15 +206,16 @@ impl<'a> Tarball<'a> {
         src: impl AsRef<Path>,
         destdir: impl AsRef<Path>,
         new_name: &str,
+        file_type: FileType,
     ) {
         let destdir = self.image_dir.join(destdir.as_ref());
         t!(std::fs::create_dir_all(&destdir));
-        self.builder.copy_link(src.as_ref(), &destdir.join(new_name));
+        self.builder.copy_link(src.as_ref(), &destdir.join(new_name), file_type);
     }
 
     pub(crate) fn add_legal_and_readme_to(&self, destdir: impl AsRef<Path>) {
         for file in self.overlay.legal_and_readme() {
-            self.add_file(self.builder.src.join(file), destdir.as_ref(), 0o644);
+            self.add_file(self.builder.src.join(file), destdir.as_ref(), FileType::Regular);
         }
     }
 
@@ -318,11 +325,20 @@ impl<'a> Tarball<'a> {
 
         // Add config file if present.
         if let Some(config) = &self.builder.config.config {
-            self.add_renamed_file(config, &self.overlay_dir, BUILDER_CONFIG_FILENAME);
+            self.add_renamed_file(
+                config,
+                &self.overlay_dir,
+                BUILDER_CONFIG_FILENAME,
+                FileType::Regular,
+            );
         }
 
         for file in self.overlay.legal_and_readme() {
-            self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644);
+            self.builder.install(
+                &self.builder.src.join(file),
+                &self.overlay_dir,
+                FileType::Regular,
+            );
         }
 
         let mut cmd = self.builder.tool_cmd(crate::core::build_steps::tool::Tool::RustInstaller);
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
index 9f778a2fd77..693e0fc8f46 100644
--- a/src/build_helper/src/git.rs
+++ b/src/build_helper/src/git.rs
@@ -1,4 +1,4 @@
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::process::{Command, Stdio};
 
 use crate::ci::CiEnv;
@@ -121,7 +121,7 @@ fn git_upstream_merge_base(
 pub fn get_closest_merge_commit(
     git_dir: Option<&Path>,
     config: &GitConfig<'_>,
-    target_paths: &[PathBuf],
+    target_paths: &[&str],
 ) -> Result<String, String> {
     let mut git = Command::new("git");
 
@@ -173,7 +173,7 @@ pub fn get_git_modified_files(
     config: &GitConfig<'_>,
     git_dir: Option<&Path>,
     extensions: &[&str],
-) -> Result<Option<Vec<String>>, String> {
+) -> Result<Vec<String>, String> {
     let merge_base = get_closest_merge_commit(git_dir, config, &[])?;
 
     let mut git = Command::new("git");
@@ -186,7 +186,10 @@ pub fn get_git_modified_files(
             let (status, name) = f.trim().split_once(char::is_whitespace).unwrap();
             if status == "D" {
                 None
-            } else if Path::new(name).extension().map_or(false, |ext| {
+            } else if Path::new(name).extension().map_or(extensions.is_empty(), |ext| {
+                // If there is no extension, we allow the path if `extensions` is empty
+                // If there is an extension, we allow it if `extension` is empty or it contains the
+                // extension.
                 extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
             }) {
                 Some(name.to_owned())
@@ -195,7 +198,7 @@ pub fn get_git_modified_files(
             }
         })
         .collect();
-    Ok(Some(files))
+    Ok(files)
 }
 
 /// Returns the files that haven't been added to git yet.
diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs
index b6daac32a44..8b82e62a327 100644
--- a/src/build_helper/src/metrics.rs
+++ b/src/build_helper/src/metrics.rs
@@ -9,6 +9,19 @@ pub struct JsonRoot {
     pub format_version: usize,
     pub system_stats: JsonInvocationSystemStats,
     pub invocations: Vec<JsonInvocation>,
+    #[serde(default)]
+    pub ci_metadata: Option<CiMetadata>,
+}
+
+/// Represents metadata about bootstrap's execution in CI.
+#[derive(Serialize, Deserialize)]
+pub struct CiMetadata {
+    /// GitHub run ID of the workflow where bootstrap was executed.
+    /// Note that the run ID will be shared amongst all jobs executed in that workflow.
+    pub workflow_run_id: u64,
+    /// Full name of a GitHub repository where bootstrap was executed in CI.
+    /// e.g. `rust-lang-ci/rust`.
+    pub repository: String,
 }
 
 #[derive(Serialize, Deserialize)]
@@ -109,6 +122,8 @@ pub struct BuildStep {
     pub r#type: String,
     pub children: Vec<BuildStep>,
     pub duration: Duration,
+    // Full name of the step, including all parent names
+    pub full_name: String,
 }
 
 impl BuildStep {
@@ -116,7 +131,7 @@ impl BuildStep {
     /// The most important thing is that the build step aggregates the
     /// durations of all children, so that it can be easily accessed.
     pub fn from_invocation(invocation: &JsonInvocation) -> Self {
-        fn parse(node: &JsonNode) -> Option<BuildStep> {
+        fn parse(node: &JsonNode, parent_name: &str) -> Option<BuildStep> {
             match node {
                 JsonNode::RustbuildStep {
                     type_: kind,
@@ -124,11 +139,14 @@ impl BuildStep {
                     duration_excluding_children_sec,
                     ..
                 } => {
-                    let children: Vec<_> = children.into_iter().filter_map(parse).collect();
+                    let full_name = format!("{parent_name}-{kind}");
+                    let children: Vec<_> =
+                        children.into_iter().filter_map(|s| parse(s, &full_name)).collect();
                     let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
                     Some(BuildStep {
                         r#type: kind.to_string(),
                         children,
+                        full_name,
                         duration: children_duration
                             + Duration::from_secs_f64(*duration_excluding_children_sec),
                     })
@@ -138,8 +156,13 @@ impl BuildStep {
         }
 
         let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
-        let children: Vec<_> = invocation.children.iter().filter_map(parse).collect();
-        Self { r#type: "total".to_string(), children, duration }
+
+        // The root "total" step is kind of a virtual step that encompasses all other steps,
+        // but it is not a real parent of the other steps.
+        // We thus start the parent name hierarchy here and use an empty string
+        // as the parent name of the top-level steps.
+        let children: Vec<_> = invocation.children.iter().filter_map(|s| parse(s, "")).collect();
+        Self { r#type: "total".to_string(), children, duration, full_name: "total".to_string() }
     }
 
     pub fn find_all_by_type(&self, r#type: &str) -> Vec<&Self> {
@@ -156,33 +179,38 @@ impl BuildStep {
             child.find_by_type(r#type, result);
         }
     }
-}
-
-/// Writes build steps into a nice indented table.
-pub fn format_build_steps(root: &BuildStep) -> String {
-    use std::fmt::Write;
 
-    let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
+    /// Returns a Vec with all substeps, ordered by their hierarchical order.
+    /// The first element of the tuple is the depth of a given step.
+    pub fn linearize_steps(&self) -> Vec<(u32, &BuildStep)> {
+        let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
 
-    fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
-        substeps.push((level, step));
-        for child in &step.children {
-            visit(child, level + 1, substeps);
+        fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
+            substeps.push((level, step));
+            for child in &step.children {
+                visit(child, level + 1, substeps);
+            }
         }
+
+        visit(self, 0, &mut substeps);
+        substeps
     }
+}
 
-    visit(root, 0, &mut substeps);
+/// Writes build steps into a nice indented table.
+pub fn format_build_steps(root: &BuildStep) -> String {
+    use std::fmt::Write;
 
     let mut output = String::new();
-    for (level, step) in substeps {
-        let label = format!(
-            "{}{}",
-            ".".repeat(level as usize),
-            // Bootstrap steps can be generic and thus contain angle brackets (<...>).
-            // However, Markdown interprets these as HTML, so we need to escap ethem.
-            step.r#type.replace('<', "&lt;").replace('>', "&gt;")
-        );
+    for (level, step) in root.linearize_steps() {
+        let label = format!("{}{}", ".".repeat(level as usize), escape_step_name(step));
         writeln!(output, "{label:.<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
     }
     output
 }
+
+/// Bootstrap steps can be generic and thus contain angle brackets (<...>).
+/// However, Markdown interprets these as HTML, so we need to escap ethem.
+pub fn escape_step_name(step: &BuildStep) -> String {
+    step.r#type.replace('<', "&lt;").replace('>', "&gt;")
+}
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
index c061ec6ebdc..800eaae0766 100644
--- a/src/ci/citool/Cargo.lock
+++ b/src/ci/citool/Cargo.lock
@@ -107,6 +107,7 @@ dependencies = [
  "build_helper",
  "clap",
  "csv",
+ "diff",
  "glob-match",
  "insta",
  "serde",
@@ -242,6 +243,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
 name = "displaydoc"
 version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml
index dde09224afe..f18436a1263 100644
--- a/src/ci/citool/Cargo.toml
+++ b/src/ci/citool/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 anyhow = "1"
 clap = { version = "4.5", features = ["derive"] }
 csv = "1"
+diff = "0.1"
 glob-match = "0.2"
 serde = { version = "1", features = ["derive"] }
 serde_yaml = "0.9"
diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs
index 2088ce29620..7fbfad467c6 100644
--- a/src/ci/citool/src/analysis.rs
+++ b/src/ci/citool/src/analysis.rs
@@ -1,33 +1,135 @@
 use std::collections::{BTreeMap, HashMap, HashSet};
+use std::fmt::Debug;
+use std::time::Duration;
 
 use build_helper::metrics::{
-    BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps,
+    BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name,
+    format_build_steps,
 };
 
 use crate::metrics;
 use crate::metrics::{JobMetrics, JobName, get_test_suites};
 use crate::utils::{output_details, pluralize};
 
-pub fn output_bootstrap_stats(metrics: &JsonRoot) {
+/// Outputs durations of individual bootstrap steps from the gathered bootstrap invocations,
+/// and also a table with summarized information about executed tests.
+pub fn output_bootstrap_stats(metrics: &JsonRoot, parent_metrics: Option<&JsonRoot>) {
     if !metrics.invocations.is_empty() {
         println!("# Bootstrap steps");
-        record_bootstrap_step_durations(&metrics);
+        record_bootstrap_step_durations(&metrics, parent_metrics);
         record_test_suites(&metrics);
     }
 }
 
-fn record_bootstrap_step_durations(metrics: &JsonRoot) {
+fn record_bootstrap_step_durations(metrics: &JsonRoot, parent_metrics: Option<&JsonRoot>) {
+    let parent_steps: HashMap<String, BuildStep> = parent_metrics
+        .map(|metrics| {
+            metrics
+                .invocations
+                .iter()
+                .map(|invocation| {
+                    (invocation.cmdline.clone(), BuildStep::from_invocation(invocation))
+                })
+                .collect()
+        })
+        .unwrap_or_default();
+
     for invocation in &metrics.invocations {
         let step = BuildStep::from_invocation(invocation);
         let table = format_build_steps(&step);
         eprintln!("Step `{}`\n{table}\n", invocation.cmdline);
-        output_details(&invocation.cmdline, || {
+        output_details(&format!("{} (steps)", invocation.cmdline), || {
             println!("<pre><code>{table}</code></pre>");
         });
+
+        // If there was a parent bootstrap invocation with the same cmdline, diff it
+        if let Some(parent_step) = parent_steps.get(&invocation.cmdline) {
+            let table = format_build_step_diffs(&step, parent_step);
+
+            let duration_before = parent_step.duration.as_secs();
+            let duration_after = step.duration.as_secs();
+            output_details(
+                &format!("{} (diff) ({duration_before}s -> {duration_after}s)", invocation.cmdline),
+                || {
+                    println!("{table}");
+                },
+            );
+        }
     }
     eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len());
 }
 
+/// Creates a table that displays a diff between the durations of steps between
+/// two bootstrap invocations.
+/// It also shows steps that were missing before/after.
+fn format_build_step_diffs(current: &BuildStep, parent: &BuildStep) -> String {
+    use std::fmt::Write;
+
+    // Helper struct that compares steps by their full name
+    struct StepByName<'a>((u32, &'a BuildStep));
+
+    impl<'a> PartialEq for StepByName<'a> {
+        fn eq(&self, other: &Self) -> bool {
+            self.0.1.full_name.eq(&other.0.1.full_name)
+        }
+    }
+
+    fn get_steps(step: &BuildStep) -> Vec<StepByName> {
+        step.linearize_steps().into_iter().map(|v| StepByName(v)).collect()
+    }
+
+    let steps_before = get_steps(parent);
+    let steps_after = get_steps(current);
+
+    let mut table = "| Step | Before | After | Change |\n".to_string();
+    writeln!(table, "|:-----|-------:|------:|-------:|").unwrap();
+
+    // Try to match removed, added and same steps using a classic diff algorithm
+    for result in diff::slice(&steps_before, &steps_after) {
+        let (step, before, after, change) = match result {
+            // The step was found both before and after
+            diff::Result::Both(before, after) => {
+                let duration_before = before.0.1.duration;
+                let duration_after = after.0.1.duration;
+                let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64();
+                let pct_change = pct_change * 100.0;
+                // Normalize around 100, to get + for regression and - for improvements
+                let pct_change = pct_change - 100.0;
+                (
+                    before,
+                    format!("{:.2}s", duration_before.as_secs_f64()),
+                    format!("{:.2}s", duration_after.as_secs_f64()),
+                    format!("{pct_change:.1}%"),
+                )
+            }
+            // The step was only found in the parent, so it was likely removed
+            diff::Result::Left(removed) => (
+                removed,
+                format!("{:.2}s", removed.0.1.duration.as_secs_f64()),
+                "".to_string(),
+                "(removed)".to_string(),
+            ),
+            // The step was only found in the current commit, so it was likely added
+            diff::Result::Right(added) => (
+                added,
+                "".to_string(),
+                format!("{:.2}s", added.0.1.duration.as_secs_f64()),
+                "(added)".to_string(),
+            ),
+        };
+
+        let prefix = ".".repeat(step.0.0 as usize);
+        writeln!(
+            table,
+            "| {prefix}{} | {before} | {after} | {change} |",
+            escape_step_name(step.0.1),
+        )
+        .unwrap();
+    }
+
+    table
+}
+
 fn record_test_suites(metrics: &JsonRoot) {
     let suites = metrics::get_test_suites(&metrics);
 
@@ -82,13 +184,71 @@ fn render_table(suites: BTreeMap<String, TestSuiteRecord>) -> String {
     table
 }
 
-/// Computes a post merge CI analysis report of test differences
-/// between the `parent` and `current` commits.
-pub fn output_test_diffs(job_metrics: HashMap<JobName, JobMetrics>) {
+/// Outputs a report of test differences between the `parent` and `current` commits.
+pub fn output_test_diffs(job_metrics: &HashMap<JobName, JobMetrics>) {
     let aggregated_test_diffs = aggregate_test_diffs(&job_metrics);
     report_test_diffs(aggregated_test_diffs);
 }
 
+/// Prints the ten largest differences in bootstrap durations.
+pub fn output_largest_duration_changes(job_metrics: &HashMap<JobName, JobMetrics>) {
+    struct Entry<'a> {
+        job: &'a JobName,
+        before: Duration,
+        after: Duration,
+        change: f64,
+    }
+
+    let mut changes: Vec<Entry> = vec![];
+    for (job, metrics) in job_metrics {
+        if let Some(parent) = &metrics.parent {
+            let duration_before = parent
+                .invocations
+                .iter()
+                .map(|i| BuildStep::from_invocation(i).duration)
+                .sum::<Duration>();
+            let duration_after = metrics
+                .current
+                .invocations
+                .iter()
+                .map(|i| BuildStep::from_invocation(i).duration)
+                .sum::<Duration>();
+            let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64();
+            let pct_change = pct_change * 100.0;
+            // Normalize around 100, to get + for regression and - for improvements
+            let pct_change = pct_change - 100.0;
+            changes.push(Entry {
+                job,
+                before: duration_before,
+                after: duration_after,
+                change: pct_change,
+            });
+        }
+    }
+    changes.sort_by(|e1, e2| e1.change.partial_cmp(&e2.change).unwrap().reverse());
+
+    println!("# Job duration changes");
+    for (index, entry) in changes.into_iter().take(10).enumerate() {
+        println!(
+            "{}. `{}`: {:.1}s -> {:.1}s ({:.1}%)",
+            index + 1,
+            entry.job,
+            entry.before.as_secs_f64(),
+            entry.after.as_secs_f64(),
+            entry.change
+        );
+    }
+
+    println!();
+    output_details("How to interpret the job duration changes?", || {
+        println!(
+            r#"Job durations can vary a lot, based on the actual runner instance
+that executed the job, system noise, invalidated caches, etc. The table above is provided
+mostly for t-infra members, for simpler debugging of potential CI slow-downs."#
+        );
+    });
+}
+
 #[derive(Default)]
 struct TestSuiteRecord {
     passed: u64,
@@ -210,6 +370,7 @@ struct TestSuiteData {
 #[derive(Hash, PartialEq, Eq, Debug, Clone)]
 struct Test {
     name: String,
+    stage: u8,
     is_doctest: bool,
 }
 
@@ -218,27 +379,24 @@ fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData {
     let mut tests = HashMap::new();
     let test_suites = get_test_suites(&metrics);
     for suite in test_suites {
+        let stage = match suite.metadata {
+            TestSuiteMetadata::CargoPackage { stage, .. } => stage,
+            TestSuiteMetadata::Compiletest { stage, .. } => stage,
+        } as u8;
         for test in &suite.tests {
             // Poor man's detection of doctests based on the "(line XYZ)" suffix
             let is_doctest = matches!(suite.metadata, TestSuiteMetadata::CargoPackage { .. })
                 && test.name.contains("(line");
-            let test_entry = Test { name: generate_test_name(&test.name, &suite), is_doctest };
+            let test_entry = Test { name: generate_test_name(&test.name), stage, is_doctest };
             tests.insert(test_entry, test.outcome.clone());
         }
     }
     TestSuiteData { tests }
 }
 
-/// Normalizes Windows-style path delimiters to Unix-style paths
-/// and adds suite metadata to the test name.
-fn generate_test_name(name: &str, suite: &TestSuite) -> String {
-    let name = name.replace('\\', "/");
-    let stage = match suite.metadata {
-        TestSuiteMetadata::CargoPackage { stage, .. } => stage,
-        TestSuiteMetadata::Compiletest { stage, .. } => stage,
-    };
-
-    format!("{name} (stage {stage})")
+/// Normalizes Windows-style path delimiters to Unix-style paths.
+fn generate_test_name(name: &str) -> String {
+    name.replace('\\', "/")
 }
 
 /// Prints test changes in Markdown format to stdout.
@@ -321,16 +479,25 @@ fn report_test_diffs(diff: AggregatedTestDiffs) {
     // Sort diffs by job group and test name
     grouped_diffs.sort_by(|(d1, g1), (d2, g2)| g1.cmp(&g2).then(d1.test.name.cmp(&d2.test.name)));
 
+    // Now group the tests by stage
+    let mut grouped_by_stage: BTreeMap<u8, Vec<(&TestDiff, u64)>> = Default::default();
+    for (diff, group) in grouped_diffs {
+        grouped_by_stage.entry(diff.test.stage).or_default().push((diff, group))
+    }
+
     output_details(
         &format!("Show {} test {}\n", original_diff_count, pluralize("diff", original_diff_count)),
         || {
-            for (diff, job_group) in grouped_diffs {
-                println!(
-                    "- `{}`: {} ({})",
-                    diff.test.name,
-                    format_diff(&diff.diff),
-                    format_job_group(job_group)
-                );
+            for (stage, diffs) in grouped_by_stage {
+                println!("## Stage {stage}");
+                for (diff, job_group) in diffs {
+                    println!(
+                        "- `{}`: {} ({})",
+                        diff.test.name,
+                        format_diff(&diff.diff),
+                        format_job_group(job_group)
+                    );
+                }
             }
 
             let extra_diffs = diffs.len().saturating_sub(max_diff_count);
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 5a84ecb5e47..6db5eab458c 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -15,7 +15,7 @@ use clap::Parser;
 use jobs::JobDatabase;
 use serde_yaml::Value;
 
-use crate::analysis::output_test_diffs;
+use crate::analysis::{output_largest_duration_changes, output_test_diffs};
 use crate::cpu_usage::load_cpu_usage;
 use crate::datadog::upload_datadog_metric;
 use crate::jobs::RunType;
@@ -144,31 +144,35 @@ fn postprocess_metrics(
     job_name: Option<String>,
 ) -> anyhow::Result<()> {
     let metrics = load_metrics(&metrics_path)?;
-    output_bootstrap_stats(&metrics);
 
-    let (Some(parent), Some(job_name)) = (parent, job_name) else {
-        return Ok(());
-    };
-
-    // This command is executed also on PR builds, which might not have parent metrics
-    // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics
-    // due to missing permissions.
-    // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs,
-    // we simply print an error if the parent metrics were not found, but otherwise exit
-    // successfully.
-    match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") {
-        Ok(parent_metrics) => {
-            let job_metrics = HashMap::from([(
-                job_name,
-                JobMetrics { parent: Some(parent_metrics), current: metrics },
-            )]);
-            output_test_diffs(job_metrics);
-        }
-        Err(error) => {
-            eprintln!("Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}");
+    if let (Some(parent), Some(job_name)) = (parent, job_name) {
+        // This command is executed also on PR builds, which might not have parent metrics
+        // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics
+        // due to missing permissions.
+        // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs,
+        // we simply print an error if the parent metrics were not found, but otherwise exit
+        // successfully.
+        match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") {
+            Ok(parent_metrics) => {
+                output_bootstrap_stats(&metrics, Some(&parent_metrics));
+
+                let job_metrics = HashMap::from([(
+                    job_name,
+                    JobMetrics { parent: Some(parent_metrics), current: metrics },
+                )]);
+                output_test_diffs(&job_metrics);
+                return Ok(());
+            }
+            Err(error) => {
+                eprintln!(
+                    "Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}"
+                );
+            }
         }
     }
 
+    output_bootstrap_stats(&metrics, None);
+
     Ok(())
 }
 
@@ -176,7 +180,8 @@ fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow
     let metrics = download_auto_job_metrics(&db, &parent, &current)?;
 
     println!("\nComparing {parent} (parent) -> {current} (this PR)\n");
-    output_test_diffs(metrics);
+    output_test_diffs(&metrics);
+    output_largest_duration_changes(&metrics);
 
     Ok(())
 }
diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs
index 086aa5009f3..a816fb3c4f1 100644
--- a/src/ci/citool/src/metrics.rs
+++ b/src/ci/citool/src/metrics.rs
@@ -1,5 +1,5 @@
 use std::collections::HashMap;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use anyhow::Context;
 use build_helper::metrics::{JsonNode, JsonRoot, TestSuite};
@@ -74,6 +74,17 @@ Maybe it was newly added?"#,
 }
 
 pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> {
+    // Best effort cache to speed-up local re-executions of citool
+    let cache_path = PathBuf::from(".citool-cache").join(sha).join(format!("{job_name}.json"));
+    if cache_path.is_file() {
+        if let Ok(metrics) = std::fs::read_to_string(&cache_path)
+            .map_err(|err| err.into())
+            .and_then(|data| anyhow::Ok::<JsonRoot>(serde_json::from_str::<JsonRoot>(&data)?))
+        {
+            return Ok(metrics);
+        }
+    }
+
     let url = get_metrics_url(job_name, sha);
     let mut response = ureq::get(&url).call()?;
     if !response.status().is_success() {
@@ -87,6 +98,13 @@ pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoo
         .body_mut()
         .read_json()
         .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?;
+
+    if let Ok(_) = std::fs::create_dir_all(cache_path.parent().unwrap()) {
+        if let Ok(data) = serde_json::to_string(&data) {
+            let _ = std::fs::write(cache_path, data);
+        }
+    }
+
     Ok(data)
 }
 
diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs
index b9b1bf4d455..a4c6ff85ef7 100644
--- a/src/ci/citool/src/utils.rs
+++ b/src/ci/citool/src/utils.rs
@@ -23,7 +23,6 @@ where
     println!(
         r"<details>
 <summary>{summary}</summary>
-
 "
     );
     func();
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
index d706927d6d9..0c85d4b449d 100755
--- 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
@@ -8,5 +8,6 @@ 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
+    # Disable CI mode, because it is not compatible with all profiles
+    python3 ../x.py check --config $config_file --dry-run --ci=false
 done
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 2805bb1118d..00d791eeb6b 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -355,6 +355,8 @@ docker \
   --env GITHUB_ACTIONS \
   --env GITHUB_REF \
   --env GITHUB_STEP_SUMMARY="/checkout/obj/${SUMMARY_FILE}" \
+  --env GITHUB_WORKFLOW_RUN_ID \
+  --env GITHUB_REPOSITORY \
   --env RUST_BACKTRACE \
   --env TOOLSTATE_REPO_ACCESS_TOKEN \
   --env TOOLSTATE_REPO \
diff --git a/src/doc/book b/src/doc/book
-Subproject 81a976a237f84b8392c4ce1bd5fd076eb757a2e
+Subproject 45f05367360f033f89235eacbbb54e8d73ce6b7
diff --git a/src/doc/reference b/src/doc/reference
-Subproject dda31c85f2ef2e5d2f0f2f643c9231690a30a62
+Subproject e95ebdfee02514d93f79ec92ae310a804e87f01
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index c8536b0045c..1190c2646af 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -202,6 +202,12 @@ several ways to match the message with the line (see the examples below):
 * `~|`: Associates the error level and message with the *same* line as the
   *previous comment*. This is more convenient than using multiple carets when
   there are multiple messages associated with the same line.
+* `~v`: Associates the error level and message with the *next* error
+  annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
+  is three lines below the error annotation line.
+* `~?`: Used to match error levels and messages with errors not having line
+  information. These can be placed on any line in the test file, but are
+  conventionally placed at the end.
 
 Example:
 
@@ -270,10 +276,35 @@ fn main() {
 //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023]
 ```
 
+#### Positioned above error line
+
+Use the `//~v` idiom with number of v's in the string to indicate the number
+of lines below. This is typically used in lexer or parser tests matching on errors like unclosed
+delimiter or unclosed literal happening at the end of file.
+
+```rust,ignore
+// ignore-tidy-trailing-newlines
+//~v ERROR this file contains an unclosed delimiter
+fn main((ؼ
+```
+
+#### Error without line information
+
+Use `//~?` to match an error without line information.
+`//~?` is precise and will not match errors if their line information is available.
+It should be preferred to using `error-pattern`, which is imprecise and non-exhaustive.
+
+```rust,ignore
+//@ compile-flags: --print yyyy
+
+//~? ERROR unknown print request: `yyyy`
+```
+
 ### `error-pattern`
 
-The `error-pattern` [directive](directives.md) can be used for messages that don't
-have a specific span.
+The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't
+have a specific span, or for compile time messages if imprecise matching is required due to
+multi-line platform specific diagnostics.
 
 Let's think about this test:
 
@@ -300,7 +331,9 @@ fn main() {
 }
 ```
 
-But for strict testing, try to use the `ERROR` annotation as much as possible.
+But for strict testing, try to use the `ERROR` annotation as much as possible,
+including `//~?` annotations for diagnostics without span.
+For compile time diagnostics `error-pattern` should very rarely be necessary.
 
 ### Error levels
 
@@ -353,7 +386,7 @@ would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of
 the different revisions.
 
 > Note: cfg revisions also work inside the source code with `#[cfg]` attributes.
-> 
+>
 > By convention, the `FALSE` cfg is used to have an always-false config.
 
 ## Controlling pass/fail expectations
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 542ee9fffce..e1ba27c07da 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -2,6 +2,7 @@
 
 - [What is rustc?](what-is-rustc.md)
 - [Command-line Arguments](command-line-arguments.md)
+    - [Print Options](command-line-arguments/print-options.md)
     - [Codegen Options](codegen-options/index.md)
 - [Jobserver](jobserver.md)
 - [Lints](lints/index.md)
@@ -13,6 +14,22 @@
         - [Deny-by-default Lints](lints/listing/deny-by-default.md)
 - [JSON Output](json.md)
 - [Tests](tests/index.md)
+- [Targets](targets/index.md)
+    - [Built-in Targets](targets/built-in.md)
+    - [Custom Targets](targets/custom.md)
+    - [Known Issues](targets/known-issues.md)
+- [Profile-guided Optimization](profile-guided-optimization.md)
+- [Instrumentation-based Code Coverage](instrument-coverage.md)
+- [Linker-plugin-based LTO](linker-plugin-lto.md)
+- [Checking Conditional Configurations](check-cfg.md)
+    - [Cargo Specifics](check-cfg/cargo-specifics.md)
+- [Exploit Mitigations](exploit-mitigations.md)
+- [Symbol Mangling](symbol-mangling/index.md)
+    - [v0 Symbol Format](symbol-mangling/v0.md)
+- [Contributing to `rustc`](contributing.md)
+
+--------
+
 - [Platform Support](platform-support.md)
     - [Target Tier Policy](target-tier-policy.md)
     - [Template for Target-specific Documentation](platform-support/TEMPLATE.md)
@@ -65,6 +82,7 @@
     - [m68k-unknown-none-elf](platform-support/m68k-unknown-none-elf.md)
     - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
     - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
+    - [mipsel-unknown-linux-gnu](platform-support/mipsel-unknown-linux-gnu.md)
     - [mips\*-mti-none-elf](platform-support/mips-mti-none-elf.md)
     - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
     - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
@@ -72,6 +90,7 @@
     - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md)
     - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
     - [powerpc64-ibm-aix](platform-support/aix.md)
+    - [powerpc64-unknown-linux-musl](platform-support/powerpc64-unknown-linux-musl.md)
     - [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md)
     - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md)
     - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
@@ -83,7 +102,7 @@
     - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
     - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
-    - [sparcv9-sun-solaris](platform-support/solaris.md)
+    - [solaris](platform-support/solaris.md)
     - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
     - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
@@ -107,21 +126,7 @@
     - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
     - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
     - [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md)
-    - [x86_64-pc-solaris](platform-support/solaris.md)
     - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [xtensa-\*-none-elf](platform-support/xtensa.md)
     - [\*-nuttx-\*](platform-support/nuttx.md)
-- [Targets](targets/index.md)
-    - [Built-in Targets](targets/built-in.md)
-    - [Custom Targets](targets/custom.md)
-    - [Known Issues](targets/known-issues.md)
-- [Profile-guided Optimization](profile-guided-optimization.md)
-- [Instrumentation-based Code Coverage](instrument-coverage.md)
-- [Linker-plugin-based LTO](linker-plugin-lto.md)
-- [Checking Conditional Configurations](check-cfg.md)
-    - [Cargo Specifics](check-cfg/cargo-specifics.md)
-- [Exploit Mitigations](exploit-mitigations.md)
-- [Symbol Mangling](symbol-mangling/index.md)
-    - [v0 Symbol Format](symbol-mangling/v0.md)
-- [Contributing to `rustc`](contributing.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 9dd2e7de1b3..b704cee705b 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -247,58 +247,7 @@ types to stdout at the same time will result in an error.
 <a id="option-print"></a>
 ## `--print`: print compiler information
 
-This flag prints out various information about the compiler. This flag may be
-specified multiple times, and the information is printed in the order the
-flags are specified. Specifying a `--print` flag will usually disable the
-[`--emit`](#option-emit) step and will only print the requested information.
-The valid types of print values are:
-
-- `crate-name` — The name of the crate.
-- `file-names` — The names of the files created by the `link` emit kind.
-- `sysroot` — Path to the sysroot.
-- `target-libdir` — Path to the target libdir.
-- `host-tuple` — The target-tuple string of the host compiler (e.g. `x86_64-unknown-linux-gnu`)
-- `cfg` — List of cfg values. See [conditional compilation] for more
-  information about cfg values.
-- `target-list` — List of known targets. The target may be selected with the
-  `--target` flag.
-- `target-cpus` — List of available CPU values for the current target. The
-  target CPU may be selected with the [`-C target-cpu=val`
-  flag](codegen-options/index.md#target-cpu).
-- `target-features` — List of available target features for the current
-  target. Target features may be enabled with the [`-C target-feature=val`
-  flag](codegen-options/index.md#target-feature).  This flag is unsafe. See
-  [known issues](targets/known-issues.md) for more details.
-- `relocation-models` — List of relocation models. Relocation models may be
-  selected with the [`-C relocation-model=val`
-  flag](codegen-options/index.md#relocation-model).
-- `code-models` — List of code models. Code models may be selected with the
-  [`-C code-model=val` flag](codegen-options/index.md#code-model).
-- `tls-models` — List of Thread Local Storage models supported. The model may
-  be selected with the `-Z tls-model=val` flag.
-- `native-static-libs` — This may be used when creating a `staticlib` crate
-  type. If this is the only flag, it will perform a full compilation and
-  include a diagnostic note that indicates the linker flags to use when
-  linking the resulting static library. The note starts with the text
-  `native-static-libs:` to make it easier to fetch the output.
-- `link-args` — This flag does not disable the `--emit` step. When linking,
-  this flag causes `rustc` to print the full linker invocation in a
-  human-readable form. This can be useful when debugging linker options. The
-  exact format of this debugging output is not a stable guarantee, other than
-  that it will include the linker executable and the text of each command-line
-  argument passed to the linker.
-- `deployment-target` — The currently selected [deployment target] (or minimum OS version)
-  for the selected Apple platform target. This value can be used or passed along to other
-  components alongside a Rust build that need this information, such as C compilers.
-  This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable
-  is present in the environment, or otherwise returns the variable's parsed value.
-
-A filepath may optionally be specified for each requested information kind, in
-the format `--print KIND=PATH`, just like for `--emit`. When a path is
-specified, information will be written there instead of to stdout.
-
-[conditional compilation]: ../reference/conditional-compilation.html
-[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html
+This flag will allow you to set [print options](command-line-arguments/print-options.md).
 
 <a id="option-g-debug"></a>
 ## `-g`: include debug information
diff --git a/src/doc/rustc/src/command-line-arguments/print-options.md b/src/doc/rustc/src/command-line-arguments/print-options.md
new file mode 100644
index 00000000000..1f33e91e5d1
--- /dev/null
+++ b/src/doc/rustc/src/command-line-arguments/print-options.md
@@ -0,0 +1,212 @@
+# Print Options
+
+All of these options are passed to `rustc` via the `--print` flag.
+
+Those options prints out various information about the compiler. Multiple options can be
+specified, and the information is printed in the order the options are specified.
+
+Specifying an option will usually disable the [`--emit`](../command-line-arguments.md#option-emit)
+step and will only print the requested information.
+
+A filepath may optionally be specified for each requested information kind, in the format
+`--print KIND=PATH`, just like for `--emit`. When a path is specified, information will be
+written there instead of to stdout.
+
+## `crate-name`
+
+The name of the crate.
+
+Generally coming from either from the `#![crate_name = "..."]` attribute,
+[`--crate-name` flag](../command-line-arguments.md#option-crate-name) or the filename.
+
+Example:
+
+```bash
+$ rustc --print crate-name --crate-name my_crate a.rs
+my_crate
+```
+
+## `file-names`
+
+The names of the files created by the `link` emit kind.
+
+## `sysroot`
+
+Abosulte path to the sysroot.
+
+Example (with rustup and the stable toolchain):
+
+```bash
+$ rustc --print sysroot a.rs
+/home/[REDACTED]/.rustup/toolchains/stable-x86_64-unknown-linux-gnu
+```
+
+## `target-libdir`
+
+Path to the target libdir.
+
+Example (with rustup and the stable toolchain):
+
+```bash
+$ rustc --print target-libdir a.rs
+/home/[REDACTED]/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib
+```
+
+## `host-tuple`
+
+The target-tuple string of the host compiler.
+
+Example:
+
+```bash
+$ rustc --print host-tuple a.rs
+x86_64-unknown-linux-gnu
+```
+
+Example with the `--target` flag:
+
+```bash
+$ rustc --print host-tuple --target "armv7-unknown-linux-gnueabihf" a.rs
+x86_64-unknown-linux-gnu
+```
+
+## `cfg`
+
+List of cfg values. See [conditional compilation] for more information about cfg values.
+
+Example (for `x86_64-unknown-linux-gnu`):
+
+```bash
+$ rustc --print cfg a.rs
+debug_assertions
+panic="unwind"
+target_abi=""
+target_arch="x86_64"
+target_endian="little"
+target_env="gnu"
+target_family="unix"
+target_feature="fxsr"
+target_feature="sse"
+target_feature="sse2"
+target_has_atomic="16"
+target_has_atomic="32"
+target_has_atomic="64"
+target_has_atomic="8"
+target_has_atomic="ptr"
+target_os="linux"
+target_pointer_width="64"
+target_vendor="unknown"
+unix
+```
+
+## `target-list`
+
+List of known targets. The target may be selected with the `--target` flag.
+
+## `target-cpus`
+
+List of available CPU values for the current target. The target CPU may be selected with
+the [`-C target-cpu=val` flag](../codegen-options/index.md#target-cpu).
+
+## `target-features`
+
+List of available target features for the *current target*.
+
+Target features may be enabled with the **unsafe**
+[`-C target-feature=val` flag](../codegen-options/index.md#target-feature).
+
+See [known issues](../targets/known-issues.md) for more details.
+
+## `relocation-models`
+
+List of relocation models. Relocation models may be selected with the
+[`-C relocation-model=val` flag](../codegen-options/index.md#relocation-model).
+
+Example:
+
+```bash
+$ rustc --print relocation-models a.rs
+Available relocation models:
+    static
+    pic
+    pie
+    dynamic-no-pic
+    ropi
+    rwpi
+    ropi-rwpi
+    default
+```
+
+## `code-models`
+
+List of code models. Code models may be selected with the
+[`-C code-model=val` flag](../codegen-options/index.md#code-model).
+
+Example:
+
+```bash
+$ rustc --print code-models a.rs
+Available code models:
+    tiny
+    small
+    kernel
+    medium
+    large
+```
+
+## `tls-models`
+
+List of Thread Local Storage models supported. The model may be selected with the
+`-Z tls-model=val` flag.
+
+Example:
+
+```bash
+$ rustc --print tls-models a.rs
+Available TLS models:
+    global-dynamic
+    local-dynamic
+    initial-exec
+    local-exec
+    emulated
+```
+
+## `native-static-libs`
+
+This may be used when creating a `staticlib` crate type.
+
+If this is the only flag, it will perform a full compilation and include a diagnostic note
+that indicates the linker flags to use when linking the resulting static library.
+
+The note starts with the text `native-static-libs:` to make it easier to fetch the output.
+
+Example:
+
+```bash
+$ rustc --print native-static-libs --crate-type staticlib a.rs
+note: Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
+
+note: native-static-libs: -lgcc_s -lutil [REDACTED] -lpthread -lm -ldl -lc
+```
+
+## `link-args`
+
+This flag does not disable the `--emit` step. This can be useful when debugging linker options.
+
+When linking, this flag causes `rustc` to print the full linker invocation in a human-readable
+form. The exact format of this debugging output is not a stable guarantee, other than that it
+will include the linker executable and the text of each command-line argument passed to the
+linker.
+
+## `deployment-target`
+
+The currently selected [deployment target] (or minimum OS version) for the selected Apple
+platform target.
+
+This value can be used or passed along to other components alongside a Rust build that need
+this information, such as C compilers. This returns rustc's minimum supported deployment target
+if no `*_DEPLOYMENT_TARGET` variable is present in the environment, or otherwise returns the
+variable's parsed value.
+
+[conditional compilation]: ../../reference/conditional-compilation.html
+[deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index e8f8684740a..bc97568f85c 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -334,7 +334,7 @@ target | std | host | notes
 `mips64el-unknown-linux-muslabi64` | ✓ |  | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.3
 `mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
 [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * |  | MIPS (LE) Sony PlayStation 1 (PSX)
-`mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
+[`mipsel-unknown-linux-gnu`](platform-support/mipsel-unknown-linux-gnu.md) | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
 `mipsel-unknown-linux-musl` | ✓ |  | MIPS (little endian) Linux with musl 1.2.3
 `mipsel-unknown-linux-uclibc` | ✓ |  | MIPS (LE) Linux with uClibc
 [`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support
@@ -356,7 +356,7 @@ target | std | host | notes
 [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ |  |
 [`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
 [`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2)
-`powerpc64-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3
+[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | ✓ | ✓ | PPC64 Linux (kernel 4.19, musl 1.2.3)
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
 [`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 [`powerpc64le-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64LE FreeBSD
diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md
index dba2c4b2aaf..22c54d04b1e 100644
--- a/src/doc/rustc/src/platform-support/apple-darwin.md
+++ b/src/doc/rustc/src/platform-support/apple-darwin.md
@@ -70,4 +70,5 @@ the `-mmacosx-version-min=...`, `-miphoneos-version-min=...` or similar flags
 to disambiguate.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.
diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
index a54656190d1..79966d908d8 100644
--- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md
+++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
@@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding macOS SDK
 iOS-specific headers, as provided by Xcode 11 or higher.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.
 
 ### OS version
 
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index cfb458fdb73..7f5dc361c49 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -26,7 +26,8 @@ These targets are cross-compiled, and require the corresponding iOS SDK
 ARM64 targets, Xcode 12 or higher is required.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk iphoneos --show-sdk-path`.
 
 ### OS version
 
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
index 166bb1b6db2..fc46db20074 100644
--- a/src/doc/rustc/src/platform-support/apple-tvos.md
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding tvOS SDK
 ARM64 targets, Xcode 12 or higher is required.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk appletvos --show-sdk-path`.
 
 ### OS version
 
diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md
index a7bbae168a4..7cf9549227d 100644
--- a/src/doc/rustc/src/platform-support/apple-visionos.md
+++ b/src/doc/rustc/src/platform-support/apple-visionos.md
@@ -18,7 +18,8 @@ These targets are cross-compiled, and require the corresponding visionOS SDK
 (`XROS.sdk` or `XRSimulator.sdk`), as provided by Xcode 15 or newer.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk xros --show-sdk-path`.
 
 ### OS version
 
diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md
index 0bf8cdf3614..7b12d9ebfd4 100644
--- a/src/doc/rustc/src/platform-support/apple-watchos.md
+++ b/src/doc/rustc/src/platform-support/apple-watchos.md
@@ -24,7 +24,8 @@ These targets are cross-compiled, and require the corresponding watchOS SDK
 ARM64 targets, Xcode 12 or higher is required.
 
 The path to the SDK can be passed to `rustc` using the common `SDKROOT`
-environment variable.
+environment variable, or will be inferred when compiling on host macOS using
+roughly the same logic as `xcrun --sdk watchos --show-sdk-path`.
 
 ### OS version
 
diff --git a/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md
new file mode 100644
index 00000000000..b1ee8728c02
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/mipsel-unknown-linux-gnu.md
@@ -0,0 +1,28 @@
+# `mipsel-unknown-linux-gnu`
+
+**Tier: 3**
+
+Little-endian 32 bit MIPS for Linux with `glibc.
+
+## Target maintainers
+
+- [@LukasWoodtli](https://github.com/LukasWoodtli)
+
+## Requirements
+
+The target supports std on Linux. Host tools are supported but not tested.
+
+
+## Building the target
+
+For cross compilation the GNU C compiler for the mipsel architecture needs to
+be installed. On Ubuntu install the packets: `gcc-mipsel-linux-gnu` and
+`g++-mipsel-linux-gnu`.
+
+Add `mipsel-unknown-linux-gnu` as `target` list in `config.toml`.
+
+## Building Rust programs
+
+Rust does not ship pre-compiled artifacts for this target. To compile for
+this target, you will need to build Rust with the target enabled (see
+"Building the target" above).
diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md
index ef9337befa6..5c2ce0ee900 100644
--- a/src/doc/rustc/src/platform-support/netbsd.md
+++ b/src/doc/rustc/src/platform-support/netbsd.md
@@ -34,7 +34,7 @@ are built for NetBSD 8.x but also work on newer OS versions).
 ## Designated Developers
 
 - [@he32](https://github.com/he32), `he@NetBSD.org`
-- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust
+- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust185/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust
 - [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc.
 - [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself
 
diff --git a/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md
new file mode 100644
index 00000000000..0f78dcc089c
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/powerpc64-unknown-linux-musl.md
@@ -0,0 +1,52 @@
+# powerpc64-unknown-linux-musl
+
+**Tier: 3**
+
+Target for 64-bit big endian PowerPC Linux programs using musl libc.
+This target uses the ELF v2 ABI.
+
+## Target maintainers
+
+- [@Gelbpunkt](https://github.com/Gelbpunkt)
+- [@famfo](https://github.com/famfo)
+- [@neuschaefer](https://github.com/neuschaefer)
+
+## Requirements
+
+Building the target itself requires a 64-bit big endian PowerPC compiler that
+is supported by `cc-rs`.
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build.
+
+```toml
+[build]
+target = ["powerpc64-unknown-linux-musl"]
+```
+
+Make sure your C compiler is included in `$PATH`, then add it to the
+`bootstrap.toml`:
+
+```toml
+[target.powerpc64-unknown-linux-musl]
+cc = "powerpc64-linux-musl-gcc"
+cxx = "powerpc64-linux-musl-g++"
+ar = "powerpc64-linux-musl-ar"
+linker = "powerpc64-linux-musl-gcc"
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will first need to build Rust with the target enabled (see
+"Building the target" above).
+
+## Cross-compilation
+
+This target can be cross-compiled from any host.
+
+## Testing
+
+This target can be tested as normal with `x.py` on a 64-bit big endian PowerPC
+host or via QEMU emulation.
diff --git a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
index f4ed6201bbd..746b8443547 100644
--- a/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
@@ -26,8 +26,7 @@ only option because there is no FPU support in [Armv6-M].
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Cortex-M
-  Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
index 11c9486cb76..12e28265678 100644
--- a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
@@ -21,8 +21,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Cortex-M
-  Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
index b258033bb0f..03324b341d0 100644
--- a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md
@@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv7-M].
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Cortex-M
-  Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
index 0ae4e3e94bd..4a92e856466 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md
@@ -22,8 +22,7 @@ only option because there is no FPU support in [Armv8-M] Baseline.
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Cortex-M
-  Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
index 82fdc5b21cf..9f85d08fa0a 100644
--- a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
+++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md
@@ -25,8 +25,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
 
 ## Target maintainers
 
-* [Rust Embedded Devices Working Group Cortex-M
-  Team](https://github.com/rust-embedded), `cortex-m@teams.rust-embedded.org`
+* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
 
 ## Target CPU and Target Feature options
 
diff --git a/src/doc/unstable-book/src/compiler-flags/embed-metadata.md b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md
new file mode 100644
index 00000000000..a2a790ee76a
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md
@@ -0,0 +1,3 @@
+## `embed-metadata`
+
+This option instructs `rustc` to include the full metadata in `rlib` and `dylib` crate types. The default value is `yes` (enabled). If disabled (`no`), only stub metadata will be stored in these files, to reduce their size on disk. When using `-Zembed-metadata=no`, you will probably want to use `--emit=metadata` to produce the full metadata into a separate `.rmeta` file.
diff --git a/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md
new file mode 100644
index 00000000000..0bad8b8ab96
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md
@@ -0,0 +1,23 @@
+# `print=crate-root-lint-levels`
+
+The tracking issue for this feature is: [#139180](https://github.com/rust-lang/rust/issues/139180).
+
+------------------------
+
+This option of the `--print` flag print the list of lints with print out all the lints and their associated levels (`allow`, `warn`, `deny`, `forbid`) based on the regular Rust rules at crate root, that is *(roughly)*:
+ - command line args (`-W`, `-A`, `--force-warn`, `--cap-lints`, ...)
+ - crate root attributes (`#![allow]`, `#![warn]`, `#[expect]`, ...)
+ - *the special `warnings` lint group*
+ - the default lint level
+
+The output format is `LINT_NAME=LINT_LEVEL`, e.g.:
+```text
+unknown_lint=warn
+arithmetic_overflow=deny
+```
+
+To be used like this:
+
+```bash
+rustc --print=crate-root-lint-levels -Zunstable-options lib.rs
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md
new file mode 100644
index 00000000000..f285d6e7175
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/print-supported-crate-types.md
@@ -0,0 +1,27 @@
+# `print=supported-crate-types`
+
+The tracking issue for this feature is: [#138640](https://github.com/rust-lang/rust/issues/138640).
+
+------------------------
+
+This option of the `--print` flag produces a list of crate types (delimited by newlines) supported for the given target.
+
+The crate type strings correspond to the values accepted by the `--crate-type` flag.
+
+Intended to be used like this:
+
+```bash
+rustc --print=supported-crate-types -Zunstable-options --target=x86_64-unknown-linux-gnu
+```
+
+Example output for `x86_64-unknown-linux-gnu`:
+
+```text
+bin
+cdylib
+dylib
+lib
+proc-macro
+rlib
+staticlib
+```
diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md
deleted file mode 100644
index c6f54d79cfc..00000000000
--- a/src/doc/unstable-book/src/language-features/inline-const-pat.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# `inline_const_pat`
-
-The tracking issue for this feature is: [#76001]
-
-------
-
-This feature allows you to use inline constant expressions in pattern position:
-
-```rust
-#![feature(inline_const_pat)]
-
-const fn one() -> i32 { 1 }
-
-let some_int = 3;
-match some_int {
-    const { 1 + 2 } => println!("Matched 1 + 2"),
-    const { one() } => println!("Matched const fn returning 1"),
-    _ => println!("Didn't match anything :("),
-}
-```
-
-[#76001]: https://github.com/rust-lang/rust/issues/76001
diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md
deleted file mode 100644
index 77762116e6b..00000000000
--- a/src/doc/unstable-book/src/library-features/c-variadic.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# `c_variadic`
-
-The tracking issue for this feature is: [#44930]
-
-[#44930]: https://github.com/rust-lang/rust/issues/44930
-
-------------------------
-
-The `c_variadic` library feature exposes the `VaList` structure,
-Rust's analogue of C's `va_list` type.
-
-## Examples
-
-```rust
-#![feature(c_variadic)]
-
-use std::ffi::VaList;
-
-pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
-    let mut sum = 0;
-    for _ in 0..n {
-        sum += args.arg::<usize>();
-    }
-    sum
-}
-```
diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs
index f29e1e4d27a..64cceccc975 100644
--- a/src/etc/installer/msi/rust.wxs
+++ b/src/etc/installer/msi/rust.wxs
@@ -172,6 +172,19 @@
                     <!-- tool-rust-docs-end -->
                     <Directory Id="Cargo" Name="." />
                     <Directory Id="Std" Name="." />
+                    <?if $(env.CFG_RUSTFMT)="1" ?>
+                        <Directory Id="RustFmt" Name="." />
+                    <?endif?>
+                    <?if $(env.CFG_RA)="1" ?>
+                        <Directory Id="RustAnalyzer" Name="." />
+                    <?endif?>
+                    <?if $(env.CFG_MIRI)="1" ?>
+                        <Directory Id="Miri" Name="." />
+                    <?endif?>
+                    <Directory Id="Analysis" Name="." />
+                    <?if $(env.CFG_CLIPPY)="1" ?>
+                        <Directory Id="Clippy" Name="." />
+                    <?endif?>
                 </Directory>
             </Directory>
 
@@ -279,7 +292,49 @@
                  <ComponentRef Id="PathEnvPerMachine" />
                  <ComponentRef Id="PathEnvPerUser" />
         </Feature>
-
+        <?if $(env.CFG_RUSTFMT)="1" ?>
+            <Feature Id="RustFmt"
+                     Title="Formatter for rust"
+                     Display="7"
+                     Level="1"
+                     AllowAdvertise="no">
+                     <ComponentGroupRef Id="RustFmtGroup" />
+            </Feature>
+        <?endif?>
+        <?if $(env.CFG_CLIPPY)="1" ?>
+            <Feature Id="Clippy"
+                     Title="Formatter and checker for rust"
+                     Display="8"
+                     Level="1"
+                     AllowAdvertise="no">
+                     <ComponentGroupRef Id="ClippyGroup" />
+            </Feature>
+        <?endif?>
+        <?if $(env.CFG_MIRI)="1" ?>
+            <Feature Id="Miri"
+                     Title="Soundness checker for rust"
+                     Display="9"
+                     Level="1"
+                     AllowAdvertise="no">
+                     <ComponentGroupRef Id="MiriGroup" />
+            </Feature>
+        <?endif?>
+        <?if $(env.CFG_RA)="1" ?>
+            <Feature Id="RustAnalyzer"
+                     Title="Analyzer for rust"
+                     Display="10"
+                     Level="1"
+                     AllowAdvertise="no">
+                     <ComponentGroupRef Id="RustAnalyzerGroup" />
+            </Feature>
+        <?endif?>
+        <Feature Id="Analysis"
+                 Title="Analysis for rust"
+                 Display="11"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="AnalysisGroup" />
+        </Feature>
         <UIRef Id="RustUI" />
     </Product>
 </Wix>
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index bacb9e09f3f..8a9c5322ef7 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "test-float-parse"
 version = "0.1.0"
-edition = "2021"
+edition = "2024"
 publish = false
 
 [dependencies]
diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen_/exhaustive.rs
index 01458fb0b60..01458fb0b60 100644
--- a/src/etc/test-float-parse/src/gen/exhaustive.rs
+++ b/src/etc/test-float-parse/src/gen_/exhaustive.rs
diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen_/exponents.rs
index 3748e9d380c..3748e9d380c 100644
--- a/src/etc/test-float-parse/src/gen/exponents.rs
+++ b/src/etc/test-float-parse/src/gen_/exponents.rs
diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen_/fuzz.rs
index 1d6c5562a14..1d6c5562a14 100644
--- a/src/etc/test-float-parse/src/gen/fuzz.rs
+++ b/src/etc/test-float-parse/src/gen_/fuzz.rs
diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen_/integers.rs
index 070d188e88c..070d188e88c 100644
--- a/src/etc/test-float-parse/src/gen/integers.rs
+++ b/src/etc/test-float-parse/src/gen_/integers.rs
diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen_/long_fractions.rs
index b75148b779c..b75148b779c 100644
--- a/src/etc/test-float-parse/src/gen/long_fractions.rs
+++ b/src/etc/test-float-parse/src/gen_/long_fractions.rs
diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen_/many_digits.rs
index 741e11437fe..741e11437fe 100644
--- a/src/etc/test-float-parse/src/gen/many_digits.rs
+++ b/src/etc/test-float-parse/src/gen_/many_digits.rs
diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen_/sparse.rs
index 72b65d4ce7f..72b65d4ce7f 100644
--- a/src/etc/test-float-parse/src/gen/sparse.rs
+++ b/src/etc/test-float-parse/src/gen_/sparse.rs
diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen_/spot_checks.rs
index 18691f9d6cf..18691f9d6cf 100644
--- a/src/etc/test-float-parse/src/gen/spot_checks.rs
+++ b/src/etc/test-float-parse/src/gen_/spot_checks.rs
diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs
index 4fe3b90a3dd..4fe3b90a3dd 100644
--- a/src/etc/test-float-parse/src/gen/subnorm.rs
+++ b/src/etc/test-float-parse/src/gen_/subnorm.rs
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index e2f84b085c6..3c3ef5802b6 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -17,7 +17,7 @@ use traits::{Float, Generator, Int};
 use validate::CheckError;
 
 /// Test generators.
-mod gen {
+mod gen_ {
     pub mod exhaustive;
     pub mod exponents;
     pub mod fuzz;
@@ -136,24 +136,24 @@ where
 {
     if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
         // Only run exhaustive tests if there is a chance of completion.
-        TestInfo::register::<F, gen::exhaustive::Exhaustive<F>>(tests);
+        TestInfo::register::<F, gen_::exhaustive::Exhaustive<F>>(tests);
     }
 
-    gen::fuzz::Fuzz::<F>::set_iterations(cfg.fuzz_count);
-
-    TestInfo::register::<F, gen::exponents::LargeExponents<F>>(tests);
-    TestInfo::register::<F, gen::exponents::SmallExponents<F>>(tests);
-    TestInfo::register::<F, gen::fuzz::Fuzz<F>>(tests);
-    TestInfo::register::<F, gen::integers::LargeInt<F>>(tests);
-    TestInfo::register::<F, gen::integers::SmallInt>(tests);
-    TestInfo::register::<F, gen::long_fractions::RepeatingDecimal>(tests);
-    TestInfo::register::<F, gen::many_digits::RandDigits<F>>(tests);
-    TestInfo::register::<F, gen::sparse::FewOnesFloat<F>>(tests);
-    TestInfo::register::<F, gen::sparse::FewOnesInt<F>>(tests);
-    TestInfo::register::<F, gen::spot_checks::RegressionCheck>(tests);
-    TestInfo::register::<F, gen::spot_checks::Special>(tests);
-    TestInfo::register::<F, gen::subnorm::SubnormComplete<F>>(tests);
-    TestInfo::register::<F, gen::subnorm::SubnormEdgeCases<F>>(tests);
+    gen_::fuzz::Fuzz::<F>::set_iterations(cfg.fuzz_count);
+
+    TestInfo::register::<F, gen_::exponents::LargeExponents<F>>(tests);
+    TestInfo::register::<F, gen_::exponents::SmallExponents<F>>(tests);
+    TestInfo::register::<F, gen_::fuzz::Fuzz<F>>(tests);
+    TestInfo::register::<F, gen_::integers::LargeInt<F>>(tests);
+    TestInfo::register::<F, gen_::integers::SmallInt>(tests);
+    TestInfo::register::<F, gen_::long_fractions::RepeatingDecimal>(tests);
+    TestInfo::register::<F, gen_::many_digits::RandDigits<F>>(tests);
+    TestInfo::register::<F, gen_::sparse::FewOnesFloat<F>>(tests);
+    TestInfo::register::<F, gen_::sparse::FewOnesInt<F>>(tests);
+    TestInfo::register::<F, gen_::spot_checks::RegressionCheck>(tests);
+    TestInfo::register::<F, gen_::spot_checks::Special>(tests);
+    TestInfo::register::<F, gen_::subnorm::SubnormComplete<F>>(tests);
+    TestInfo::register::<F, gen_::subnorm::SubnormEdgeCases<F>>(tests);
 }
 
 /// Configuration for a single test.
@@ -343,7 +343,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
 ///
 /// This calls the generator's iterator multiple times (in parallel) and validates each output.
 fn test_runner<F: Float, G: Generator<F>>(test: &TestInfo, cfg: &Config) {
-    let gen = G::new();
+    let gen_ = G::new();
     let executed = AtomicU64::new(0);
     let failures = AtomicU64::new(0);
 
@@ -387,7 +387,7 @@ fn test_runner<F: Float, G: Generator<F>>(test: &TestInfo, cfg: &Config) {
 
     // Run the test iterations in parallel. Each thread gets a string buffer to write
     // its check values to.
-    let res = gen.par_bridge().try_for_each_init(String::new, check_one);
+    let res = gen_.par_bridge().try_for_each_init(String::new, check_one);
 
     let elapsed = started.elapsed();
     let executed = executed.into_inner();
diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs
index 1ee57723e6a..73473eef0bf 100644
--- a/src/etc/test-float-parse/src/ui.rs
+++ b/src/etc/test-float-parse/src/ui.rs
@@ -157,7 +157,7 @@ pub fn set_panic_hook(drop_bars: &[ProgressBar]) {
     }));
 }
 
-/// Allow non-Debug items in a `derive(Debug)` struct`.
+/// Allow non-Debug items in a `derive(Debug)` struct.
 #[derive(Clone)]
 struct NoDebug<T>(T);
 
diff --git a/src/gcc b/src/gcc
-Subproject 48664a6cab29d48138ffa004b7978d52ef73e3a
+Subproject 13cc8243226a9028bb08ab6c5e1c5fe6d533bcd
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 6ace626fdcd..a48f5c623cd 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -114,8 +114,8 @@ fn synthesize_auto_trait_impl<'tcx>(
     };
 
     Some(clean::Item {
-        name: None,
         inner: Box::new(clean::ItemInner {
+            name: None,
             attrs: Default::default(),
             stability: None,
             kind: clean::ImplItem(Box::new(clean::Impl {
@@ -127,10 +127,10 @@ fn synthesize_auto_trait_impl<'tcx>(
                 polarity,
                 kind: clean::ImplKind::Auto,
             })),
+            item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
+            cfg: None,
+            inline_stmt_id: None,
         }),
-        item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
-        cfg: None,
-        inline_stmt_id: None,
     })
 }
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index a6d9676dd84..89245fee515 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -83,9 +83,9 @@ pub(crate) fn synthesize_blanket_impls(
             cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));
 
             blanket_impls.push(clean::Item {
-                name: None,
-                item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                 inner: Box::new(clean::ItemInner {
+                    name: None,
+                    item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                     attrs: Default::default(),
                     stability: None,
                     kind: clean::ImplItem(Box::new(clean::Impl {
@@ -122,9 +122,9 @@ pub(crate) fn synthesize_blanket_impls(
                             None,
                         ))),
                     })),
+                    cfg: None,
+                    inline_stmt_id: None,
                 }),
-                cfg: None,
-                inline_stmt_id: None,
             });
         }
     }
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index ab169f3c2a4..1541e7201ce 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -8,7 +8,6 @@ use std::{mem, ops};
 
 use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_feature::Features;
 use rustc_session::parse::ParseSess;
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
@@ -132,18 +131,13 @@ impl Cfg {
     /// Checks whether the given configuration can be matched in the current session.
     ///
     /// Equivalent to `attr::cfg_matches`.
-    // FIXME: Actually make use of `features`.
-    pub(crate) fn matches(&self, psess: &ParseSess, features: Option<&Features>) -> bool {
+    pub(crate) fn matches(&self, psess: &ParseSess) -> bool {
         match *self {
             Cfg::False => false,
             Cfg::True => true,
-            Cfg::Not(ref child) => !child.matches(psess, features),
-            Cfg::All(ref sub_cfgs) => {
-                sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess, features))
-            }
-            Cfg::Any(ref sub_cfgs) => {
-                sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess, features))
-            }
+            Cfg::Not(ref child) => !child.matches(psess),
+            Cfg::All(ref sub_cfgs) => sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess)),
+            Cfg::Any(ref sub_cfgs) => sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess)),
             Cfg::Cfg(name, value) => psess.config.contains(&(name, value)),
         }
     }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e973b89b237..e0e09b53fc2 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -151,7 +151,7 @@ pub(crate) fn try_inline(
     let mut item =
         crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None);
     // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
-    item.inline_stmt_id = import_def_id;
+    item.inner.inline_stmt_id = import_def_id;
     ret.push(item);
     Some(ret)
 }
@@ -211,17 +211,7 @@ pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir:
 }
 
 pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
-    tcx.def_path(def_id)
-        .data
-        .into_iter()
-        .filter_map(|elem| {
-            // extern blocks (and a few others things) have an empty name.
-            match elem.data.get_opt_name() {
-                Some(s) if !s.is_empty() => Some(s),
-                _ => None,
-            }
-        })
-        .collect()
+    tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect()
 }
 
 /// Record an external fully qualified name in the external_paths cache.
@@ -665,11 +655,11 @@ fn build_module_items(
                 // Primitive types can't be inlined so generate an import instead.
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
-                    name: None,
-                    // We can use the item's `DefId` directly since the only information ever used
-                    // from it is `DefId.krate`.
-                    item_id: ItemId::DefId(did),
                     inner: Box::new(clean::ItemInner {
+                        name: None,
+                        // We can use the item's `DefId` directly since the only information ever
+                        // used from it is `DefId.krate`.
+                        item_id: ItemId::DefId(did),
                         attrs: Default::default(),
                         stability: None,
                         kind: clean::ImportItem(clean::Import::new_simple(
@@ -689,9 +679,9 @@ fn build_module_items(
                             },
                             true,
                         )),
+                        cfg: None,
+                        inline_stmt_id: None,
                     }),
-                    cfg: None,
-                    inline_stmt_id: None,
                 });
             } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
                 items.extend(i)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index de6dc088176..c08ae168d69 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -210,7 +210,7 @@ fn generate_item_with_correct_attrs(
 
     let name = renamed.or(Some(name));
     let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
-    item.inline_stmt_id = import_id;
+    item.inner.inline_stmt_id = import_id;
     item
 }
 
@@ -1943,14 +1943,11 @@ fn clean_trait_object_lifetime_bound<'tcx>(
     // latter contrary to `clean_middle_region`.
     match *region {
         ty::ReStatic => Some(Lifetime::statik()),
-        ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)),
-        ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. })
-            if name != kw::Empty =>
-        {
+        ty::ReEarlyParam(region) => Some(Lifetime(region.name)),
+        ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => {
             Some(Lifetime(name))
         }
-        ty::ReEarlyParam(_)
-        | ty::ReBound(..)
+        ty::ReBound(..)
         | ty::ReLateParam(_)
         | ty::ReVar(_)
         | ty::RePlaceholder(_)
@@ -2773,7 +2770,7 @@ fn add_without_unwanted_attributes<'hir>(
                 if ident == sym::doc {
                     filter_doc_attr(&mut normal.args, is_inline);
                     attrs.push((Cow::Owned(attr), import_parent));
-                } else if is_inline || ident != sym::cfg {
+                } else if is_inline || ident != sym::cfg_trace {
                     // If it's not a `cfg()` attribute, we keep it.
                     attrs.push((Cow::Owned(attr), import_parent));
                 }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3b2dcb3db81..d3ddb77c0b3 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -311,26 +311,31 @@ pub(crate) enum ExternalLocation {
 /// directly to the AST's concept of an item; it's a strict superset.
 #[derive(Clone)]
 pub(crate) struct Item {
-    /// The name of this item.
-    /// Optional because not every item has a name, e.g. impls.
-    pub(crate) name: Option<Symbol>,
     pub(crate) inner: Box<ItemInner>,
-    pub(crate) item_id: ItemId,
-    /// This is the `LocalDefId` of the `use` statement if the item was inlined.
-    /// The crate metadata doesn't hold this information, so the `use` statement
-    /// always belongs to the current crate.
-    pub(crate) inline_stmt_id: Option<LocalDefId>,
-    pub(crate) cfg: Option<Arc<Cfg>>,
 }
 
+// Why does the `Item`/`ItemInner` split exist? `Vec<Item>`s are common, and
+// without the split `Item` would be a large type (100+ bytes) which results in
+// lots of wasted space in the unused parts of a `Vec<Item>`. With the split,
+// `Item` is just 8 bytes, and the wasted space is avoided, at the cost of an
+// extra allocation per item. This is a performance win.
 #[derive(Clone)]
 pub(crate) struct ItemInner {
+    /// The name of this item.
+    /// Optional because not every item has a name, e.g. impls.
+    pub(crate) name: Option<Symbol>,
     /// Information about this item that is specific to what kind of item it is.
     /// E.g., struct vs enum vs function.
     pub(crate) kind: ItemKind,
     pub(crate) attrs: Attributes,
     /// The effective stability, filled out by the `propagate-stability` pass.
     pub(crate) stability: Option<Stability>,
+    pub(crate) item_id: ItemId,
+    /// This is the `LocalDefId` of the `use` statement if the item was inlined.
+    /// The crate metadata doesn't hold this information, so the `use` statement
+    /// always belongs to the current crate.
+    pub(crate) inline_stmt_id: Option<LocalDefId>,
+    pub(crate) cfg: Option<Arc<Cfg>>,
 }
 
 impl std::ops::Deref for Item {
@@ -362,10 +367,7 @@ impl fmt::Debug for Item {
 pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
     Span::new(def_id.as_local().map_or_else(
         || tcx.def_span(def_id),
-        |local| {
-            let hir = tcx.hir();
-            hir.span_with_body(tcx.local_def_id_to_hir_id(local))
-        },
+        |local| tcx.hir_span_with_body(tcx.local_def_id_to_hir_id(local)),
     ))
 }
 
@@ -488,11 +490,15 @@ impl Item {
         trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
 
         Item {
-            item_id: def_id.into(),
-            inner: Box::new(ItemInner { kind, attrs, stability: None }),
-            name,
-            cfg,
-            inline_stmt_id: None,
+            inner: Box::new(ItemInner {
+                item_id: def_id.into(),
+                kind,
+                attrs,
+                stability: None,
+                name,
+                cfg,
+                inline_stmt_id: None,
+            }),
         }
     }
 
@@ -768,12 +774,22 @@ impl Item {
             .iter()
             .filter_map(|attr| {
                 if is_json {
-                    if matches!(attr, hir::Attribute::Parsed(AttributeKind::Deprecation { .. })) {
-                        // rustdoc-json stores this in `Item::deprecation`, so we
-                        // don't want it it `Item::attrs`.
-                        None
-                    } else {
-                        Some(rustc_hir_pretty::attribute_to_string(&tcx, attr))
+                    match attr {
+                        hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => {
+                            // rustdoc-json stores this in `Item::deprecation`, so we
+                            // don't want it it `Item::attrs`.
+                            None
+                        }
+                        rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
+                            ..,
+                        )) => {
+                            // We have separate pretty-printing logic for `#[repr(..)]` attributes.
+                            // For example, there are circumstances where `#[repr(transparent)]`
+                            // is applied but should not be publicly shown in rustdoc
+                            // because it isn't public API.
+                            None
+                        }
+                        _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
                     }
                 } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
                     Some(
@@ -789,8 +805,7 @@ impl Item {
             .collect();
 
         // Add #[repr(...)]
-        if !is_json
-            && let Some(def_id) = self.def_id()
+        if let Some(def_id) = self.def_id()
             && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
         {
             let adt = tcx.adt_def(def_id);
@@ -1004,7 +1019,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
     tcx: TyCtxt<'_>,
     hidden_cfg: &FxHashSet<Cfg>,
 ) -> Option<Arc<Cfg>> {
-    let sess = tcx.sess;
     let doc_cfg_active = tcx.features().doc_cfg();
     let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
 
@@ -1025,15 +1039,33 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
             .filter(|attr| attr.has_name(sym::cfg))
             .peekable();
         if doc_cfg.peek().is_some() && doc_cfg_active {
-            doc_cfg
-                .filter_map(|attr| Cfg::parse(&attr).ok())
-                .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+            let sess = tcx.sess;
+            doc_cfg.fold(Cfg::True, |mut cfg, item| {
+                if let Some(cfg_mi) =
+                    item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
+                {
+                    // The result is unused here but we can gate unstable predicates
+                    rustc_attr_parsing::cfg_matches(
+                        cfg_mi,
+                        tcx.sess,
+                        rustc_ast::CRATE_NODE_ID,
+                        Some(tcx.features()),
+                    );
+                    match Cfg::parse(cfg_mi) {
+                        Ok(new_cfg) => cfg &= new_cfg,
+                        Err(e) => {
+                            sess.dcx().span_err(e.span, e.msg);
+                        }
+                    }
+                }
+                cfg
+            })
         } else if doc_auto_cfg_active {
             // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
             // `doc(cfg())` overrides `cfg()`).
             attrs
                 .clone()
-                .filter(|attr| attr.has_name(sym::cfg))
+                .filter(|attr| attr.has_name(sym::cfg_trace))
                 .filter_map(|attr| single(attr.meta_item_list()?))
                 .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
                 .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
@@ -1044,33 +1076,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
         Cfg::True
     };
 
-    for attr in attrs.clone() {
-        // #[doc]
-        if attr.doc_str().is_none() && attr.has_name(sym::doc) {
-            // #[doc(...)]
-            if let Some(list) = attr.meta_item_list() {
-                for item in list {
-                    // #[doc(hidden)]
-                    if !item.has_name(sym::cfg) {
-                        continue;
-                    }
-                    // #[doc(cfg(...))]
-                    if let Some(cfg_mi) = item
-                        .meta_item()
-                        .and_then(|item| rustc_expand::config::parse_cfg(item, sess))
-                    {
-                        match Cfg::parse(cfg_mi) {
-                            Ok(new_cfg) => cfg &= new_cfg,
-                            Err(e) => {
-                                sess.dcx().span_err(e.span, e.msg);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     // treat #[target_feature(enable = "feat")] attributes as if they were
     // #[doc(cfg(target_feature = "feat"))] attributes as well
     for attr in hir_attr_lists(attrs, sym::target_feature) {
@@ -1536,6 +1541,10 @@ impl Type {
         matches!(self, Type::BorrowedRef { .. })
     }
 
+    fn is_type_alias(&self) -> bool {
+        matches!(self, Type::Path { path: Path { res: Res::Def(DefKind::TyAlias, _), .. } })
+    }
+
     /// Check if two types are "the same" for documentation purposes.
     ///
     /// This is different from `Eq`, because it knows that things like
@@ -1564,6 +1573,16 @@ impl Type {
         } else {
             (self, other)
         };
+
+        // FIXME: `Cache` does not have the data required to unwrap type aliases,
+        // so we just assume they are equal.
+        // This is only remotely acceptable because we were previously
+        // assuming all types were equal when used
+        // as a generic parameter of a type in `Deref::Target`.
+        if self_cleared.is_type_alias() || other_cleared.is_type_alias() {
+            return true;
+        }
+
         match (self_cleared, other_cleared) {
             // Recursive cases.
             (Type::Tuple(a), Type::Tuple(b)) => {
@@ -2609,13 +2628,14 @@ mod size_asserts {
 
     use super::*;
     // tidy-alphabetical-start
-    static_assert_size!(Crate, 56); // frequently moved by-value
+    static_assert_size!(Crate, 16); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
     static_assert_size!(GenericArg, 32);
     static_assert_size!(GenericArgs, 24);
     static_assert_size!(GenericParamDef, 40);
     static_assert_size!(Generics, 16);
-    static_assert_size!(Item, 48);
+    static_assert_size!(Item, 8);
+    static_assert_size!(ItemInner, 136);
     static_assert_size!(ItemKind, 48);
     static_assert_size!(PathSegment, 32);
     static_assert_size!(Type, 32);
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 9935074877b..4edd5433de6 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -5,22 +5,36 @@ use std::fmt::{self, Write as _};
 use std::io;
 use std::sync::Arc;
 
-use rustc_ast as ast;
+use rustc_ast::token::{Delimiter, TokenKind};
+use rustc_ast::tokenstream::TokenTree;
+use rustc_ast::{self as ast, AttrStyle, HasAttrs, StmtKind};
+use rustc_errors::ColorConfig;
 use rustc_errors::emitter::stderr_destination;
-use rustc_errors::{ColorConfig, FatalError};
 use rustc_parse::new_parser_from_source_str;
-use rustc_parse::parser::attr::InnerAttrPolicy;
 use rustc_session::parse::ParseSess;
-use rustc_span::FileName;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
+use rustc_span::{FileName, kw};
 use tracing::debug;
 
 use super::GlobalTestOptions;
 use crate::display::Joined as _;
 use crate::html::markdown::LangString;
 
+#[derive(Default)]
+struct ParseSourceInfo {
+    has_main_fn: bool,
+    already_has_extern_crate: bool,
+    supports_color: bool,
+    has_global_allocator: bool,
+    has_macro_def: bool,
+    everything_else: String,
+    crates: String,
+    crate_attrs: String,
+    maybe_crate_attrs: String,
+}
+
 /// This struct contains information about the doctest itself which is then used to generate
 /// doctest source code appropriately.
 pub(crate) struct DocTestBuilder {
@@ -34,7 +48,7 @@ pub(crate) struct DocTestBuilder {
     pub(crate) crates: String,
     pub(crate) everything_else: String,
     pub(crate) test_id: Option<String>,
-    pub(crate) failed_ast: bool,
+    pub(crate) invalid_ast: bool,
     pub(crate) can_be_merged: bool,
 }
 
@@ -53,9 +67,26 @@ impl DocTestBuilder {
                 !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate
             });
 
-        let Some(SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else }) =
-            partition_source(source, edition)
+        let result = rustc_driver::catch_fatal_errors(|| {
+            rustc_span::create_session_if_not_set_then(edition, |_| {
+                parse_source(source, &crate_name)
+            })
+        });
+
+        let Ok(Ok(ParseSourceInfo {
+            has_main_fn,
+            already_has_extern_crate,
+            supports_color,
+            has_global_allocator,
+            has_macro_def,
+            everything_else,
+            crates,
+            crate_attrs,
+            maybe_crate_attrs,
+        })) = result
         else {
+            // If the AST returned an error, we don't want this doctest to be merged with the
+            // others.
             return Self::invalid(
                 String::new(),
                 String::new(),
@@ -65,35 +96,12 @@ impl DocTestBuilder {
             );
         };
 
-        // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
-        // crate already is included.
-        let Ok((
-            ParseSourceInfo {
-                has_main_fn,
-                found_extern_crate,
-                supports_color,
-                has_global_allocator,
-                has_macro_def,
-                ..
-            },
-            failed_ast,
-        )) = check_for_main_and_extern_crate(
-            crate_name,
-            source,
-            &everything_else,
-            &crates,
-            edition,
-            can_merge_doctests,
-        )
-        else {
-            // If the parser panicked due to a fatal error, pass the test code through unchanged.
-            // The error will be reported during compilation.
-            return Self::invalid(crate_attrs, maybe_crate_attrs, crates, everything_else, test_id);
-        };
-        // If the AST returned an error, we don't want this doctest to be merged with the
-        // others. Same if it contains `#[feature]` or `#[no_std]`.
+        debug!("crate_attrs:\n{crate_attrs}{maybe_crate_attrs}");
+        debug!("crates:\n{crates}");
+        debug!("after:\n{everything_else}");
+
+        // If it contains `#[feature]` or `#[no_std]`, we don't want it to be merged either.
         let can_be_merged = can_merge_doctests
-            && !failed_ast
             && !has_global_allocator
             && crate_attrs.is_empty()
             // If this is a merged doctest and a defined macro uses `$crate`, then the path will
@@ -106,9 +114,9 @@ impl DocTestBuilder {
             maybe_crate_attrs,
             crates,
             everything_else,
-            already_has_extern_crate: found_extern_crate,
+            already_has_extern_crate,
             test_id,
-            failed_ast: false,
+            invalid_ast: false,
             can_be_merged,
         }
     }
@@ -129,7 +137,7 @@ impl DocTestBuilder {
             everything_else,
             already_has_extern_crate: false,
             test_id,
-            failed_ast: true,
+            invalid_ast: true,
             can_be_merged: false,
         }
     }
@@ -143,9 +151,10 @@ impl DocTestBuilder {
         opts: &GlobalTestOptions,
         crate_name: Option<&str>,
     ) -> (String, usize) {
-        if self.failed_ast {
+        if self.invalid_ast {
             // If the AST failed to compile, no need to go generate a complete doctest, the error
             // will be better this way.
+            debug!("invalid AST:\n{test_code}");
             return (test_code.to_string(), 0);
         }
         let mut line_offset = 0;
@@ -168,9 +177,24 @@ impl DocTestBuilder {
 
         // Now push any outer attributes from the example, assuming they
         // are intended to be crate attributes.
-        prog.push_str(&self.crate_attrs);
-        prog.push_str(&self.maybe_crate_attrs);
-        prog.push_str(&self.crates);
+        if !self.crate_attrs.is_empty() {
+            prog.push_str(&self.crate_attrs);
+            if !self.crate_attrs.ends_with('\n') {
+                prog.push('\n');
+            }
+        }
+        if !self.maybe_crate_attrs.is_empty() {
+            prog.push_str(&self.maybe_crate_attrs);
+            if !self.maybe_crate_attrs.ends_with('\n') {
+                prog.push('\n');
+            }
+        }
+        if !self.crates.is_empty() {
+            prog.push_str(&self.crates);
+            if !self.crates.ends_with('\n') {
+                prog.push('\n');
+            }
+        }
 
         // Don't inject `extern crate std` because it's already injected by the
         // compiler.
@@ -255,14 +279,7 @@ impl DocTestBuilder {
     }
 }
 
-#[derive(PartialEq, Eq, Debug)]
-enum ParsingResult {
-    Failed,
-    AstError,
-    Ok,
-}
-
-fn cancel_error_count(psess: &ParseSess) {
+fn reset_error_count(psess: &ParseSess) {
     // Reset errors so that they won't be reported as compiler bugs when dropping the
     // dcx. Any errors in the tests will be reported when the test file is compiled,
     // Note that we still need to cancel the errors above otherwise `Diag` will panic on
@@ -270,17 +287,19 @@ fn cancel_error_count(psess: &ParseSess) {
     psess.dcx().reset_err_count();
 }
 
-fn parse_source(
-    source: String,
-    info: &mut ParseSourceInfo,
-    crate_name: &Option<&str>,
-) -> ParsingResult {
+const DOCTEST_CODE_WRAPPER: &str = "fn f(){";
+
+fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceInfo, ()> {
     use rustc_errors::DiagCtxt;
     use rustc_errors::emitter::{Emitter, HumanEmitter};
-    use rustc_parse::parser::ForceCollect;
     use rustc_span::source_map::FilePathMapping;
 
-    let filename = FileName::anon_source_code(&source);
+    let mut info =
+        ParseSourceInfo { already_has_extern_crate: crate_name.is_none(), ..Default::default() };
+
+    let wrapped_source = format!("{DOCTEST_CODE_WRAPPER}{source}\n}}");
+
+    let filename = FileName::anon_source_code(&wrapped_source);
 
     // Any errors in parsing should also appear when the doctest is compiled for real, so just
     // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
@@ -299,25 +318,32 @@ fn parse_source(
     let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
     let psess = ParseSess::with_dcx(dcx, sm);
 
-    let mut parser = match new_parser_from_source_str(&psess, filename, source) {
+    let mut parser = match new_parser_from_source_str(&psess, filename, wrapped_source) {
         Ok(p) => p,
         Err(errs) => {
             errs.into_iter().for_each(|err| err.cancel());
-            cancel_error_count(&psess);
-            return ParsingResult::Failed;
+            reset_error_count(&psess);
+            return Err(());
         }
     };
-    let mut parsing_result = ParsingResult::Ok;
+
+    fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi: &mut usize) {
+        let extra_len = DOCTEST_CODE_WRAPPER.len();
+        // We need to shift by the length of `DOCTEST_CODE_WRAPPER` because we
+        // added it at the beginning of the source we provided to the parser.
+        let mut hi = span.hi().0 as usize - extra_len;
+        if hi > source.len() {
+            hi = source.len();
+        }
+        s.push_str(&source[*prev_span_hi..hi]);
+        *prev_span_hi = hi;
+    }
 
     // Recurse through functions body. It is necessary because the doctest source code is
     // wrapped in a function to limit the number of AST errors. If we don't recurse into
     // functions, we would thing all top-level items (so basically nothing).
-    fn check_item(
-        item: &ast::Item,
-        info: &mut ParseSourceInfo,
-        crate_name: &Option<&str>,
-        is_top_level: bool,
-    ) {
+    fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {
+        let mut is_extern_crate = false;
         if !info.has_global_allocator
             && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
         {
@@ -325,320 +351,130 @@ fn parse_source(
         }
         match item.kind {
             ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => {
-                if item.ident.name == sym::main && is_top_level {
+                // We only push if it's the top item because otherwise, we would duplicate
+                // its content since the top-level item was already added.
+                if fn_item.ident.name == sym::main {
                     info.has_main_fn = true;
                 }
-                if let Some(ref body) = fn_item.body {
-                    for stmt in &body.stmts {
-                        match stmt.kind {
-                            ast::StmtKind::Item(ref item) => {
-                                check_item(item, info, crate_name, false)
-                            }
-                            ast::StmtKind::MacCall(..) => info.found_macro = true,
-                            _ => {}
-                        }
-                    }
-                }
             }
-            ast::ItemKind::ExternCrate(original) => {
-                if !info.found_extern_crate
+            ast::ItemKind::ExternCrate(original, ident) => {
+                is_extern_crate = true;
+                if !info.already_has_extern_crate
                     && let Some(crate_name) = crate_name
                 {
-                    info.found_extern_crate = match original {
+                    info.already_has_extern_crate = match original {
                         Some(name) => name.as_str() == *crate_name,
-                        None => item.ident.as_str() == *crate_name,
+                        None => ident.as_str() == *crate_name,
                     };
                 }
             }
-            ast::ItemKind::MacCall(..) => info.found_macro = true,
-            ast::ItemKind::MacroDef(..) => info.has_macro_def = true,
+            ast::ItemKind::MacroDef(..) => {
+                info.has_macro_def = true;
+            }
             _ => {}
         }
+        is_extern_crate
     }
 
-    loop {
-        match parser.parse_item(ForceCollect::No) {
-            Ok(Some(item)) => {
-                check_item(&item, info, crate_name, true);
+    let mut prev_span_hi = 0;
+    let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
+    let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No);
 
-                if info.has_main_fn && info.found_extern_crate {
-                    break;
+    let result = match parsed {
+        Ok(Some(ref item))
+            if let ast::ItemKind::Fn(ref fn_item) = item.kind
+                && let Some(ref body) = fn_item.body =>
+        {
+            for attr in &item.attrs {
+                let attr_name = attr.name_or_empty();
+
+                if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) {
+                    // There is one exception to these attributes:
+                    // `#![allow(internal_features)]`. If this attribute is used, we need to
+                    // consider it only as a crate-level attribute.
+                    if attr_name == sym::allow
+                        && let Some(list) = attr.meta_item_list()
+                        && list.iter().any(|sub_attr| {
+                            sub_attr.name_or_empty().as_str() == "internal_features"
+                        })
+                    {
+                        push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
+                    } else {
+                        push_to_s(
+                            &mut info.maybe_crate_attrs,
+                            source,
+                            attr.span,
+                            &mut prev_span_hi,
+                        );
+                    }
+                } else {
+                    push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
                 }
             }
-            Ok(None) => break,
-            Err(e) => {
-                parsing_result = ParsingResult::AstError;
-                e.cancel();
-                break;
-            }
-        }
-
-        // The supplied item is only used for diagnostics,
-        // which are swallowed here anyway.
-        parser.maybe_consume_incorrect_semicolon(None);
-    }
-
-    cancel_error_count(&psess);
-    parsing_result
-}
-
-#[derive(Default)]
-struct ParseSourceInfo {
-    has_main_fn: bool,
-    found_extern_crate: bool,
-    found_macro: bool,
-    supports_color: bool,
-    has_global_allocator: bool,
-    has_macro_def: bool,
-}
-
-fn check_for_main_and_extern_crate(
-    crate_name: Option<&str>,
-    original_source_code: &str,
-    everything_else: &str,
-    crates: &str,
-    edition: Edition,
-    can_merge_doctests: bool,
-) -> Result<(ParseSourceInfo, bool), FatalError> {
-    let result = rustc_driver::catch_fatal_errors(|| {
-        rustc_span::create_session_if_not_set_then(edition, |_| {
-            let mut info =
-                ParseSourceInfo { found_extern_crate: crate_name.is_none(), ..Default::default() };
-
-            let mut parsing_result =
-                parse_source(format!("{crates}{everything_else}"), &mut info, &crate_name);
-            // No need to double-check this if the "merged doctests" feature isn't enabled (so
-            // before the 2024 edition).
-            if can_merge_doctests && parsing_result != ParsingResult::Ok {
-                // If we found an AST error, we want to ensure it's because of an expression being
-                // used outside of a function.
-                //
-                // To do so, we wrap in a function in order to make sure that the doctest AST is
-                // correct. For example, if your doctest is `foo::bar()`, if we don't wrap it in a
-                // block, it would emit an AST error, which would be problematic for us since we
-                // want to filter out such errors which aren't "real" errors.
-                //
-                // The end goal is to be able to merge as many doctests as possible as one for much
-                // faster doctests run time.
-                parsing_result = parse_source(
-                    format!("{crates}\nfn __doctest_wrap(){{{everything_else}\n}}"),
-                    &mut info,
-                    &crate_name,
-                );
-            }
-
-            (info, parsing_result)
-        })
-    });
-    let (mut info, parsing_result) = match result {
-        Err(..) | Ok((_, ParsingResult::Failed)) => return Err(FatalError),
-        Ok((info, parsing_result)) => (info, parsing_result),
-    };
-
-    // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
-    // see it. In that case, run the old text-based scan to see if they at least have a main
-    // function written inside a macro invocation. See
-    // https://github.com/rust-lang/rust/issues/56898
-    if info.found_macro
-        && !info.has_main_fn
-        && original_source_code
-            .lines()
-            .map(|line| {
-                let comment = line.find("//");
-                if let Some(comment_begins) = comment { &line[0..comment_begins] } else { line }
-            })
-            .any(|code| code.contains("fn main"))
-    {
-        info.has_main_fn = true;
-    }
-
-    Ok((info, parsing_result != ParsingResult::Ok))
-}
-
-enum AttrKind {
-    CrateAttr,
-    Attr,
-}
-
-/// Returns `Some` if the attribute is complete and `Some(true)` if it is an attribute that can be
-/// placed at the crate root.
-fn check_if_attr_is_complete(source: &str, edition: Edition) -> Option<AttrKind> {
-    if source.is_empty() {
-        // Empty content so nothing to check in here...
-        return None;
-    }
-    let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny];
-
-    rustc_driver::catch_fatal_errors(|| {
-        rustc_span::create_session_if_not_set_then(edition, |_| {
-            use rustc_errors::DiagCtxt;
-            use rustc_errors::emitter::HumanEmitter;
-            use rustc_span::source_map::FilePathMapping;
-
-            let filename = FileName::anon_source_code(source);
-            // Any errors in parsing should also appear when the doctest is compiled for real, so just
-            // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
-            let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
-            let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-                rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-                false,
-            );
-
-            let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
-
-            let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
-            let psess = ParseSess::with_dcx(dcx, sm);
-            let mut parser = match new_parser_from_source_str(&psess, filename, source.to_owned()) {
-                Ok(p) => p,
-                Err(errs) => {
-                    errs.into_iter().for_each(|err| err.cancel());
-                    // If there is an unclosed delimiter, an error will be returned by the
-                    // tokentrees.
-                    return None;
-                }
-            };
-            // If a parsing error happened, it's very likely that the attribute is incomplete.
-            let ret = match parser.parse_attribute(InnerAttrPolicy::Permitted) {
-                Ok(attr) => {
-                    let attr_name = attr.name_or_empty();
-
-                    if not_crate_attrs.contains(&attr_name) {
-                        // There is one exception to these attributes:
-                        // `#![allow(internal_features)]`. If this attribute is used, we need to
-                        // consider it only as a crate-level attribute.
-                        if attr_name == sym::allow
-                            && let Some(list) = attr.meta_item_list()
-                            && list.iter().any(|sub_attr| {
-                                sub_attr.name_or_empty().as_str() == "internal_features"
-                            })
-                        {
-                            Some(AttrKind::CrateAttr)
-                        } else {
-                            Some(AttrKind::Attr)
+            for stmt in &body.stmts {
+                let mut is_extern_crate = false;
+                match stmt.kind {
+                    StmtKind::Item(ref item) => {
+                        is_extern_crate = check_item(&item, &mut info, crate_name);
+                    }
+                    StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => {
+                        reset_error_count(&psess);
+                        return Err(());
+                    }
+                    StmtKind::MacCall(ref mac_call) if !info.has_main_fn => {
+                        let mut iter = mac_call.mac.args.tokens.iter();
+
+                        while let Some(token) = iter.next() {
+                            if let TokenTree::Token(token, _) = token
+                                && let TokenKind::Ident(name, _) = token.kind
+                                && name == kw::Fn
+                                && let Some(TokenTree::Token(fn_token, _)) = iter.peek()
+                                && let TokenKind::Ident(fn_name, _) = fn_token.kind
+                                && fn_name == sym::main
+                                && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = {
+                                    iter.next();
+                                    iter.peek()
+                                }
+                            {
+                                info.has_main_fn = true;
+                                break;
+                            }
                         }
-                    } else {
-                        Some(AttrKind::CrateAttr)
                     }
+                    _ => {}
                 }
-                Err(e) => {
-                    e.cancel();
-                    None
-                }
-            };
-            ret
-        })
-    })
-    .unwrap_or(None)
-}
 
-fn handle_attr(mod_attr_pending: &mut String, source_info: &mut SourceInfo, edition: Edition) {
-    if let Some(attr_kind) = check_if_attr_is_complete(mod_attr_pending, edition) {
-        let push_to = match attr_kind {
-            AttrKind::CrateAttr => &mut source_info.crate_attrs,
-            AttrKind::Attr => &mut source_info.maybe_crate_attrs,
-        };
-        push_to.push_str(mod_attr_pending);
-        push_to.push('\n');
-        // If it's complete, then we can clear the pending content.
-        mod_attr_pending.clear();
-    } else {
-        mod_attr_pending.push('\n');
-    }
-}
-
-#[derive(Default)]
-struct SourceInfo {
-    crate_attrs: String,
-    maybe_crate_attrs: String,
-    crates: String,
-    everything_else: String,
-}
-
-fn partition_source(s: &str, edition: Edition) -> Option<SourceInfo> {
-    #[derive(Copy, Clone, PartialEq)]
-    enum PartitionState {
-        Attrs,
-        Crates,
-        Other,
-    }
-    let mut source_info = SourceInfo::default();
-    let mut state = PartitionState::Attrs;
-    let mut mod_attr_pending = String::new();
-
-    for line in s.lines() {
-        let trimline = line.trim();
-
-        // FIXME(misdreavus): if a doc comment is placed on an extern crate statement, it will be
-        // shunted into "everything else"
-        match state {
-            PartitionState::Attrs => {
-                state = if trimline.starts_with("#![") {
-                    mod_attr_pending = line.to_owned();
-                    handle_attr(&mut mod_attr_pending, &mut source_info, edition);
-                    continue;
-                } else if trimline.chars().all(|c| c.is_whitespace())
-                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
+                // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to
+                // tweak the span to include the attributes as well.
+                let mut span = stmt.span;
+                if let Some(attr) =
+                    stmt.kind.attrs().iter().find(|attr| attr.style == AttrStyle::Outer)
                 {
-                    PartitionState::Attrs
-                } else if trimline.starts_with("extern crate")
-                    || trimline.starts_with("#[macro_use] extern crate")
-                {
-                    PartitionState::Crates
-                } else {
-                    // First we check if the previous attribute was "complete"...
-                    if !mod_attr_pending.is_empty() {
-                        // If not, then we append the new line into the pending attribute to check
-                        // if this time it's complete...
-                        mod_attr_pending.push_str(line);
-                        if !trimline.is_empty() {
-                            handle_attr(&mut mod_attr_pending, &mut source_info, edition);
-                        }
-                        continue;
-                    } else {
-                        PartitionState::Other
-                    }
-                };
-            }
-            PartitionState::Crates => {
-                state = if trimline.starts_with("extern crate")
-                    || trimline.starts_with("#[macro_use] extern crate")
-                    || trimline.chars().all(|c| c.is_whitespace())
-                    || (trimline.starts_with("//") && !trimline.starts_with("///"))
+                    span = span.with_lo(attr.span.lo());
+                }
+                if info.everything_else.is_empty()
+                    && (!info.maybe_crate_attrs.is_empty() || !info.crate_attrs.is_empty())
                 {
-                    PartitionState::Crates
+                    // To keep the doctest code "as close as possible" to the original, we insert
+                    // all the code located between this new span and the previous span which
+                    // might contain code comments and backlines.
+                    push_to_s(&mut info.crates, source, span.shrink_to_lo(), &mut prev_span_hi);
+                }
+                if !is_extern_crate {
+                    push_to_s(&mut info.everything_else, source, span, &mut prev_span_hi);
                 } else {
-                    PartitionState::Other
-                };
+                    push_to_s(&mut info.crates, source, span, &mut prev_span_hi);
+                }
             }
-            PartitionState::Other => {}
+            Ok(info)
         }
-
-        match state {
-            PartitionState::Attrs => {
-                source_info.crate_attrs.push_str(line);
-                source_info.crate_attrs.push('\n');
-            }
-            PartitionState::Crates => {
-                source_info.crates.push_str(line);
-                source_info.crates.push('\n');
-            }
-            PartitionState::Other => {
-                source_info.everything_else.push_str(line);
-                source_info.everything_else.push('\n');
-            }
+        Err(e) => {
+            e.cancel();
+            Err(())
         }
-    }
-
-    if !mod_attr_pending.is_empty() {
-        debug!("invalid doctest code: {s:?}");
-        return None;
-    }
-
-    source_info.everything_else = source_info.everything_else.trim().to_string();
-
-    debug!("crate_attrs:\n{}{}", source_info.crate_attrs, source_info.maybe_crate_attrs);
-    debug!("crates:\n{}", source_info.crates);
-    debug!("after:\n{}", source_info.everything_else);
+        _ => Err(()),
+    };
 
-    Some(source_info)
+    reset_error_count(&psess);
+    result
 }
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index d0072256941..be2dea641d7 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -80,7 +80,7 @@ impl<'tcx> HirCollector<'tcx> {
 
     pub fn collect_crate(mut self) -> Vec<ScrapedDocTest> {
         let tcx = self.tcx;
-        self.visit_testable(None, CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| {
+        self.visit_testable(None, CRATE_DEF_ID, tcx.hir_span(CRATE_HIR_ID), |this| {
             tcx.hir_walk_toplevel_module(this)
         });
         self.collector.tests
@@ -98,7 +98,7 @@ impl HirCollector<'_> {
         let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
         if let Some(ref cfg) =
             extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
-            && !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features()))
+            && !cfg.matches(&self.tcx.sess.psess)
         {
             return;
         }
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index e2b964bf5af..49add73e9d6 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -197,6 +197,7 @@ fn make_test_crate_attrs() {
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 #![feature(sick_rad)]
+
 fn main() {
 assert_eq!(2+2, 4);
 }"
@@ -228,8 +229,8 @@ fn make_test_fake_main() {
     let input = "//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
-//Ceci n'est pas une `fn main`
 fn main() {
+//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);
 }"
     .to_string();
@@ -259,8 +260,8 @@ fn make_test_issues_21299() {
 assert_eq!(2+2, 4);";
 
     let expected = "#![allow(unused)]
-// fn main
 fn main() {
+// fn main
 assert_eq!(2+2, 4);
 }"
     .to_string();
@@ -401,3 +402,76 @@ fn check_split_args() {
     compare("a\n\t \rb", &["a", "b"]);
     compare("a\n\t1 \rb", &["a", "1", "b"]);
 }
+
+#[test]
+fn comment_in_attrs() {
+    // If there is an inline code comment after attributes, we need to ensure that
+    // a backline will be added to prevent generating code "inside" it (and thus generating)
+    // invalid code.
+    let opts = default_global_opts("");
+    let input = "\
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.";
+    let expected = "\
+#![allow(unused)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+fn main() {
+
+}"
+    .to_string();
+    let (output, len) = make_test(input, None, false, &opts, None);
+    assert_eq!((output, len), (expected, 2));
+
+    // And same, if there is a `main` function provided by the user, we ensure that it's
+    // correctly separated.
+    let input = "\
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+fn main() {}";
+    let expected = "\
+#![allow(unused)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+
+fn main() {}"
+        .to_string();
+    let (output, len) = make_test(input, None, false, &opts, None);
+    assert_eq!((output, len), (expected, 1));
+}
+
+// This test ensures that the only attributes taken into account when we switch between
+// "crate level" content and the rest doesn't include inner attributes span, as it would
+// include part of the item and generate broken code.
+#[test]
+fn inner_attributes() {
+    let opts = default_global_opts("");
+    let input = r#"
+//! A doc comment that applies to the implicit anonymous module of this crate
+
+pub mod outer_module {
+    //!! - Still an inner line doc (but with a bang at the beginning)
+}
+"#;
+    let expected = "#![allow(unused)]
+
+//! A doc comment that applies to the implicit anonymous module of this crate
+
+
+fn main() {
+pub mod outer_module {
+    //!! - Still an inner line doc (but with a bang at the beginning)
+}
+}"
+    .to_string();
+    let (output, len) = make_test(input, None, false, &opts, None);
+    assert_eq!((output, len), (expected, 2));
+}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 2648641e53e..19402004ed5 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -288,7 +288,7 @@ impl DocFolder for CacheBuilder<'_, '_> {
 
         // Keep track of the fully qualified path for this item.
         let pushed = match item.name {
-            Some(n) if !n.is_empty() => {
+            Some(n) => {
                 self.cache.stack.push(n);
                 true
             }
@@ -385,7 +385,6 @@ impl DocFolder for CacheBuilder<'_, '_> {
         // implementations elsewhere.
         let ret = if let clean::Item {
             inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. },
-            ..
         } = item
         {
             // Figure out the id of this impl. This may map to a
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b067dbf750e..334a7a86989 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1200,9 +1200,11 @@ impl LangString {
                         data.ignore = Ignore::All;
                         seen_rust_tags = !seen_other_tags;
                     }
-                    LangStringToken::LangToken(x) if x.starts_with("ignore-") => {
+                    LangStringToken::LangToken(x)
+                        if let Some(ignore) = x.strip_prefix("ignore-") =>
+                    {
                         if enable_per_target_ignores {
-                            ignores.push(x.trim_start_matches("ignore-").to_owned());
+                            ignores.push(ignore.to_owned());
                             seen_rust_tags = !seen_other_tags;
                         }
                     }
@@ -1226,37 +1228,39 @@ impl LangString {
                         data.standalone_crate = true;
                         seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     }
-                    LangStringToken::LangToken(x) if x.starts_with("edition") => {
-                        data.edition = x[7..].parse::<Edition>().ok();
+                    LangStringToken::LangToken(x)
+                        if let Some(edition) = x.strip_prefix("edition") =>
+                    {
+                        data.edition = edition.parse::<Edition>().ok();
                     }
                     LangStringToken::LangToken(x)
-                        if x.starts_with("rust") && x[4..].parse::<Edition>().is_ok() =>
+                        if let Some(edition) = x.strip_prefix("rust")
+                            && edition.parse::<Edition>().is_ok()
+                            && let Some(extra) = extra =>
                     {
-                        if let Some(extra) = extra {
-                            extra.error_invalid_codeblock_attr_with_help(
-                                format!("unknown attribute `{x}`"),
-                                |lint| {
-                                    lint.help(format!(
-                                        "there is an attribute with a similar name: `edition{}`",
-                                        &x[4..],
-                                    ));
-                                },
-                            );
-                        }
+                        extra.error_invalid_codeblock_attr_with_help(
+                            format!("unknown attribute `{x}`"),
+                            |lint| {
+                                lint.help(format!(
+                                    "there is an attribute with a similar name: `edition{edition}`"
+                                ));
+                            },
+                        );
                     }
                     LangStringToken::LangToken(x)
-                        if allow_error_code_check && x.starts_with('E') && x.len() == 5 =>
+                        if allow_error_code_check
+                            && let Some(error_code) = x.strip_prefix('E')
+                            && error_code.len() == 4 =>
                     {
-                        if x[1..].parse::<u32>().is_ok() {
+                        if error_code.parse::<u32>().is_ok() {
                             data.error_codes.push(x.to_owned());
                             seen_rust_tags = !seen_other_tags || seen_rust_tags;
                         } else {
                             seen_other_tags = true;
                         }
                     }
-                    LangStringToken::LangToken(x) if extra.is_some() => {
-                        let s = x.to_lowercase();
-                        if let Some(help) = match s.as_str() {
+                    LangStringToken::LangToken(x) if let Some(extra) = extra => {
+                        if let Some(help) = match x.to_lowercase().as_str() {
                             "compile-fail" | "compile_fail" | "compilefail" => Some(
                                 "use `compile_fail` to invert the results of this test, so that it \
                                 passes if it cannot be compiled and fails if it can",
@@ -1273,33 +1277,27 @@ impl LangString {
                                 "use `test_harness` to run functions marked `#[test]` instead of a \
                                 potentially-implicit `main` function",
                             ),
-                            "standalone" | "standalone_crate" | "standalone-crate" => {
-                                if let Some(extra) = extra
-                                    && extra.sp.at_least_rust_2024()
-                                {
-                                    Some(
-                                        "use `standalone_crate` to compile this code block \
+                            "standalone" | "standalone_crate" | "standalone-crate"
+                                if extra.sp.at_least_rust_2024() =>
+                            {
+                                Some(
+                                    "use `standalone_crate` to compile this code block \
                                         separately",
-                                    )
-                                } else {
-                                    None
-                                }
+                                )
                             }
                             _ => None,
                         } {
-                            if let Some(extra) = extra {
-                                extra.error_invalid_codeblock_attr_with_help(
-                                    format!("unknown attribute `{x}`"),
-                                    |lint| {
-                                        lint.help(help).help(
-                                            "this code block may be skipped during testing, \
+                            extra.error_invalid_codeblock_attr_with_help(
+                                format!("unknown attribute `{x}`"),
+                                |lint| {
+                                    lint.help(help).help(
+                                        "this code block may be skipped during testing, \
                                             because unknown attributes are treated as markers for \
                                             code samples written in other programming languages, \
                                             unless it is also explicitly marked as `rust`",
-                                        );
-                                    },
-                                );
-                            }
+                                    );
+                                },
+                            );
                         }
                         seen_other_tags = true;
                         data.unknown.push(x.to_owned());
@@ -1726,6 +1724,7 @@ pub(crate) fn markdown_links<'md, R>(
     md: &'md str,
     preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
 ) -> Vec<R> {
+    use itertools::Itertools;
     if md.is_empty() {
         return vec![];
     }
@@ -1884,7 +1883,7 @@ pub(crate) fn markdown_links<'md, R>(
     let mut links = Vec::new();
 
     let mut refdefs = FxIndexMap::default();
-    for (label, refdef) in event_iter.reference_definitions().iter() {
+    for (label, refdef) in event_iter.reference_definitions().iter().sorted_by_key(|x| x.0) {
         refdefs.insert(label.to_string(), (false, refdef.dest.to_string(), refdef.span.clone()));
     }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8dfde1679fe..2237e0f987b 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -89,7 +89,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display {
 
 /// Specifies whether rendering directly implemented trait items or ones from a certain Deref
 /// impl.
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub(crate) enum AssocItemRender<'a> {
     All,
     DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
@@ -1296,7 +1296,8 @@ fn render_assoc_items_inner(
     info!("Documenting associated items of {:?}", containing_item.name);
     let cache = &cx.shared.cache;
     let Some(v) = cache.impls.get(&it) else { return };
-    let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
+    let (mut non_trait, traits): (Vec<_>, _) =
+        v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
         let mut close_tags = <Vec<&str>>::with_capacity(1);
         let mut tmp_buf = String::new();
@@ -1314,6 +1315,16 @@ fn render_assoc_items_inner(
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
                 let id =
                     cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
+                // the `impls.get` above only looks at the outermost type,
+                // and the Deref impl may only be implemented for certain
+                // values of generic parameters.
+                // for example, if an item impls `Deref<[u8]>`,
+                // we should not show methods from `[MaybeUninit<u8>]`.
+                // this `retain` filters out any instances where
+                // the types do not line up perfectly.
+                non_trait.retain(|impl_| {
+                    type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache)
+                });
                 let derived_id = cx.derive_id(&id);
                 close_tags.push("</details>");
                 write_str(
@@ -1392,6 +1403,7 @@ fn render_assoc_items_inner(
     }
 }
 
+/// `derefs` is the set of all deref targets that have already been handled.
 fn render_deref_methods(
     mut w: impl Write,
     cx: &Context<'_>,
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 3130815af0b..89ff61ecb03 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -533,7 +533,10 @@ fn sidebar_deref_methods<'a>(
             debug!("found inner_impl: {impls:?}");
             let mut ret = impls
                 .iter()
-                .filter(|i| i.inner_impl().trait_.is_none())
+                .filter(|i| {
+                    i.inner_impl().trait_.is_none()
+                        && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c)
+                })
                 .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
@@ -731,20 +734,20 @@ fn get_methods<'a>(
 ) -> Vec<Link<'a>> {
     i.items
         .iter()
-        .filter_map(|item| match item.name {
-            Some(ref name) if !name.is_empty() && item.is_method() => {
-                if !for_deref || super::should_render_item(item, deref_mut, tcx) {
-                    Some(Link::new(
-                        get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)),
-                        name.as_str(),
-                    ))
-                } else {
-                    None
-                }
+        .filter_map(|item| {
+            if let Some(ref name) = item.name
+                && item.is_method()
+                && (!for_deref || super::should_render_item(item, deref_mut, tcx))
+            {
+                Some(Link::new(
+                    get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)),
+                    name.as_str(),
+                ))
+            } else {
+                None
             }
-            _ => None,
         })
-        .collect::<Vec<_>>()
+        .collect()
 }
 
 fn get_associated_constants<'a>(
@@ -753,14 +756,19 @@ fn get_associated_constants<'a>(
 ) -> Vec<Link<'a>> {
     i.items
         .iter()
-        .filter_map(|item| match item.name {
-            Some(ref name) if !name.is_empty() && item.is_associated_const() => Some(Link::new(
-                get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)),
-                name.as_str(),
-            )),
-            _ => None,
+        .filter_map(|item| {
+            if let Some(ref name) = item.name
+                && item.is_associated_const()
+            {
+                Some(Link::new(
+                    get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)),
+                    name.as_str(),
+                ))
+            } else {
+                None
+            }
         })
-        .collect::<Vec<_>>()
+        .collect()
 }
 
 fn get_associated_types<'a>(
@@ -769,12 +777,17 @@ fn get_associated_types<'a>(
 ) -> Vec<Link<'a>> {
     i.items
         .iter()
-        .filter_map(|item| match item.name {
-            Some(ref name) if !name.is_empty() && item.is_associated_type() => Some(Link::new(
-                get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
-                name.as_str(),
-            )),
-            _ => None,
+        .filter_map(|item| {
+            if let Some(ref name) = item.name
+                && item.is_associated_type()
+            {
+                Some(Link::new(
+                    get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
+                    name.as_str(),
+                ))
+            } else {
+                None
+            }
         })
-        .collect::<Vec<_>>()
+        .collect()
 }
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 3676051b1bd..846d3ad310c 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -95,7 +95,7 @@ impl SpanMapVisitor<'_> {
                     .unwrap_or(path.span);
                 self.matches.insert(span, link);
             }
-            Res::Local(_) if let Some(span) = self.tcx.hir().res_span(path.res) => {
+            Res::Local(_) if let Some(span) = self.tcx.hir_res_span(path.res) => {
                 self.matches.insert(path.span, LinkFromSrc::Local(clean::Span::new(span)));
             }
             Res::PrimTy(p) => {
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index 4b43c00730d..91a58fab86e 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -4,6 +4,12 @@
 
 /* eslint-disable */
 declare global {
+    /** Map from crate name to directory structure, for source view */
+    declare var srcIndex: Map<string, rustdoc.Dir>;
+    /** Defined and documented in `storage.js` */
+    declare function nonnull(x: T|null, msg: string|undefined);
+    /** Defined and documented in `storage.js` */
+    declare function nonundef(x: T|undefined, msg: string|undefined);
     interface Window {
         /** Make the current theme easy to find */
         currentTheme: HTMLLinkElement|null;
@@ -41,6 +47,23 @@ declare global {
          */
         rustdocShowSourceSidebar: function(),
         /**
+         * Close the sidebar in source code view
+         */
+        rustdocCloseSourceSidebar?: function(),
+        /**
+         * Shows the sidebar in source code view
+         */
+        rustdocShowSourceSidebar?: function(),
+        /**
+         * Toggles the sidebar in source code view
+         */
+        rustdocToggleSrcSidebar?: function(),
+        /**
+         * create's the sidebar in source code view.
+         * called in generated `src-files.js`.
+         */
+        createSrcSidebar?: function(),
+        /**
          * Set up event listeners for a scraped source example.
          */
         updateScrapedExample?: function(HTMLElement, HTMLElement),
@@ -234,13 +257,21 @@ declare namespace rustdoc {
         ty: number,
         type?: FunctionSearchType,
         paramNames?: string[],
-        displayType: Promise<Array<Array<string>>>|null,
-        displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
+        displayTypeSignature: Promise<rustdoc.DisplayTypeSignature> | null,
         item: Row,
         dontValidate?: boolean,
     }
 
     /**
+     * output of `formatDisplayTypeSignature`
+     */
+    interface DisplayTypeSignature {
+        type: Array<string>,
+        mappedNames: Map<string, string>,
+        whereClause: Map<string, Array<string>>,
+    }
+
+    /**
      * A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
      * The JavaScript deserializes this into FunctionSearchType.
      *
@@ -438,4 +469,12 @@ declare namespace rustdoc {
     type TypeImpls = {
         [cratename: string]: Array<Array<string|0>>
     }
+
+    /**
+     * Directory structure for source code view,
+     * defined in generated `src-files.js`.
+     *
+     * is a tuple of (filename, subdirs, filenames).
+     */
+    type Dir = [string, rustdoc.Dir[], string[]]
 }
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c275127997a..dce5fddb317 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -33,6 +33,20 @@ function onEachBtwn(arr, func, funcBtwn) {
     }
 }
 
+/**
+ * Convert any `undefined` to `null`.
+ *
+ * @template T
+ * @param {T|undefined} x
+ * @returns {T|null}
+ */
+function undef2null(x) {
+    if (x !== undefined) {
+        return x;
+    }
+    return null;
+}
+
 // ==================== Core search logic begin ====================
 // This mapping table should match the discriminants of
 // `rustdoc::formats::item_type::ItemType` type in Rust.
@@ -338,7 +352,7 @@ function getFilteredNextElem(query, parserState, elems, isInGenerics) {
         // The type filter doesn't count as an element since it's a modifier.
         const typeFilterElem = elems.pop();
         checkExtraTypeFilterCharacters(start, parserState);
-        // typeFilterElem is not null. If it was, the elems.length check would have fired.
+        // typeFilterElem is not undefined. If it was, the elems.length check would have fired.
         // @ts-expect-error
         parserState.typeFilter = typeFilterElem.normalizedPathLast;
         parserState.pos += 1;
@@ -1311,10 +1325,9 @@ class NameTrie {
                 let sste;
                 if (substart >= 2) {
                     const tail = name.substring(substart - 2, substart + 1);
-                    if (tailTable.has(tail)) {
-                        // it's not undefined
-                        // @ts-expect-error
-                        sste = tailTable.get(tail);
+                    const entry = tailTable.get(tail);
+                    if (entry !== undefined) {
+                        sste = entry;
                     } else {
                         sste = [];
                         tailTable.set(tail, sste);
@@ -1338,10 +1351,9 @@ class NameTrie {
                 new Lev1TParametricDescription(name.length);
             this.searchLev(name, 0, levParams, results);
             const tail = name.substring(0, 3);
-            if (tailTable.has(tail)) {
-                // it's not undefined
-                // @ts-expect-error
-                for (const entry of tailTable.get(tail)) {
+            const list = tailTable.get(tail);
+            if (list !== undefined) {
+                for (const entry of list) {
                     entry.searchSubstringPrefix(name, 3, results);
                 }
             }
@@ -1600,10 +1612,8 @@ class DocSearch {
             return null;
         }
 
-        if (this.typeNameIdMap.has(name)) {
-            /** @type {{id: number, assocOnly: boolean}} */
-            // @ts-expect-error
-            const obj = this.typeNameIdMap.get(name);
+        const obj = this.typeNameIdMap.get(name);
+        if (obj !== undefined) {
             obj.assocOnly = !!(isAssocType && obj.assocOnly);
             return obj.id;
         } else {
@@ -2082,7 +2092,8 @@ class DocSearch {
                 descIndex += 1;
             }
 
-            // a String of one character item type codes
+            // see `RawSearchIndexCrate` in `rustdoc.d.ts` for a more
+            // up to date description of these fields
             const itemTypes = crateCorpus.t;
             // an array of (String) item names
             const itemNames = crateCorpus.n;
@@ -2099,8 +2110,6 @@ class DocSearch {
             const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop);
             // a map Number, string for impl disambiguators
             const implDisambiguator = new Map(crateCorpus.b);
-            // an array of [(Number) item type,
-            //              (String) name]
             const rawPaths = crateCorpus.p;
             const aliases = crateCorpus.a;
             // an array of [(Number) item index,
@@ -2139,30 +2148,31 @@ class DocSearch {
             // convert `rawPaths` entries into object form
             // generate normalizedPaths for function search mode
             let len = rawPaths.length;
-            let lastPath = itemPaths.get(0);
+            let lastPath = undef2null(itemPaths.get(0));
             for (let i = 0; i < len; ++i) {
                 const elem = rawPaths[i];
                 const ty = elem[0];
                 const name = elem[1];
-                let path = null;
-                if (elem.length > 2 && elem[2] !== null) {
-                    // @ts-expect-error
-                    path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath;
-                    lastPath = path;
-                }
-                let exactPath = elem.length > 3 && elem[3] !== null ?
-                    // @ts-expect-error
-                    itemPaths.get(elem[3]) :
-                    path;
+                /**
+                 * @param {2|3} idx
+                 * @param {string|null} if_null
+                 * @param {string|null} if_not_found
+                 * @returns {string|null}
+                 */
+                const elemPath = (idx, if_null, if_not_found) => {
+                    if (elem.length > idx && elem[idx] !== undefined) {
+                        const p = itemPaths.get(elem[idx]);
+                        if (p !== undefined) {
+                            return p;
+                        }
+                        return if_not_found;
+                    }
+                    return if_null;
+                };
+                const path = elemPath(2, lastPath, null);
+                const exactPath = elemPath(3, path, path);
                 const unboxFlag = elem.length > 4 && !!elem[4];
 
-                if (path === undefined) {
-                    path = null;
-                }
-                if (exactPath === undefined) {
-                    exactPath = null;
-                }
-
                 lowercasePaths.push({ ty, name: name.toLowerCase(), path, exactPath, unboxFlag });
                 paths[i] = { ty, name, path, exactPath, unboxFlag };
             }
@@ -2196,12 +2206,11 @@ class DocSearch {
                 }
                 const name = itemNames[i] === "" ? lastName : itemNames[i];
                 const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase();
-                /** @type {string} */
-                // @ts-expect-error
-                const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
-                const paramNames = itemParamNames.has(i) ?
-                    // @ts-expect-error
-                    itemParamNames.get(i).split(",") :
+                const pathU = itemPaths.get(i);
+                const path = pathU !== undefined ? pathU : lastPath;
+                const paramNameString = itemParamNames.get(i);
+                const paramNames = paramNameString !== undefined ?
+                    paramNameString.split(",") :
                     lastParamNames;
                 const type = itemFunctionDecoder.next();
                 if (type !== null) {
@@ -2243,8 +2252,7 @@ class DocSearch {
                     word,
                     normalizedName,
                     bitIndex,
-                    implDisambiguator: implDisambiguator.has(i) ?
-                        implDisambiguator.get(i) : null,
+                    implDisambiguator: undef2null(implDisambiguator.get(i)),
                 };
                 this.nameTrie.insert(normalizedName, id, this.tailTable);
                 id += 1;
@@ -2482,9 +2490,13 @@ class DocSearch {
             }
         } catch (err) {
             query = newParsedQuery(userQuery);
-            // is string list
-            // @ts-expect-error
-            query.error = err;
+            if (Array.isArray(err) && err.every(elem => typeof elem === "string")) {
+                query.error = err;
+            } else {
+                // rethrow the error if it isn't a string array
+                throw err;
+            }
+
             return query;
         }
         if (!query.literalSearch) {
@@ -2572,9 +2584,9 @@ class DocSearch {
             if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1
                 && elem.generics.length === 0 && elem.bindings.size === 0)
                 || elem.typeFilter === TY_GENERIC) {
-                if (genericSymbols.has(elem.normalizedPathLast)) {
-                    // @ts-expect-error
-                    elem.id = genericSymbols.get(elem.normalizedPathLast);
+                const id = genericSymbols.get(elem.normalizedPathLast);
+                if (id !== undefined) {
+                    elem.id = id;
                 } else {
                     elem.id = -(genericSymbols.size + 1);
                     genericSymbols.set(elem.normalizedPathLast, elem.id);
@@ -2766,15 +2778,28 @@ class DocSearch {
             for (const result of results) {
                 if (result.id !== -1) {
                     const res = buildHrefAndPath(this.searchIndex[result.id]);
+                    // many of these properties don't strictly need to be
+                    // copied over, but copying them over satisfies tsc,
+                    // and hopefully plays nice with the shape optimization
+                    // of the browser engine.
+                    /** @type {rustdoc.ResultObject} */
                     const obj = Object.assign({
+                        parent: result.parent,
+                        type: result.type,
                         dist: result.dist,
+                        path_dist: result.path_dist,
+                        index: result.index,
+                        desc: result.desc,
+                        item: result.item,
                         displayPath: pathSplitter(res[0]),
+                        fullPath: "",
+                        href: "",
+                        displayTypeSignature: null,
                     }, this.searchIndex[result.id]);
 
                     // To be sure than it some items aren't considered as duplicate.
-                    // @ts-expect-error
                     obj.fullPath = res[2] + "|" + obj.ty;
-                    // @ts-expect-error
+
                     if (duplicates.has(obj.fullPath)) {
                         continue;
                     }
@@ -2787,18 +2812,15 @@ class DocSearch {
                     if (duplicates.has(res[2] + "|" + TY_IMPORT)) {
                         continue;
                     }
-                    // @ts-expect-error
                     duplicates.add(obj.fullPath);
                     duplicates.add(res[2]);
 
                     if (typeInfo !== null) {
-                        // @ts-expect-error
                         obj.displayTypeSignature =
                             // @ts-expect-error
                             this.formatDisplayTypeSignature(obj, typeInfo);
                     }
 
-                    // @ts-expect-error
                     obj.href = res[1];
                     out.push(obj);
                     if (out.length >= MAX_RESULTS) {
@@ -2806,7 +2828,6 @@ class DocSearch {
                     }
                 }
             }
-            // @ts-expect-error
             return out;
         };
 
@@ -2819,11 +2840,7 @@ class DocSearch {
          *
          * @param {rustdoc.ResultObject} obj
          * @param {"sig"|"elems"|"returned"|null} typeInfo
-         * @returns {Promise<{
-         *   "type": Array<string>,
-         *   "mappedNames": Map<string, string>,
-         *   "whereClause": Map<string, Array<string>>,
-         * }>}
+         * @returns {Promise<rustdoc.DisplayTypeSignature>}
          */
         this.formatDisplayTypeSignature = async(obj, typeInfo) => {
             const objType = obj.type;
@@ -2885,7 +2902,7 @@ class DocSearch {
             const whereClause = new Map();
 
             const fnParamNames = obj.paramNames || [];
-            // @ts-expect-error
+            /** @type {string[]} */
             const queryParamNames = [];
             /**
              * Recursively writes a map of IDs to query generic names,
@@ -2918,7 +2935,7 @@ class DocSearch {
              * index 2 is not highlighted, etc.
              *
              * @param {{name?: string, highlighted?: boolean}} fnType - input
-             * @param {[string]} result
+             * @param {string[]} result
              */
             const pushText = (fnType, result) => {
                 // If !!(result.length % 2) == false, then pushing a new slot starts an even
@@ -2930,7 +2947,6 @@ class DocSearch {
                 // needs coerced to a boolean.
                 if (!!(result.length % 2) === !!fnType.highlighted) {
                     result.push("");
-                // @ts-expect-error
                 } else if (result.length === 0 && !!fnType.highlighted) {
                     result.push("");
                     result.push("");
@@ -2944,7 +2960,7 @@ class DocSearch {
              * or a trait bound on Fn, FnMut, or FnOnce.
              *
              * @param {rustdoc.HighlightedFunctionType} fnType - input
-             * @param {[string]} result
+             * @param {string[]} result
              */
             const writeHof = (fnType, result) => {
                 const hofOutput = fnType.bindings.get(this.typeNameIdOfOutput) || [];
@@ -2984,7 +3000,7 @@ class DocSearch {
              * Returns `false` if the supplied type isn't special.
              *
              * @param {rustdoc.HighlightedFunctionType} fnType
-             * @param {[string]} result
+             * @param {string[]} result
              */
             const writeSpecialPrimitive = (fnType, result) => {
                 if (fnType.id === this.typeNameIdOfArray || fnType.id === this.typeNameIdOfSlice ||
@@ -3031,7 +3047,7 @@ class DocSearch {
              * updating the where clause and generic type param map.
              *
              * @param {rustdoc.HighlightedFunctionType} fnType
-             * @param {[string]} result
+             * @param {string[]} result
              */
             const writeFn = (fnType, result) => {
                 if (fnType.id !== null && fnType.id < 0) {
@@ -3049,7 +3065,6 @@ class DocSearch {
                         for (const [queryId, fnId] of mgens) {
                             if (fnId === fnType.id) {
                                 mappedNames.set(
-                                    // @ts-expect-error
                                     queryParamNames[-1 - queryId],
                                     fnParamNames[-1 - fnType.id],
                                 );
@@ -3064,7 +3079,6 @@ class DocSearch {
                     const where = [];
                     onEachBtwn(
                         fnType.generics,
-                        // @ts-expect-error
                         nested => writeFn(nested, where),
                         // @ts-expect-error
                         () => pushText({ name: " + ", highlighted: false }, where),
@@ -3099,7 +3113,6 @@ class DocSearch {
                                     // shown in the where clause and name mapping output, but is
                                     // redundant in this spot
                                     for (const value of values) {
-                                        // @ts-expect-error
                                         writeFn(value, []);
                                     }
                                     return true;
@@ -3141,26 +3154,22 @@ class DocSearch {
                     }
                 }
             };
-            // @ts-expect-error
+            /** @type {string[]} */
             const type = [];
             onEachBtwn(
                 fnInputs,
-                // @ts-expect-error
                 fnType => writeFn(fnType, type),
                 // @ts-expect-error
                 () => pushText({ name: ", ",  highlighted: false }, type),
             );
-            // @ts-expect-error
             pushText({ name: " -> ", highlighted: false }, type);
             onEachBtwn(
                 fnOutput,
-                // @ts-expect-error
                 fnType => writeFn(fnType, type),
                 // @ts-expect-error
                 () => pushText({ name: ", ",  highlighted: false }, type),
             );
 
-            // @ts-expect-error
             return {type, mappedNames, whereClause};
         };
 
@@ -3475,8 +3484,7 @@ class DocSearch {
                         }
                     }
                 }
-                // @ts-expect-error
-                return false;
+                return null;
             }
 
             // Multiple element recursive case
@@ -3532,7 +3540,7 @@ class DocSearch {
                 }
                 /** @type {rustdoc.HighlightedFunctionType[]|null} */
                 let unifiedGenerics = [];
-                // @ts-expect-error
+                /** @type {null|Map<number, number>} */
                 let unifiedGenericsMgens = null;
                 /** @type {rustdoc.HighlightedFunctionType[]|null} */
                 const passesUnification = unifyFunctionTypes(
@@ -3586,7 +3594,6 @@ class DocSearch {
                                 // @ts-expect-error
                                 queryElem.bindings.get(k),
                                 whereClause,
-                                // @ts-expect-error
                                 unifiedGenericsMgens,
                                 solutionCb,
                                 unboxingDepth,
@@ -3984,7 +3991,7 @@ class DocSearch {
                     }
                     const fnTypeBindings = fnType.bindings.get(name);
                     mgensSolutionSet = mgensSolutionSet.flatMap(mgens => {
-                        // @ts-expect-error
+                        /** @type{Array<Map<number, number> | null>} */
                         const newSolutions = [];
                         unifyFunctionTypes(
                             // @ts-expect-error
@@ -4000,7 +4007,6 @@ class DocSearch {
                             },
                             unboxingDepth,
                         );
-                        // @ts-expect-error
                         return newSolutions;
                     });
                 }
@@ -4248,6 +4254,7 @@ class DocSearch {
             return false;
         }
 
+        // this does not yet have a type in `rustdoc.d.ts`.
         // @ts-expect-error
         function createAliasFromItem(item) {
             return {
diff --git a/src/librustdoc/html/static/js/src-script.js b/src/librustdoc/html/static/js/src-script.js
index fc27241334b..b9ab6e85603 100644
--- a/src/librustdoc/html/static/js/src-script.js
+++ b/src/librustdoc/html/static/js/src-script.js
@@ -3,10 +3,8 @@
 
 // Local js definitions:
 /* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */
-/* global updateLocalStorage, getVar */
+/* global updateLocalStorage, getVar, nonnull */
 
-// Eventually fix this.
-// @ts-nocheck
 
 "use strict";
 
@@ -29,6 +27,14 @@ function closeSidebarIfMobile() {
     }
 }
 
+/**
+ * @param {rustdoc.Dir} elem
+ * @param {HTMLElement} parent
+ * @param {string} fullPath
+ * @param {boolean} hasFoundFile
+ *
+ * @returns {boolean} - new value for hasFoundFile
+ */
 function createDirEntry(elem, parent, fullPath, hasFoundFile) {
     const dirEntry = document.createElement("details");
     const summary = document.createElement("summary");
@@ -95,7 +101,7 @@ window.rustdocToggleSrcSidebar = () => {
 // This function is called from "src-files.js", generated in `html/render/write_shared.rs`.
 // eslint-disable-next-line no-unused-vars
 function createSrcSidebar() {
-    const container = document.querySelector("nav.sidebar");
+    const container = nonnull(document.querySelector("nav.sidebar"));
 
     const sidebar = document.createElement("div");
     sidebar.id = "src-sidebar";
@@ -111,6 +117,7 @@ function createSrcSidebar() {
     // Focus on the current file in the source files sidebar.
     const selected_elem = sidebar.getElementsByClassName("selected")[0];
     if (typeof selected_elem !== "undefined") {
+        // @ts-expect-error
         selected_elem.focus();
     }
 }
@@ -130,11 +137,12 @@ function highlightSrcLines() {
         to = from;
         from = tmp;
     }
-    let elem = document.getElementById(from);
+    const from_s = "" + from;
+    let elem = document.getElementById(from_s);
     if (!elem) {
         return;
     }
-    const x = document.getElementById(from);
+    const x = document.getElementById(from_s);
     if (x) {
         x.scrollIntoView();
     }
@@ -142,7 +150,7 @@ function highlightSrcLines() {
         removeClass(e, "line-highlighted");
     });
     for (let i = from; i <= to; ++i) {
-        elem = document.getElementById(i);
+        elem = document.getElementById("" + i);
         if (!elem) {
             break;
         }
@@ -153,11 +161,12 @@ function highlightSrcLines() {
 const handleSrcHighlight = (function() {
     let prev_line_id = 0;
 
+    /** @type {function(string): void} */
     const set_fragment = name => {
         const x = window.scrollX,
             y = window.scrollY;
         if (browserSupportsHistoryApi()) {
-            history.replaceState(null, null, "#" + name);
+            history.replaceState(null, "", "#" + name);
             highlightSrcLines();
         } else {
             location.replace("#" + name);
@@ -166,6 +175,7 @@ const handleSrcHighlight = (function() {
         window.scrollTo(x, y);
     };
 
+    // @ts-expect-error
     return ev => {
         let cur_line_id = parseInt(ev.target.id, 10);
         // This event handler is attached to the entire line number column, but it should only
@@ -191,7 +201,7 @@ const handleSrcHighlight = (function() {
         } else {
             prev_line_id = cur_line_id;
 
-            set_fragment(cur_line_id);
+            set_fragment("" + cur_line_id);
         }
     };
 }());
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 425b915b5f9..76113726894 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -22,6 +22,50 @@ const settingsDataset = (function() {
 })();
 
 /**
+ * Assert that the passed value is nonnull, then return it.
+ *
+ * Takes an optional error message argument.
+ *
+ * Must be defined in this file, as it is loaded before all others.
+ *
+ * @template T
+ * @param {T|null} x
+ * @param {string=} msg
+ * @returns T
+ */
+// used in other files, not yet used in this one.
+// eslint-disable-next-line no-unused-vars
+function nonnull(x, msg) {
+    if (x === null) {
+        throw (msg || "unexpected null value!");
+    } else {
+        return x;
+    }
+}
+
+/**
+ * Assert that the passed value is not undefined, then return it.
+ *
+ * Takes an optional error message argument.
+ *
+ * Must be defined in this file, as it is loaded before all others.
+ *
+ * @template T
+ * @param {T|undefined} x
+ * @param {string=} msg
+ * @returns T
+ */
+// used in other files, not yet used in this one.
+// eslint-disable-next-line no-unused-vars
+function nonundef(x, msg) {
+    if (x === undefined) {
+        throw (msg || "unexpected null value!");
+    } else {
+        return x;
+    }
+}
+
+/**
  * Get a configuration value. If it's not set, get the default.
  *
  * @param {string} settingName
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index a5351b350dd..9d8eb70fbe0 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -43,7 +43,7 @@ impl JsonRenderer<'_> {
         let attrs = item.attributes(self.tcx, self.cache(), true);
         let span = item.span(self.tcx);
         let visibility = item.visibility(self.tcx);
-        let clean::Item { name, item_id, .. } = item;
+        let clean::ItemInner { name, item_id, .. } = *item.inner;
         let id = self.id_from_item(&item);
         let inner = match item.kind {
             clean::KeywordItem => return None,
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 572c9bf7552..eddafa9ba8e 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -61,7 +61,7 @@ impl CfgPropagator<'_, '_> {
 
         let (_, cfg) =
             merge_attrs(self.cx, item.attrs.other_attrs.as_slice(), Some((&attrs, None)));
-        item.cfg = cfg;
+        item.inner.cfg = cfg;
     }
 }
 
@@ -71,7 +71,7 @@ impl DocFolder for CfgPropagator<'_, '_> {
 
         self.merge_with_parent_attributes(&mut item);
 
-        let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
+        let new_cfg = match (self.parent_cfg.take(), item.inner.cfg.take()) {
             (None, None) => None,
             (Some(rc), None) | (None, Some(rc)) => Some(rc),
             (Some(mut a), Some(b)) => {
@@ -81,7 +81,7 @@ impl DocFolder for CfgPropagator<'_, '_> {
             }
         };
         self.parent_cfg = new_cfg.clone();
-        item.cfg = new_cfg;
+        item.inner.cfg = new_cfg;
 
         let old_parent =
             if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 44551d75903..fceacb69fb5 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -176,8 +176,7 @@ where
 
         // If the enclosing item has a span coming from a proc macro, then we also don't want to
         // include the example.
-        let enclosing_item_span =
-            tcx.hir().span_with_body(tcx.hir_get_parent_item(ex.hir_id).into());
+        let enclosing_item_span = tcx.hir_span_with_body(tcx.hir_get_parent_item(ex.hir_id).into());
         if enclosing_item_span.from_expansion() {
             trace!("Rejecting expr ({call_span:?}) from macro item: {enclosing_item_span:?}");
             return;
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 44e82c7d8b1..137fe4c4c35 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 42;
+pub const FORMAT_VERSION: u32 = 43;
 
 /// The root of the emitted JSON blob.
 ///
@@ -120,9 +120,23 @@ pub struct Item {
     pub docs: Option<String>,
     /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs
     pub links: HashMap<String, Id>,
-    /// Stringified versions of parsed attributes on this item.
-    /// Essentially debug printed (e.g. `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`).
-    /// Equivalent to the hir pretty-printing of attributes.
+    /// Attributes on this item.
+    ///
+    /// Does not include `#[deprecated]` attributes: see the [`Self::deprecation`] field instead.
+    ///
+    /// Some attributes appear in pretty-printed Rust form, regardless of their formatting
+    /// in the original source code. For example:
+    /// - `#[non_exhaustive]` and `#[must_use]` are represented as themselves.
+    /// - `#[no_mangle]` and `#[export_name]` are also represented as themselves.
+    /// - `#[repr(C)]` and other reprs also appear as themselves,
+    ///   though potentially with a different order: e.g. `repr(i8, C)` may become `repr(C, i8)`.
+    ///   Multiple repr attributes on the same item may be combined into an equivalent single attr.
+    ///
+    /// Other attributes may appear debug-printed. For example:
+    /// - `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`.
+    ///
+    /// As an internal implementation detail subject to change, this debug-printing format
+    /// is currently equivalent to the HIR pretty-printing of parsed attributes.
     pub attrs: Vec<String>,
     /// Information about the item’s deprecation, if present.
     pub deprecation: Option<Deprecation>,
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 6cf8267012570f63d6b86e85a2ae5627de52df9
+Subproject a6c604d1b8a2f2a8ff1f3ba6092f9fda42f4b7e
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 5c486eb90cc..4c84e61b1f2 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -37,7 +37,6 @@ fn check_duplicated_attr(
     let Some(ident) = attr.ident() else { return };
     let name = ident.name;
     if name == sym::doc
-        || name == sym::cfg_attr
         || name == sym::cfg_attr_trace
         || name == sym::rustc_on_unimplemented
         || name == sym::reason {
@@ -47,7 +46,7 @@ fn check_duplicated_attr(
         return;
     }
     if let Some(direct_parent) = parent.last()
-        && ["cfg", "cfg_attr"].contains(&direct_parent.as_str())
+        && direct_parent == sym::cfg_trace.as_str()
         && [sym::all, sym::not, sym::any].contains(&name)
     {
         // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 7885f171461..72953818a70 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -143,7 +143,7 @@ pub(super) fn check<'tcx>(
 
     if cast_from.kind() == cast_to.kind() && !expr.span.in_external_macro(cx.sess().source_map()) {
         if let Some(id) = path_to_local(cast_expr)
-            && !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span)
+            && !cx.tcx.hir_span(id).eq_ctxt(cast_expr.span)
         {
             // Binding context is different than the identifiers context.
             // Weird macro wizardry could be involved here.
diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
index 84136a2e6c2..7590fe96fd2 100644
--- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
+++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
@@ -32,7 +32,7 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]);
 
 impl EarlyLintPass for CfgNotTest {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
-        if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) {
+        if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) {
             span_lint_and_then(
                 cx,
                 CFG_NOT_TEST,
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index 7d86bd3e540..c2aac7ca090 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -53,7 +53,7 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]);
 
 impl EarlyLintPass for CrateInMacroDef {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::MacroDef(macro_def) = &item.kind
+        if let ItemKind::MacroDef(_, macro_def) = &item.kind
             && item.attrs.iter().any(is_macro_export)
             && let Some(span) = contains_unhygienic_crate_reference(&macro_def.body.tokens)
         {
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 7fa23dad698..39e45163707 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -638,7 +638,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::precedence::PRECEDENCE_INFO,
     crate::precedence::PRECEDENCE_BITS_INFO,
     crate::ptr::CMP_NULL_INFO,
-    crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
     crate::ptr::MUT_FROM_REF_INFO,
     crate::ptr::PTR_ARG_INFO,
     crate::ptr::PTR_EQ_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 0031da406f1..de66ead4f42 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -131,6 +131,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
     ("clippy::clone_double_ref", "suspicious_double_ref_op"),
     #[clippy::version = ""]
     ("clippy::cmp_nan", "invalid_nan_comparisons"),
+    #[clippy::version = "CURRENT_RUSTC_VERSION"]
+    ("clippy::invalid_null_ptr_usage", "invalid_null_arguments"),
     #[clippy::version = "1.86.0"]
     ("clippy::double_neg", "double_negations"),
     #[clippy::version = ""]
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 2ae35b40055..c85aca8d04e 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -254,7 +254,7 @@ fn check_hash_peq<'tcx>(
                     |diag| {
                         if let Some(local_def_id) = impl_id.as_local() {
                             let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id);
-                            diag.span_note(cx.tcx.hir().span(hir_id), "`PartialEq` implemented here");
+                            diag.span_note(cx.tcx.hir_span(hir_id), "`PartialEq` implemented here");
                         }
                     },
                 );
@@ -298,7 +298,7 @@ fn check_ord_partial_ord<'tcx>(
                 span_lint_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, span, mess, |diag| {
                     if let Some(local_def_id) = impl_id.as_local() {
                         let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id);
-                        diag.span_note(cx.tcx.hir().span(hir_id), "`PartialOrd` implemented here");
+                        diag.span_note(cx.tcx.hir_span(hir_id), "`PartialOrd` implemented here");
                     }
                 });
             }
@@ -324,11 +324,9 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
     // there's a Copy impl for any instance of the adt.
     if !is_copy(cx, ty) {
         if ty_subs.non_erasable_generics().next().is_some() {
-            let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).is_some_and(|impls| {
-                impls.iter().any(|&id| {
-                    matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
+            let has_copy_impl = cx.tcx.local_trait_impls(copy_id).iter().any(|&id| {
+                matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
                                         if ty_adt.did() == adt.did())
-                })
             });
             if !has_copy_impl {
                 return;
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index 3008082c232..f6c10da1596 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -13,16 +13,16 @@ use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{FileName, Pos, sym};
+use rustc_span::{FileName, Ident, Pos, sym};
 
 use super::Fragments;
 
-fn get_test_spans(item: &Item, test_attr_spans: &mut Vec<Range<usize>>) {
+fn get_test_spans(item: &Item, ident: Ident, test_attr_spans: &mut Vec<Range<usize>>) {
     test_attr_spans.extend(
         item.attrs
             .iter()
             .find(|attr| attr.has_name(sym::test))
-            .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()),
+            .map(|attr| attr.span.lo().to_usize()..ident.span.hi().to_usize()),
     );
 }
 
@@ -64,10 +64,10 @@ pub fn check(
                     match parser.parse_item(ForceCollect::No) {
                         Ok(Some(item)) => match &item.kind {
                             ItemKind::Fn(box Fn {
-                                sig, body: Some(block), ..
-                            }) if item.ident.name == sym::main => {
+                                ident, sig, body: Some(block), ..
+                            }) if ident.name == sym::main => {
                                 if !ignore {
-                                    get_test_spans(&item, &mut test_attr_spans);
+                                    get_test_spans(&item, *ident, &mut test_attr_spans);
                                 }
                                 let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. }));
                                 let returns_nothing = match &sig.decl.output {
@@ -85,10 +85,10 @@ pub fn check(
                                 }
                             },
                             // Another function was found; this case is ignored for needless_doctest_main
-                            ItemKind::Fn(box Fn { .. }) => {
+                            ItemKind::Fn(fn_) => {
                                 eligible = false;
                                 if !ignore {
-                                    get_test_spans(&item, &mut test_attr_spans);
+                                    get_test_spans(&item, fn_.ident, &mut test_attr_spans);
                                 }
                             },
                             // Tests with one of these items are ignored
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index 1dac7b971f9..243c99a19ce 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
 
 impl EarlyLintPass for DuplicateMod {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
+        if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
             && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
             && let Some(local_path) = real.into_local_path()
             && let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
index 80c2b03c41c..c67dcd3c82b 100644
--- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
@@ -8,8 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
 use rustc_lexer::TokenKind;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::kw;
-use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol};
+use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -375,21 +374,23 @@ impl EmptyLineAfter {
         &mut self,
         cx: &EarlyContext<'_>,
         kind: &ItemKind,
-        ident: &Ident,
+        ident: Option<Ident>,
         span: Span,
         attrs: &[Attribute],
         id: NodeId,
     ) {
         self.items.push(ItemInfo {
             kind: kind.descr(),
-            name: ident.name,
-            span: if span.contains(ident.span) {
+            // FIXME: this `sym::empty` can be leaked, see
+            // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899
+            name: if let Some(ident) = ident { ident.name } else { kw::Empty },
+            span: if let Some(ident) = ident {
                 span.with_hi(ident.span.hi())
             } else {
                 span.with_hi(span.lo())
             },
             mod_items: match kind {
-                ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items
+                ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
                     .iter()
                     .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
                     .map(|i| i.id)
@@ -471,7 +472,7 @@ impl EarlyLintPass for EmptyLineAfter {
         self.check_item_kind(
             cx,
             &item.kind.clone().into(),
-            &item.ident,
+            item.kind.ident(),
             item.span,
             &item.attrs,
             item.id,
@@ -482,7 +483,7 @@ impl EarlyLintPass for EmptyLineAfter {
         self.check_item_kind(
             cx,
             &item.kind.clone().into(),
-            &item.ident,
+            item.kind.ident(),
             item.span,
             &item.attrs,
             item.id,
@@ -490,6 +491,6 @@ impl EarlyLintPass for EmptyLineAfter {
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id);
+        self.check_item_kind(cx, &item.kind, item.kind.ident(), item.span, &item.attrs, item.id);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 743ec5b9ea7..7d87f04fef9 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -74,10 +74,9 @@ declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM
 
 impl EarlyLintPass for EmptyWithBrackets {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let span_after_ident = item.span.with_lo(item.ident.span.hi());
-
-        if let ItemKind::Struct(var_data, _) = &item.kind
+        if let ItemKind::Struct(ident, var_data, _) = &item.kind
             && has_brackets(var_data)
+            && let span_after_ident = item.span.with_lo(ident.span.hi())
             && has_no_fields(cx, var_data, span_after_ident)
         {
             span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index de0fc2b1bf4..e248f08789b 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
                 cx,
                 BOXED_LOCAL,
                 node,
-                cx.tcx.hir().span(node),
+                cx.tcx.hir_span(node),
                 "local variable doesn't need to be boxed here",
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index ba2b37fbf11..aae8291905d 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO
 
 impl EarlyLintPass for FieldScopedVisibilityModifiers {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(ref st, _) = item.kind else {
+        let ItemKind::Struct(_, ref st, _) = item.kind else {
             return;
         };
         for field in st.fields() {
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index d53e139de01..989997d69f7 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -248,7 +248,7 @@ impl<'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'_, 'tcx> {
             {
                 use_info
                     .index_use
-                    .push((index_value, cx.tcx.hir().span(parent_expr.hir_id)));
+                    .push((index_value, cx.tcx.hir_span(parent_expr.hir_id)));
                 return;
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 5afcf51167d..a24dd44790e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -85,10 +85,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         if bk == ty::BorrowKind::Mutable {
             if let PlaceBase::Local(id) = cmt.place.base {
                 if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                    self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
+                    self.span_low = Some(self.cx.tcx.hir_span(diag_expr_id));
                 }
                 if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                    self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
+                    self.span_high = Some(self.cx.tcx.hir_span(diag_expr_id));
                 }
             }
         }
@@ -97,10 +97,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         if let PlaceBase::Local(id) = cmt.place.base {
             if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
+                self.span_low = Some(self.cx.tcx.hir_span(diag_expr_id));
             }
             if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
+                self.span_high = Some(self.cx.tcx.hir_span(diag_expr_id));
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
index 006addb987f..df6e85611fb 100644
--- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -253,7 +253,7 @@ impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe {
                 // Remove the syntax context to hide "in this macro invocation" in the diagnostic.
                 // The invocation doesn't matter. Also we want to dedupe by the unsafe block and not by anything
                 // related to the callsite.
-                let span = cx.tcx.hir().span(id);
+                let span = cx.tcx.hir_span(id);
 
                 (id, Span::new(span.lo(), span.hi(), SyntaxContext::root(), None))
             })
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index ab53ad98572..9bbef8da0a4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -246,7 +246,6 @@ fn emit_redundant_guards<'tcx>(
 fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     for_each_expr_without_closures(expr, |expr| {
         if match expr.kind {
-            ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat(),
             ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
                 // Allow ctors
                 matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index 7c190e123b7..4c81b22861b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
 fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
     cx.tcx
         .hir_parent_id_iter(id)
-        .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
+        .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace)))
 }
 
 /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 693d1a8dd76..09ee6f7037c 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -329,7 +329,7 @@ fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     let name = ident.name.as_str();
     if name.starts_with('_')
         && !name.starts_with("__")
-        && let definition_span = cx.tcx.hir().span(definition_hir_id)
+        && let definition_span = cx.tcx.hir_span(definition_hir_id)
         && !definition_span.from_expansion()
         && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id])
     {
diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
index 0e1980a6acb..4b32ba83b32 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
@@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]);
 
 impl EarlyLintPass for MultipleBoundLocations {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) {
-        if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind
+        if let FnKind::Fn(_, _, Fn { generics, .. }) = kind
             && !generics.params.is_empty()
             && !generics.where_clause.predicates.is_empty()
         {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 576bb27b254..b61061d076b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                             diag.span_suggestion(
                                 sp,
                                 "consider changing to".to_string(),
-                                format!("&{}", snippet(cx, cx.tcx.hir().span(inner_ty.ty.hir_id), "_"),),
+                                format!("&{}", snippet(cx, cx.tcx.hir_span(inner_ty.ty.hir_id), "_"),),
                                 Applicability::Unspecified,
                             );
                             if cx.effective_visibilities.is_exported(*fn_def_id) {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 55ca875edce..978fde33d51 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 // Dereference suggestion
                 let sugg = |diag: &mut Diag<'_, ()>| {
                     if let ty::Adt(def, ..) = ty.kind() {
-                        if let Some(span) = cx.tcx.hir().span_if_local(def.did()) {
+                        if let Some(span) = cx.tcx.hir_span_if_local(def.did()) {
                             if type_allowed_to_implement_copy(
                                 cx.tcx,
                                 cx.param_env,
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index f0ee613791f..1e469c3b63a 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -97,14 +97,14 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                         {
                             if self.impling_types.is_none() {
                                 let mut impls = HirIdSet::default();
-                                cx.tcx.for_each_impl(default_trait_id, |d| {
+                                for &d in cx.tcx.local_trait_impls(default_trait_id) {
                                     let ty = cx.tcx.type_of(d).instantiate_identity();
                                     if let Some(ty_def) = ty.ty_adt_def() {
                                         if let Some(local_def_id) = ty_def.did().as_local() {
                                             impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
                                         }
                                     }
-                                });
+                                }
                                 self.impling_types = Some(impls);
                             }
 
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index 594101427f5..08fcd17e555 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -354,7 +354,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
 
         let body_owner_kind = cx.tcx.hir_body_owner_kind(body_owner_def_id);
         if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind {
-            let body_span = cx.tcx.hir().span_with_body(body_owner);
+            let body_span = cx.tcx.hir_span_with_body(body_owner);
             if let Some(span) = self.const_span
                 && span.contains(body_span)
             {
@@ -366,7 +366,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
 
     fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
         let body_owner = cx.tcx.hir_body_owner(body.id());
-        let body_span = cx.tcx.hir().span(body_owner);
+        let body_span = cx.tcx.hir_span(body_owner);
         if let Some(span) = self.const_span
             && span.contains(body_span)
         {
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index c261fd9bd9c..96c9775e292 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -73,7 +73,7 @@ impl Context {
 
         match cx.tcx.hir_body_owner_kind(body_owner_def_id) {
             hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => {
-                let body_span = cx.tcx.hir().span_with_body(body_owner);
+                let body_span = cx.tcx.hir_span_with_body(body_owner);
 
                 if let Some(span) = self.const_span {
                     if span.contains(body_span) {
@@ -88,7 +88,7 @@ impl Context {
 
     pub fn body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
         let body_owner = cx.tcx.hir_body_owner(body.id());
-        let body_span = cx.tcx.hir().span_with_body(body_owner);
+        let body_span = cx.tcx.hir_span_with_body(body_owner);
 
         if let Some(span) = self.const_span {
             if span.contains(body_span) {
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
index 267e2067e10..cda752d003f 100644
--- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
 
 impl EarlyLintPass for PartialPubFields {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(ref st, _) = item.kind else {
+        let ItemKind::Struct(_, ref st, _) = item.kind else {
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 55f1ece0559..50ef56db167 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -127,29 +127,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// This lint checks for invalid usages of `ptr::null`.
-    ///
-    /// ### Why is this bad?
-    /// This causes undefined behavior.
-    ///
-    /// ### Example
-    /// ```ignore
-    /// // Undefined behavior
-    /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```ignore
-    /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); }
-    /// ```
-    #[clippy::version = "1.53.0"]
-    pub INVALID_NULL_PTR_USAGE,
-    correctness,
-    "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Use `std::ptr::eq` when applicable
     ///
     /// ### Why is this bad?
@@ -177,7 +154,7 @@ declare_clippy_lint! {
     "use `std::ptr::eq` when comparing raw pointers"
 }
 
-declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]);
+declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, PTR_EQ]);
 
 impl<'tcx> LateLintPass<'tcx> for Ptr {
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
@@ -301,54 +278,6 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                 format!("{non_null_path_snippet}.is_null()"),
                 Applicability::MachineApplicable,
             );
-        } else {
-            check_invalid_ptr_usage(cx, expr);
-        }
-    }
-}
-
-fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    if let ExprKind::Call(fun, args) = expr.kind
-        && let ExprKind::Path(ref qpath) = fun.kind
-        && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
-        && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id)
-    {
-        // TODO: `ptr_slice_from_raw_parts` and its mutable variant should probably still be linted
-        // conditionally based on how the return value is used, but not universally like the other
-        // functions since there are valid uses for null slice pointers.
-        //
-        // See: https://github.com/rust-lang/rust-clippy/pull/13452/files#r1773772034
-
-        // `arg` positions where null would cause U.B.
-        let arg_indices: &[_] = match name {
-            sym::ptr_read
-            | sym::ptr_read_unaligned
-            | sym::ptr_read_volatile
-            | sym::ptr_replace
-            | sym::ptr_write
-            | sym::ptr_write_bytes
-            | sym::ptr_write_unaligned
-            | sym::ptr_write_volatile
-            | sym::slice_from_raw_parts
-            | sym::slice_from_raw_parts_mut => &[0],
-            sym::ptr_copy | sym::ptr_copy_nonoverlapping | sym::ptr_swap | sym::ptr_swap_nonoverlapping => &[0, 1],
-            _ => return,
-        };
-
-        for &arg_idx in arg_indices {
-            if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg))
-                && let Some(std_or_core) = std_or_core(cx)
-            {
-                span_lint_and_sugg(
-                    cx,
-                    INVALID_NULL_PTR_USAGE,
-                    arg.span,
-                    "pointer must be non-null",
-                    "change this to",
-                    format!("{std_or_core}::ptr::NonNull::dangling().as_ptr()"),
-                    Applicability::MachineApplicable,
-                );
-            }
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index ee282ee1dfb..b82ddedd56c 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -218,7 +218,7 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
         },
     };
     span_lint_and_then(cx, lint, span, msg, |diag| {
-        diag.span_note(cx.tcx.hir().span(shadowed), "previous binding is here");
+        diag.span_note(cx.tcx.hir_span(shadowed), "previous binding is here");
     });
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index e9db7c9d031..76874cc3420 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -79,10 +79,11 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
             if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
                 continue;
             }
+            let first_bind_ident = apa.first_bind_ident.unwrap();
             span_lint_and_then(
                 cx,
                 SIGNIFICANT_DROP_TIGHTENING,
-                apa.first_bind_ident.span,
+                first_bind_ident.span,
                 "temporary with significant `Drop` can be early dropped",
                 |diag| {
                     match apa.counter {
@@ -91,13 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                             let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0));
                             let init_method = snippet(cx, apa.first_method_span, "..");
                             let usage_method = snippet(cx, apa.last_method_span, "..");
-                            let stmt = if apa.last_bind_ident == Ident::empty() {
-                                format!("\n{indent}{init_method}.{usage_method};")
-                            } else {
+                            let stmt = if let Some(last_bind_ident) = apa.last_bind_ident {
                                 format!(
                                     "\n{indent}let {} = {init_method}.{usage_method};",
-                                    snippet(cx, apa.last_bind_ident.span, ".."),
+                                    snippet(cx, last_bind_ident.span, ".."),
                                 )
+                            } else {
+                                format!("\n{indent}{init_method}.{usage_method};")
                             };
 
                             diag.multipart_suggestion_verbose(
@@ -113,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                                 format!(
                                     "\n{}drop({});",
                                     " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)),
-                                    apa.first_bind_ident
+                                    first_bind_ident
                                 ),
                                 Applicability::MaybeIncorrect,
                             );
@@ -124,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                         apa.first_block_span,
                         format!(
                             "temporary `{}` is currently being dropped at the end of its contained scope",
-                            apa.first_bind_ident
+                            first_bind_ident
                         ),
                     );
                 },
@@ -283,7 +284,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
                 let mut apa = AuxParamsAttr {
                     first_block_hir_id: self.ap.curr_block_hir_id,
                     first_block_span: self.ap.curr_block_span,
-                    first_bind_ident: ident,
+                    first_bind_ident: Some(ident),
                     first_method_span: {
                         let expr_or_init = expr_or_init(self.cx, expr);
                         if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind {
@@ -307,7 +308,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
                 match self.ap.curr_stmt.kind {
                     hir::StmtKind::Let(local) => {
                         if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
-                            apa.last_bind_ident = ident;
+                            apa.last_bind_ident = Some(ident);
                         }
                         if let Some(local_init) = local.init
                             && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind
@@ -373,7 +374,7 @@ struct AuxParamsAttr {
     first_block_span: Span,
     /// The binding or variable that references the initial construction of the type marked with
     /// `#[has_significant_drop]`.
-    first_bind_ident: Ident,
+    first_bind_ident: Option<Ident>,
     /// Similar to `init_bind_ident` but encompasses the right-hand method call.
     first_method_span: Span,
     /// Similar to `init_bind_ident` but encompasses the whole contained statement.
@@ -381,7 +382,7 @@ struct AuxParamsAttr {
 
     /// The last visited binding or variable span within a block that had any referenced inner type
     /// marked with `#[has_significant_drop]`.
-    last_bind_ident: Ident,
+    last_bind_ident: Option<Ident>,
     /// Similar to `last_bind_span` but encompasses the right-hand method call.
     last_method_span: Span,
     /// Similar to `last_bind_span` but encompasses the whole contained statement.
@@ -395,10 +396,10 @@ impl Default for AuxParamsAttr {
             has_expensive_expr_after_last_attr: false,
             first_block_hir_id: HirId::INVALID,
             first_block_span: DUMMY_SP,
-            first_bind_ident: Ident::empty(),
+            first_bind_ident: None,
             first_method_span: DUMMY_SP,
             first_stmt_span: DUMMY_SP,
-            last_bind_ident: Ident::empty(),
+            last_bind_ident: None,
             last_method_span: DUMMY_SP,
             last_stmt_span: DUMMY_SP,
         }
@@ -413,7 +414,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     }
 }
 
-fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool {
+fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option<Ident>, lcx: &LateContext<'_>) -> bool {
     if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind
         && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
         && let Res::Def(DefKind::Fn, did) = fun_path.res
@@ -422,6 +423,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_
         let has_ident = |local_expr: &hir::Expr<'_>| {
             if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind
                 && let [first_arg_ps, ..] = arg_path.segments
+                && let Some(first_bind_ident) = first_bind_ident
                 && &first_arg_ps.ident == first_bind_ident
             {
                 true
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
index 1a2fb77acc1..64891743dc6 100644
--- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn {
         for (&def_id, usage) in &self.def_id_to_usage {
             if let CallState::Once { call_site } = *usage
                 && let fn_hir_id = cx.tcx.local_def_id_to_hir_id(def_id)
-                && let fn_span = cx.tcx.hir().span_with_body(fn_hir_id)
+                && let fn_span = cx.tcx.hir_span_with_body(fn_hir_id)
                 && !self.is_function_allowed(cx, def_id, fn_hir_id, fn_span)
             {
                 span_lint_hir_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index fa082453504..35f80b2acda 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -174,11 +174,11 @@ impl SingleComponentPathImports {
         }
 
         match &item.kind {
-            ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
+            ItemKind::Mod(_, _, ModKind::Loaded(items, ..)) => {
                 self.check_mod(items);
             },
-            ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
-                macros.push(item.ident.name);
+            ItemKind::MacroDef(ident, MacroDef { macro_rules: true, .. }) => {
+                macros.push(ident.name);
             },
             ItemKind::Use(use_tree) => {
                 let segments = &use_tree.prefix.segments;
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 54261079fca..eba576392eb 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -321,47 +321,64 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool {
 }
 
 pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool {
-    eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
+    over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
 }
 
 #[expect(clippy::similar_names, clippy::too_many_lines)] // Just a big match statement
 pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
     use ItemKind::*;
     match (l, r) {
-        (ExternCrate(l), ExternCrate(r)) => l == r,
+        (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri),
         (Use(l), Use(r)) => eq_use_tree(l, r),
         (
             Static(box StaticItem {
+                ident: li,
                 ty: lt,
                 mutability: lm,
                 expr: le,
                 safety: ls,
+                define_opaque: _,
             }),
             Static(box StaticItem {
+                ident: ri,
                 ty: rt,
                 mutability: rm,
                 expr: re,
                 safety: rs,
+                define_opaque: _,
             }),
-        ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => eq_id(*li, *ri)
+                && lm == rm
+                && ls == rs
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref()),
         (
             Const(box ConstItem {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
                 ty: lt,
                 expr: le,
+                define_opaque: _,
             }),
             Const(box ConstItem {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
                 ty: rt,
                 expr: re,
+                define_opaque: _,
             }),
-        ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
+                && eq_generics(lg, rg)
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref()),
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -370,6 +387,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -378,12 +396,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
-        (Mod(lu, lmk), Mod(ru, rmk)) => {
-            lu == ru
+        (Mod(ls, li, lmk), Mod(rs, ri, rmk)) => {
+            ls == rs
+                && eq_id(*li, *ri)
                 && match (lmk, rmk) {
                     (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
                         linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
@@ -417,33 +437,40 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
         },
-        (Enum(le, lg), Enum(re, rg)) => over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg),
-        (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
-            eq_variant_data(lv, rv) && eq_generics(lg, rg)
+        (Enum(li, le, lg), Enum(ri, re, rg)) => {
+            eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
+        }
+        (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
+            eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
         },
         (
             Trait(box ast::Trait {
                 is_auto: la,
                 safety: lu,
+                ident: li,
                 generics: lg,
                 bounds: lb,
-                items: li,
+                items: lis,
             }),
             Trait(box ast::Trait {
                 is_auto: ra,
                 safety: ru,
+                ident: ri,
                 generics: rg,
                 bounds: rb,
-                items: ri,
+                items: ris,
             }),
         ) => {
             la == ra
                 && matches!(lu, Safety::Default) == matches!(ru, Safety::Default)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
-                && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
+                && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind))
         },
-        (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
+        (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
+            eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
+        }
         (
             Impl(box ast::Impl {
                 safety: lu,
@@ -476,7 +503,9 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
         },
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
-        (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body),
+        (MacroDef(li, ld), MacroDef(ri, rd)) => {
+            eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body)
+        }
         _ => false,
     }
 }
@@ -486,22 +515,33 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
     match (l, r) {
         (
             Static(box StaticItem {
+                ident: li,
                 ty: lt,
                 mutability: lm,
                 expr: le,
                 safety: ls,
+                define_opaque: _,
             }),
             Static(box StaticItem {
+                ident: ri,
                 ty: rt,
                 mutability: rm,
                 expr: re,
                 safety: rs,
+                define_opaque: _,
             }),
-        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
+        ) => {
+            eq_id(*li, *ri)
+                && eq_ty(lt, rt)
+                && lm == rm
+                && eq_expr_opt(le.as_ref(), re.as_ref())
+                && ls == rs
+        }
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -510,6 +550,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -518,6 +559,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -525,20 +567,23 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
         (
             TyAlias(box ast::TyAlias {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
+                where_clauses: _,
                 bounds: lb,
                 ty: lt,
-                ..
             }),
             TyAlias(box ast::TyAlias {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
+                where_clauses: _,
                 bounds: rb,
                 ty: rt,
-                ..
             }),
         ) => {
             eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
@@ -554,21 +599,32 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         (
             Const(box ConstItem {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
                 ty: lt,
                 expr: le,
+                define_opaque: _,
             }),
             Const(box ConstItem {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
                 ty: rt,
                 expr: re,
+                define_opaque: _,
             }),
-        ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => {
+            eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
+                && eq_generics(lg, rg)
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref())
+        }
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -577,6 +633,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -585,6 +642,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -592,20 +650,23 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         (
             Type(box TyAlias {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
+                where_clauses: _,
                 bounds: lb,
                 ty: lt,
-                ..
             }),
             Type(box TyAlias {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
+                where_clauses: _,
                 bounds: rb,
                 ty: rt,
-                ..
             }),
         ) => {
             eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 1307ff79bc5..8dc28fa3077 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>
 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
     if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
         if let Res::Def(_, def_id) = path.res {
-            return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
+            return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr);
         }
     }
     false
@@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
 /// use [`is_in_cfg_test`]
 pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
     tcx.hir_attrs(id).iter().any(|attr| {
-        if attr.has_name(sym::cfg)
+        if attr.has_name(sym::cfg_trace)
             && let Some(items) = attr.meta_item_list()
             && let [item] = &*items
             && item.has_name(sym::test)
@@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
 
 /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
 pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    tcx.has_attr(def_id, sym::cfg)
+    tcx.has_attr(def_id, sym::cfg_trace)
         || tcx
             .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
             .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
-            .any(|attr| attr.has_name(sym::cfg))
+            .any(|attr| attr.has_name(sym::cfg_trace))
 }
 
 /// Walks up the HIR tree from the given expression in an attempt to find where the value is
@@ -2990,7 +2990,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU
         {
             adjustments = cx.typeck_results().expr_adjustments(e);
         }
-        same_ctxt &= cx.tcx.hir().span(parent_id).ctxt() == ctxt;
+        same_ctxt &= cx.tcx.hir_span(parent_id).ctxt() == ctxt;
         if let Node::Expr(e) = parent {
             match e.kind {
                 ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id != child_id => {
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 1a457bc7f21..dfb30b9c218 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -178,7 +178,6 @@ pub fn first_node_in_macro(cx: &LateContext<'_>, node: &impl HirNode) -> Option<
 
     // get the parent node, possibly skipping over a statement
     // if the parent is not found, it is sensible to return `Some(root)`
-    let hir = cx.tcx.hir();
     let mut parent_iter = cx.tcx.hir_parent_iter(node.hir_id());
     let (parent_id, _) = match parent_iter.next() {
         None => return Some(ExpnId::root()),
@@ -190,7 +189,7 @@ pub fn first_node_in_macro(cx: &LateContext<'_>, node: &impl HirNode) -> Option<
     };
 
     // get the macro expansion of the parent node
-    let parent_span = hir.span(parent_id);
+    let parent_span = cx.tcx.hir_span(parent_id);
     let Some(parent_macro_call) = macro_backtrace(parent_span).next() else {
         // the parent node is not in a macro
         return Some(ExpnId::root());
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 68a1de96a35..065d48119a2 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -839,8 +839,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
         if let PlaceBase::Local(id) = cmt.place.base {
-            let map = self.cx.tcx.hir();
-            let span = map.span(cmt.hir_id);
+            let span = self.cx.tcx.hir_span(cmt.hir_id);
             let start_span = Span::new(self.next_pos, span.lo(), span.ctxt(), None);
             let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
index fefdc405cce..4a1886c08af 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![allow(dead_code, unused_variables)]
+#![allow(dead_code, unused_variables, invalid_null_arguments)]
 #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
deleted file mode 100644
index ce78e89ee82..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed
+++ /dev/null
@@ -1,66 +0,0 @@
-fn main() {
-    unsafe {
-        let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        struct A; // zero sized struct
-        assert_eq!(std::mem::size_of::<A>(), 0);
-
-        let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::replace(std::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-        let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint
-        let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0);
-
-        std::ptr::swap::<A>(std::ptr::NonNull::dangling().as_ptr(), &mut A);
-        //~^ invalid_null_ptr_usage
-        std::ptr::swap::<A>(&mut A, std::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::swap_nonoverlapping::<A>(std::ptr::NonNull::dangling().as_ptr(), &mut A, 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write(std::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_unaligned(std::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_volatile(std::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_bytes::<usize>(std::ptr::NonNull::dangling().as_ptr(), 42, 0);
-        //~^ invalid_null_ptr_usage
-    }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
deleted file mode 100644
index 361865fbd96..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-fn main() {
-    unsafe {
-        let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0);
-        //~^ invalid_null_ptr_usage
-        let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        struct A; // zero sized struct
-        assert_eq!(std::mem::size_of::<A>(), 0);
-
-        let _a: A = std::ptr::read(std::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read(std::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::read_unaligned(std::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read_unaligned(std::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::read_volatile(std::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = std::ptr::read_volatile(std::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = std::ptr::replace(std::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-        let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint
-        let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0);
-
-        std::ptr::swap::<A>(std::ptr::null_mut(), &mut A);
-        //~^ invalid_null_ptr_usage
-        std::ptr::swap::<A>(&mut A, std::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0);
-        //~^ invalid_null_ptr_usage
-        std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write(std::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_unaligned(std::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_volatile(std::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0);
-        //~^ invalid_null_ptr_usage
-    }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr
deleted file mode 100644
index 3f9d15b9040..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr
+++ /dev/null
@@ -1,136 +0,0 @@
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:3:59
-   |
-LL |         let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0);
-   |                                                           ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-   |
-   = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:5:59
-   |
-LL |         let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0);
-   |                                                           ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:8:63
-   |
-LL |         let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
-   |                                                               ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:11:33
-   |
-LL |         std::ptr::copy::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
-   |                                 ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:13:73
-   |
-LL |         std::ptr::copy::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
-   |                                                                         ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:16:48
-   |
-LL |         std::ptr::copy_nonoverlapping::<usize>(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0);
-   |                                                ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:18:88
-   |
-LL |         std::ptr::copy_nonoverlapping::<usize>(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0);
-   |                                                                                        ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:24:36
-   |
-LL |         let _a: A = std::ptr::read(std::ptr::null());
-   |                                    ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:26:36
-   |
-LL |         let _a: A = std::ptr::read(std::ptr::null_mut());
-   |                                    ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:29:46
-   |
-LL |         let _a: A = std::ptr::read_unaligned(std::ptr::null());
-   |                                              ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:31:46
-   |
-LL |         let _a: A = std::ptr::read_unaligned(std::ptr::null_mut());
-   |                                              ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:34:45
-   |
-LL |         let _a: A = std::ptr::read_volatile(std::ptr::null());
-   |                                             ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:36:45
-   |
-LL |         let _a: A = std::ptr::read_volatile(std::ptr::null_mut());
-   |                                             ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:39:39
-   |
-LL |         let _a: A = std::ptr::replace(std::ptr::null_mut(), A);
-   |                                       ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:44:29
-   |
-LL |         std::ptr::swap::<A>(std::ptr::null_mut(), &mut A);
-   |                             ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:46:37
-   |
-LL |         std::ptr::swap::<A>(&mut A, std::ptr::null_mut());
-   |                                     ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:49:44
-   |
-LL |         std::ptr::swap_nonoverlapping::<A>(std::ptr::null_mut(), &mut A, 0);
-   |                                            ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:51:52
-   |
-LL |         std::ptr::swap_nonoverlapping::<A>(&mut A, std::ptr::null_mut(), 0);
-   |                                                    ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:54:25
-   |
-LL |         std::ptr::write(std::ptr::null_mut(), A);
-   |                         ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:57:35
-   |
-LL |         std::ptr::write_unaligned(std::ptr::null_mut(), A);
-   |                                   ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:60:34
-   |
-LL |         std::ptr::write_volatile(std::ptr::null_mut(), A);
-   |                                  ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage.rs:63:40
-   |
-LL |         std::ptr::write_bytes::<usize>(std::ptr::null_mut(), 42, 0);
-   |                                        ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()`
-
-error: aborting due to 22 previous errors
-
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed
deleted file mode 100644
index df7ab166187..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed
+++ /dev/null
@@ -1,79 +0,0 @@
-#![no_std]
-#![feature(lang_items)]
-
-use core::panic::PanicInfo;
-
-#[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
-
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
-    loop {}
-}
-
-fn main() {
-    unsafe {
-        let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        struct A; // zero sized struct
-        assert_eq!(core::mem::size_of::<A>(), 0);
-
-        let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-        let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint
-        let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0);
-
-        core::ptr::swap::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A);
-        //~^ invalid_null_ptr_usage
-        core::ptr::swap::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr());
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::swap_nonoverlapping::<A>(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_bytes::<usize>(core::ptr::NonNull::dangling().as_ptr(), 42, 0);
-        //~^ invalid_null_ptr_usage
-    }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs
deleted file mode 100644
index 38ddfff0553..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-#![no_std]
-#![feature(lang_items)]
-
-use core::panic::PanicInfo;
-
-#[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
-
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
-    loop {}
-}
-
-fn main() {
-    unsafe {
-        let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0);
-        //~^ invalid_null_ptr_usage
-        let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::copy::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::copy_nonoverlapping::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        struct A; // zero sized struct
-        assert_eq!(core::mem::size_of::<A>(), 0);
-
-        let _a: A = core::ptr::read(core::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read(core::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::read_unaligned(core::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read_unaligned(core::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::read_volatile(core::ptr::null());
-        //~^ invalid_null_ptr_usage
-        let _a: A = core::ptr::read_volatile(core::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        let _a: A = core::ptr::replace(core::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-        let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint
-        let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0);
-
-        core::ptr::swap::<A>(core::ptr::null_mut(), &mut A);
-        //~^ invalid_null_ptr_usage
-        core::ptr::swap::<A>(&mut A, core::ptr::null_mut());
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::swap_nonoverlapping::<A>(core::ptr::null_mut(), &mut A, 0);
-        //~^ invalid_null_ptr_usage
-        core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::null_mut(), 0);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write(core::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_unaligned(core::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_volatile(core::ptr::null_mut(), A);
-        //~^ invalid_null_ptr_usage
-
-        core::ptr::write_bytes::<usize>(core::ptr::null_mut(), 42, 0);
-        //~^ invalid_null_ptr_usage
-    }
-}
diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr
deleted file mode 100644
index b5dd21ce624..00000000000
--- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr
+++ /dev/null
@@ -1,136 +0,0 @@
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:16:60
-   |
-LL |         let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0);
-   |                                                            ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-   |
-   = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:18:60
-   |
-LL |         let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0);
-   |                                                            ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:64
-   |
-LL |         let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0);
-   |                                                                ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:34
-   |
-LL |         core::ptr::copy::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
-   |                                  ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:26:75
-   |
-LL |         core::ptr::copy::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
-   |                                                                           ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:29:49
-   |
-LL |         core::ptr::copy_nonoverlapping::<usize>(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0);
-   |                                                 ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:90
-   |
-LL |         core::ptr::copy_nonoverlapping::<usize>(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0);
-   |                                                                                          ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:37
-   |
-LL |         let _a: A = core::ptr::read(core::ptr::null());
-   |                                     ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:37
-   |
-LL |         let _a: A = core::ptr::read(core::ptr::null_mut());
-   |                                     ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:42:47
-   |
-LL |         let _a: A = core::ptr::read_unaligned(core::ptr::null());
-   |                                               ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:47
-   |
-LL |         let _a: A = core::ptr::read_unaligned(core::ptr::null_mut());
-   |                                               ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:46
-   |
-LL |         let _a: A = core::ptr::read_volatile(core::ptr::null());
-   |                                              ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:46
-   |
-LL |         let _a: A = core::ptr::read_volatile(core::ptr::null_mut());
-   |                                              ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:52:40
-   |
-LL |         let _a: A = core::ptr::replace(core::ptr::null_mut(), A);
-   |                                        ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:57:30
-   |
-LL |         core::ptr::swap::<A>(core::ptr::null_mut(), &mut A);
-   |                              ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:59:38
-   |
-LL |         core::ptr::swap::<A>(&mut A, core::ptr::null_mut());
-   |                                      ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:62:45
-   |
-LL |         core::ptr::swap_nonoverlapping::<A>(core::ptr::null_mut(), &mut A, 0);
-   |                                             ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:64:53
-   |
-LL |         core::ptr::swap_nonoverlapping::<A>(&mut A, core::ptr::null_mut(), 0);
-   |                                                     ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:67:26
-   |
-LL |         core::ptr::write(core::ptr::null_mut(), A);
-   |                          ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:70:36
-   |
-LL |         core::ptr::write_unaligned(core::ptr::null_mut(), A);
-   |                                    ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:73:35
-   |
-LL |         core::ptr::write_volatile(core::ptr::null_mut(), A);
-   |                                   ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: pointer must be non-null
-  --> tests/ui/invalid_null_ptr_usage_no_std.rs:76:41
-   |
-LL |         core::ptr::write_bytes::<usize>(core::ptr::null_mut(), 42, 0);
-   |                                         ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
-
-error: aborting due to 22 previous errors
-
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 501811fa491..79640470696 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -119,6 +119,7 @@
 #![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
 #![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref`
 #![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
 #![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg`
 #![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 7f4b8062e1b..aa7b905b4b8 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -119,6 +119,7 @@
 #![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
 #![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref`
 #![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
 #![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg`
 #![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index f24eaec3917..b3c88167c11 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -343,71 +343,77 @@ error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_fro
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
-error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
+error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments`
   --> tests/ui/rename.rs:122:9
    |
+LL | #![warn(clippy::invalid_null_ptr_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments`
+
+error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
+  --> tests/ui/rename.rs:123:9
+   |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:123:9
+  --> tests/ui/rename.rs:124:9
    |
 LL | #![warn(clippy::maybe_misused_cfg)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> tests/ui/rename.rs:124:9
+  --> tests/ui/rename.rs:125:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:125:9
+  --> tests/ui/rename.rs:126:9
    |
 LL | #![warn(clippy::mismatched_target_os)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> tests/ui/rename.rs:126:9
+  --> tests/ui/rename.rs:127:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> tests/ui/rename.rs:127:9
+  --> tests/ui/rename.rs:128:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
-  --> tests/ui/rename.rs:128:9
+  --> tests/ui/rename.rs:129:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> tests/ui/rename.rs:129:9
+  --> tests/ui/rename.rs:130:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> tests/ui/rename.rs:130:9
+  --> tests/ui/rename.rs:131:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> tests/ui/rename.rs:131:9
+  --> tests/ui/rename.rs:132:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
 error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
-  --> tests/ui/rename.rs:132:9
+  --> tests/ui/rename.rs:133:9
    |
 LL | #![warn(clippy::vtable_address_comparisons)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
 
-error: aborting due to 68 previous errors
+error: aborting due to 69 previous errors
 
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 37ef63ae42e..b68f817146f 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -9,8 +9,6 @@ use std::sync::OnceLock;
 use regex::Regex;
 use tracing::*;
 
-use self::WhichLine::*;
-
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum ErrorKind {
     Help,
@@ -50,7 +48,7 @@ impl fmt::Display for ErrorKind {
 
 #[derive(Debug)]
 pub struct Error {
-    pub line_num: usize,
+    pub line_num: Option<usize>,
     /// What kind of message we expect (e.g., warning, error, suggestion).
     /// `None` if not specified or unknown message kind.
     pub kind: Option<ErrorKind>,
@@ -63,17 +61,14 @@ impl Error {
         format!(
             "{: <10}line {: >3}: {}",
             self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
-            self.line_num,
+            self.line_num_str(),
             self.msg.cyan(),
         )
     }
-}
 
-#[derive(PartialEq, Debug)]
-enum WhichLine {
-    ThisLine,
-    FollowPrevious(usize),
-    AdjustBackward(usize),
+    pub fn line_num_str(&self) -> String {
+        self.line_num.map_or("?".to_string(), |line_num| line_num.to_string())
+    }
 }
 
 /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
@@ -105,12 +100,10 @@ pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec<Error> {
         .filter(|(_, line)| line.is_ok())
         .filter_map(|(line_num, line)| {
             parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), revision).map(
-                |(which, error)| {
-                    match which {
-                        FollowPrevious(_) => {}
-                        _ => last_nonfollow_error = Some(error.line_num),
+                |(follow_prev, error)| {
+                    if !follow_prev {
+                        last_nonfollow_error = error.line_num;
                     }
-
                     error
                 },
             )
@@ -123,18 +116,23 @@ fn parse_expected(
     line_num: usize,
     line: &str,
     test_revision: Option<&str>,
-) -> Option<(WhichLine, Error)> {
+) -> Option<(bool, Error)> {
     // Matches comments like:
     //     //~
     //     //~|
     //     //~^
     //     //~^^^^^
+    //     //~v
+    //     //~vvvvv
+    //     //~?
     //     //[rev1]~
     //     //[rev1,rev2]~^^
     static RE: OnceLock<Regex> = OnceLock::new();
 
     let captures = RE
-        .get_or_init(|| Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\||\^*)").unwrap())
+        .get_or_init(|| {
+            Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||[v\^]*)").unwrap()
+        })
         .captures(line)?;
 
     match (test_revision, captures.name("revs")) {
@@ -151,11 +149,6 @@ fn parse_expected(
         (Some(_), None) | (None, None) => {}
     }
 
-    let (follow, adjusts) = match &captures["adjust"] {
-        "|" => (true, 0),
-        circumflexes => (false, circumflexes.len()),
-    };
-
     // Get the part of the comment after the sigil (e.g. `~^^` or ~|).
     let whole_match = captures.get(0).unwrap();
     let (_, mut msg) = line.split_at(whole_match.end());
@@ -170,28 +163,26 @@ fn parse_expected(
 
     let msg = msg.trim().to_owned();
 
-    let (which, line_num) = if follow {
-        assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
-        let line_num = last_nonfollow_error.expect(
-            "encountered //~| without \
-             preceding //~^ line.",
-        );
-        (FollowPrevious(line_num), line_num)
+    let line_num_adjust = &captures["adjust"];
+    let (follow_prev, line_num) = if line_num_adjust == "|" {
+        (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line")))
+    } else if line_num_adjust == "?" {
+        (false, None)
+    } else if line_num_adjust.starts_with('v') {
+        (false, Some(line_num + line_num_adjust.len()))
     } else {
-        let which = if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine };
-        let line_num = line_num - adjusts;
-        (which, line_num)
+        (false, Some(line_num - line_num_adjust.len()))
     };
 
     debug!(
-        "line={} tag={:?} which={:?} kind={:?} msg={:?}",
+        "line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}",
         line_num,
         whole_match.as_str(),
-        which,
+        follow_prev,
         kind,
         msg
     );
-    Some((which, Error { line_num, kind, msg }))
+    Some((follow_prev, Error { line_num, kind, msg }))
 }
 
 #[cfg(test)]
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 7675e13990d..f654bd9c90b 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -924,7 +924,14 @@ fn iter_header(
 
 impl Config {
     fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec<String>) {
-        const FORBIDDEN_REVISION_NAMES: [&str; 9] =
+        const FORBIDDEN_REVISION_NAMES: [&str; 2] = [
+            // `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very
+            // weird for the test, since if the test writer wants a cfg of the same revision name
+            // they'd have to use `cfg(r#true)` and `cfg(r#false)`.
+            "true", "false",
+        ];
+
+        const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] =
             ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"];
 
         if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
@@ -933,25 +940,38 @@ impl Config {
             }
 
             let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
-            for revision in raw.split_whitespace().map(|r| r.to_string()) {
-                if !duplicates.insert(revision.clone()) {
+            for revision in raw.split_whitespace() {
+                if !duplicates.insert(revision.to_string()) {
                     panic!(
                         "duplicate revision: `{}` in line `{}`: {}",
                         revision,
                         raw,
                         testfile.display()
                     );
-                } else if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt)
-                    && FORBIDDEN_REVISION_NAMES.contains(&revision.as_str())
+                }
+
+                if FORBIDDEN_REVISION_NAMES.contains(&revision) {
+                    panic!(
+                        "revision name `{revision}` is not permitted: `{}` in line `{}`: {}",
+                        revision,
+                        raw,
+                        testfile.display()
+                    );
+                }
+
+                if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt)
+                    && FILECHECK_FORBIDDEN_REVISION_NAMES.contains(&revision)
                 {
                     panic!(
-                        "revision name `{revision}` is not permitted in a test suite that uses `FileCheck` annotations\n\
-                         as it is confusing when used as custom `FileCheck` prefix: `{revision}` in line `{}`: {}",
+                        "revision name `{revision}` is not permitted in a test suite that uses \
+                        `FileCheck` annotations as it is confusing when used as custom `FileCheck` \
+                        prefix: `{revision}` in line `{}`: {}",
                         raw,
                         testfile.display()
                     );
                 }
-                existing.push(revision);
+
+                existing.push(revision.to_string());
             }
         }
     }
@@ -1385,7 +1405,7 @@ pub fn make_test_description<R: Read>(
             decision!(cfg::handle_ignore(config, ln));
             decision!(cfg::handle_only(config, ln));
             decision!(needs::handle_needs(&cache.needs, config, ln));
-            decision!(ignore_llvm(config, ln));
+            decision!(ignore_llvm(config, path, ln));
             decision!(ignore_cdb(config, ln));
             decision!(ignore_gdb(config, ln));
             decision!(ignore_lldb(config, ln));
@@ -1525,7 +1545,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
-fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
+fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
     if let Some(needed_components) =
         config.parse_name_value_directive(line, "needs-llvm-components")
     {
@@ -1536,8 +1556,9 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
         {
             if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() {
                 panic!(
-                    "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set",
-                    missing_component
+                    "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}",
+                    missing_component,
+                    path.display()
                 );
             }
             return IgnoreDecision::Ignore {
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 007318be7cc..4d90f152ee2 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -568,6 +568,13 @@ fn test_assembly_mode_forbidden_revisions() {
 }
 
 #[test]
+#[should_panic(expected = "revision name `true` is not permitted")]
+fn test_forbidden_revisions() {
+    let config = cfg().mode("ui").build();
+    parse_rs(&config, "//@ revisions: true");
+}
+
+#[test]
 #[should_panic(
     expected = "revision name `CHECK` is not permitted in a test suite that uses `FileCheck` annotations"
 )]
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 0da93dcafa2..9bc26fedf8f 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -2,7 +2,9 @@
 
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
+use std::sync::OnceLock;
 
+use regex::Regex;
 use serde::Deserialize;
 
 use crate::errors::{Error, ErrorKind};
@@ -213,36 +215,24 @@ fn push_expected_errors(
     // also ensure that `//~ ERROR E123` *always* works. The
     // assumption is that these multi-line error messages are on their
     // way out anyhow.
-    let with_code = |span: &DiagnosticSpan, text: &str| {
-        match diagnostic.code {
-            Some(ref code) =>
-            // FIXME(#33000) -- it'd be better to use a dedicated
-            // UI harness than to include the line/col number like
-            // this, but some current tests rely on it.
-            //
-            // Note: Do NOT include the filename. These can easily
-            // cause false matches where the expected message
-            // appears in the filename, and hence the message
-            // changes but the test still passes.
-            {
-                format!(
-                    "{}:{}: {}:{}: {} [{}]",
-                    span.line_start,
-                    span.column_start,
-                    span.line_end,
-                    span.column_end,
-                    text,
-                    code.code.clone()
-                )
-            }
-            None =>
-            // FIXME(#33000) -- it'd be better to use a dedicated UI harness
-            {
-                format!(
-                    "{}:{}: {}:{}: {}",
-                    span.line_start, span.column_start, span.line_end, span.column_end, text
-                )
+    let with_code = |span: Option<&DiagnosticSpan>, text: &str| {
+        // FIXME(#33000) -- it'd be better to use a dedicated
+        // UI harness than to include the line/col number like
+        // this, but some current tests rely on it.
+        //
+        // Note: Do NOT include the filename. These can easily
+        // cause false matches where the expected message
+        // appears in the filename, and hence the message
+        // changes but the test still passes.
+        let span_str = match span {
+            Some(DiagnosticSpan { line_start, column_start, line_end, column_end, .. }) => {
+                format!("{line_start}:{column_start}: {line_end}:{column_end}")
             }
+            None => format!("?:?: ?:?"),
+        };
+        match &diagnostic.code {
+            Some(code) => format!("{span_str}: {text} [{}]", code.code),
+            None => format!("{span_str}: {text}"),
         }
     };
 
@@ -251,19 +241,41 @@ fn push_expected_errors(
     // more structured shortly anyhow.
     let mut message_lines = diagnostic.message.lines();
     if let Some(first_line) = message_lines.next() {
-        for span in primary_spans {
-            let msg = with_code(span, first_line);
+        let ignore = |s| {
+            static RE: OnceLock<Regex> = OnceLock::new();
+            RE.get_or_init(|| {
+                Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap()
+            })
+            .is_match(s)
+        };
+
+        if primary_spans.is_empty() && !ignore(first_line) {
+            let msg = with_code(None, first_line);
             let kind = ErrorKind::from_str(&diagnostic.level).ok();
-            expected_errors.push(Error { line_num: span.line_start, kind, msg });
+            expected_errors.push(Error { line_num: None, kind, msg });
+        } else {
+            for span in primary_spans {
+                let msg = with_code(Some(span), first_line);
+                let kind = ErrorKind::from_str(&diagnostic.level).ok();
+                expected_errors.push(Error { line_num: Some(span.line_start), kind, msg });
+            }
         }
     }
     for next_line in message_lines {
-        for span in primary_spans {
+        if primary_spans.is_empty() {
             expected_errors.push(Error {
-                line_num: span.line_start,
+                line_num: None,
                 kind: None,
-                msg: with_code(span, next_line),
+                msg: with_code(None, next_line),
             });
+        } else {
+            for span in primary_spans {
+                expected_errors.push(Error {
+                    line_num: Some(span.line_start),
+                    kind: None,
+                    msg: with_code(Some(span), next_line),
+                });
+            }
         }
     }
 
@@ -272,7 +284,7 @@ fn push_expected_errors(
         if let Some(ref suggested_replacement) = span.suggested_replacement {
             for (index, line) in suggested_replacement.lines().enumerate() {
                 expected_errors.push(Error {
-                    line_num: span.line_start + index,
+                    line_num: Some(span.line_start + index),
                     kind: Some(ErrorKind::Suggestion),
                     msg: line.to_string(),
                 });
@@ -290,7 +302,7 @@ fn push_expected_errors(
     // Add notes for any labels that appear in the message.
     for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) {
         expected_errors.push(Error {
-            line_num: span.line_start,
+            line_num: Some(span.line_start),
             kind: Some(ErrorKind::Note),
             msg: span.label.clone().unwrap(),
         });
@@ -309,7 +321,7 @@ fn push_backtrace(
 ) {
     if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
         expected_errors.push(Error {
-            line_num: expansion.span.line_start,
+            line_num: Some(expansion.span.line_start),
             kind: Some(ErrorKind::Note),
             msg: format!("in this expansion of {}", expansion.macro_decl_name),
         });
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index dd611b19a8d..950566b2582 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -22,6 +22,7 @@ pub mod util;
 use core::panic;
 use std::collections::HashSet;
 use std::ffi::OsString;
+use std::fmt::Write;
 use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
@@ -570,18 +571,22 @@ pub fn run_tests(config: Arc<Config>) {
             // easy to miss which tests failed, and as such fail to reproduce
             // the failure locally.
 
-            println!(
-                "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
-                config.suite,
-                config
-                    .compare_mode
-                    .as_ref()
-                    .map(|c| format!(" compare_mode={:?}", c))
-                    .unwrap_or_default(),
-                config.mode,
-                config.host,
-                config.target
-            );
+            let mut msg = String::from("Some tests failed in compiletest");
+            write!(msg, " suite={}", config.suite).unwrap();
+
+            if let Some(compare_mode) = config.compare_mode.as_ref() {
+                write!(msg, " compare_mode={}", compare_mode).unwrap();
+            }
+
+            if let Some(pass_mode) = config.force_pass_mode.as_ref() {
+                write!(msg, " pass_mode={}", pass_mode).unwrap();
+            }
+
+            write!(msg, " mode={}", config.mode).unwrap();
+            write!(msg, " host={}", config.host).unwrap();
+            write!(msg, " target={}", config.target).unwrap();
+
+            println!("{msg}");
 
             std::process::exit(1);
         }
@@ -747,8 +752,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
     }
 
     let files =
-        get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?
-            .unwrap_or(vec![]);
+        get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?;
     // Add new test cases to the list, it will be convenient in daily development.
     let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]);
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 6e250ca12c9..c8a60b68da8 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -747,7 +747,7 @@ impl<'test> TestCx<'test> {
                         self.error(&format!(
                             "{}:{}: unexpected {}: '{}'",
                             file_name,
-                            actual_error.line_num,
+                            actual_error.line_num_str(),
                             actual_error
                                 .kind
                                 .as_ref()
@@ -767,7 +767,7 @@ impl<'test> TestCx<'test> {
                 self.error(&format!(
                     "{}:{}: expected {} not found: {}",
                     file_name,
-                    expected_error.line_num,
+                    expected_error.line_num_str(),
                     expected_error.kind.as_ref().map_or("message".into(), |k| k.to_string()),
                     expected_error.msg
                 ));
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index 3329e10745f..9b5b8b56b60 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -182,7 +182,7 @@ impl TestCx<'_> {
         } else if explicit && !expected_errors.is_empty() {
             let msg = format!(
                 "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
-                expected_errors[0].line_num,
+                expected_errors[0].line_num_str(),
                 expected_errors[0].kind.unwrap_or(ErrorKind::Error),
             );
             self.fatal(&msg);
diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml
index e1eb6d05665..80fc26cbe66 100644
--- a/src/tools/jsondocck/Cargo.toml
+++ b/src/tools/jsondocck/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-jsonpath_lib = "0.3"
+jsonpath-rust = "1.0.0"
 getopts = "0.2"
 regex = "1.4"
 shlex = "1.0"
diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs
index 47512039740..1369c8ded00 100644
--- a/src/tools/jsondocck/src/cache.rs
+++ b/src/tools/jsondocck/src/cache.rs
@@ -30,6 +30,6 @@ impl Cache {
 
     // FIXME: Make this failible, so jsonpath syntax error has line number.
     pub fn select(&self, path: &str) -> Vec<&Value> {
-        jsonpath_lib::select(&self.value, path).unwrap()
+        jsonpath_rust::query::js_path_vals(path, &self.value).unwrap()
     }
 }
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index cf36b6fd038..bc254efcd30 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-4ac032f857b46037b55c1fc0fa702450aad37f43
+d5b4c2e4f19b6d7037371cdaecc3cc2c701c68df
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index b1ca434361b..923031dbbd1 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -717,7 +717,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
         // The program didn't actually do a read, so suppress the memory access hooks.
         // This is also a very special exception where we just ignore an error -- if this read
         // was UB e.g. because the memory is uninitialized, we don't want to know!
-        let old_val = this.run_for_validation(|this| this.read_scalar(dest)).discard_err();
+        let old_val = this.run_for_validation_mut(|this| this.read_scalar(dest)).discard_err();
         this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?;
         this.validate_atomic_store(dest, atomic)?;
         this.buffered_atomic_write(val, dest, atomic, old_val)
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 0e2239147f1..a7081d4f86a 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -22,12 +22,6 @@ pub fn bare_rustc() -> Rustc {
     Rustc::bare()
 }
 
-/// Construct a new `rustc` aux-build invocation.
-#[track_caller]
-pub fn aux_build() -> Rustc {
-    Rustc::new_aux_build()
-}
-
 /// A `rustc` invocation builder.
 #[derive(Debug)]
 #[must_use]
@@ -67,14 +61,6 @@ impl Rustc {
         Self { cmd }
     }
 
-    /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
-    #[track_caller]
-    pub fn new_aux_build() -> Self {
-        let mut cmd = setup_common();
-        cmd.arg("--crate-type=lib");
-        Self { cmd }
-    }
-
     // Argument provider methods
 
     /// Configure the compilation environment.
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index e0ad3ee9bed..fd22ff6c8bc 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -68,7 +68,7 @@ pub use llvm::{
     LlvmFilecheck, LlvmNm, LlvmObjcopy, LlvmObjdump, LlvmProfdata, LlvmReadobj,
 };
 pub use python::python_command;
-pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc};
+pub use rustc::{bare_rustc, rustc, rustc_path, Rustc};
 pub use rustdoc::{rustdoc, Rustdoc};
 
 /// [`diff`][mod@diff] is implemented in terms of the [similar] library.
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 7812863ccc2..60e711d3402 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -12,7 +12,20 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
     bin_path.push(cwd());
     bin_path.push(name);
     let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
-    let mut cmd = Command::new(bin_path);
+
+    let mut cmd = if let Some(rtc) = env::var_os("REMOTE_TEST_CLIENT") {
+        let mut cmd = Command::new(rtc);
+        cmd.arg("run");
+        // FIXME: the "0" indicates how many support files should be uploaded along with the binary
+        // to execute. If a test requires additional files to be pushed to the remote machine, this
+        // will have to be changed (and the support files will have to be uploaded).
+        cmd.arg("0");
+        cmd.arg(bin_path);
+        cmd
+    } else {
+        Command::new(bin_path)
+    };
+
     if let Some(args) = args {
         for arg in args {
             cmd.arg(arg);
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index 9a7a1a01a09..4c4174e2680 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -665,10 +665,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
     rustc_attr!(TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
     rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
-    rustc_attr!(
-        TEST, rustc_error, Normal,
-        template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly
-    ),
     rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
     rustc_attr!(
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
index 4e28aaced9b..7668f419040 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs
@@ -110,7 +110,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result<String> {
         ));
     }
     let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
-    // Last supported version is:
+    // Last breaking version change is:
     // https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318
     let (mut metadata_portion, bytes_before_version) = match version {
         8 => {
@@ -118,7 +118,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result<String> {
             let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
             (&dot_rustc[12..data_len + 12], 13)
         }
-        9 => {
+        9 | 10 => {
             let len_bytes = &dot_rustc[8..16];
             let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize;
             (&dot_rustc[16..data_len + 12], 17)
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index e54747c129a..08011e1d427 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -97,9 +97,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.95"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
 
 [[package]]
 name = "autocfg"
@@ -124,9 +124,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.8.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
 
 [[package]]
 name = "block-buffer"
@@ -155,16 +155,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 
 [[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
 name = "cc"
-version = "1.2.10"
+version = "1.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
+checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
 dependencies = [
  "shlex",
 ]
@@ -177,23 +171,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
+checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
  "js-sys",
  "num-traits",
  "wasm-bindgen",
- "windows-targets",
+ "windows-link",
 ]
 
 [[package]]
 name = "clap"
-version = "4.5.27"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796"
+checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -201,9 +195,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.27"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
+checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
 dependencies = [
  "anstream",
  "anstyle",
@@ -214,18 +208,18 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.43"
+version = "4.5.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0952013545c9c6dca60f491602655b795c6c062ab180c9cb0bccb83135461861"
+checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.24"
+version = "4.5.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
+checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -419,22 +413,22 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.11.6"
+version = "0.11.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
+checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697"
 dependencies = [
  "anstream",
  "anstyle",
  "env_filter",
- "humantime",
+ "jiff",
  "log",
 ]
 
 [[package]]
 name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
 name = "errno"
@@ -461,9 +455,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
 name = "flate2"
-version = "1.0.35"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
+checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -515,20 +509,21 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.15"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
 dependencies = [
  "cfg-if",
  "libc",
+ "r-efi",
  "wasi",
 ]
 
 [[package]]
 name = "handlebars"
-version = "6.3.0"
+version = "6.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6b224b95c1e668ac0270325ad563b2eef1469fbbb8959bc7c692c844b813d9"
+checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098"
 dependencies = [
  "derive_builder",
  "log",
@@ -537,7 +532,7 @@ dependencies = [
  "pest_derive",
  "serde",
  "serde_json",
- "thiserror 2.0.11",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -588,12 +583,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
 name = "iana-time-zone"
 version = "0.1.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -763,9 +752,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.7.1"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
+checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -779,9 +768,33 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 
 [[package]]
 name = "itoa"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
+[[package]]
+name = "jiff"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "js-sys"
@@ -801,9 +814,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.169"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 
 [[package]]
 name = "libdbus-sys"
@@ -826,15 +839,15 @@ dependencies = [
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.15"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
 
 [[package]]
 name = "litemap"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
 
 [[package]]
 name = "lock_api"
@@ -848,9 +861,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.25"
+version = "0.4.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
+checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
 
 [[package]]
 name = "mac"
@@ -880,9 +893,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.47"
+version = "0.4.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84"
+checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -910,17 +923,17 @@ dependencies = [
 
 [[package]]
 name = "mdbook-i18n-helpers"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cac78e4f518f326e5fc1ff95e79e7e0e58330cb8ac6e4b559d9659cf69bb1ab"
+checksum = "5644bf29b95683ea60979e30188221c374965c3a1dc0ad2d5c69e867dc0c09dc"
 dependencies = [
  "anyhow",
  "chrono",
  "dateparser",
  "mdbook",
  "polib",
- "pulldown-cmark 0.11.3",
- "pulldown-cmark-to-cmark 15.0.1",
+ "pulldown-cmark 0.12.2",
+ "pulldown-cmark-to-cmark 20.0.1",
  "regex",
  "semver",
  "serde_json",
@@ -956,7 +969,7 @@ dependencies = [
  "pulldown-cmark-to-cmark 19.0.1",
  "serde_json",
  "thiserror 1.0.69",
- "toml 0.8.19",
+ "toml 0.8.20",
 ]
 
 [[package]]
@@ -967,9 +980,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.3"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
 dependencies = [
  "adler2",
 ]
@@ -1015,9 +1028,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
 
 [[package]]
 name = "onig"
@@ -1095,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc"
 dependencies = [
  "memchr",
- "thiserror 2.0.11",
+ "thiserror 2.0.12",
  "ucd-trie",
 ]
 
@@ -1139,7 +1152,7 @@ version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
 dependencies = [
- "phf_shared 0.11.3",
+ "phf_shared",
 ]
 
 [[package]]
@@ -1148,18 +1161,8 @@ version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
 dependencies = [
- "phf_generator 0.11.3",
- "phf_shared 0.11.3",
-]
-
-[[package]]
-name = "phf_generator"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
-dependencies = [
- "phf_shared 0.10.0",
- "rand",
+ "phf_generator",
+ "phf_shared",
 ]
 
 [[package]]
@@ -1168,33 +1171,24 @@ version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
 dependencies = [
- "phf_shared 0.11.3",
+ "phf_shared",
  "rand",
 ]
 
 [[package]]
 name = "phf_shared"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
-dependencies = [
- "siphasher 0.3.11",
-]
-
-[[package]]
-name = "phf_shared"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
 dependencies = [
- "siphasher 1.0.1",
+ "siphasher",
 ]
 
 [[package]]
 name = "pkg-config"
-version = "0.3.31"
+version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
 
 [[package]]
 name = "polib"
@@ -1206,12 +1200,18 @@ dependencies = [
 ]
 
 [[package]]
-name = "ppv-lite86"
-version = "0.2.20"
+name = "portable-atomic"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
 dependencies = [
- "zerocopy",
+ "portable-atomic",
 ]
 
 [[package]]
@@ -1222,9 +1222,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.93"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
 dependencies = [
  "unicode-ident",
 ]
@@ -1235,7 +1235,7 @@ version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
 dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
  "memchr",
  "pulldown-cmark-escape 0.10.1",
  "unicase",
@@ -1243,23 +1243,11 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
-dependencies = [
- "bitflags 2.8.0",
- "memchr",
- "pulldown-cmark-escape 0.11.0",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark"
 version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
 dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
  "getopts",
  "memchr",
  "pulldown-cmark-escape 0.11.0",
@@ -1280,49 +1268,43 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
 
 [[package]]
 name = "pulldown-cmark-to-cmark"
-version = "15.0.1"
+version = "19.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1"
+checksum = "e84a87de49d1b6c63f0998da7ade299905387ae1feae350efc98e0632637f589"
 dependencies = [
- "pulldown-cmark 0.11.3",
+ "pulldown-cmark 0.12.2",
 ]
 
 [[package]]
 name = "pulldown-cmark-to-cmark"
-version = "19.0.1"
+version = "20.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e84a87de49d1b6c63f0998da7ade299905387ae1feae350efc98e0632637f589"
+checksum = "6c0f333311d2d8fda65bcf76af35054e9f38e253332a0289746156a59656988b"
 dependencies = [
  "pulldown-cmark 0.12.2",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
-name = "rand"
-version = "0.8.5"
+name = "r-efi"
+version = "5.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
 
 [[package]]
-name = "rand_chacha"
-version = "0.3.1"
+name = "rand"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
- "ppv-lite86",
  "rand_core",
 ]
 
@@ -1331,17 +1313,14 @@ name = "rand_core"
 version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.8"
+version = "0.5.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
+checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
 dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
 ]
 
 [[package]]
@@ -1387,11 +1366,11 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.38.44"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
+checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96"
 dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
  "errno",
  "libc",
  "linux-raw-sys",
@@ -1400,15 +1379,15 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
+checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
 
 [[package]]
 name = "ryu"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "same-file"
@@ -1427,24 +1406,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "semver"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
 
 [[package]]
 name = "serde"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.217"
+version = "1.0.219"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1453,9 +1432,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.138"
+version = "1.0.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
 dependencies = [
  "itoa",
  "memchr",
@@ -1491,21 +1470,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
 [[package]]
 name = "siphasher"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
-
-[[package]]
-name = "siphasher"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
 
 [[package]]
 name = "smallvec"
-version = "1.13.2"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
 
 [[package]]
 name = "stable_deref_trait"
@@ -1515,26 +1488,25 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "string_cache"
-version = "0.8.7"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
+checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe"
 dependencies = [
  "new_debug_unreachable",
- "once_cell",
  "parking_lot",
- "phf_shared 0.10.0",
+ "phf_shared",
  "precomputed-hash",
  "serde",
 ]
 
 [[package]]
 name = "string_cache_codegen"
-version = "0.5.2"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
+checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
 dependencies = [
- "phf_generator 0.10.0",
- "phf_shared 0.10.0",
+ "phf_generator",
+ "phf_shared",
  "proc-macro2",
  "quote",
 ]
@@ -1547,9 +1519,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "syn"
-version = "2.0.96"
+version = "2.0.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1589,11 +1561,10 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.15.0"
+version = "3.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
+checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
 dependencies = [
- "cfg-if",
  "fastrand",
  "getrandom",
  "once_cell",
@@ -1614,9 +1585,9 @@ dependencies = [
 
 [[package]]
 name = "terminal_size"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9"
+checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
 dependencies = [
  "rustix",
  "windows-sys",
@@ -1624,9 +1595,9 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.16.1"
+version = "0.16.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
+checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
 
 [[package]]
 name = "thiserror"
@@ -1639,11 +1610,11 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "2.0.11"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
 dependencies = [
- "thiserror-impl 2.0.11",
+ "thiserror-impl 2.0.12",
 ]
 
 [[package]]
@@ -1659,9 +1630,9 @@ dependencies = [
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.11"
+version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1689,9 +1660,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.19"
+version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -1710,9 +1681,9 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.22.22"
+version = "0.22.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
 dependencies = [
  "indexmap",
  "serde",
@@ -1729,9 +1700,9 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
 
 [[package]]
 name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 
 [[package]]
 name = "ucd-trie"
@@ -1747,9 +1718,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.16"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-width"
@@ -1810,9 +1781,12 @@ dependencies = [
 
 [[package]]
 name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
+version = "0.14.2+wasi-0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
 
 [[package]]
 name = "wasm-bindgen"
@@ -1913,6 +1887,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "windows-link"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+
+[[package]]
 name = "windows-sys"
 version = "0.59.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1987,14 +1967,23 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "winnow"
-version = "0.6.25"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad699df48212c6cc6eb4435f35500ac6fd3b9913324f938aea302022ce19d310"
+checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags 2.9.0",
+]
+
+[[package]]
 name = "write16"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2031,40 +2020,19 @@ dependencies = [
 ]
 
 [[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "byteorder",
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "zerofrom"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 831233e3065..a0b220c3557 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
 [dependencies.mdbook]
-version = "0.4.47"
+version = "0.4.48"
 default-features = false
 features = ["search"]
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index ea575f27799..f70fc917770 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -451,7 +451,7 @@ function loadSearchJS(doc_folder, resource_suffix) {
                         if (!Object.prototype.hasOwnProperty.call(entry, key)) {
                             continue;
                         }
-                        if (key === "displayTypeSignature") {
+                        if (key === "displayTypeSignature" && entry.displayTypeSignature !== null) {
                             const {type, mappedNames, whereClause} =
                                 await entry.displayTypeSignature;
                             entry.displayType = arrayToCode(type);
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index a37b47e3bc9..61e148cdf18 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -176,7 +176,6 @@ fn rewrite_closure_with_block(
             .first()
             .map(|attr| attr.span.to(body.span))
             .unwrap_or(body.span),
-        could_be_bare_literal: false,
     };
     let block = crate::expr::rewrite_block_with_visitor(
         context,
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index e866f13efc7..65120770edd 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -246,7 +246,7 @@ pub(crate) fn format_expr(
         | ast::ExprKind::Await(_, _)
         | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape),
         ast::ExprKind::MacCall(ref mac) => {
-            rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
+            rewrite_macro(mac, context, shape, MacroPosition::Expression).or_else(|_| {
                 wrap_str(
                     context.snippet(expr.span).to_owned(),
                     context.config.max_width(),
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 3fb3284e3d7..322af97d9dc 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -6,7 +6,7 @@ use std::cmp::{Ordering, max, min};
 use regex::Regex;
 use rustc_ast::visit;
 use rustc_ast::{ast, ptr};
-use rustc_span::{BytePos, DUMMY_SP, Span, symbol};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol};
 use tracing::debug;
 
 use crate::attr::filter_inline_attrs;
@@ -333,12 +333,12 @@ impl<'a> FnSig<'a> {
         defaultness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => {
+            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), vis, ast::Fn { sig, generics, .. }) => {
                 let mut fn_sig = FnSig::from_method_sig(sig, generics, vis);
                 fn_sig.defaultness = defaultness;
                 fn_sig
             }
-            visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig {
+            visit::FnKind::Fn(_, vis, ast::Fn { sig, generics, .. }) => FnSig {
                 decl,
                 generics,
                 ext: sig.header.ext,
@@ -750,11 +750,10 @@ impl<'a> FmtVisitor<'a> {
                 (Type(lty), Type(rty))
                     if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                 {
-                    a.ident.as_str().cmp(b.ident.as_str())
-                }
-                (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => {
-                    a.ident.as_str().cmp(b.ident.as_str())
+                    lty.ident.as_str().cmp(rty.ident.as_str())
                 }
+                (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()),
+                (MacCall(..), MacCall(..)) => Ordering::Equal,
                 (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => {
                     a.span.lo().cmp(&b.span.lo())
                 }
@@ -1105,14 +1104,16 @@ impl<'a> StructParts<'a> {
     }
 
     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
-        let (prefix, def, generics) = match item.kind {
-            ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
-            ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
+        let (prefix, def, ident, generics) = match item.kind {
+            ast::ItemKind::Struct(ident, ref def, ref generics) => {
+                ("struct ", def, ident, generics)
+            }
+            ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics),
             _ => unreachable!(),
         };
         StructParts {
             prefix,
-            ident: item.ident,
+            ident,
             vis: &item.vis,
             def,
             generics: Some(generics),
@@ -1168,6 +1169,7 @@ pub(crate) fn format_trait(
     let ast::Trait {
         is_auto,
         safety,
+        ident,
         ref generics,
         ref bounds,
         ref items,
@@ -1186,13 +1188,13 @@ pub(crate) fn format_trait(
 
     let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
     let generics_str =
-        rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?;
+        rewrite_generics(context, rewrite_ident(context, ident), generics, shape).ok()?;
     result.push_str(&generics_str);
 
     // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
     if !bounds.is_empty() {
         // Retrieve *unnormalized* ident (See #6069)
-        let source_ident = context.snippet(item.ident.span);
+        let source_ident = context.snippet(ident.span);
         let ident_hi = context.snippet_provider.span_after(item.span, source_ident);
         let bound_hi = bounds.last().unwrap().span().hi();
         let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
@@ -1679,11 +1681,12 @@ fn format_tuple_struct(
     Some(result)
 }
 
-pub(crate) enum ItemVisitorKind<'a> {
-    Item(&'a ast::Item),
-    AssocTraitItem(&'a ast::AssocItem),
-    AssocImplItem(&'a ast::AssocItem),
-    ForeignItem(&'a ast::ForeignItem),
+#[derive(Clone, Copy)]
+pub(crate) enum ItemVisitorKind {
+    Item,
+    AssocTraitItem,
+    AssocImplItem,
+    ForeignItem,
 }
 
 struct TyAliasRewriteInfo<'c, 'g>(
@@ -1695,17 +1698,19 @@ struct TyAliasRewriteInfo<'c, 'g>(
     Span,
 );
 
-pub(crate) fn rewrite_type_alias<'a, 'b>(
+pub(crate) fn rewrite_type_alias<'a>(
     ty_alias_kind: &ast::TyAlias,
+    vis: &ast::Visibility,
     context: &RewriteContext<'a>,
     indent: Indent,
-    visitor_kind: &ItemVisitorKind<'b>,
+    visitor_kind: ItemVisitorKind,
     span: Span,
 ) -> RewriteResult {
     use ItemVisitorKind::*;
 
     let ast::TyAlias {
         defaultness,
+        ident,
         ref generics,
         ref bounds,
         ref ty,
@@ -1715,11 +1720,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     let rhs_hi = ty
         .as_ref()
         .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi());
-    let (ident, vis) = match visitor_kind {
-        Item(i) => (i.ident, &i.vis),
-        AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
-        ForeignItem(i) => (i.ident, &i.vis),
-    };
     let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span);
     let op_ty = opaque_ty(ty);
     // Type Aliases are formatted slightly differently depending on the context
@@ -1727,14 +1727,14 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
     // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
     match (visitor_kind, &op_ty) {
-        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
+        (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => {
             let op = OpaqueType { bounds: op_bounds };
             rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis)
         }
-        (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
+        (Item | AssocTraitItem | ForeignItem, None) => {
             rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
         }
-        (AssocImplItem(_), _) => {
+        (AssocImplItem, _) => {
             let result = if let Some(op_bounds) = op_ty {
                 let op = OpaqueType { bounds: op_bounds };
                 rewrite_ty(
@@ -2024,14 +2024,23 @@ pub(crate) struct StaticParts<'a> {
 
 impl<'a> StaticParts<'a> {
     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
-        let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind {
-            ast::ItemKind::Static(s) => {
-                (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None)
-            }
+        let (defaultness, prefix, safety, ident, ty, mutability, expr, generics) = match &item.kind
+        {
+            ast::ItemKind::Static(s) => (
+                None,
+                "static",
+                s.safety,
+                s.ident,
+                &s.ty,
+                s.mutability,
+                &s.expr,
+                None,
+            ),
             ast::ItemKind::Const(c) => (
                 Some(c.defaultness),
                 "const",
                 ast::Safety::Default,
+                c.ident,
                 &c.ty,
                 ast::Mutability::Not,
                 &c.expr,
@@ -2043,7 +2052,7 @@ impl<'a> StaticParts<'a> {
             prefix,
             safety,
             vis: &item.vis,
-            ident: item.ident,
+            ident,
             generics,
             ty,
             mutability,
@@ -2053,7 +2062,7 @@ impl<'a> StaticParts<'a> {
         }
     }
 
-    pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
+    pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
         let (defaultness, ty, expr_opt, generics) = match &ti.kind {
             ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
             _ => unreachable!(),
@@ -2062,7 +2071,7 @@ impl<'a> StaticParts<'a> {
             prefix: "const",
             safety: ast::Safety::Default,
             vis: &ti.vis,
-            ident: ti.ident,
+            ident,
             generics,
             ty,
             mutability: ast::Mutability::Not,
@@ -2072,7 +2081,7 @@ impl<'a> StaticParts<'a> {
         }
     }
 
-    pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self {
+    pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
         let (defaultness, ty, expr, generics) = match &ii.kind {
             ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
             _ => unreachable!(),
@@ -2081,7 +2090,7 @@ impl<'a> StaticParts<'a> {
             prefix: "const",
             safety: ast::Safety::Default,
             vis: &ii.vis,
-            ident: ii.ident,
+            ident,
             generics,
             ty,
             mutability: ast::Mutability::Not,
@@ -3442,6 +3451,7 @@ impl Rewrite for ast::ForeignItem {
                 let ast::Fn {
                     defaultness,
                     ref sig,
+                    ident,
                     ref generics,
                     ref body,
                     ..
@@ -3453,7 +3463,8 @@ impl Rewrite for ast::ForeignItem {
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind),
+                        ident,
+                        visit::FnKind::Fn(fn_ctxt, &self.vis, fn_kind),
                         &sig.decl,
                         self.span,
                         defaultness,
@@ -3464,7 +3475,7 @@ impl Rewrite for ast::ForeignItem {
                     rewrite_fn_base(
                         context,
                         shape.indent,
-                        self.ident,
+                        ident,
                         &FnSig::from_method_sig(sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
@@ -3483,7 +3494,7 @@ impl Rewrite for ast::ForeignItem {
                     vis,
                     safety,
                     mut_str,
-                    rewrite_ident(context, self.ident)
+                    rewrite_ident(context, static_foreign_item.ident)
                 );
                 // 1 = ;
                 rewrite_assign_rhs(
@@ -3498,11 +3509,11 @@ impl Rewrite for ast::ForeignItem {
                 .map(|s| s + ";")
             }
             ast::ForeignItemKind::TyAlias(ref ty_alias) => {
-                let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span);
-                rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
+                let kind = ItemVisitorKind::ForeignItem;
+                rewrite_type_alias(ty_alias, &self.vis, context, shape.indent, kind, self.span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Item)
+                rewrite_macro(mac, context, shape, MacroPosition::Item)
             }
         }?;
 
@@ -3562,12 +3573,13 @@ fn rewrite_attrs(
 pub(crate) fn rewrite_mod(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    ident: Ident,
     attrs_shape: Shape,
 ) -> Option<String> {
     let mut result = String::with_capacity(32);
     result.push_str(&*format_visibility(context, &item.vis));
     result.push_str("mod ");
-    result.push_str(rewrite_ident(context, item.ident));
+    result.push_str(rewrite_ident(context, ident));
     result.push(';');
     rewrite_attrs(context, item, &result, attrs_shape)
 }
@@ -3594,7 +3606,7 @@ pub(crate) fn rewrite_extern_crate(
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     !matches!(
         item.kind,
-        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
+        ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
     )
 }
 
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 664c90b991a..ddf3d2ce96a 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -16,10 +16,7 @@ use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
-use rustc_span::{
-    BytePos, DUMMY_SP, Span, Symbol,
-    symbol::{self, kw},
-};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol};
 use tracing::debug;
 
 use crate::comment::{
@@ -60,7 +57,7 @@ pub(crate) enum MacroArg {
     Ty(ptr::P<ast::Ty>),
     Pat(ptr::P<ast::Pat>),
     Item(ptr::P<ast::Item>),
-    Keyword(symbol::Ident, Span),
+    Keyword(Ident, Span),
 }
 
 impl MacroArg {
@@ -103,20 +100,12 @@ impl Rewrite for MacroArg {
 }
 
 /// Rewrite macro name without using pretty-printer if possible.
-fn rewrite_macro_name(
-    context: &RewriteContext<'_>,
-    path: &ast::Path,
-    extra_ident: Option<symbol::Ident>,
-) -> String {
-    let name = if path.segments.len() == 1 {
+fn rewrite_macro_name(context: &RewriteContext<'_>, path: &ast::Path) -> String {
+    if path.segments.len() == 1 {
         // Avoid using pretty-printer in the common case.
         format!("{}!", rewrite_ident(context, path.segments[0].ident))
     } else {
         format!("{}!", pprust::path_to_string(path))
-    };
-    match extra_ident {
-        Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"),
-        _ => name,
     }
 }
 
@@ -165,7 +154,6 @@ fn return_macro_parse_failure_fallback(
 
 pub(crate) fn rewrite_macro(
     mac: &ast::MacCall,
-    extra_ident: Option<symbol::Ident>,
     context: &RewriteContext<'_>,
     shape: Shape,
     position: MacroPosition,
@@ -179,14 +167,7 @@ pub(crate) fn rewrite_macro(
     } else {
         let guard = context.enter_macro();
         let result = catch_unwind(AssertUnwindSafe(|| {
-            rewrite_macro_inner(
-                mac,
-                extra_ident,
-                context,
-                shape,
-                position,
-                guard.is_nested(),
-            )
+            rewrite_macro_inner(mac, context, shape, position, guard.is_nested())
         }));
         match result {
             Err(..) => {
@@ -207,7 +188,6 @@ pub(crate) fn rewrite_macro(
 
 fn rewrite_macro_inner(
     mac: &ast::MacCall,
-    extra_ident: Option<symbol::Ident>,
     context: &RewriteContext<'_>,
     shape: Shape,
     position: MacroPosition,
@@ -222,7 +202,7 @@ fn rewrite_macro_inner(
 
     let original_style = macro_style(mac, context);
 
-    let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
+    let macro_name = rewrite_macro_name(context, &mac.path);
     let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&&macro_name[..]);
 
     let style = if is_forced_bracket && !is_nested_macro {
@@ -423,7 +403,6 @@ fn rewrite_empty_macro_def_body(
         rules: ast::BlockCheckMode::Default,
         span,
         tokens: None,
-        could_be_bare_literal: false,
     };
     block.rewrite_result(context, shape)
 }
@@ -433,7 +412,7 @@ pub(crate) fn rewrite_macro_def(
     shape: Shape,
     indent: Indent,
     def: &ast::MacroDef,
-    ident: symbol::Ident,
+    ident: Ident,
     vis: &ast::Visibility,
     span: Span,
 ) -> RewriteResult {
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index a40ee7f66a9..bc5a6d3e704 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -152,7 +152,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
         let mut visitor = visitor::CfgIfVisitor::new(self.psess);
         visitor.visit_item(&item);
         for module_item in visitor.mods() {
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = module_item.item.kind {
                 self.visit_sub_mod(
                     &module_item.item,
                     Module::new(
@@ -178,7 +178,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 continue;
             }
 
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
                 let span = item.span;
                 self.visit_sub_mod(
                     &item,
@@ -204,7 +204,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 self.visit_cfg_if(Cow::Borrowed(item))?;
             }
 
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
                 let span = item.span;
                 self.visit_sub_mod(
                     item,
@@ -248,7 +248,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
         if is_mod_decl(item) {
             // mod foo;
             // Look for an extern file.
-            self.find_external_module(item.ident, &item.attrs, sub_mod)
+            self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod)
         } else {
             // An internal module (`mod foo { /* ... */ }`);
             Ok(Some(SubModKind::Internal(item)))
@@ -291,7 +291,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
             }
             SubModKind::Internal(item) => {
-                self.push_inline_mod_directory(item.ident, &item.attrs);
+                self.push_inline_mod_directory(item.kind.ident().unwrap(), &item.attrs);
                 self.visit_sub_mod_after_directory_update(sub_mod, None)
             }
             SubModKind::MultiExternal(mods) => {
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index 680a35f7e03..d7964484b26 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -81,7 +81,7 @@ pub(crate) struct ParsedMacroArgs {
 }
 
 fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
-    if parser.token.is_any_keyword()
+    if parser.token.is_reserved_ident()
         && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma)
     {
         let keyword = parser.token.ident().unwrap().0.name;
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index bafed41e39f..8dc94574503 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -307,9 +307,7 @@ impl Rewrite for Pat {
                 context,
                 shape,
             ),
-            PatKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
-            }
+            PatKind::MacCall(ref mac) => rewrite_macro(mac, context, shape, MacroPosition::Pat),
             PatKind::Paren(ref pat) => pat
                 .rewrite_result(
                     context,
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 8a31e0ac816..2460b61698c 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -25,14 +25,17 @@ use crate::visitor::FmtVisitor;
 /// Choose the ordering between the given two items.
 fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
     match (&a.kind, &b.kind) {
-        (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => {
-            a.ident.as_str().cmp(b.ident.as_str())
+        (&ast::ItemKind::Mod(_, a_ident, _), &ast::ItemKind::Mod(_, b_ident, _)) => {
+            a_ident.as_str().cmp(b_ident.as_str())
         }
-        (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => {
+        (
+            &ast::ItemKind::ExternCrate(ref a_name, a_ident),
+            &ast::ItemKind::ExternCrate(ref b_name, b_ident),
+        ) => {
             // `extern crate foo as bar;`
             //               ^^^ Comparing this.
-            let a_orig_name = a_name.unwrap_or(a.ident.name);
-            let b_orig_name = b_name.unwrap_or(b.ident.name);
+            let a_orig_name = a_name.unwrap_or(a_ident.name);
+            let b_orig_name = b_name.unwrap_or(b_ident.name);
             let result = a_orig_name.as_str().cmp(b_orig_name.as_str());
             if result != Ordering::Equal {
                 return result;
@@ -44,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
                 (Some(..), None) => Ordering::Greater,
                 (None, Some(..)) => Ordering::Less,
                 (None, None) => Ordering::Equal,
-                (Some(..), Some(..)) => a.ident.as_str().cmp(b.ident.as_str()),
+                (Some(..), Some(..)) => a_ident.as_str().cmp(b_ident.as_str()),
             }
         }
         _ => unreachable!(),
@@ -69,7 +72,7 @@ fn rewrite_reorderable_item(
 ) -> Option<String> {
     match item.kind {
         ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape),
-        ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape),
+        ast::ItemKind::Mod(_, ident, _) => rewrite_mod(context, item, ident, shape),
         _ => None,
     }
 }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 06a67334086..75a5a8532b8 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1018,7 +1018,7 @@ impl Rewrite for ast::Ty {
             ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape),
             ast::TyKind::Never => Ok(String::from("!")),
             ast::TyKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
+                rewrite_macro(mac, context, shape, MacroPosition::Expression)
             }
             ast::TyKind::ImplicitSelf => Ok(String::from("")),
             ast::TyKind::ImplTrait(_, ref it) => {
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index a5cfc542a17..16d1f5105d5 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -3,7 +3,7 @@ use std::rc::Rc;
 use std::sync::Arc;
 
 use rustc_ast::{ast, token::Delimiter, visit};
-use rustc_span::{BytePos, Pos, Span, symbol};
+use rustc_span::{BytePos, Ident, Pos, Span, symbol};
 use tracing::debug;
 
 use crate::attr::*;
@@ -172,7 +172,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         get_span_without_attrs(stmt.as_ast_node()),
                     );
                 } else {
-                    self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement);
+                    self.visit_mac(&mac_stmt.mac, MacroPosition::Statement);
                 }
                 self.format_missing(stmt.span().hi());
             }
@@ -377,6 +377,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     // on traits do not get handled here.
     pub(crate) fn visit_fn(
         &mut self,
+        ident: Ident,
         fk: visit::FnKind<'_>,
         fd: &ast::FnDecl,
         s: Span,
@@ -388,7 +389,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let rewrite = match fk {
             visit::FnKind::Fn(
                 _,
-                ident,
                 _,
                 ast::Fn {
                     body: Some(ref b), ..
@@ -397,7 +397,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 block = b;
                 self.rewrite_fn_before_block(
                     indent,
-                    *ident,
+                    ident,
                     &FnSig::from_fn_kind(&fk, fd, defaultness),
                     mk_sp(s.lo(), b.span.lo()),
                 )
@@ -444,7 +444,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         let should_visit_node_again = match item.kind {
             // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
-            ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => {
+            ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(..) => {
                 if contains_skip(attrs) {
                     self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span());
                     false
@@ -497,11 +497,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
-                ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
+                ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => {
                     let shape = Shape::indented(self.block_indent, self.config);
                     let rw = format_trait_alias(
                         &self.get_context(),
-                        item.ident,
+                        ident,
                         &item.vis,
                         generics,
                         generic_bounds,
@@ -509,7 +509,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                     self.push_rewrite(item.span, rw);
                 }
-                ast::ItemKind::ExternCrate(_) => {
+                ast::ItemKind::ExternCrate(..) => {
                     let rw = rewrite_extern_crate(&self.get_context(), item, self.shape());
                     let span = if attrs.is_empty() {
                         item.span
@@ -521,17 +521,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => {
                     self.visit_struct(&StructParts::from_item(item));
                 }
-                ast::ItemKind::Enum(ref def, ref generics) => {
+                ast::ItemKind::Enum(ident, ref def, ref generics) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.visit_enum(item.ident, &item.vis, def, generics, item.span);
+                    self.visit_enum(ident, &item.vis, def, generics, item.span);
                     self.last_pos = source!(self, item.span).hi();
                 }
-                ast::ItemKind::Mod(safety, ref mod_kind) => {
+                ast::ItemKind::Mod(safety, ident, ref mod_kind) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs);
+                    self.format_mod(mod_kind, safety, &item.vis, item.span, ident, attrs);
                 }
                 ast::ItemKind::MacCall(ref mac) => {
-                    self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
+                    self.visit_mac(mac, MacroPosition::Item);
                 }
                 ast::ItemKind::ForeignMod(ref foreign_mod) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
@@ -544,6 +544,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let ast::Fn {
                         defaultness,
                         ref sig,
+                        ident,
                         ref generics,
                         ref body,
                         ..
@@ -555,7 +556,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind),
+                            ident,
+                            visit::FnKind::Fn(fn_ctxt, &item.vis, fn_kind),
                             &sig.decl,
                             item.span,
                             defaultness,
@@ -564,28 +566,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     } else {
                         let indent = self.block_indent;
                         let rewrite = self
-                            .rewrite_required_fn(
-                                indent, item.ident, sig, &item.vis, generics, item.span,
-                            )
+                            .rewrite_required_fn(indent, ident, sig, &item.vis, generics, item.span)
                             .ok();
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
                 ast::ItemKind::TyAlias(ref ty_alias) => {
                     use ItemVisitorKind::Item;
-                    self.visit_ty_alias_kind(ty_alias, &Item(item), item.span);
+                    self.visit_ty_alias_kind(ty_alias, &item.vis, Item, item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
                     self.push_rewrite(item.span, snippet);
                 }
-                ast::ItemKind::MacroDef(ref def) => {
+                ast::ItemKind::MacroDef(ident, ref def) => {
                     let rewrite = rewrite_macro_def(
                         &self.get_context(),
                         self.shape(),
                         self.block_indent,
                         def,
-                        item.ident,
+                        ident,
                         &item.vis,
                         item.span,
                     )
@@ -605,11 +605,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     fn visit_ty_alias_kind(
         &mut self,
         ty_kind: &ast::TyAlias,
-        visitor_kind: &ItemVisitorKind<'_>,
+        vis: &ast::Visibility,
+        visitor_kind: ItemVisitorKind,
         span: Span,
     ) {
         let rewrite = rewrite_type_alias(
             ty_kind,
+            vis,
             &self.get_context(),
             self.block_indent,
             visitor_kind,
@@ -619,14 +621,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         self.push_rewrite(span, rewrite);
     }
 
-    fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+    fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) {
         use ItemVisitorKind::*;
-        // TODO(calebcartwright): Not sure the skip spans are correct
-        let (ai, skip_span, assoc_ctxt) = match visitor_kind {
-            AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
-            AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
+        let assoc_ctxt = match visitor_kind {
+            AssocTraitItem => visit::AssocCtxt::Trait,
+            // There is no difference between trait and inherent assoc item formatting
+            AssocImplItem => visit::AssocCtxt::Impl { of_trait: false },
             _ => unreachable!(),
         };
+        // TODO(calebcartwright): Not sure the skip spans are correct
+        let skip_span = ai.span;
         skip_out_of_file_lines_range_visitor!(self, ai.span);
 
         if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
@@ -636,16 +640,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
         match (&ai.kind, visitor_kind) {
-            (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
-                self.visit_static(&StaticParts::from_trait_item(ai))
+            (ast::AssocItemKind::Const(c), AssocTraitItem) => {
+                self.visit_static(&StaticParts::from_trait_item(ai, c.ident))
             }
-            (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
-                self.visit_static(&StaticParts::from_impl_item(ai))
+            (ast::AssocItemKind::Const(c), AssocImplItem) => {
+                self.visit_static(&StaticParts::from_impl_item(ai, c.ident))
             }
             (ast::AssocItemKind::Fn(ref fn_kind), _) => {
                 let ast::Fn {
                     defaultness,
                     ref sig,
+                    ident,
                     ref generics,
                     ref body,
                     ..
@@ -654,7 +659,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let inner_attrs = inner_attributes(&ai.attrs);
                     let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind),
+                        ident,
+                        visit::FnKind::Fn(fn_ctxt, &ai.vis, fn_kind),
                         &sig.decl,
                         ai.span,
                         defaultness,
@@ -663,35 +669,35 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 } else {
                     let indent = self.block_indent;
                     let rewrite = self
-                        .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span)
+                        .rewrite_required_fn(indent, fn_kind.ident, sig, &ai.vis, generics, ai.span)
                         .ok();
                     self.push_rewrite(ai.span, rewrite);
                 }
             }
             (ast::AssocItemKind::Type(ref ty_alias), _) => {
-                self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
+                self.visit_ty_alias_kind(ty_alias, &ai.vis, visitor_kind, ai.span);
             }
             (ast::AssocItemKind::MacCall(ref mac), _) => {
-                self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
+                self.visit_mac(mac, MacroPosition::Item);
             }
             _ => unreachable!(),
         }
     }
 
     pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
-        self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+        self.visit_assoc_item(ti, ItemVisitorKind::AssocTraitItem);
     }
 
     pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
-        self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
+        self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem);
     }
 
-    fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
+    fn visit_mac(&mut self, mac: &ast::MacCall, pos: MacroPosition) {
         skip_out_of_file_lines_range_visitor!(self, mac.span());
 
         // 1 = ;
         let shape = self.shape().saturating_sub_width(1);
-        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok());
+        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ctx, shape, pos).ok());
         // As of v638 of the rustc-ap-* crates, the associated span no longer includes
         // the trailing semicolon. This determines the correct span to ensure scenarios
         // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc)     ;`)
diff --git a/src/tools/rustfmt/tests/source/pattern.rs b/src/tools/rustfmt/tests/source/pattern.rs
index ed6ad690fa9..0e5abb52394 100644
--- a/src/tools/rustfmt/tests/source/pattern.rs
+++ b/src/tools/rustfmt/tests/source/pattern.rs
@@ -91,7 +91,7 @@ fn issue3728() {
 
 fn literals() {
     match 42 {
-        const { 1 + 2 } | 4
+        1 | 2 | 4
         | 6 => {}
         10 | 11 | 12
         | 13 | 14 => {}
diff --git a/src/tools/rustfmt/tests/target/pattern.rs b/src/tools/rustfmt/tests/target/pattern.rs
index e867f65929d..483725f95c4 100644
--- a/src/tools/rustfmt/tests/target/pattern.rs
+++ b/src/tools/rustfmt/tests/target/pattern.rs
@@ -99,7 +99,7 @@ fn issue3728() {
 
 fn literals() {
     match 42 {
-        const { 1 + 2 } | 4 | 6 => {}
+        1 | 2 | 4 | 6 => {}
         10 | 11 | 12 | 13 | 14 => {}
         _ => {}
     }
diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs
index ee8cc40404d..ee212af3626 100644
--- a/src/tools/suggest-tests/src/main.rs
+++ b/src/tools/suggest-tests/src/main.rs
@@ -14,11 +14,7 @@ fn main() -> ExitCode {
         &Vec::new(),
     );
     let modified_files = match modified_files {
-        Ok(Some(files)) => files,
-        Ok(None) => {
-            eprintln!("git error");
-            return ExitCode::FAILURE;
-        }
+        Ok(files) => files,
         Err(err) => {
             eprintln!("Could not get modified files from git: \"{err}\"");
             return ExitCode::FAILURE;
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 81c55ecaa7a..8f761d349cc 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -181,6 +181,8 @@ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[
 
 const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-start
+    ("cranelift-assembler-x64", "Apache-2.0 WITH LLVM-exception"),
+    ("cranelift-assembler-x64-meta", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"),
     ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
@@ -240,7 +242,6 @@ const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
 const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
     "adler2",
-    "ahash",
     "aho-corasick",
     "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801
     "annotate-snippets",
@@ -253,7 +254,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "blake3",
     "block-buffer",
     "bstr",
-    "byteorder", // via ruzstd in object in thorin-dwp
     "cc",
     "cfg-if",
     "cfg_aliases",
@@ -350,6 +350,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "pulldown-cmark-escape",
     "punycode",
     "quote",
+    "r-efi",
     "rand",
     "rand_chacha",
     "rand_core",
@@ -433,6 +434,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "windows-core",
     "windows-implement",
     "windows-interface",
+    "windows-link",
     "windows-result",
     "windows-strings",
     "windows-sys",
@@ -445,7 +447,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "windows_x86_64_gnu",
     "windows_x86_64_gnullvm",
     "windows_x86_64_msvc",
-    "wit-bindgen-rt@0.33.0", // via wasi
+    "wit-bindgen-rt@0.39.0", // pinned to a specific version due to using a binary blob: <https://github.com/rust-lang/rust/pull/136395#issuecomment-2692769062>
     "writeable",
     "yoke",
     "yoke-derive",
@@ -513,6 +515,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
     "bitflags",
     "bumpalo",
     "cfg-if",
+    "cranelift-assembler-x64",
+    "cranelift-assembler-x64-meta",
     "cranelift-bforest",
     "cranelift-bitset",
     "cranelift-codegen",
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 2b9ae195478..d2ae9b1f6ef 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2000,7 +2000,6 @@ ui/issues/issue-28586.rs
 ui/issues/issue-28600.rs
 ui/issues/issue-28625.rs
 ui/issues/issue-28776.rs
-ui/issues/issue-28777.rs
 ui/issues/issue-28828.rs
 ui/issues/issue-28839.rs
 ui/issues/issue-28936.rs
@@ -2063,7 +2062,6 @@ ui/issues/issue-3091.rs
 ui/issues/issue-31011.rs
 ui/issues/issue-3109.rs
 ui/issues/issue-3121.rs
-ui/issues/issue-31260.rs
 ui/issues/issue-31267-additional.rs
 ui/issues/issue-31267.rs
 ui/issues/issue-31299.rs
@@ -2608,7 +2606,6 @@ ui/issues/issue-9243.rs
 ui/issues/issue-9249.rs
 ui/issues/issue-9259.rs
 ui/issues/issue-92741.rs
-ui/issues/issue-9382.rs
 ui/issues/issue-9446.rs
 ui/issues/issue-9719.rs
 ui/issues/issue-9725.rs
@@ -2876,7 +2873,6 @@ ui/macros/rfc-3086-metavar-expr/issue-111904.rs
 ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
 ui/malformed/issue-69341-malformed-derive-inert.rs
 ui/marker_trait_attr/issue-61651-type-mismatch.rs
-ui/match/issue-112438.rs
 ui/match/issue-113012.rs
 ui/match/issue-11319.rs
 ui/match/issue-114691.rs
@@ -3192,7 +3188,6 @@ ui/parser/issues/issue-108495-dec.rs
 ui/parser/issues/issue-110014.rs
 ui/parser/issues/issue-111148.rs
 ui/parser/issues/issue-111416.rs
-ui/parser/issues/issue-111692.rs
 ui/parser/issues/issue-112188.rs
 ui/parser/issues/issue-112458.rs
 ui/parser/issues/issue-113110-non-item-at-module-root.rs
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index fe51231c481..61728d0553f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -17,7 +17,7 @@ use ignore::Walk;
 const ENTRY_LIMIT: u32 = 901;
 // FIXME: The following limits should be reduced eventually.
 
-const ISSUES_ENTRY_LIMIT: u32 = 1634;
+const ISSUES_ENTRY_LIMIT: u32 = 1631;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 8be25b98df0..a2453a6c960 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -72,6 +72,19 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -
     collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
 }
 
+/// Would switching underscores for dashes work?
+fn maybe_suggest_dashes(names: &BTreeSet<String>, feature_name: &str, bad: &mut bool) {
+    let with_dashes = feature_name.replace('_', "-");
+    if names.contains(&with_dashes) {
+        tidy_error!(
+            bad,
+            "the file `{}.md` contains underscores; use dashes instead: `{}.md`",
+            feature_name,
+            with_dashes,
+        );
+    }
+}
+
 pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     let lang_features = features.lang;
     let lib_features = features
@@ -93,14 +106,13 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     // Check for Unstable Book sections that don't have a corresponding unstable feature
     for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names
     {
-        if !unstable_lang_feature_names.contains(&feature_name) {
-            tidy_error!(
-                bad,
-                "The Unstable Book has a 'library feature' section '{}' which doesn't \
+        tidy_error!(
+            bad,
+            "The Unstable Book has a 'library feature' section '{}' which doesn't \
                          correspond to an unstable library feature",
-                feature_name
-            );
-        }
+            feature_name
+        );
+        maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad);
     }
 
     // Check for Unstable Book sections that don't have a corresponding unstable feature.
@@ -112,7 +124,8 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
             "The Unstable Book has a 'language feature' section '{}' which doesn't \
                      correspond to an unstable language feature",
             feature_name
-        )
+        );
+        maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad);
     }
 
     // List unstable features that don't have Unstable Book sections.
diff --git a/src/version b/src/version
index f6342716723..59be592144c 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.87.0
+1.88.0
diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs
new file mode 100644
index 00000000000..7436e241823
--- /dev/null
+++ b/tests/assembly/cstring-merging.rs
@@ -0,0 +1,27 @@
+//@ only-linux
+//@ assembly-output: emit-asm
+//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024
+
+use std::ffi::CStr;
+
+// CHECK: .section .rodata.str1.1,"aMS"
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "foo"
+#[unsafe(no_mangle)]
+static CSTR: &[u8; 4] = b"foo\0";
+
+// CHECK-NOT: .section
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "bar"
+#[unsafe(no_mangle)]
+pub fn cstr() -> &'static CStr {
+    c"bar"
+}
+
+// CHECK-NOT: .section
+// CHECK: .Lanon.{{.+}}:
+// CHECK-NEXT: .asciz "baz"
+#[unsafe(no_mangle)]
+pub fn manual_cstr() -> &'static str {
+    "baz\0"
+}
diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs
index eb27afc4f23..ee4965deb4f 100644
--- a/tests/assembly/powerpc64-struct-abi.rs
+++ b/tests/assembly/powerpc64-struct-abi.rs
@@ -6,7 +6,7 @@
 //@[elfv1-be] needs-llvm-components: powerpc
 //@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl
 //@[elfv2-be] needs-llvm-components: powerpc
-//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu -C target-cpu=pwr8
 //@[elfv2-le] needs-llvm-components: powerpc
 //@[aix] compile-flags: --target powerpc64-ibm-aix
 //@[aix] needs-llvm-components: powerpc
diff --git a/tests/assembly/s390x-vector-abi.rs b/tests/assembly/s390x-vector-abi.rs
index 7d86559c002..e159a357685 100644
--- a/tests/assembly/s390x-vector-abi.rs
+++ b/tests/assembly/s390x-vector-abi.rs
@@ -2,9 +2,9 @@
 // ignore-tidy-linelength
 //@ assembly-output: emit-asm
 //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
-//@[z10] compile-flags: --target s390x-unknown-linux-gnu --cfg no_vector
+//@[z10] compile-flags: --target s390x-unknown-linux-gnu  -C target-cpu=z10 --cfg no_vector
 //@[z10] needs-llvm-components: systemz
-//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
+//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 -C target-feature=+vector
 //@[z10_vector] needs-llvm-components: systemz
 //@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13
 //@[z13] needs-llvm-components: systemz
diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs
index 8cccab7d40d..26c9013d96f 100644
--- a/tests/assembly/x86_64-cmp.rs
+++ b/tests/assembly/x86_64-cmp.rs
@@ -1,5 +1,8 @@
-//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
-//@ [DEBUG] compile-flags: -C opt-level=0
+//@ revisions: LLVM-PRE-20-DEBUG LLVM-20-DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
+//@ [LLVM-PRE-20-DEBUG] compile-flags: -C opt-level=0
+//@ [LLVM-PRE-20-DEBUG] max-llvm-major-version: 19
+//@ [LLVM-20-DEBUG] compile-flags: -C opt-level=0
+//@ [LLVM-20-DEBUG] min-llvm-version: 20
 //@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3
 //@ [LLVM-PRE-20-OPTIM] max-llvm-major-version: 19
 //@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3
@@ -16,13 +19,19 @@ use std::intrinsics::three_way_compare;
 #[no_mangle]
 // CHECK-LABEL: signed_cmp:
 pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
-    // DEBUG: cmp
-    // DEBUG: setg
-    // DEBUG: and
-    // DEBUG: cmp
-    // DEBUG: setl
-    // DEBUG: and
-    // DEBUG: sub
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setg
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setl
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: sub
+    //
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: setl
+    // LLVM-20-DEBUG: setg
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: ret
 
     // LLVM-PRE-20-OPTIM: xor
     // LLVM-PRE-20-OPTIM: cmp
@@ -42,13 +51,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
 #[no_mangle]
 // CHECK-LABEL: unsigned_cmp:
 pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
-    // DEBUG: cmp
-    // DEBUG: seta
-    // DEBUG: and
-    // DEBUG: cmp
-    // DEBUG: setb
-    // DEBUG: and
-    // DEBUG: sub
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: seta
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: cmp
+    // LLVM-PRE-20-DEBUG: setb
+    // LLVM-PRE-20-DEBUG: and
+    // LLVM-PRE-20-DEBUG: sub
+    //
+    // LLVM-20-DEBUG: sub
+    // LLVM-20-DEBUG: seta
+    // LLVM-20-DEBUG: sbb
+    // LLVM-20-DEBUG: ret
 
     // LLVM-PRE-20-OPTIM: xor
     // LLVM-PRE-20-OPTIM: cmp
diff --git a/tests/codegen/asm/s390x-clobbers.rs b/tests/codegen/asm/s390x-clobbers.rs
index cbb6630553c..0ba22a32abf 100644
--- a/tests/codegen/asm/s390x-clobbers.rs
+++ b/tests/codegen/asm/s390x-clobbers.rs
@@ -1,6 +1,6 @@
 //@ add-core-stubs
 //@ revisions: s390x
-//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//@[s390x] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10
 //@[s390x] needs-llvm-components: systemz
 
 #![crate_type = "rlib"]
diff --git a/tests/codegen/assign-desugar-debuginfo.rs b/tests/codegen/assign-desugar-debuginfo.rs
new file mode 100644
index 00000000000..77ee8758b3b
--- /dev/null
+++ b/tests/codegen/assign-desugar-debuginfo.rs
@@ -0,0 +1,18 @@
+//@ compile-flags: -g -Zmir-opt-level=0
+
+#![crate_type = "lib"]
+
+#[inline(never)]
+fn swizzle(a: u32, b: u32, c: u32) -> (u32, (u32, u32)) {
+    (b, (c, a))
+}
+
+pub fn work() {
+    let mut a = 1;
+    let mut b = 2;
+    let mut c = 3;
+    (a, (b, c)) = swizzle(a, b, c);
+    println!("{a} {b} {c}");
+}
+
+// CHECK-NOT: !DILocalVariable(name: "lhs",
diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs
index 186198bc631..e1a7ad718a0 100644
--- a/tests/codegen/cast-target-abi.rs
+++ b/tests/codegen/cast-target-abi.rs
@@ -2,7 +2,7 @@
 //@ add-core-stubs
 //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64
 //@ min-llvm-version: 19
-//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
+//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir
 
 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
 //@[aarch64] needs-llvm-components: arm
diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
index 404f6237849..73bc7ef6b77 100644
--- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
+++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs
@@ -1,7 +1,7 @@
 //@ add-core-stubs
 //@ revisions: linux apple
 //@ min-llvm-version: 19
-//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error
+//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir
 
 //@[linux] compile-flags: --target x86_64-unknown-linux-gnu
 //@[linux] needs-llvm-components: x86
diff --git a/tests/codegen/comparison-operators-2-tuple.rs b/tests/codegen/comparison-operators-2-tuple.rs
index 91a99f9b91f..6a7e489c82d 100644
--- a/tests/codegen/comparison-operators-2-tuple.rs
+++ b/tests/codegen/comparison-operators-2-tuple.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=1 -Z merge-functions=disabled
-//@ only-x86_64
 //@ min-llvm-version: 20
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/const-array.rs b/tests/codegen/const-array.rs
index e257d8acc08..b3df76c3d8e 100644
--- a/tests/codegen/const-array.rs
+++ b/tests/codegen/const-array.rs
@@ -2,7 +2,7 @@
 
 #![crate_type = "lib"]
 
-const LUT: [u8; 2] = [1, 1];
+const LUT: [u8; 4] = [1, 1, 1, 1];
 
 // CHECK-LABEL: @decode
 #[no_mangle]
@@ -11,5 +11,5 @@ pub fn decode(i: u8) -> u8 {
     // CHECK-NEXT: icmp
     // CHECK-NEXT: select
     // CHECK-NEXT: ret
-    if i < 2 { LUT[i as usize] } else { 2 }
+    if i < 4 { LUT[i as usize] } else { 2 }
 }
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index b9808e4079b..8a7b1cc3c4b 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -15,7 +15,7 @@
 
 // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
 // This helps debuggers more reliably map from dyn pointer to concrete type.
-// CHECK: @vtable.2 = private constant <{
+// CHECK: @vtable.2 = private constant [
 // CHECK: @vtable.3 = private constant <{
 // CHECK: @vtable.4 = private constant <{
 
diff --git a/tests/codegen/external-no-mangle-statics.rs b/tests/codegen/external-no-mangle-statics.rs
index dc4eca8c7b4..49f42ee977d 100644
--- a/tests/codegen/external-no-mangle-statics.rs
+++ b/tests/codegen/external-no-mangle-statics.rs
@@ -6,72 +6,72 @@
 // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
 // definitions
 
-// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
+// CHECK-DAG: @A = {{(dso_local )?}}local_unnamed_addr constant
 #[no_mangle]
 static A: u8 = 0;
 
-// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
+// CHECK-DAG: @B = {{(dso_local )?}}local_unnamed_addr global
 #[no_mangle]
 static mut B: u8 = 0;
 
-// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
+// CHECK-DAG: @C = {{(dso_local )?}}local_unnamed_addr constant
 #[no_mangle]
 pub static C: u8 = 0;
 
-// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
+// CHECK-DAG: @D = {{(dso_local )?}}local_unnamed_addr global
 #[no_mangle]
 pub static mut D: u8 = 0;
 
 mod private {
-    // CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @E = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static E: u8 = 0;
 
-    // CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @F = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut F: u8 = 0;
 
-    // CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @G = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static G: u8 = 0;
 
-    // CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @H = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut H: u8 = 0;
 }
 
 const HIDDEN: () = {
-    // CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @I = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static I: u8 = 0;
 
-    // CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @J = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut J: u8 = 0;
 
-    // CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @K = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static K: u8 = 0;
 
-    // CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @L = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut L: u8 = 0;
 };
 
 fn x() {
-    // CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @M = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     static M: fn() = x;
 
-    // CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @N = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     static mut N: u8 = 0;
 
-    // CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
+    // CHECK-DAG: @O = {{(dso_local )?}}local_unnamed_addr constant
     #[no_mangle]
     pub static O: u8 = 0;
 
-    // CHECK: @P = {{(dso_local )?}}local_unnamed_addr global
+    // CHECK-DAG: @P = {{(dso_local )?}}local_unnamed_addr global
     #[no_mangle]
     pub static mut P: u8 = 0;
 }
diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs
index 9bbf243946d..812fa8e4a42 100644
--- a/tests/codegen/integer-cmp.rs
+++ b/tests/codegen/integer-cmp.rs
@@ -4,7 +4,7 @@
 //@ revisions: llvm-pre-20 llvm-20
 //@ [llvm-20] min-llvm-version: 20
 //@ [llvm-pre-20] max-llvm-major-version: 19
-//@ compile-flags: -C opt-level=3
+//@ compile-flags: -C opt-level=3 -Zmerge-functions=disabled
 
 #![crate_type = "lib"]
 
@@ -13,7 +13,7 @@ use std::cmp::Ordering;
 // CHECK-LABEL: @cmp_signed
 #[no_mangle]
 pub fn cmp_signed(a: i64, b: i64) -> Ordering {
-    // llvm-20: @llvm.scmp.i8.i64
+    // llvm-20: call{{.*}} i8 @llvm.scmp.i8.i64
     // llvm-pre-20: icmp slt
     // llvm-pre-20: icmp ne
     // llvm-pre-20: zext i1
@@ -24,10 +24,39 @@ pub fn cmp_signed(a: i64, b: i64) -> Ordering {
 // CHECK-LABEL: @cmp_unsigned
 #[no_mangle]
 pub fn cmp_unsigned(a: u32, b: u32) -> Ordering {
-    // llvm-20: @llvm.ucmp.i8.i32
+    // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32
     // llvm-pre-20: icmp ult
     // llvm-pre-20: icmp ne
     // llvm-pre-20: zext i1
     // llvm-pre-20: select i1
     a.cmp(&b)
 }
+
+// CHECK-LABEL: @cmp_char
+#[no_mangle]
+pub fn cmp_char(a: char, b: char) -> Ordering {
+    // llvm-20: call{{.*}} i8 @llvm.ucmp.i8.i32
+    // llvm-pre-20: icmp ult
+    // llvm-pre-20: icmp ne
+    // llvm-pre-20: zext i1
+    // llvm-pre-20: select i1
+    a.cmp(&b)
+}
+
+// CHECK-LABEL: @cmp_tuple
+#[no_mangle]
+pub fn cmp_tuple(a: (i16, u16), b: (i16, u16)) -> Ordering {
+    // llvm-20-DAG: call{{.*}} i8 @llvm.ucmp.i8.i16
+    // llvm-20-DAG: call{{.*}} i8 @llvm.scmp.i8.i16
+    // llvm-20: ret i8
+    // llvm-pre-20: icmp slt
+    // llvm-pre-20: icmp ne
+    // llvm-pre-20: zext i1
+    // llvm-pre-20: select i1
+    // llvm-pre-20: icmp ult
+    // llvm-pre-20: icmp ne
+    // llvm-pre-20: zext i1
+    // llvm-pre-20: select i1
+    // llvm-pre-20: select i1
+    a.cmp(&b)
+}
diff --git a/tests/codegen/intrinsics/three_way_compare.rs b/tests/codegen/intrinsics/three_way_compare.rs
index 9a476abe891..95fcb636f7c 100644
--- a/tests/codegen/intrinsics/three_way_compare.rs
+++ b/tests/codegen/intrinsics/three_way_compare.rs
@@ -2,6 +2,7 @@
 //@ [DEBUG] compile-flags: -C opt-level=0
 //@ [OPTIM] compile-flags: -C opt-level=3
 //@ compile-flags: -C no-prepopulate-passes
+//@ min-llvm-version: 20
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
@@ -12,17 +13,8 @@ use std::intrinsics::three_way_compare;
 // CHECK-LABEL: @signed_cmp
 // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
 pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
-    // DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b
-    // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
-    // DEBUG: %[[LT:.+]] = icmp slt i16 %a, %b
-    // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8
-    // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]]
-
-    // OPTIM: %[[LT:.+]] = icmp slt i16 %a, %b
-    // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b
-    // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0
-    // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]]
-    // OPTIM: ret i8 %[[CGEL]]
+    // CHECK: %[[CMP:.+]] = call i8 @llvm.scmp.i8.i16(i16 %a, i16 %b)
+    // CHECK-NEXT: ret i8 %[[CMP]]
     three_way_compare(a, b)
 }
 
@@ -30,16 +22,7 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
 // CHECK-LABEL: @unsigned_cmp
 // CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
 pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
-    // DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b
-    // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
-    // DEBUG: %[[LT:.+]] = icmp ult i16 %a, %b
-    // DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8
-    // DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]]
-
-    // OPTIM: %[[LT:.+]] = icmp ult i16 %a, %b
-    // OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b
-    // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0
-    // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]]
-    // OPTIM: ret i8 %[[CGEL]]
+    // CHECK: %[[CMP:.+]] = call i8 @llvm.ucmp.i8.i16(i16 %a, i16 %b)
+    // CHECK-NEXT: ret i8 %[[CMP]]
     three_way_compare(a, b)
 }
diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs
index 196f5edb7d6..f62f6948079 100644
--- a/tests/codegen/link_section.rs
+++ b/tests/codegen/link_section.rs
@@ -3,7 +3,7 @@
 
 #![crate_type = "lib"]
 
-// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
+// CHECK: @VAR1 = {{(dso_local )?}}constant [4 x i8] c"\01\00\00\00", section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
 #[cfg(target_endian = "little")]
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
index bfbccfe0df8..7d17b3b67cf 100644
--- a/tests/codegen/remap_path_prefix/main.rs
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+// CHECK: @alloc_5761061597a97f66e13ef2ff92712c4b = private unnamed_addr constant [34 x i8] c"/the/src/remap_path_prefix/main.rs"
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
diff --git a/tests/codegen/slice-is-ascii.rs b/tests/codegen/slice-is-ascii.rs
index b1e97154609..67537c871a0 100644
--- a/tests/codegen/slice-is-ascii.rs
+++ b/tests/codegen/slice-is-ascii.rs
@@ -1,5 +1,5 @@
 //@ only-x86_64
-//@ compile-flags: -C opt-level=3
+//@ compile-flags: -C opt-level=3 -C target-cpu=x86-64
 #![crate_type = "lib"]
 
 /// Check that the fast-path of `is_ascii` uses a `pmovmskb` instruction.
diff --git a/tests/codegen/slice-last-elements-optimization.rs b/tests/codegen/slice-last-elements-optimization.rs
new file mode 100644
index 00000000000..b90f91d7b17
--- /dev/null
+++ b/tests/codegen/slice-last-elements-optimization.rs
@@ -0,0 +1,37 @@
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+//@ min-llvm-version: 20
+#![crate_type = "lib"]
+
+// This test verifies that LLVM 20 properly optimizes the bounds check
+// when accessing the last few elements of a slice with proper conditions.
+// Previously, this would generate an unreachable branch to
+// slice_start_index_len_fail even when the bounds check was provably safe.
+
+// CHECK-LABEL: @last_four_initial(
+#[no_mangle]
+pub fn last_four_initial(s: &[u8]) -> &[u8] {
+    // Previously this would generate a branch to slice_start_index_len_fail
+    // that is unreachable. The LLVM 20 fix should eliminate this branch.
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: unreachable
+    let start = if s.len() <= 4 { 0 } else { s.len() - 4 };
+    &s[start..]
+}
+
+// CHECK-LABEL: @last_four_optimized(
+#[no_mangle]
+pub fn last_four_optimized(s: &[u8]) -> &[u8] {
+    // This version was already correctly optimized before the fix in LLVM 20.
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: unreachable
+    if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] }
+}
+
+// Just to verify we're correctly checking for the right thing
+// CHECK-LABEL: @test_bounds_check_happens(
+#[no_mangle]
+pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] {
+    // CHECK: slice_start_index_len_fail
+    &s[i..]
+}
diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs
index a58008e171e..bde71a35c47 100644
--- a/tests/codegen/uninit-consts.rs
+++ b/tests/codegen/uninit-consts.rs
@@ -11,15 +11,15 @@ pub struct PartiallyUninit {
     y: MaybeUninit<[u8; 10]>,
 }
 
-// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant <{ [10 x i8] }> undef
+// CHECK: [[FULLY_UNINIT:@.*]] = private unnamed_addr constant [10 x i8] undef
 
 // CHECK: [[PARTIALLY_UNINIT:@.*]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
 
 // This shouldn't contain undef, since it contains more chunks
 // than the default value of uninit_const_chunk_threshold.
-// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4
+// CHECK: [[UNINIT_PADDING_HUGE:@.*]] = private unnamed_addr constant [32768 x i8] c"{{.+}}", align 4
 
-// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant <{ [16384 x i8] }> undef
+// CHECK: [[FULLY_UNINIT_HUGE:@.*]] = private unnamed_addr constant [16384 x i8] undef
 
 // CHECK-LABEL: @fully_uninit
 #[no_mangle]
diff --git a/tests/codegen/uninit-repeat-in-aggregate.rs b/tests/codegen/uninit-repeat-in-aggregate.rs
new file mode 100644
index 00000000000..0fa2eb7d56c
--- /dev/null
+++ b/tests/codegen/uninit-repeat-in-aggregate.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+// We need to make sure len is at offset 0, otherwise codegen needs an extra instruction
+#[repr(C)]
+pub struct SmallVec<T> {
+    pub len: u64,
+    pub arr: [MaybeUninit<T>; 24],
+}
+
+// CHECK-LABEL: @uninit_arr_via_const
+#[no_mangle]
+pub fn uninit_arr_via_const() -> SmallVec<String> {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: store i64 0,
+    // CHECK-NEXT: ret
+    SmallVec { len: 0, arr: [const { MaybeUninit::uninit() }; 24] }
+}
diff --git a/tests/coverage-run-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage
index f007eb0cade..0fa94361c47 100644
--- a/tests/coverage-run-rustdoc/doctest.coverage
+++ b/tests/coverage-run-rustdoc/doctest.coverage
@@ -58,21 +58,21 @@ $DIR/doctest.rs:
    LL|       |//!
    LL|       |//! doctest with custom main:
    LL|       |//! ```
-   LL|      1|//! fn some_func() {
-   LL|      1|//!     println!("called some_func()");
-   LL|      1|//! }
-   LL|       |//!
-   LL|       |//! #[derive(Debug)]
-   LL|       |//! struct SomeError;
+   LL|       |//! fn some_func() {
+   LL|       |//!     println!("called some_func()");
+   LL|       |//! }
+   LL|      1|//!
+   LL|      1|//! #[derive(Debug)]
+   LL|      1|//! struct SomeError;
    LL|       |//!
    LL|       |//! extern crate doctest_crate;
    LL|       |//!
-   LL|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   LL|       |//! fn doctest_main() -> Result<(), SomeError> {
    LL|      1|//!     some_func();
    LL|      1|//!     doctest_crate::fn_run_in_doctests(2);
    LL|      1|//!     Ok(())
    LL|      1|//! }
-   LL|       |//!
+   LL|      1|//!
    LL|       |//! // this `main` is not shown as covered, as it clashes with all the other
    LL|       |//! // `main` functions that were automatically generated for doctests
    LL|       |//! fn main() -> Result<(), SomeError> {
diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map
index 84fae4a595a..26536caeba5 100644
--- a/tests/coverage/abort.cov-map
+++ b/tests/coverage/abort.cov-map
@@ -34,14 +34,14 @@ Number of file 0 mappings: 13
 Highest counter ID seen: c4
 
 Function name: abort::might_abort
-Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 3, 1) to (start + 1, 20)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15)
 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2)
     = (c0 - c1)
 Highest counter ID seen: c1
diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map
index b432e63c168..27d4b0382de 100644
--- a/tests/coverage/assert-ne.cov-map
+++ b/tests/coverage/assert-ne.cov-map
@@ -1,12 +1,12 @@
 Function name: assert_ne::main
-Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 1c, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02]
+Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 15, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 21)
 - Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19)
 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19)
     = (c0 - c1)
diff --git a/tests/coverage/assert-ne.coverage b/tests/coverage/assert-ne.coverage
index 236a8fd1385..fc43d4a8e06 100644
--- a/tests/coverage/assert-ne.coverage
+++ b/tests/coverage/assert-ne.coverage
@@ -7,7 +7,7 @@
    LL|       |
    LL|      1|fn main() {
    LL|      1|    assert_ne!(
-   LL|      1|        Foo(5), // Make sure this expression's span isn't lost.
+   LL|      1|        black_box(Foo(5)), // Make sure this expression's span isn't lost.
    LL|      1|        if black_box(false) {
    LL|      0|            Foo(0) //
    LL|       |        } else {
diff --git a/tests/coverage/assert-ne.rs b/tests/coverage/assert-ne.rs
index 8a8fe089804..9d9fcb71ba7 100644
--- a/tests/coverage/assert-ne.rs
+++ b/tests/coverage/assert-ne.rs
@@ -7,7 +7,7 @@ struct Foo(u32);
 
 fn main() {
     assert_ne!(
-        Foo(5), // Make sure this expression's span isn't lost.
+        black_box(Foo(5)), // Make sure this expression's span isn't lost.
         if black_box(false) {
             Foo(0) //
         } else {
diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map
index 526110ebbb7..3aef4274edc 100644
--- a/tests/coverage/assert_not.cov-map
+++ b/tests/coverage/assert_not.cov-map
@@ -1,13 +1,13 @@
 Function name: assert_not::main
-Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 01, 02, 05, 00, 14, 01, 01, 05, 00, 14, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02]
+Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 11, 01, 02, 05, 00, 13, 01, 01, 05, 00, 13, 01, 01, 05, 00, 15, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18)
-- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 20)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 20)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 17)
+- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21)
 - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map
index 5eb69e668ca..d9196f446f1 100644
--- a/tests/coverage/async_block.cov-map
+++ b/tests/coverage/async_block.cov-map
@@ -1,5 +1,5 @@
 Function name: async_block::main
-Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 00, 14, 01, 16, 02, 07, 0a, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
@@ -9,11 +9,11 @@ Number of file 0 mappings: 6
 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
     = (c1 - c0)
 - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19)
-- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 1, 22)
+- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19)
     = (c1 - c0)
-- Code(Expression(0, Sub)) at (prev + 7, 10) to (start + 2, 6)
+- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34)
     = (c1 - c0)
-- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
 Highest counter ID seen: c1
 
 Function name: async_block::main::{closure#0}
diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage
index 9e3294492cd..4e00024aebd 100644
--- a/tests/coverage/async_block.coverage
+++ b/tests/coverage/async_block.coverage
@@ -15,6 +15,6 @@
    LL|     12|            }
    LL|     16|        };
    LL|     16|        executor::block_on(future);
-   LL|     16|    }
+   LL|       |    }
    LL|      1|}
 
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 9144a938a9e..a4ef0ceeb6d 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -30,29 +30,31 @@ Number of file 0 mappings: 2
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
-Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Function name: async_closure::main::{closure#0}
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
-Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
+Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
index 7fbea265812..5aed131de2e 100644
--- a/tests/coverage/async_closure.coverage
+++ b/tests/coverage/async_closure.coverage
@@ -9,12 +9,14 @@
    LL|       |
    LL|      1|pub fn main() {
    LL|      2|    let async_closure = async || {};
-                                               ^1
   ------------------
   | async_closure::main::{closure#0}:
   |   LL|      1|    let async_closure = async || {};
   ------------------
-  | async_closure::main::{closure#0}::{closure#1}::<i32>:
+  | async_closure::main::{closure#0}:
+  |   LL|      1|    let async_closure = async || {};
+  ------------------
+  | async_closure::main::{closure#0}::{closure#0}::<i16>:
   |   LL|      1|    let async_closure = async || {};
   ------------------
    LL|      1|    executor::block_on(async_closure());
diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map
index ef6f5a9dc42..c55c5897d8b 100644
--- a/tests/coverage/attr/off-on-sandwich.cov-map
+++ b/tests/coverage/attr/off-on-sandwich.cov-map
@@ -1,30 +1,30 @@
 Function name: off_on_sandwich::dense_a::dense_b
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 12, 01, 07, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 10, 01, 07, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 18)
+- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 16)
 - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6)
 Highest counter ID seen: c0
 
 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 17, 01, 0b, 09, 00, 0a]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 15, 01, 0b, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 23)
+- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 21)
 - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10)
 Highest counter ID seen: c0
 
 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 1b, 01, 07, 0d, 00, 0e]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 19, 01, 07, 0d, 00, 0e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 27)
+- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 25)
 - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map
index baac0073fcb..f08a70a899d 100644
--- a/tests/coverage/bad_counter_ids.cov-map
+++ b/tests/coverage/bad_counter_ids.cov-map
@@ -1,10 +1,10 @@
 Function name: bad_counter_ids::eq_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 0f, 00, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 15)
 - Code(Zero) at (prev + 3, 1) to (start + 0, 2)
 Highest counter ID seen: c0
 
@@ -20,12 +20,12 @@ Number of file 0 mappings: 3
 Highest counter ID seen: c0
 
 Function name: bad_counter_ids::eq_good
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 01, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 0f, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15)
 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
 Highest counter ID seen: c0
 
@@ -41,12 +41,12 @@ Number of file 0 mappings: 3
 Highest counter ID seen: c0
 
 Function name: bad_counter_ids::ne_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 0f, 00, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 15)
 - Code(Zero) at (prev + 3, 1) to (start + 0, 2)
 Highest counter ID seen: c0
 
@@ -62,12 +62,12 @@ Number of file 0 mappings: 3
 Highest counter ID seen: c0
 
 Function name: bad_counter_ids::ne_good
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 1f, 01, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 0f, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 15)
 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map
index 55f45daa9c9..46533df00f7 100644
--- a/tests/coverage/branch/guard.cov-map
+++ b/tests/coverage/branch/guard.cov-map
@@ -1,5 +1,5 @@
 Function name: guard::branch_match_guard
-Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 10, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
+Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 0e, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
@@ -12,7 +12,7 @@ Number of expressions: 8
 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
 - expression 7 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 13
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
 - Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12)
     = (c1 - c3)
 - Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10)
diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map
index db45df2a5cd..7f6b174615a 100644
--- a/tests/coverage/branch/if-let.cov-map
+++ b/tests/coverage/branch/if-let.cov-map
@@ -1,11 +1,11 @@
 Function name: if_let::if_let
-Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02]
+Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
 - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 12) to (start + 0, 19)
     true  = (c0 - c1)
     false = c1
diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map
index a6b865318c6..1d40f032aa8 100644
--- a/tests/coverage/branch/if.cov-map
+++ b/tests/coverage/branch/if.cov-map
@@ -1,5 +1,5 @@
 Function name: if::branch_and
-Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
@@ -7,7 +7,7 @@ Number of expressions: 3
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -23,7 +23,7 @@ Number of file 0 mappings: 8
 Highest counter ID seen: c2
 
 Function name: if::branch_not
-Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 7
@@ -35,12 +35,12 @@ Number of expressions: 7
 - expression 5 operands: lhs = Counter(0), rhs = Counter(4)
 - expression 6 operands: lhs = Counter(0), rhs = Counter(4)
 Number of file 0 mappings: 18
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
-- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17)
+- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16)
 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6)
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 1, 8) to (start + 0, 10)
@@ -68,7 +68,7 @@ Number of file 0 mappings: 18
 Highest counter ID seen: c4
 
 Function name: if::branch_not_as
-Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 10, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02]
+Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 0e, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 5
@@ -78,7 +78,7 @@ Number of expressions: 5
 - expression 3 operands: lhs = Counter(0), rhs = Counter(3)
 - expression 4 operands: lhs = Counter(0), rhs = Counter(3)
 Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 20)
 - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 0, 8) to (start + 0, 20)
     true  = (c0 - c1)
@@ -104,7 +104,7 @@ Number of file 0 mappings: 14
 Highest counter ID seen: c3
 
 Function name: if::branch_or
-Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 6
@@ -115,7 +115,7 @@ Number of expressions: 6
 - expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add)
 - expression 5 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map
index 622f30e2b56..5d4fc57eb8f 100644
--- a/tests/coverage/branch/lazy-boolean.cov-map
+++ b/tests/coverage/branch/lazy-boolean.cov-map
@@ -1,11 +1,11 @@
 Function name: lazy_boolean::branch_and
-Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02]
+Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14)
@@ -16,13 +16,13 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: lazy_boolean::branch_or
-Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02]
+Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14)
@@ -34,7 +34,7 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: lazy_boolean::chain
-Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02]
+Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 15
@@ -54,7 +54,7 @@ Number of expressions: 15
 - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(6)
 - expression 14 operands: lhs = Counter(4), rhs = Counter(5)
 Number of file 0 mappings: 19
-- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 18)
@@ -69,7 +69,7 @@ Number of file 0 mappings: 19
     true  = c3
     false = (c2 - c3)
 - Code(Counter(3)) at (prev + 0, 40) to (start + 0, 45)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18)
 - Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 18)
@@ -91,7 +91,7 @@ Number of file 0 mappings: 19
 Highest counter ID seen: c6
 
 Function name: lazy_boolean::nested_mixed
-Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02]
+Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 13
@@ -109,7 +109,7 @@ Number of expressions: 13
 - expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add)
 - expression 12 operands: lhs = Counter(5), rhs = Counter(6)
 Number of file 0 mappings: 19
-- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19)
@@ -127,7 +127,7 @@ Number of file 0 mappings: 19
     false = ((c1 + c2) - c3)
 - Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51)
     = ((c1 + c2) - c3)
-- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19)
 - Branch { true: Counter(4), false: Expression(8, Sub) } at (prev + 0, 14) to (start + 0, 19)
diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map
index 215d71599e4..78507a32638 100644
--- a/tests/coverage/branch/let-else.cov-map
+++ b/tests/coverage/branch/let-else.cov-map
@@ -1,11 +1,11 @@
 Function name: let_else::let_else
-Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
 - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 9) to (start + 0, 16)
     true  = (c0 - c1)
     false = c1
@@ -13,7 +13,7 @@ Number of file 0 mappings: 7
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 0, 19) to (start + 0, 24)
 - Code(Counter(1)) at (prev + 1, 9) to (start + 1, 15)
-- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11)
+- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 10)
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
 Highest counter ID seen: c1
diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map
index d5b4d04d401..ef71d12c8af 100644
--- a/tests/coverage/branch/match-arms.cov-map
+++ b/tests/coverage/branch/match-arms.cov-map
@@ -1,5 +1,5 @@
 Function name: match_arms::guards
-Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 29, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 29, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 29, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 29, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 18, 01, 03, 05, 01, 02]
+Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 0e, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
@@ -12,31 +12,31 @@ Number of expressions: 8
 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3)
 - expression 7 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 12
-- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 14)
 - Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27)
     true  = c1
     false = (c5 - c1)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 40)
 - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27)
     true  = c2
     false = (c6 - c2)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 40)
 - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27)
     true  = c3
     false = (c7 - c3)
-- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 41)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 40)
 - Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27)
     true  = c4
     false = (c8 - c4)
-- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 24)
+- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21)
     = (c0 - (((c1 + c2) + c3) + c4))
 - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
 Highest counter ID seen: c8
 
 Function name: match_arms::match_arms
-Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 21, 09, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 02, 01, 11, 00, 21, 01, 03, 05, 01, 02]
+Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
@@ -44,18 +44,18 @@ Number of expressions: 3
 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
 - expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 7
-- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 32)
+- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 32)
     = (c0 - ((c1 + c2) + c3))
 - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
 Highest counter ID seen: c3
 
 Function name: match_arms::or_patterns
-Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2e, 01, 03, 05, 01, 02]
+Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -64,16 +64,16 @@ Number of expressions: 4
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add)
 Number of file 0 mappings: 9
-- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16)
 - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18)
 - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31)
-- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46)
+- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 45)
     = (c1 + c2)
 - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
 - Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31)
     = (c0 - ((c1 + c2) + c3))
-- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 46)
+- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 45)
     = (c0 - (c1 + c2))
 - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2)
 Highest counter ID seen: c3
diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map
index 31322f127af..1b0c6d12e3d 100644
--- a/tests/coverage/branch/match-trivial.cov-map
+++ b/tests/coverage/branch/match-trivial.cov-map
@@ -1,19 +1,19 @@
 Function name: match_trivial::_uninhabited (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 10]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 0e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 22, 1) to (start + 1, 16)
+- Code(Zero) at (prev + 22, 1) to (start + 1, 14)
 Highest counter ID seen: (none)
 
 Function name: match_trivial::trivial
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 01, 03, 0b, 05, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 0e, 01, 03, 0b, 05, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 11) to (start + 5, 2)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map
index 5ce92c72b51..67746af051b 100644
--- a/tests/coverage/branch/while.cov-map
+++ b/tests/coverage/branch/while.cov-map
@@ -1,11 +1,11 @@
 Function name: while::while_cond
-Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(1), rhs = Counter(0)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18)
 - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16)
 - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 16)
@@ -17,13 +17,13 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: while::while_cond_not
-Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(1), rhs = Counter(0)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18)
 - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 20)
 - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 20)
@@ -35,7 +35,7 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: while::while_op_and
-Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
+Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 5
@@ -45,7 +45,7 @@ Number of expressions: 5
 - expression 3 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 4 operands: lhs = Counter(1), rhs = Counter(0)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18)
 - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16)
 - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16)
@@ -61,7 +61,7 @@ Number of file 0 mappings: 8
 Highest counter ID seen: c2
 
 Function name: while::while_op_or
-Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
+Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -70,7 +70,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(0)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 14)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18)
 - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16)
 - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16)
diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map
index fa20c8cf6d7..2d784ba09b6 100644
--- a/tests/coverage/closure.cov-map
+++ b/tests/coverage/closure.cov-map
@@ -1,15 +1,15 @@
 Function name: closure::main
-Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
+Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 24
-- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13)
-- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10)
-- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13)
-- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10)
-- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22)
+- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27)
+- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10)
+- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27)
+- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10)
+- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22)
 - Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24)
 - Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30)
 - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41)
diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage
index 3eac52eb723..2deeb9806c4 100644
--- a/tests/coverage/closure.coverage
+++ b/tests/coverage/closure.coverage
@@ -20,18 +20,18 @@
    LL|      1|        some_string
    LL|      1|            .
    LL|      1|            unwrap_or_else
-   LL|      1|        (
-   LL|      1|            ||
+   LL|       |        (
+   LL|       |            ||
    LL|      0|            {
    LL|      0|                let mut countdown = 0;
    LL|      0|                if is_false {
    LL|      0|                    countdown = 10;
    LL|      0|                }
    LL|      0|                "alt string 1".to_owned()
-   LL|      1|            }
-   LL|      1|        )
-   LL|      1|    );
-   LL|      1|
+   LL|      0|            }
+   LL|       |        )
+   LL|       |    );
+   LL|       |
    LL|      1|    some_string = Some(String::from("the string content"));
    LL|      1|    let
    LL|      1|        a
@@ -62,8 +62,8 @@
    LL|      1|        some_string
    LL|      1|            .
    LL|      1|            unwrap_or_else
-   LL|      1|        (
-   LL|      1|            ||
+   LL|       |        (
+   LL|       |            ||
    LL|      1|            {
    LL|      1|                let mut countdown = 0;
    LL|      1|                if is_false {
@@ -71,9 +71,9 @@
    LL|      1|                }
    LL|      1|                "alt string 3".to_owned()
    LL|      1|            }
-   LL|      1|        )
-   LL|      1|    );
-   LL|      1|
+   LL|       |        )
+   LL|       |    );
+   LL|       |
    LL|      1|    some_string = None;
    LL|      1|    let
    LL|      1|        a
diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map
index 653848dd6ff..9dd99c8fab3 100644
--- a/tests/coverage/closure_macro.cov-map
+++ b/tests/coverage/closure_macro.cov-map
@@ -8,16 +8,16 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: closure_macro::main
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33)
+- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 32)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
-- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84)
+- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52)
 - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
     = (c0 - c1)
diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index 1bd1460a147..2548754d754 100644
--- a/tests/coverage/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
@@ -17,16 +17,16 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: closure_macro_async::test::{closure#0}
-Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
+Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33)
+- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 32)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
-- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84)
+- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52)
 - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
     = (c0 - c1)
diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map
index 417637f2d2e..c34075a0bcf 100644
--- a/tests/coverage/condition/conditions.cov-map
+++ b/tests/coverage/condition/conditions.cov-map
@@ -109,15 +109,17 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: conditions::func_call
-Raw bytes (37): 0x[01, 01, 02, 01, 05, 05, 09, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
+Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10)
-- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10)
+Number of file 0 mappings: 7
+- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8)
+- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10)
+- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 9) to (start + 0, 10)
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15)
diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map
index c6f2d415056..fee32376d83 100644
--- a/tests/coverage/coroutine.cov-map
+++ b/tests/coverage/coroutine.cov-map
@@ -13,7 +13,7 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: coroutine::main
-Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02]
+Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
@@ -21,14 +21,14 @@ Number of expressions: 2
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22)
-- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46)
+- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45)
 - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45)
-- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46)
 - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39)
 - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46)
-- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20)
     = (c1 - c2)
 - Code(Counter(2)) at (prev + 2, 1) to (start + 0, 2)
 Highest counter ID seen: c3
diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map
index 3deacbc8e12..6e2d243e8dd 100644
--- a/tests/coverage/holes.cov-map
+++ b/tests/coverage/holes.cov-map
@@ -8,24 +8,24 @@ Number of file 0 mappings: 1
 Highest counter ID seen: (none)
 
 Function name: holes::main
-Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02]
+Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 13
-- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18)
-- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 17)
+- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17)
-- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
-- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18)
+- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
+- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15)
 - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15)
-- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13)
-- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2)
+- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39)
+- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2)
 Highest counter ID seen: c0
 
 Function name: holes::main::_unused_fn (unused)
diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage
index 1b45c12156a..a6a02f1b9d0 100644
--- a/tests/coverage/holes.coverage
+++ b/tests/coverage/holes.coverage
@@ -84,18 +84,18 @@
    LL|      1|    // `nested_filter::OnlyBodies` or equivalent.
    LL|      1|    #[rustfmt::skip]
    LL|      1|    let _const_block_inside_anon_const =
-   LL|      1|        [
-   LL|      1|            0
-   LL|      1|            ;
-   LL|      1|            7
-   LL|      1|            +
-   LL|      1|            const
+   LL|       |        [
+   LL|       |            0
+   LL|       |            ;
+   LL|       |            7
+   LL|       |            +
+   LL|       |            const
    LL|       |            {
    LL|       |                3
-   LL|      1|            }
-   LL|      1|        ]
-   LL|      1|        ;
-   LL|      1|
+   LL|       |            }
+   LL|       |        ]
+   LL|       |        ;
+   LL|       |
    LL|      1|    black_box(());
    LL|      1|}
 
diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map
index 49cdc514fed..65cefe76c29 100644
--- a/tests/coverage/inline-dead.cov-map
+++ b/tests/coverage/inline-dead.cov-map
@@ -8,14 +8,14 @@ Number of file 0 mappings: 1
 Highest counter ID seen: (none)
 
 Function name: inline_dead::live::<false>
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
 - Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 13)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10)
     = (c0 - c1)
 - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map
index a569ad53cbc..7264391baaf 100644
--- a/tests/coverage/inline.cov-map
+++ b/tests/coverage/inline.cov-map
@@ -15,12 +15,12 @@ Number of file 0 mappings: 5
 Highest counter ID seen: c1
 
 Function name: inline::error
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 0b]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20)
+- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 11)
 Highest counter ID seen: c0
 
 Function name: inline::length::<char>
diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map
index c188cca1b51..f1023109008 100644
--- a/tests/coverage/issue-83601.cov-map
+++ b/tests/coverage/issue-83601.cov-map
@@ -1,12 +1,12 @@
 Function name: issue_83601::main
-Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 0f, 05, 03, 09, 01, 0f, 02, 02, 05, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
-- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 15)
+- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 15)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
     = (c1 - c2)
 Highest counter ID seen: c1
diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index c8f75cddcb5..3bd4e7d2a36 100644
--- a/tests/coverage/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
@@ -1,11 +1,11 @@
 Function name: <issue_84561::Foo as core::fmt::Debug>::fmt
-Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 24, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37)
+- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 36)
 - Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38)
 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15)
     = (c0 - c1)
@@ -59,7 +59,7 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: issue_84561::test3
-Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02]
+Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 27
@@ -91,13 +91,13 @@ Number of expressions: 27
 - expression 25 operands: lhs = Counter(30), rhs = Counter(31)
 - expression 26 operands: lhs = Counter(31), rhs = Counter(32)
 Number of file 0 mappings: 51
-- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
-- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
-- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 31)
-- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
-- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 31)
-- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
-- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 31)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15)
+- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15)
+- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15)
+- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15)
+- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15)
+- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15)
+- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15)
 - Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15)
 - Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48)
     = (c7 - c8)
@@ -112,14 +112,14 @@ Number of file 0 mappings: 51
 - Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27)
 - Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28)
     = (c11 - c12)
-- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 5, 6)
+- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15)
     = (c8 - (c9 + c11))
-- Code(Counter(13)) at (prev + 6, 5) to (start + 3, 6)
-- Code(Counter(14)) at (prev + 4, 5) to (start + 3, 6)
-- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6)
+- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15)
+- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15)
+- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15)
 - Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15)
-- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10)
-- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 3, 10)
+- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19)
+- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19)
     = (c16 - c17)
 - Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15)
     = (c18 + c19)
@@ -144,7 +144,7 @@ Number of file 0 mappings: 51
 - Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15)
     = (c28 + c29)
 - Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19)
-- Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14)
+- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23)
 - Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19)
 - Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23)
     = (c26 - c27)
diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage
index 2a642e2427b..a55f42a696e 100644
--- a/tests/coverage/issue-84561.coverage
+++ b/tests/coverage/issue-84561.coverage
@@ -47,32 +47,32 @@
    LL|      1|    let is_true = std::env::args().len() == 1;
    LL|      1|
    LL|      1|    assert_eq!(
-   LL|      1|        Foo(1),
-   LL|      1|        Foo(1)
-   LL|      1|    );
+   LL|       |        Foo(1),
+   LL|       |        Foo(1)
+   LL|       |    );
    LL|      1|    assert_ne!(
-   LL|      1|        Foo(0),
-   LL|      1|        Foo(1)
-   LL|      1|    );
+   LL|       |        Foo(0),
+   LL|       |        Foo(1)
+   LL|       |    );
    LL|      1|    assert_eq!(
-   LL|      1|        Foo(2),
-   LL|      1|        Foo(2)
-   LL|      1|    );
+   LL|       |        Foo(2),
+   LL|       |        Foo(2)
+   LL|       |    );
    LL|      1|    let bar = Foo(1);
    LL|      1|    assert_ne!(
-   LL|      1|        bar,
-   LL|      1|        Foo(3)
-   LL|      1|    );
+   LL|       |        bar,
+   LL|       |        Foo(3)
+   LL|       |    );
    LL|      1|    if is_true {
    LL|      1|        assert_ne!(
-   LL|      1|            Foo(0),
-   LL|      1|            Foo(4)
-   LL|      1|        );
+   LL|       |            Foo(0),
+   LL|       |            Foo(4)
+   LL|       |        );
    LL|       |    } else {
    LL|      0|        assert_eq!(
-   LL|      0|            Foo(3),
-   LL|      0|            Foo(3)
-   LL|      0|        );
+   LL|       |            Foo(3),
+   LL|       |            Foo(3)
+   LL|       |        );
    LL|       |    }
    LL|      1|    if is_true {
    LL|      1|        assert_ne!(
@@ -106,9 +106,9 @@
    LL|      1|    assert_ne!(
    LL|      1|        if is_true {
    LL|      1|            assert_eq!(
-   LL|      1|                Foo(3),
-   LL|      1|                Foo(3)
-   LL|      1|            );
+   LL|       |                Foo(3),
+   LL|       |                Foo(3)
+   LL|       |            );
    LL|      1|            Foo(0)
    LL|       |        } else {
    LL|      0|            assert_ne!(
diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map
index f13e82da151..fccc4d64395 100644
--- a/tests/coverage/loop-break.cov-map
+++ b/tests/coverage/loop-break.cov-map
@@ -1,12 +1,12 @@
 Function name: loop_break::main
-Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02]
+Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(1), rhs = Counter(0)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11)
-- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 39)
+- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 33)
 - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18)
 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
     = (c1 - c0)
diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map
index 2cb0f948b3e..2157cd6ee3f 100644
--- a/tests/coverage/loops_branches.cov-map
+++ b/tests/coverage/loops_branches.cov-map
@@ -1,5 +1,5 @@
 Function name: <loops_branches::DebugTest as core::fmt::Debug>::fmt
-Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 22, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -13,7 +13,7 @@ Number of file 0 mappings: 20
 - Code(Zero) at (prev + 1, 23) to (start + 0, 27)
 - Code(Zero) at (prev + 0, 28) to (start + 0, 30)
 - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14)
-- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30)
+- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29)
 - Code(Counter(1)) at (prev + 0, 30) to (start + 0, 31)
 - Code(Zero) at (prev + 1, 16) to (start + 1, 10)
 - Code(Counter(3)) at (prev + 3, 13) to (start + 0, 14)
@@ -23,7 +23,7 @@ Number of file 0 mappings: 20
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
 - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
 - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35)
     = ((c0 + c3) - (c1 + c2))
 - Code(Zero) at (prev + 1, 20) to (start + 1, 14)
@@ -33,7 +33,7 @@ Number of file 0 mappings: 20
 Highest counter ID seen: c3
 
 Function name: <loops_branches::DisplayTest as core::fmt::Display>::fmt
-Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 22, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
+Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -48,7 +48,7 @@ Number of file 0 mappings: 20
 - Code(Zero) at (prev + 1, 23) to (start + 0, 27)
 - Code(Zero) at (prev + 0, 28) to (start + 0, 30)
 - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14)
-- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30)
+- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29)
 - Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31)
 - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14)
 - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23)
@@ -58,7 +58,7 @@ Number of file 0 mappings: 20
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
 - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
 - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35)
     = ((c0 + c2) - (c1 + c3))
 - Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15)
diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map
index 58620452b2b..bd033faa551 100644
--- a/tests/coverage/macro_name_span.cov-map
+++ b/tests/coverage/macro_name_span.cov-map
@@ -1,10 +1,10 @@
 Function name: macro_name_span::affected_function
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 3e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64)
+- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 62)
 Highest counter ID seen: c0
 
 Function name: macro_name_span::main
diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map
index c282d53c5ac..959d21901de 100644
--- a/tests/coverage/mcdc/non_control_flow.cov-map
+++ b/tests/coverage/mcdc/non_control_flow.cov-map
@@ -113,15 +113,17 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: non_control_flow::func_call
-Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
+Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 29, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
-- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
+Number of file 0 mappings: 8
+- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8)
+- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10)
+- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
     true  = c1
     false = (c0 - c1)
diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map
index 04171fdb79b..244b0099544 100644
--- a/tests/coverage/no_cov_crate.cov-map
+++ b/tests/coverage/no_cov_crate.cov-map
@@ -35,22 +35,22 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: no_cov_crate::nested_fns::outer
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 23, 01, 0c, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 22, 01, 0c, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 35)
+- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 34)
 - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6)
 Highest counter ID seen: c0
 
 Function name: no_cov_crate::nested_fns::outer_both_covered
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 17, 01, 0b, 05, 00, 06]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 16, 01, 0b, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 23)
+- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 22)
 - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map
index 4628a24689e..18b13919fe5 100644
--- a/tests/coverage/panic_unwind.cov-map
+++ b/tests/coverage/panic_unwind.cov-map
@@ -26,14 +26,14 @@ Number of file 0 mappings: 9
 Highest counter ID seen: c3
 
 Function name: panic_unwind::might_panic
-Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20)
-- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25)
+- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15)
 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2)
     = (c0 - c1)
 Highest counter ID seen: c1
diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map
index 69e13422296..898d68171c5 100644
--- a/tests/coverage/sort_groups.cov-map
+++ b/tests/coverage/sort_groups.cov-map
@@ -55,13 +55,13 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: sort_groups::main
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 1c, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35)
+- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 28)
 - Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
     = (c0 - c1)
diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map
index 35b2c36a575..e45f3de1081 100644
--- a/tests/coverage/try_error_result.cov-map
+++ b/tests/coverage/try_error_result.cov-map
@@ -41,13 +41,13 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: try_error_result::main
-Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0a, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12)
+- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 10)
 - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11)
     = (c0 - c1)
@@ -55,7 +55,7 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: try_error_result::test1
-Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 29, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02]
+Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -67,13 +67,13 @@ Number of file 0 mappings: 11
 - Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23)
 - Code(Counter(1)) at (prev + 7, 9) to (start + 0, 14)
 - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26)
-- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 41)
+- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 17)
     = ((c0 + c2) - c1)
 - Code(Expression(0, Sub)) at (prev + 0, 41) to (start + 0, 42)
     = ((c0 + c2) - c1)
-- Code(Zero) at (prev + 1, 13) to (start + 0, 42)
+- Code(Zero) at (prev + 1, 13) to (start + 0, 17)
 - Code(Zero) at (prev + 0, 42) to (start + 0, 43)
-- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 42)
+- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 17)
     = (c1 - c0)
 - Code(Zero) at (prev + 0, 42) to (start + 0, 43)
 - Code(Expression(3, Sub)) at (prev + 3, 5) to (start + 0, 11)
@@ -82,7 +82,7 @@ Number of file 0 mappings: 11
 Highest counter ID seen: c2
 
 Function name: try_error_result::test2
-Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 35, 15, 04, 11, 00, 12, 1e, 02, 11, 04, 12, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 41, 19, 00, 41, 00, 42, 26, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 41, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 42, 29, 00, 42, 00, 43, 66, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 36, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02]
+Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 17, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 17, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 17, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 17, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 17, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 54
@@ -144,59 +144,59 @@ Number of file 0 mappings: 40
 - Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23)
 - Code(Counter(1)) at (prev + 8, 9) to (start + 0, 14)
 - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26)
-- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 47)
+- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 31)
 - Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48)
-- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 53)
+- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 28)
     = (c3 - c4)
 - Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18)
-- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 4, 18)
+- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 3, 39)
     = (c3 - (c4 + c5))
 - Code(Expression(12, Sub)) at (prev + 5, 17) to (start + 0, 20)
     = (c3 - (((c4 + c5) + c6) + c7))
-- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 65)
+- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 41)
     = (c3 - (c4 + c5))
 - Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 95)
+- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71)
     = (c3 - ((c4 + c5) + c6))
 - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96)
-- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 23)
     = (c3 - (((c4 + c5) + c6) + c7))
 - Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20)
     = (c16 - (c8 + c9))
-- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 65)
+- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 41)
 - Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 96)
+- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71)
     = (c16 - c8)
 - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97)
-- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 23)
     = (c16 - (c8 + c9))
 - Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20)
     = (c2 - ((c3 + c10) + c11))
-- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 66)
+- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 41)
     = (c2 - c3)
 - Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67)
-- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 97)
+- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72)
     = (c2 - (c3 + c10))
 - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98)
-- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 23)
     = (c2 - ((c3 + c10) + c11))
 - Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20)
     = (c17 - (c12 + c13))
-- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54)
+- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 29)
 - Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55)
-- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22)
     = (c17 - c12)
 - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48)
-- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32)
+- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 23)
     = (c17 - (c12 + c13))
 - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20)
     = (c18 - (c14 + c15))
-- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 54)
+- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 29)
 - Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18)
-- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22)
     = (c18 - c14)
 - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32)
+- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 23)
     = (c18 - (c14 + c15))
 - Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 11)
     = (c1 - c2)
diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage
index 7100248f7df..7a89c0452ac 100644
--- a/tests/coverage/try_error_result.coverage
+++ b/tests/coverage/try_error_result.coverage
@@ -86,7 +86,7 @@
    LL|      1|                .
    LL|      1|                expect_err(
    LL|      1|                    "call should fail"
-   LL|      1|                );
+   LL|       |                );
    LL|      1|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
                               ^0                                                ^0                          ^0
    LL|      0|            assert_eq!(val, 57);
diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map
index 7b9dc0b9bc8..29d40a05513 100644
--- a/tests/coverage/unicode.cov-map
+++ b/tests/coverage/unicode.cov-map
@@ -1,5 +1,5 @@
 Function name: unicode::main
-Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02]
+Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
@@ -12,8 +12,8 @@ Number of file 0 mappings: 9
 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 27)
 - Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 0, 40)
     = (c1 - c0)
-- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37)
-- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70)
+- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 35)
+- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 68)
 - Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6)
 - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6)
     = (c0 - c3)
diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage
index 84c5f05a8c4..44349954550 100644
--- a/tests/coverage/unicode.coverage
+++ b/tests/coverage/unicode.coverage
@@ -15,7 +15,7 @@
    LL|     33|    for _İ in 'А'..='Я' { /* Я */ }
                       ^32                ^32
    LL|       |
-   LL|      1|    if 申し訳ございません() && 申し訳ございません() {
+   LL|      1|    if 申し訳ございません() && 申し訳ございません() {
                                                       ^0
    LL|      0|        println!("true");
    LL|      1|    }
diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map
index 97961bc7414..0bc18bfcbd3 100644
--- a/tests/coverage/unreachable.cov-map
+++ b/tests/coverage/unreachable.cov-map
@@ -1,27 +1,27 @@
 Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 47]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 45]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 14, 39) to (start + 0, 71)
+- Code(Zero) at (prev + 14, 39) to (start + 0, 69)
 Highest counter ID seen: (none)
 
 Function name: unreachable::unreachable_function (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 25]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 23]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 16, 1) to (start + 1, 37)
+- Code(Zero) at (prev + 16, 1) to (start + 1, 35)
 Highest counter ID seen: (none)
 
 Function name: unreachable::unreachable_intrinsic (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2c]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 21, 1) to (start + 1, 44)
+- Code(Zero) at (prev + 21, 1) to (start + 1, 42)
 Highest counter ID seen: (none)
 
diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map
index d296f9bd778..bf0916e5503 100644
--- a/tests/coverage/yield.cov-map
+++ b/tests/coverage/yield.cov-map
@@ -1,5 +1,5 @@
 Function name: yield::main
-Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 34, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 34, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 34, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 34, 12, 02, 01, 00, 02]
+Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 5
@@ -12,22 +12,22 @@ Number of file 0 mappings: 16
 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22)
 - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46)
 - Code(Counter(1)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46)
 - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39)
 - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46)
-- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20)
     = (c1 - c2)
 - Code(Counter(2)) at (prev + 3, 9) to (start + 0, 22)
 - Code(Counter(2)) at (prev + 8, 11) to (start + 0, 46)
 - Code(Counter(4)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 20)
     = (c2 - c4)
 - Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46)
 - Code(Expression(4, Sub)) at (prev + 1, 39) to (start + 0, 41)
     = (c4 - c5)
-- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 20)
 - Code(Expression(4, Sub)) at (prev + 2, 1) to (start + 0, 2)
     = (c4 - c5)
 Highest counter ID seen: c5
diff --git a/tests/crashes/122904.rs b/tests/crashes/122904.rs
deleted file mode 100644
index 2068cd9d239..00000000000
--- a/tests/crashes/122904.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #122904
-trait T {}
-
-type Alias<'a> = impl T;
-
-struct S;
-impl<'a> T for &'a S {}
-
-#[define_opaque(Alias)]
-fn with_positive(fun: impl Fn(Alias<'_>)) {
-    with_positive(|&n| ());
-}
diff --git a/tests/crashes/134334.rs b/tests/crashes/134334.rs
deleted file mode 100644
index d99df7bdc1e..00000000000
--- a/tests/crashes/134334.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #134334
-//@ only-x86_64
-
-#[repr(simd)]
-struct A();
-
-fn main() {
-    std::arch::asm!("{}", in(xmm_reg) A());
-}
diff --git a/tests/crashes/134335.rs b/tests/crashes/134335.rs
deleted file mode 100644
index bee6686ff3f..00000000000
--- a/tests/crashes/134335.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #134335
-//@compile-flags: -Zunstable-options --edition=2024 --crate-type=lib
-pub async fn async_closure(x: &mut i32) {
-    let c = async move || {
-        *x += 1;
-    };
-    call_once(c).await;
-}
-
-fn call_once<T>(f: impl FnOnce() -> T) -> T {
-    f()
-}
diff --git a/tests/incremental/define-opaques.rs b/tests/incremental/define-opaques.rs
new file mode 100644
index 00000000000..d6eae238341
--- /dev/null
+++ b/tests/incremental/define-opaques.rs
@@ -0,0 +1,19 @@
+//@ revisions: rpass1 cfail2
+
+#![feature(type_alias_impl_trait)]
+
+pub type Foo = impl Sized;
+
+#[cfg_attr(rpass1, define_opaque())]
+#[cfg_attr(cfail2, define_opaque(Foo))]
+fn a() {
+    //[cfail2]~^ ERROR item does not constrain `Foo::{opaque#0}`
+    let _: Foo = b();
+}
+
+#[define_opaque(Foo)]
+fn b() -> Foo {
+    ()
+}
+
+fn main() {}
diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs
index 958e9dd07e2..1534aca5ddd 100644
--- a/tests/incremental/delayed_span_bug.rs
+++ b/tests/incremental/delayed_span_bug.rs
@@ -1,8 +1,8 @@
 //@ revisions: cfail1 cfail2
 //@ should-ice
-//@ error-pattern: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]
+//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
 
 #![feature(rustc_attrs)]
 
-#[rustc_error(delayed_bug_from_inside_query)]
+#[rustc_delayed_bug_from_inside_query]
 fn main() {}
diff --git a/tests/incremental/env/env_macro.rs b/tests/incremental/env/env_macro.rs
new file mode 100644
index 00000000000..0c026328874
--- /dev/null
+++ b/tests/incremental/env/env_macro.rs
@@ -0,0 +1,18 @@
+// Check that changes to environment variables are propagated to `env!`.
+//
+// This test is intentionally written to not use any `#[cfg(rpass*)]`, to
+// _really_ test that we re-compile if the environment variable changes.
+
+//@ revisions: cfail1 rpass2 rpass3 cfail4
+//@ [cfail1]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass2]rustc-env:EXAMPLE_ENV=one
+//@ [rpass2]exec-env:EXAMPLE_ENV=one
+//@ [rpass3]rustc-env:EXAMPLE_ENV=two
+//@ [rpass3]exec-env:EXAMPLE_ENV=two
+//@ [cfail4]unset-rustc-env:EXAMPLE_ENV
+
+fn main() {
+    assert_eq!(env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").unwrap());
+    //[cfail1]~^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time
+    //[cfail4]~^^ ERROR environment variable `EXAMPLE_ENV` not defined at compile time
+}
diff --git a/tests/incremental/env/option_env_macro.rs b/tests/incremental/env/option_env_macro.rs
new file mode 100644
index 00000000000..44c3bfd69e0
--- /dev/null
+++ b/tests/incremental/env/option_env_macro.rs
@@ -0,0 +1,18 @@
+// Check that changes to environment variables are propagated to `option_env!`.
+//
+// This test is intentionally written to not use any `#[cfg(rpass*)]`, to
+// _really_ test that we re-compile if the environment variable changes.
+
+//@ revisions: rpass1 rpass2 rpass3 rpass4
+//@ [rpass1]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass1]unset-exec-env:EXAMPLE_ENV
+//@ [rpass2]rustc-env:EXAMPLE_ENV=one
+//@ [rpass2]exec-env:EXAMPLE_ENV=one
+//@ [rpass3]rustc-env:EXAMPLE_ENV=two
+//@ [rpass3]exec-env:EXAMPLE_ENV=two
+//@ [rpass4]unset-rustc-env:EXAMPLE_ENV
+//@ [rpass4]unset-exec-env:EXAMPLE_ENV
+
+fn main() {
+    assert_eq!(option_env!("EXAMPLE_ENV"), std::env::var("EXAMPLE_ENV").ok().as_deref());
+}
diff --git a/tests/incremental/user-written-closure-synthetic-closure-conflict.rs b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
new file mode 100644
index 00000000000..618604d06b1
--- /dev/null
+++ b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs
@@ -0,0 +1,15 @@
+//@ revisions: rpass1 rpass2
+//@ edition: 2024
+
+#![allow(unused)]
+
+fn main() {
+    #[cfg(rpass1)]
+    async || {};
+
+    #[cfg(rpass2)]
+    || {
+        || ();
+        || ();
+    };
+}
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
index bd0baddb1f8..9070c95bca4 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `foo::{closure#0}::{closure#1}` after built
+// MIR for `foo::{closure#0}::{synthetic#0}` after built
 
-fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
+fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
index 3c5aec94bbf..e78671f5e9d 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.rs
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs
@@ -7,7 +7,7 @@ enum Foo {
 }
 
 // EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
 fn foo(f: &Foo) {
     let x = async move || match f {
         Foo::Bar if true => {}
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
index a9e08d2e8f6..c5f538e5ecd 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built
 
-fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
index 4452ae7812e..e295f9b3cf1 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
+// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built
 
-fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index cd2e83e939a..93cc7834a64 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -42,11 +42,11 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
 
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
 pub fn main() {
     block_on(async {
         let b = 2i32;
diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs
index 33fdd2dd0d9..4ae97273cd9 100644
--- a/tests/mir-opt/coroutine_drop_cleanup.rs
+++ b/tests/mir-opt/coroutine_drop_cleanup.rs
@@ -8,7 +8,7 @@
 
 // EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir
 fn main() {
-    let gen = #[coroutine]
+    let gen_ = #[coroutine]
     || {
         let _s = String::new();
         yield;
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index 8e1cdb7182b..542b70bcee9 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -27,10 +27,10 @@
       }
   
 +     coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0);
-+     coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0);
-+     coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0);
-+     coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:33 (#0);
-+     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:33 (#0);
++     coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:32 (#0);
++     coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:32 (#0);
++     coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:32 (#0);
++     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:32 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
 + 
       bb0: {
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index 1a71cb8dea7..30de92f3b86 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -8,7 +8,7 @@
       let mut _3: !;
   
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0);
-+     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:17 (#0);
++     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
 +     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff
index 45fc7365d8d..6baa902b6f4 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff
@@ -29,16 +29,10 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
-                      let mut _22: std::option::Option<u16>;
-                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
-                          let mut _23: isize;
-                          let _24: u16;
-                          let mut _25: usize;
-                          scope 7 {
-                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
-                              }
-                          }
-                      }
+                      let mut _22: u32;
+                      let mut _23: u32;
+                      let mut _24: usize;
+                      let mut _25: u16;
                   }
               }
           }
@@ -53,7 +47,7 @@
           StorageLive(_20);
           StorageLive(_21);
           _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
-          _20 = BitAnd(move _21, const 1_u32);
+          _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
           StorageDead(_20);
@@ -75,12 +69,12 @@
   
       bb3: {
           StorageLive(_6);
-          StorageLive(_24);
           StorageLive(_22);
-          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
           StorageLive(_23);
-          _23 = discriminant(_22);
-          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+          _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
+          StorageDead(_23);
+          switchInt(move _22) -> [0: bb10, otherwise: bb11];
       }
   
       bb4: {
@@ -148,30 +142,31 @@
       }
   
       bb9: {
-          StorageDead(_23);
-          StorageDead(_22);
-          StorageDead(_24);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12];
       }
   
       bb10: {
-          unreachable;
-      }
-  
-      bb11: {
+          StorageDead(_22);
           _6 = const Option::<usize>::None;
           goto -> bb9;
       }
   
-      bb12: {
-          _24 = move ((_22 as Some).0: u16);
+      bb11: {
+          StorageDead(_22);
+          StorageLive(_24);
           StorageLive(_25);
-          _25 = copy _24 as usize (IntToInt);
-          _6 = Option::<usize>::Some(move _25);
+          _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16);
+          _24 = move _25 as usize (IntToInt);
           StorageDead(_25);
+          _6 = Option::<usize>::Some(move _24);
+          StorageDead(_24);
           goto -> bb9;
       }
+  
+      bb12: {
+          unreachable;
+      }
   }
   
   ALLOC0 (size: 8, align: 4) {
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff
index 578d2c2194b..36540e03865 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff
@@ -29,16 +29,10 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
-                      let mut _22: std::option::Option<u16>;
-                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
-                          let mut _23: isize;
-                          let _24: u16;
-                          let mut _25: usize;
-                          scope 7 {
-                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
-                              }
-                          }
-                      }
+                      let mut _22: u32;
+                      let mut _23: u32;
+                      let mut _24: usize;
+                      let mut _25: u16;
                   }
               }
           }
@@ -53,7 +47,7 @@
           StorageLive(_20);
           StorageLive(_21);
           _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
-          _20 = BitAnd(move _21, const 1_u32);
+          _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
           StorageDead(_20);
@@ -75,12 +69,12 @@
   
       bb3: {
           StorageLive(_6);
-          StorageLive(_24);
           StorageLive(_22);
-          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
           StorageLive(_23);
-          _23 = discriminant(_22);
-          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+          _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
+          StorageDead(_23);
+          switchInt(move _22) -> [0: bb10, otherwise: bb11];
       }
   
       bb4: {
@@ -148,30 +142,31 @@
       }
   
       bb9: {
-          StorageDead(_23);
-          StorageDead(_22);
-          StorageDead(_24);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12];
       }
   
       bb10: {
-          unreachable;
-      }
-  
-      bb11: {
+          StorageDead(_22);
           _6 = const Option::<usize>::None;
           goto -> bb9;
       }
   
-      bb12: {
-          _24 = move ((_22 as Some).0: u16);
+      bb11: {
+          StorageDead(_22);
+          StorageLive(_24);
           StorageLive(_25);
-          _25 = copy _24 as usize (IntToInt);
-          _6 = Option::<usize>::Some(move _25);
+          _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16);
+          _24 = move _25 as usize (IntToInt);
           StorageDead(_25);
+          _6 = Option::<usize>::Some(move _24);
+          StorageDead(_24);
           goto -> bb9;
       }
+  
+      bb12: {
+          unreachable;
+      }
   }
   
   ALLOC0 (size: 8, align: 4) {
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff
index 5f0f7d6cc74..41c350f3eae 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff
@@ -29,16 +29,10 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
-                      let mut _22: std::option::Option<u16>;
-                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
-                          let mut _23: isize;
-                          let _24: u16;
-                          let mut _25: usize;
-                          scope 7 {
-                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
-                              }
-                          }
-                      }
+                      let mut _22: u32;
+                      let mut _23: u32;
+                      let mut _24: usize;
+                      let mut _25: u16;
                   }
               }
           }
@@ -53,7 +47,7 @@
           StorageLive(_20);
           StorageLive(_21);
           _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
-          _20 = BitAnd(move _21, const 1_u32);
+          _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
           StorageDead(_20);
@@ -75,12 +69,12 @@
   
       bb3: {
           StorageLive(_6);
-          StorageLive(_24);
           StorageLive(_22);
-          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
           StorageLive(_23);
-          _23 = discriminant(_22);
-          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+          _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
+          StorageDead(_23);
+          switchInt(move _22) -> [0: bb10, otherwise: bb11];
       }
   
       bb4: {
@@ -148,30 +142,31 @@
       }
   
       bb9: {
-          StorageDead(_23);
-          StorageDead(_22);
-          StorageDead(_24);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12];
       }
   
       bb10: {
-          unreachable;
-      }
-  
-      bb11: {
+          StorageDead(_22);
           _6 = const Option::<usize>::None;
           goto -> bb9;
       }
   
-      bb12: {
-          _24 = move ((_22 as Some).0: u16);
+      bb11: {
+          StorageDead(_22);
+          StorageLive(_24);
           StorageLive(_25);
-          _25 = copy _24 as usize (IntToInt);
-          _6 = Option::<usize>::Some(move _25);
+          _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16);
+          _24 = move _25 as usize (IntToInt);
           StorageDead(_25);
+          _6 = Option::<usize>::Some(move _24);
+          StorageDead(_24);
           goto -> bb9;
       }
+  
+      bb12: {
+          unreachable;
+      }
   }
   
   ALLOC0 (size: 16, align: 8) {
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff
index 10cc46a8b82..b839bf81eaf 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff
@@ -29,16 +29,10 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
-                      let mut _22: std::option::Option<u16>;
-                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
-                          let mut _23: isize;
-                          let _24: u16;
-                          let mut _25: usize;
-                          scope 7 {
-                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
-                              }
-                          }
-                      }
+                      let mut _22: u32;
+                      let mut _23: u32;
+                      let mut _24: usize;
+                      let mut _25: u16;
                   }
               }
           }
@@ -53,7 +47,7 @@
           StorageLive(_20);
           StorageLive(_21);
           _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
-          _20 = BitAnd(move _21, const 1_u32);
+          _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG);
           StorageDead(_21);
           _4 = Ne(move _20, const 0_u32);
           StorageDead(_20);
@@ -75,12 +69,12 @@
   
       bb3: {
           StorageLive(_6);
-          StorageLive(_24);
           StorageLive(_22);
-          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
           StorageLive(_23);
-          _23 = discriminant(_22);
-          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+          _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG);
+          StorageDead(_23);
+          switchInt(move _22) -> [0: bb10, otherwise: bb11];
       }
   
       bb4: {
@@ -148,30 +142,31 @@
       }
   
       bb9: {
-          StorageDead(_23);
-          StorageDead(_22);
-          StorageDead(_24);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12];
       }
   
       bb10: {
-          unreachable;
-      }
-  
-      bb11: {
+          StorageDead(_22);
           _6 = const Option::<usize>::None;
           goto -> bb9;
       }
   
-      bb12: {
-          _24 = move ((_22 as Some).0: u16);
+      bb11: {
+          StorageDead(_22);
+          StorageLive(_24);
           StorageLive(_25);
-          _25 = copy _24 as usize (IntToInt);
-          _6 = Option::<usize>::Some(move _25);
+          _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16);
+          _24 = move _25 as usize (IntToInt);
           StorageDead(_25);
+          _6 = Option::<usize>::Some(move _24);
+          StorageDead(_24);
           goto -> bb9;
       }
+  
+      bb12: {
+          unreachable;
+      }
   }
   
   ALLOC0 (size: 16, align: 8) {
diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs
index 56f8e3f8338..8fd340503f5 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.rs
+++ b/tests/mir-opt/pre-codegen/checked_ops.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 //@ compile-flags: -O -Zmir-opt-level=2
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
@@ -8,10 +7,48 @@
 // EMIT_MIR checked_ops.step_forward.PreCodegen.after.mir
 pub fn step_forward(x: u16, n: usize) -> u16 {
     // This uses `u16` so that the conversion to usize is always widening.
+
+    // CHECK-LABEL: fn step_forward
+    // CHECK: inlined{{.+}}forward
     std::iter::Step::forward(x, n)
 }
 
 // EMIT_MIR checked_ops.checked_shl.PreCodegen.after.mir
 pub fn checked_shl(x: u32, rhs: u32) -> Option<u32> {
+    // CHECK-LABEL: fn checked_shl
+    // CHECK: [[TEMP:_[0-9]+]] = ShlUnchecked(copy _1, copy _2)
+    // CHECK: _0 = Option::<u32>::Some({{move|copy}} [[TEMP]])
     x.checked_shl(rhs)
 }
+
+// EMIT_MIR checked_ops.use_checked_sub.PreCodegen.after.mir
+pub fn use_checked_sub(x: u32, rhs: u32) {
+    // We want this to be equivalent to open-coding it, leaving no `Option`s around.
+    // FIXME(#138544): It's not yet.
+
+    // CHECK-LABEL: fn use_checked_sub
+    // CHECK: inlined{{.+}}u32{{.+}}checked_sub
+    // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2)
+    // CHECK: [[TEMP1:_.+]] = Option::<u32>::Some(move [[DELTA]]);
+    // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32);
+    // CHECK: do_something({{move|copy}} [[TEMP2]])
+    if let Some(delta) = x.checked_sub(rhs) {
+        do_something(delta);
+    }
+}
+
+// EMIT_MIR checked_ops.saturating_sub_at_home.PreCodegen.after.mir
+pub fn saturating_sub_at_home(lhs: u32, rhs: u32) -> u32 {
+    // FIXME(#138544): Similarly here, the `Option` ought to optimize away
+
+    // CHECK-LABEL: fn saturating_sub_at_home
+    // CHECK: [[DELTA:_[0-9]+]] = SubUnchecked(copy _1, copy _2)
+    // CHECK: [[TEMP1:_.+]] = Option::<u32>::Some({{move|copy}} [[DELTA]]);
+    // CHECK: [[TEMP2:_.+]] = {{move|copy}} (([[TEMP1]] as Some).0: u32);
+    // CHECK: _0 = {{move|copy}} [[TEMP2]];
+    u32::checked_sub(lhs, rhs).unwrap_or(0)
+}
+
+unsafe extern "Rust" {
+    safe fn do_something(_: u32);
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
new file mode 100644
index 00000000000..5b4fdeda857
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,48 @@
+// MIR for `saturating_sub_at_home` after PreCodegen
+
+fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
+    debug lhs => _1;
+    debug rhs => _2;
+    let mut _0: u32;
+    let mut _5: std::option::Option<u32>;
+    scope 1 (inlined core::num::<impl u32>::checked_sub) {
+        let mut _3: bool;
+        let mut _4: u32;
+    }
+    scope 2 (inlined Option::<u32>::unwrap_or) {
+        let _6: u32;
+        scope 3 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_6);
+        _6 = move ((_5 as Some).0: u32);
+        _0 = move _6;
+        StorageDead(_6);
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 00000000000..5b4fdeda857
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.saturating_sub_at_home.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,48 @@
+// MIR for `saturating_sub_at_home` after PreCodegen
+
+fn saturating_sub_at_home(_1: u32, _2: u32) -> u32 {
+    debug lhs => _1;
+    debug rhs => _2;
+    let mut _0: u32;
+    let mut _5: std::option::Option<u32>;
+    scope 1 (inlined core::num::<impl u32>::checked_sub) {
+        let mut _3: bool;
+        let mut _4: u32;
+    }
+    scope 2 (inlined Option::<u32>::unwrap_or) {
+        let _6: u32;
+        scope 3 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_6);
+        _6 = move ((_5 as Some).0: u32);
+        _0 = move _6;
+        StorageDead(_6);
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_3);
+        _0 = const 0_u32;
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir
new file mode 100644
index 00000000000..3c475cd4030
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,44 @@
+// MIR for `use_checked_sub` after PreCodegen
+
+fn use_checked_sub(_1: u32, _2: u32) -> () {
+    debug x => _1;
+    debug rhs => _2;
+    let mut _0: ();
+    let mut _5: std::option::Option<u32>;
+    let _7: ();
+    scope 1 {
+        debug delta => _6;
+        let _6: u32;
+        scope 2 (inlined core::num::<impl u32>::checked_sub) {
+            let mut _3: bool;
+            let mut _4: u32;
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        _6 = copy ((_5 as Some).0: u32);
+        _7 = do_something(move _6) -> [return: bb3, unwind unreachable];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 00000000000..3ef09764b1c
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,44 @@
+// MIR for `use_checked_sub` after PreCodegen
+
+fn use_checked_sub(_1: u32, _2: u32) -> () {
+    debug x => _1;
+    debug rhs => _2;
+    let mut _0: ();
+    let mut _5: std::option::Option<u32>;
+    let _7: ();
+    scope 1 {
+        debug delta => _6;
+        let _6: u32;
+        scope 2 (inlined core::num::<impl u32>::checked_sub) {
+            let mut _3: bool;
+            let mut _4: u32;
+        }
+    }
+
+    bb0: {
+        StorageLive(_5);
+        StorageLive(_3);
+        _3 = Lt(copy _1, copy _2);
+        switchInt(move _3) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_4);
+        _4 = SubUnchecked(copy _1, copy _2);
+        _5 = Option::<u32>::Some(move _4);
+        StorageDead(_4);
+        StorageDead(_3);
+        _6 = copy ((_5 as Some).0: u32);
+        _7 = do_something(move _6) -> [return: bb3, unwind continue];
+    }
+
+    bb2: {
+        StorageDead(_3);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_5);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
index cbfc58194cc..7595ad88d9d 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
@@ -3,7 +3,7 @@
 fn ezmap(_1: Option<i32>) -> Option<i32> {
     debug x => _1;
     let mut _0: std::option::Option<i32>;
-    scope 1 (inlined map::<i32, i32, {closure@$DIR/simple_option_map.rs:17:12: 17:15}>) {
+    scope 1 (inlined map::<i32, i32, {closure@$DIR/simple_option_map.rs:23:12: 23:15}>) {
         let mut _2: isize;
         let _3: i32;
         let mut _4: i32;
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir
new file mode 100644
index 00000000000..b921b96966b
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir
@@ -0,0 +1,70 @@
+// MIR for `map_via_question_mark` after PreCodegen
+
+fn map_via_question_mark(_1: Option<i32>) -> Option<i32> {
+    debug x => _1;
+    let mut _0: std::option::Option<i32>;
+    let mut _4: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, i32>;
+    let _5: i32;
+    let mut _6: i32;
+    scope 1 {
+        debug residual => const Option::<Infallible>::None;
+        scope 2 {
+            scope 7 (inlined <Option<i32> as FromResidual<Option<Infallible>>>::from_residual) {
+            }
+        }
+    }
+    scope 3 {
+        debug val => _5;
+        scope 4 {
+        }
+    }
+    scope 5 (inlined <Option<i32> as Try>::branch) {
+        let mut _2: isize;
+        let _3: i32;
+        scope 6 {
+        }
+    }
+
+    bb0: {
+        StorageLive(_6);
+        StorageLive(_4);
+        StorageLive(_2);
+        StorageLive(_3);
+        _2 = discriminant(_1);
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4];
+    }
+
+    bb1: {
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const Option::<i32>::None;
+        StorageDead(_6);
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb2: {
+        _3 = copy ((_1 as Some).0: i32);
+        _4 = ControlFlow::<Option<Infallible>, i32>::Continue(copy _3);
+        StorageDead(_3);
+        StorageDead(_2);
+        _5 = copy ((_4 as Continue).0: i32);
+        _6 = Add(copy _5, const 1_i32);
+        _0 = Option::<i32>::Some(move _6);
+        StorageDead(_6);
+        StorageDead(_4);
+        goto -> bb3;
+    }
+
+    bb3: {
+        return;
+    }
+
+    bb4: {
+        unreachable;
+    }
+}
+
+ALLOC0 (size: 8, align: 4) {
+    00 00 00 00 __ __ __ __                         │ ....░░░░
+}
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.rs b/tests/mir-opt/pre-codegen/simple_option_map.rs
index 0c432be0419..f0d7b51a643 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.rs
+++ b/tests/mir-opt/pre-codegen/simple_option_map.rs
@@ -1,7 +1,6 @@
-// skip-filecheck
 //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
 
-#[inline(always)]
+#[inline]
 fn map<T, U, F>(slf: Option<T>, f: F) -> Option<U>
 where
     F: FnOnce(T) -> U,
@@ -14,9 +13,30 @@ where
 
 // EMIT_MIR simple_option_map.ezmap.PreCodegen.after.mir
 pub fn ezmap(x: Option<i32>) -> Option<i32> {
+    // We expect this to all be inlined, as though it was written without the
+    // combinator and without the closure, using just a plain match.
+
+    // CHECK-LABEL: fn ezmap
+    // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32);
+    // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[INNER]], const 1_i32);
+    // CHECK: _0 = Option::<i32>::Some({{copy|move}} [[SUCC]]);
     map(x, |n| n + 1)
 }
 
+// EMIT_MIR simple_option_map.map_via_question_mark.PreCodegen.after.mir
+pub fn map_via_question_mark(x: Option<i32>) -> Option<i32> {
+    // FIXME(#138544): Ideally this would optimize out the `ControlFlow` local.
+
+    // CHECK-LABEL: fn map_via_question_mark
+    // CHECK: [[INNER:_.+]] = copy ((_1 as Some).0: i32);
+    // CHECK: [[TEMP1:_.+]] = ControlFlow::<Option<Infallible>, i32>::Continue(copy [[INNER]]);
+    // CHECK: [[TEMP2:_.+]] = copy (([[TEMP1]] as Continue).0: i32);
+    // CHECK: [[SUCC:_.+]] = Add({{copy|move}} [[TEMP2]], const 1_i32);
+    // CHECK: _0 = Option::<i32>::Some({{copy|move}} [[SUCC]]);
+    Some(x? + 1)
+}
+
 fn main() {
     assert_eq!(None, ezmap(None));
+    assert_eq!(None, map_via_question_mark(None));
 }
diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir
new file mode 100644
index 00000000000..dd2eebc8f4a
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir
@@ -0,0 +1,70 @@
+// MIR for `demo_ge_partial` after PreCodegen
+
+fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
+    debug a => _1;
+    debug b => _2;
+    let mut _0: bool;
+    scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(f32, f32)>::ge) {
+        scope 2 (inlined core::tuple::<impl PartialOrd for (f32, f32)>::ge) {
+            let mut _7: std::ops::ControlFlow<bool>;
+            let _8: bool;
+            scope 3 {
+            }
+            scope 4 (inlined std::cmp::impls::<impl PartialOrd for f32>::__chaining_ge) {
+                let mut _3: f32;
+                let mut _4: f32;
+                let mut _5: bool;
+                let mut _6: bool;
+                scope 5 {
+                }
+            }
+            scope 6 (inlined std::cmp::impls::<impl PartialOrd for f32>::ge) {
+                let mut _9: f32;
+                let mut _10: f32;
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_7);
+        StorageLive(_3);
+        StorageLive(_4);
+        _3 = copy ((*_1).0: f32);
+        _4 = copy ((*_2).0: f32);
+        StorageLive(_5);
+        _5 = Eq(copy _3, copy _4);
+        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_6);
+        _6 = Ge(copy _3, copy _4);
+        _7 = ControlFlow::<bool>::Break(move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageDead(_4);
+        StorageDead(_3);
+        _8 = copy ((_7 as Break).0: bool);
+        _0 = copy _8;
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_5);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_9);
+        _9 = copy ((*_1).1: f32);
+        StorageLive(_10);
+        _10 = copy ((*_2).1: f32);
+        _0 = Ge(move _9, move _10);
+        StorageDead(_10);
+        StorageDead(_9);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_7);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir
new file mode 100644
index 00000000000..ea1d164cefa
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir
@@ -0,0 +1,70 @@
+// MIR for `demo_le_total` after PreCodegen
+
+fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
+    debug a => _1;
+    debug b => _2;
+    let mut _0: bool;
+    scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(u16, i16)>::le) {
+        scope 2 (inlined core::tuple::<impl PartialOrd for (u16, i16)>::le) {
+            let mut _7: std::ops::ControlFlow<bool>;
+            let _8: bool;
+            scope 3 {
+            }
+            scope 4 (inlined std::cmp::impls::<impl PartialOrd for u16>::__chaining_le) {
+                let mut _3: u16;
+                let mut _4: u16;
+                let mut _5: bool;
+                let mut _6: bool;
+                scope 5 {
+                }
+            }
+            scope 6 (inlined std::cmp::impls::<impl PartialOrd for i16>::le) {
+                let mut _9: i16;
+                let mut _10: i16;
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_7);
+        StorageLive(_3);
+        StorageLive(_4);
+        _3 = copy ((*_1).0: u16);
+        _4 = copy ((*_2).0: u16);
+        StorageLive(_5);
+        _5 = Eq(copy _3, copy _4);
+        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+    }
+
+    bb1: {
+        StorageLive(_6);
+        _6 = Le(copy _3, copy _4);
+        _7 = ControlFlow::<bool>::Break(move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageDead(_4);
+        StorageDead(_3);
+        _8 = copy ((_7 as Break).0: bool);
+        _0 = copy _8;
+        goto -> bb3;
+    }
+
+    bb2: {
+        StorageDead(_5);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageLive(_9);
+        _9 = copy ((*_1).1: i16);
+        StorageLive(_10);
+        _10 = copy ((*_2).1: i16);
+        _0 = Le(move _9, move _10);
+        StorageDead(_10);
+        StorageDead(_9);
+        goto -> bb3;
+    }
+
+    bb3: {
+        StorageDead(_7);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/tuple_ord.rs b/tests/mir-opt/pre-codegen/tuple_ord.rs
new file mode 100644
index 00000000000..74a919e5424
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/tuple_ord.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0
+//@ needs-unwind
+
+#![crate_type = "lib"]
+
+// EMIT_MIR tuple_ord.demo_le_total.PreCodegen.after.mir
+pub fn demo_le_total(a: &(u16, i16), b: &(u16, i16)) -> bool {
+    // CHECK-LABEL: demo_le_total
+    a <= b
+}
+
+// EMIT_MIR tuple_ord.demo_ge_partial.PreCodegen.after.mir
+pub fn demo_ge_partial(a: &(f32, f32), b: &(f32, f32)) -> bool {
+    // CHECK-LABEL: demo_ge_partial
+    a >= b
+}
diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp
index 23c3b5b34a8..dc7a2712f42 100644
--- a/tests/pretty/autodiff_forward.pp
+++ b/tests/pretty/autodiff_forward.pp
@@ -53,7 +53,7 @@ pub fn df2(x: &[f64], bx: &[f64], y: f64) -> f64 {
 pub fn f3(x: &[f64], y: f64) -> f64 {
     ::core::panicking::panic("not implemented")
 }
-#[rustc_autodiff(ForwardFirst, Dual, Const, Const,)]
+#[rustc_autodiff(Forward, Dual, Const, Const,)]
 #[inline(never)]
 pub fn df3(x: &[f64], bx: &[f64], y: f64) -> f64 {
     unsafe { asm!("NOP", options(pure, nomem)); };
@@ -73,10 +73,6 @@ pub fn df4() {
 }
 #[rustc_autodiff]
 #[inline(never)]
-#[rustc_autodiff]
-#[inline(never)]
-#[rustc_autodiff]
-#[inline(never)]
 pub fn f5(x: &[f64], y: f64) -> f64 {
     ::core::panicking::panic("not implemented")
 }
diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs
index 35108d0d6f1..bc558211632 100644
--- a/tests/pretty/autodiff_forward.rs
+++ b/tests/pretty/autodiff_forward.rs
@@ -19,7 +19,7 @@ pub fn f2(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
-#[autodiff(df3, ForwardFirst, Dual, Const, Const)]
+#[autodiff(df3, Forward, Dual, Const, Const)]
 pub fn f3(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff_reverse.pp
index a98d3782c70..b2cf0244af4 100644
--- a/tests/pretty/autodiff_reverse.pp
+++ b/tests/pretty/autodiff_reverse.pp
@@ -51,7 +51,7 @@ pub fn df2() {
 pub fn f3(x: &[f64], y: f64) -> f64 {
     ::core::panicking::panic("not implemented")
 }
-#[rustc_autodiff(ReverseFirst, Duplicated, Const, Active,)]
+#[rustc_autodiff(Reverse, Duplicated, Const, Active,)]
 #[inline(never)]
 pub fn df3(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 {
     unsafe { asm!("NOP", options(pure, nomem)); };
diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff_reverse.rs
index 657201caa94..3c024272f40 100644
--- a/tests/pretty/autodiff_reverse.rs
+++ b/tests/pretty/autodiff_reverse.rs
@@ -18,7 +18,7 @@ pub fn f1(x: &[f64], y: f64) -> f64 {
 #[autodiff(df2, Reverse)]
 pub fn f2() {}
 
-#[autodiff(df3, ReverseFirst, Duplicated, Const, Active)]
+#[autodiff(df3, Reverse, Duplicated, Const, Active)]
 pub fn f3(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp
new file mode 100644
index 00000000000..4d1ab9d383b
--- /dev/null
+++ b/tests/pretty/hir-lifetimes.pp
@@ -0,0 +1,96 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-lifetimes.pp
+
+// This tests the pretty-printing of lifetimes in lots of ways.
+
+#![allow(unused)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+struct Foo<'a> {
+    x: &'a u32,
+}
+
+impl <'a> Foo<'a> {
+    fn f<'b>(x: &'b u32) { }
+}
+
+impl  Foo<'_> {
+    fn a(x: &'_ u32) { }
+
+    fn b(x: &'_ u32) { }
+
+    fn c(x: &'_ u32, y: &'static u32) { }
+
+    // FIXME: `'a` before `self` is omitted
+    fn d<'a>(&self, x: &'a u32) { }
+
+    // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh
+    fn iter1<'a>(&self)
+        -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
+
+    fn iter2(&self)
+        -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } }
+}
+
+fn a(x: Foo<'_>) { }
+
+fn b<'a>(x: Foo<'a>) { }
+
+struct Bar<'a, 'b, 'c, T> {
+    x: &'a u32,
+    y: &'b &'c u32,
+    z: T,
+}
+
+fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) { }
+
+fn f2(x: Bar<'_, '_, '_, u32>) { }
+
+trait MyTrait<'a, 'b> {
+    fn f(&self, x: Foo<'a>, y: Foo<'b>);
+}
+
+impl <'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> {
+    fn f(&self, x: Foo<'a>, y: Foo<'b>) { }
+}
+
+fn g(x: &'_ dyn for<'a, 'b> MyTrait<'a, 'b>) { }
+
+trait Blah { }
+
+type T<'a> = dyn Blah + 'a;
+
+type Q<'a> = dyn MyTrait<'a, 'a> + 'a;
+
+fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> { }
+
+// FIXME(?): attr printing is weird
+#[attr = Repr([ReprC])]
+struct S<'a>(&'a u32);
+
+extern "C" {
+    unsafe fn g1(s: S<'_>);
+    unsafe fn g2(s: S<'_>);
+    unsafe fn g3<'a>(s: S<'a>);
+}
+
+struct St<'a> {
+    x: &'a u32,
+}
+
+fn f() { { let _ = St { x: &0 }; }; { let _ = St { x: &0 }; }; }
+
+struct Name<'a>(&'a str);
+
+const A: Name<'_> = Name("a");
+const B: &'_ str = "";
+static C: &'_ str = "";
+static D: &'static str = "";
+
+fn tr(_: Box<dyn Blah>) { }
+
+fn main() { }
diff --git a/tests/pretty/hir-lifetimes.rs b/tests/pretty/hir-lifetimes.rs
new file mode 100644
index 00000000000..1379be34392
--- /dev/null
+++ b/tests/pretty/hir-lifetimes.rs
@@ -0,0 +1,91 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-lifetimes.pp
+
+// This tests the pretty-printing of lifetimes in lots of ways.
+
+#![allow(unused)]
+
+struct Foo<'a> {
+    x: &'a u32,
+}
+
+impl<'a> Foo<'a> {
+    fn f<'b>(x: &'b u32) {}
+}
+
+impl Foo<'_> {
+    fn a(x: &u32) {}
+
+    fn b(x: &'_ u32) {}
+
+    fn c(x: &'_ u32, y: &'static u32) {}
+
+    // FIXME: `'a` before `self` is omitted
+    fn d<'a>(&'a self, x: &'a u32) {}
+
+    // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh
+    fn iter1<'a>(&self) -> impl Iterator<Item = u32> + 'a { 0..1 }
+
+    fn iter2(&self) -> impl Iterator<Item = u32> + '_ { 0..1 }
+}
+
+fn a(x: Foo<'_>) {}
+
+fn b<'a>(x: Foo<'a>) {}
+
+struct Bar<'a, 'b, 'c, T> {
+    x: &'a u32,
+    y: &'b &'c u32,
+    z: T,
+}
+
+fn f1<'a, 'b, T>(x: Bar<'a, 'b, '_, T>) {}
+
+fn f2(x: Bar<'_, '_, '_, u32>) {}
+
+trait MyTrait<'a, 'b> {
+    fn f(&self, x: Foo<'a>, y: Foo<'b>);
+}
+
+impl<'a, 'b, 'c, T> MyTrait<'a, 'b> for Bar<'a, 'b, 'c, T> {
+    fn f(&self, x: Foo<'a>, y: Foo<'b>) {}
+}
+
+fn g(x: &dyn for<'a, 'b> MyTrait<'a, 'b>) {}
+
+trait Blah {}
+
+type T<'a> = dyn Blah + 'a;
+
+type Q<'a> = dyn MyTrait<'a, 'a> + 'a;
+
+fn h<'b, F>(f: F, y: Foo<'b>) where F: for<'d> MyTrait<'d, 'b> {}
+
+// FIXME(?): attr printing is weird
+#[repr(C)]
+struct S<'a>(&'a u32);
+
+extern "C" {
+    fn g1(s: S);
+    fn g2(s: S<'_>);
+    fn g3<'a>(s: S<'a>);
+}
+
+struct St<'a> { x: &'a u32 }
+
+fn f() {
+    _ = St { x: &0 };
+    _ = St::<'_> { x: &0 };
+}
+
+struct Name<'a>(&'a str);
+
+const A: Name = Name("a");
+const B: &str = "";
+static C: &'_ str = "";
+static D: &'static str = "";
+
+fn tr(_: Box<dyn Blah>) {}
+
+fn main() {}
diff --git a/tests/pretty/hir-struct-expr.pp b/tests/pretty/hir-struct-expr.pp
new file mode 100644
index 00000000000..f85d17542df
--- /dev/null
+++ b/tests/pretty/hir-struct-expr.pp
@@ -0,0 +1,28 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-struct-expr.pp
+
+struct StructWithSomeFields {
+    field_1: i32,
+    field_2: i32,
+    field_3: i32,
+    field_4: i32,
+    field_5: i32,
+    field_6: i32,
+}
+
+fn main() {
+    let a =
+        StructWithSomeFields {
+            field_1: 1,
+            field_2: 2,
+            field_3: 3,
+            field_4: 4,
+            field_5: 5,
+            field_6: 6 };
+    let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
+}
diff --git a/tests/pretty/hir-struct-expr.rs b/tests/pretty/hir-struct-expr.rs
new file mode 100644
index 00000000000..9580f5d557d
--- /dev/null
+++ b/tests/pretty/hir-struct-expr.rs
@@ -0,0 +1,24 @@
+//@ pretty-compare-only
+//@ pretty-mode:hir
+//@ pp-exact:hir-struct-expr.pp
+
+struct StructWithSomeFields {
+    field_1: i32,
+    field_2: i32,
+    field_3: i32,
+    field_4: i32,
+    field_5: i32,
+    field_6: i32,
+}
+
+fn main() {
+    let a = StructWithSomeFields {
+        field_1: 1,
+        field_2: 2,
+        field_3: 3,
+        field_4: 4,
+        field_5: 5,
+        field_6: 6,
+    };
+    let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
+}
diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs
index 01a503ce7ee..90d2b2f5e1e 100644
--- a/tests/pretty/stmt_expr_attributes.rs
+++ b/tests/pretty/stmt_expr_attributes.rs
@@ -1,6 +1,5 @@
 //@ pp-exact
 
-#![feature(inline_const_pat)]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 
@@ -206,9 +205,7 @@ fn _11() {
             let _ = ();
             ()
         };
-    let const {
-                    #![rustc_dummy]
-                } =
+    let _ =
         #[rustc_dummy] const {
                 #![rustc_dummy]
             };
diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp
index 31449b51dc3..d6a2c0ff979 100644
--- a/tests/pretty/tests-are-sorted.pp
+++ b/tests/pretty/tests-are-sorted.pp
@@ -10,7 +10,6 @@ extern crate std;
 //@ pp-exact:tests-are-sorted.pp
 
 extern crate test;
-#[cfg(test)]
 #[rustc_test_marker = "m_test"]
 #[doc(hidden)]
 pub const m_test: test::TestDescAndFn =
@@ -35,7 +34,6 @@ pub const m_test: test::TestDescAndFn =
 fn m_test() {}
 
 extern crate test;
-#[cfg(test)]
 #[rustc_test_marker = "z_test"]
 #[doc(hidden)]
 pub const z_test: test::TestDescAndFn =
@@ -61,7 +59,6 @@ pub const z_test: test::TestDescAndFn =
 fn z_test() {}
 
 extern crate test;
-#[cfg(test)]
 #[rustc_test_marker = "a_test"]
 #[doc(hidden)]
 pub const a_test: test::TestDescAndFn =
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index 024ce975cd6..ba887b3d791 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -3,10 +3,10 @@
 // Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current
 // `rustc` version and the `since` property in feature stability gating is properly respected.
 
-use run_make_support::{aux_build, rfs, rustc, source_root};
+use run_make_support::{rfs, rustc, source_root};
 
 fn main() {
-    aux_build().input("stable.rs").emit("metadata").run();
+    rustc().crate_type("lib").input("stable.rs").emit("metadata").run();
 
     let output =
         rustc().input("main.rs").emit("metadata").extern_("stable", "libstable.rmeta").run();
diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs
index 246539bcf82..a05223994df 100644
--- a/tests/run-make/doctests-keep-binaries/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries/rmake.rs
@@ -1,3 +1,5 @@
+//@ ignore-cross-compile attempts to run the doctests
+
 // Check that valid binaries are persisted by running them, regardless of whether the
 // --run or --no-run option is used.
 
diff --git a/tests/run-make/embed-metadata/dep1.rs b/tests/run-make/embed-metadata/dep1.rs
new file mode 100644
index 00000000000..be70c3933e0
--- /dev/null
+++ b/tests/run-make/embed-metadata/dep1.rs
@@ -0,0 +1 @@
+pub fn func_dep1() {}
diff --git a/tests/run-make/embed-metadata/foo.rs b/tests/run-make/embed-metadata/foo.rs
new file mode 100644
index 00000000000..0cc9cede860
--- /dev/null
+++ b/tests/run-make/embed-metadata/foo.rs
@@ -0,0 +1,5 @@
+extern crate dep1;
+
+fn main() {
+    dep1::func_dep1();
+}
diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs
new file mode 100644
index 00000000000..acefb186484
--- /dev/null
+++ b/tests/run-make/embed-metadata/rmake.rs
@@ -0,0 +1,86 @@
+// Tests the -Zembed-metadata compiler flag.
+// Tracking issue: https://github.com/rust-lang/rust/issues/139165
+
+use run_make_support::rfs::{create_dir, remove_file, rename};
+use run_make_support::{Rustc, dynamic_lib_name, path, run_in_tmpdir, rust_lib_name, rustc};
+
+#[derive(Debug, Copy, Clone)]
+enum LibraryKind {
+    Rlib,
+    Dylib,
+}
+
+impl LibraryKind {
+    fn crate_type(&self) -> &str {
+        match self {
+            LibraryKind::Rlib => "rlib",
+            LibraryKind::Dylib => "dylib",
+        }
+    }
+
+    fn add_extern(&self, rustc: &mut Rustc, dep_name: &str, dep_path: &str) {
+        let dep_path = match self {
+            LibraryKind::Dylib => format!("{dep_path}/{}", dynamic_lib_name(dep_name)),
+            LibraryKind::Rlib => format!("{dep_path}/{}", rust_lib_name(dep_name)),
+        };
+        rustc.extern_(dep_name, dep_path);
+    }
+}
+
+fn main() {
+    // The compiler takes different paths based on if --extern is passed or not, so we test all
+    // combinations (`rlib`/`dylib` x `--extern`/`no --extern`).
+    for kind in [LibraryKind::Rlib, LibraryKind::Dylib] {
+        eprintln!("Testing library kind {kind:?}");
+        lookup_rmeta_in_lib_dir(kind);
+        lookup_rmeta_through_extern(kind);
+        lookup_rmeta_missing(kind);
+    }
+}
+
+// Lookup .rmeta file in the same directory as a rlib/dylib with stub metadata.
+fn lookup_rmeta_in_lib_dir(kind: LibraryKind) {
+    run_in_tmpdir(|| {
+        build_dep_rustc(kind).run();
+        rustc().input("foo.rs").run();
+    });
+}
+
+// Lookup .rmeta file when specifying the dependency using --extern.
+fn lookup_rmeta_through_extern(kind: LibraryKind) {
+    run_in_tmpdir(|| {
+        // Generate libdep1.rlib and libdep1.rmeta in deps
+        create_dir("deps");
+        build_dep_rustc(kind).out_dir("deps").run();
+
+        let mut rustc = rustc();
+        kind.add_extern(&mut rustc, "dep1", "deps");
+        rustc.extern_("dep1", path("deps").join("libdep1.rmeta"));
+        rustc.input("foo.rs").run();
+    });
+}
+
+// Check the error message when the .rmeta file is missing.
+fn lookup_rmeta_missing(kind: LibraryKind) {
+    run_in_tmpdir(|| {
+        create_dir("deps");
+        build_dep_rustc(kind).out_dir("deps").run();
+
+        let mut rustc = rustc();
+        kind.add_extern(&mut rustc, "dep1", "deps");
+        rustc.input("foo.rs").run_fail().assert_stderr_contains("only metadata stub found");
+    });
+}
+
+fn build_dep_rustc(kind: LibraryKind) -> Rustc {
+    let mut dep_rustc = rustc();
+    dep_rustc
+        .arg("-Zembed-metadata=no")
+        .crate_type(kind.crate_type())
+        .input("dep1.rs")
+        .emit("metadata,link");
+    if matches!(kind, LibraryKind::Dylib) {
+        dep_rustc.arg("-Cprefer-dynamic");
+    }
+    dep_rustc
+}
diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs
index 228cfb0864e..87d4faaa77a 100644
--- a/tests/run-make/issue-107495-archive-permissions/rmake.rs
+++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs
@@ -4,7 +4,7 @@ use std::path::Path;
 
 #[cfg(unix)]
 use run_make_support::libc;
-use run_make_support::{aux_build, rfs};
+use run_make_support::{rfs, rustc};
 
 fn main() {
     #[cfg(unix)]
@@ -12,7 +12,7 @@ fn main() {
         libc::umask(0o002);
     }
 
-    aux_build().arg("foo.rs").run();
+    rustc().crate_type("lib").arg("foo.rs").run();
     verify(Path::new("libfoo.rlib"));
 }
 
diff --git a/tests/run-make/print-crate-root-lint-levels/lib.rs b/tests/run-make/print-crate-root-lint-levels/lib.rs
new file mode 100644
index 00000000000..dc846f8fd95
--- /dev/null
+++ b/tests/run-make/print-crate-root-lint-levels/lib.rs
@@ -0,0 +1,5 @@
+#![allow(unexpected_cfgs)]
+#![expect(unused_mut)]
+
+#[deny(unknown_lints)]
+mod my_mod {}
diff --git a/tests/run-make/print-crate-root-lint-levels/rmake.rs b/tests/run-make/print-crate-root-lint-levels/rmake.rs
new file mode 100644
index 00000000000..e373c91102d
--- /dev/null
+++ b/tests/run-make/print-crate-root-lint-levels/rmake.rs
@@ -0,0 +1,118 @@
+//! This checks the output of `--print=crate-root-lint-levels`
+
+extern crate run_make_support;
+
+use std::collections::HashSet;
+use std::iter::FromIterator;
+
+use run_make_support::rustc;
+
+struct CrateRootLintLevels {
+    args: &'static [&'static str],
+    contains: Contains,
+}
+
+struct Contains {
+    contains: &'static [&'static str],
+    doesnt_contain: &'static [&'static str],
+}
+
+fn main() {
+    check(CrateRootLintLevels {
+        args: &[],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "unused_mut=expect",
+                "warnings=warn",
+                "stable_features=warn",
+                "unknown_lints=warn",
+            ],
+            doesnt_contain: &["unexpected_cfgs=warn", "unused_mut=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Wunexpected_cfgs"],
+        contains: Contains {
+            contains: &["unexpected_cfgs=allow", "warnings=warn"],
+            doesnt_contain: &["unexpected_cfgs=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings"],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "warnings=deny",
+                "stable_features=deny",
+                "unknown_lints=deny",
+            ],
+            doesnt_contain: &["warnings=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dstable_features"],
+        contains: Contains {
+            contains: &["warnings=warn", "stable_features=deny", "unexpected_cfgs=allow"],
+            doesnt_contain: &["warnings=deny"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings", "--force-warn=stable_features"],
+        contains: Contains {
+            contains: &["warnings=deny", "stable_features=force-warn", "unknown_lints=deny"],
+            doesnt_contain: &["warnings=warn"],
+        },
+    });
+    check(CrateRootLintLevels {
+        args: &["-Dwarnings", "--cap-lints=warn"],
+        contains: Contains {
+            contains: &[
+                "unexpected_cfgs=allow",
+                "warnings=warn",
+                "stable_features=warn",
+                "unknown_lints=warn",
+            ],
+            doesnt_contain: &["warnings=deny"],
+        },
+    });
+}
+
+#[track_caller]
+fn check(CrateRootLintLevels { args, contains }: CrateRootLintLevels) {
+    let output = rustc()
+        .input("lib.rs")
+        .arg("-Zunstable-options")
+        .print("crate-root-lint-levels")
+        .args(args)
+        .run();
+
+    let stdout = output.stdout_utf8();
+
+    let mut found = HashSet::<String>::new();
+
+    for l in stdout.lines() {
+        assert!(l == l.trim());
+        if let Some((left, right)) = l.split_once('=') {
+            assert!(!left.contains("\""));
+            assert!(!right.contains("\""));
+        } else {
+            assert!(l.contains('='));
+        }
+        assert!(found.insert(l.to_string()), "{}", &l);
+    }
+
+    let Contains { contains, doesnt_contain } = contains;
+
+    {
+        let should_found = HashSet::<String>::from_iter(contains.iter().map(|s| s.to_string()));
+        let diff: Vec<_> = should_found.difference(&found).collect();
+        assert!(diff.is_empty(), "should found: {:?}, didn't found {:?}", &should_found, &diff);
+    }
+    {
+        let should_not_find =
+            HashSet::<String>::from_iter(doesnt_contain.iter().map(|s| s.to_string()));
+        let diff: Vec<_> = should_not_find.intersection(&found).collect();
+        assert!(diff.is_empty(), "should not find {:?}, did found {:?}", &should_not_find, &diff);
+    }
+}
diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout
index c8ea09ee2c8..f19ca1e9f90 100644
--- a/tests/run-make/rustc-help/help-v.stdout
+++ b/tests/run-make/rustc-help/help-v.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout
index 434e71e901e..f7d35296603 100644
--- a/tests/run-make/rustc-help/help.stdout
+++ b/tests/run-make/rustc-help/help.stdout
@@ -29,7 +29,7 @@ Options:
         --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
                         Comma separated list of types of output for the
                         compiler to emit
-        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+        --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                         Compiler information to print on stdout
     -g                  Equivalent to -C debuginfo=2
     -O                  Equivalent to -C opt-level=3
diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs
index ea5ec2faed9..0d8c500ed1e 100644
--- a/tests/run-make/rustdoc-error-lines/rmake.rs
+++ b/tests/run-make/rustdoc-error-lines/rmake.rs
@@ -8,11 +8,11 @@ fn main() {
 
     let should_contain = &[
         "input.rs - foo (line 5)",
-        "input.rs:7:15",
+        "input.rs:8:15",
         "input.rs - bar (line 13)",
-        "input.rs:15:15",
+        "input.rs:16:15",
         "input.rs - bar (line 22)",
-        "input.rs:24:15",
+        "input.rs:25:15",
     ];
     for text in should_contain {
         assert!(output.contains(text), "output doesn't contains {:?}", text);
diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs
index 81f2678e55c..1fb03c62399 100644
--- a/tests/run-make/symbols-all-mangled/rmake.rs
+++ b/tests/run-make/symbols-all-mangled/rmake.rs
@@ -41,7 +41,13 @@ fn symbols_check_archive(path: &str) {
             continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
         }
 
-        panic!("Unmangled symbol found: {name}");
+        if name.contains(".llvm.") {
+            // Starting in LLVM 21 we get various implementation-detail functions which
+            // contain .llvm. that are not a problem.
+            continue;
+        }
+
+        panic!("Unmangled symbol found in {path}: {name}");
     }
 }
 
@@ -75,7 +81,13 @@ fn symbols_check(path: &str) {
             continue; // Unfortunately LLVM doesn't allow us to mangle this symbol
         }
 
-        panic!("Unmangled symbol found: {name}");
+        if name.contains(".llvm.") {
+            // Starting in LLVM 21 we get various implementation-detail functions which
+            // contain .llvm. that are not a problem.
+            continue;
+        }
+
+        panic!("Unmangled symbol found in {path}: {name}");
     }
 }
 
diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs
index fd5fb6193fe..7b7974f3097 100644
--- a/tests/run-make/target-cpu-native/rmake.rs
+++ b/tests/run-make/target-cpu-native/rmake.rs
@@ -3,6 +3,8 @@
 // warnings when used, and that binaries produced by it can also be successfully executed.
 // See https://github.com/rust-lang/rust/pull/23238
 
+//@ ignore-cross-compile target-cpu=native doesn't work well when cross compiling
+
 use run_make_support::{run, rustc};
 
 fn main() {
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index f315f37966d..f47a522e81a 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.type" 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.type" 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.value" 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.value" 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.type.primitive" \"usize\"
+    //@ has "$.index[?(@.docs=='ToDeclare impl')].inner.assoc_type"
+    //@ is "$.index[?(@.docs=='ToDeclare impl')].inner.assoc_type.type.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.value" \"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.value" \"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 43b4d387d92..816075ca17a 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/attrs/automatically_derived.rs b/tests/rustdoc-json/attrs/automatically_derived.rs
new file mode 100644
index 00000000000..4e1ab3d145e
--- /dev/null
+++ b/tests/rustdoc-json/attrs/automatically_derived.rs
@@ -0,0 +1,13 @@
+#[derive(Default)]
+pub struct Derive;
+
+pub struct Manual;
+
+impl Default for Manual {
+    fn default() -> Self {
+        Self
+    }
+}
+
+//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]'
+//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]'
diff --git a/tests/rustdoc-json/attrs/deprecated.rs b/tests/rustdoc-json/attrs/deprecated.rs
index 5cde7af841f..0799471fc88 100644
--- a/tests/rustdoc-json/attrs/deprecated.rs
+++ b/tests/rustdoc-json/attrs/deprecated.rs
@@ -1,38 +1,38 @@
-//@ is "$.index[*][?(@.name=='not')].attrs" []
-//@ is "$.index[*][?(@.name=='not')].deprecation" null
+//@ is "$.index[?(@.name=='not')].attrs" []
+//@ is "$.index[?(@.name=='not')].deprecation" null
 pub fn not() {}
 
-//@ is "$.index[*][?(@.name=='raw')].attrs" []
-//@ is "$.index[*][?(@.name=='raw')].deprecation" '{"since": null, "note": null}'
+//@ is "$.index[?(@.name=='raw')].attrs" []
+//@ is "$.index[?(@.name=='raw')].deprecation" '{"since": null, "note": null}'
 #[deprecated]
 pub fn raw() {}
 
-//@ is "$.index[*][?(@.name=='equals_string')].attrs" []
-//@ is "$.index[*][?(@.name=='equals_string')].deprecation" '{"since": null, "note": "here is a reason"}'
+//@ is "$.index[?(@.name=='equals_string')].attrs" []
+//@ is "$.index[?(@.name=='equals_string')].deprecation" '{"since": null, "note": "here is a reason"}'
 #[deprecated = "here is a reason"]
 pub fn equals_string() {}
 
-//@ is "$.index[*][?(@.name=='since')].attrs" []
-//@ is "$.index[*][?(@.name=='since')].deprecation" '{"since": "yoinks ago", "note": null}'
+//@ is "$.index[?(@.name=='since')].attrs" []
+//@ is "$.index[?(@.name=='since')].deprecation" '{"since": "yoinks ago", "note": null}'
 #[deprecated(since = "yoinks ago")]
 pub fn since() {}
 
-//@ is "$.index[*][?(@.name=='note')].attrs" []
-//@ is "$.index[*][?(@.name=='note')].deprecation" '{"since": null, "note": "7"}'
+//@ is "$.index[?(@.name=='note')].attrs" []
+//@ is "$.index[?(@.name=='note')].deprecation" '{"since": null, "note": "7"}'
 #[deprecated(note = "7")]
 pub fn note() {}
 
-//@ is "$.index[*][?(@.name=='since_and_note')].attrs" []
-//@ is "$.index[*][?(@.name=='since_and_note')].deprecation" '{"since": "tomorrow", "note": "sorry"}'
+//@ is "$.index[?(@.name=='since_and_note')].attrs" []
+//@ is "$.index[?(@.name=='since_and_note')].deprecation" '{"since": "tomorrow", "note": "sorry"}'
 #[deprecated(since = "tomorrow", note = "sorry")]
 pub fn since_and_note() {}
 
-//@ is "$.index[*][?(@.name=='note_and_since')].attrs" []
-//@ is "$.index[*][?(@.name=='note_and_since')].deprecation" '{"since": "a year from tomorrow", "note": "your welcome"}'
+//@ is "$.index[?(@.name=='note_and_since')].attrs" []
+//@ is "$.index[?(@.name=='note_and_since')].deprecation" '{"since": "a year from tomorrow", "note": "your welcome"}'
 #[deprecated(note = "your welcome", since = "a year from tomorrow")]
 pub fn note_and_since() {}
 
-//@ is "$.index[*][?(@.name=='neither_but_parens')].attrs" []
-//@ is "$.index[*][?(@.name=='neither_but_parens')].deprecation" '{"since": null, "note": null}'
+//@ is "$.index[?(@.name=='neither_but_parens')].attrs" []
+//@ is "$.index[?(@.name=='neither_but_parens')].deprecation" '{"since": null, "note": null}'
 #[deprecated()]
 pub fn neither_but_parens() {}
diff --git a/tests/rustdoc-json/attrs/export_name_2021.rs b/tests/rustdoc-json/attrs/export_name_2021.rs
index badf124bdde..254e9f6ef5b 100644
--- a/tests/rustdoc-json/attrs/export_name_2021.rs
+++ b/tests/rustdoc-json/attrs/export_name_2021.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
+//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
 #[export_name = "altered"]
 pub extern "C" fn example() {}
diff --git a/tests/rustdoc-json/attrs/export_name_2024.rs b/tests/rustdoc-json/attrs/export_name_2024.rs
index c5bb9dcc8f6..8129c109306 100644
--- a/tests/rustdoc-json/attrs/export_name_2024.rs
+++ b/tests/rustdoc-json/attrs/export_name_2024.rs
@@ -4,6 +4,6 @@
 // The representation of `#[unsafe(export_name = ..)]` in rustdoc in edition 2024
 // is still `#[export_name = ..]` without the `unsafe` attribute wrapper.
 
-//@ is "$.index[*][?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
+//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]'
 #[unsafe(export_name = "altered")]
 pub extern "C" fn example() {}
diff --git a/tests/rustdoc-json/attrs/must_use.rs b/tests/rustdoc-json/attrs/must_use.rs
index dca73abc76a..64df8e5f509 100644
--- a/tests/rustdoc-json/attrs/must_use.rs
+++ b/tests/rustdoc-json/attrs/must_use.rs
@@ -1,9 +1,9 @@
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='example')].attrs" '["#[must_use]"]'
+//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]"]'
 #[must_use]
 pub fn example() -> impl Iterator<Item = i64> {}
 
-//@ is "$.index[*][?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]'
+//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]'
 #[must_use = "does nothing if you do not use it"]
 pub fn explicit_message() -> impl Iterator<Item = i64> {}
diff --git a/tests/rustdoc-json/attrs/no_mangle_2021.rs b/tests/rustdoc-json/attrs/no_mangle_2021.rs
index 258542086ec..588be7256db 100644
--- a/tests/rustdoc-json/attrs/no_mangle_2021.rs
+++ b/tests/rustdoc-json/attrs/no_mangle_2021.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='example')].attrs" '["#[no_mangle]"]'
+//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]'
 #[no_mangle]
 pub extern "C" fn example() {}
diff --git a/tests/rustdoc-json/attrs/no_mangle_2024.rs b/tests/rustdoc-json/attrs/no_mangle_2024.rs
index 4c01082d045..0d500e20e6c 100644
--- a/tests/rustdoc-json/attrs/no_mangle_2024.rs
+++ b/tests/rustdoc-json/attrs/no_mangle_2024.rs
@@ -4,6 +4,6 @@
 // The representation of `#[unsafe(no_mangle)]` in rustdoc in edition 2024
 // is still `#[no_mangle]` without the `unsafe` attribute wrapper.
 
-//@ is "$.index[*][?(@.name=='example')].attrs" '["#[no_mangle]"]'
+//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]'
 #[unsafe(no_mangle)]
 pub extern "C" fn example() {}
diff --git a/tests/rustdoc-json/attrs/non_exhaustive.rs b/tests/rustdoc-json/attrs/non_exhaustive.rs
index 5d738fc0560..b95f1a8171f 100644
--- a/tests/rustdoc-json/attrs/non_exhaustive.rs
+++ b/tests/rustdoc-json/attrs/non_exhaustive.rs
@@ -1,18 +1,18 @@
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]'
+//@ is "$.index[?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]'
 #[non_exhaustive]
 pub enum MyEnum {
     First,
 }
 
 pub enum NonExhaustiveVariant {
-    //@ is "$.index[*][?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]'
+    //@ is "$.index[?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]'
     #[non_exhaustive]
     Variant(i64),
 }
 
-//@ is "$.index[*][?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]'
+//@ is "$.index[?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]'
 #[non_exhaustive]
 pub struct MyStruct {
     pub x: i64,
diff --git a/tests/rustdoc-json/attrs/repr_align.rs b/tests/rustdoc-json/attrs/repr_align.rs
index bebbe1fea34..c6debda7f1c 100644
--- a/tests/rustdoc-json/attrs/repr_align.rs
+++ b/tests/rustdoc-json/attrs/repr_align.rs
@@ -1,6 +1,6 @@
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='Aligned')].attrs" '["#[attr = Repr([ReprAlign(Align(4 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='Aligned')].attrs" '["#[repr(align(4))]"]'
 #[repr(align(4))]
 pub struct Aligned {
     a: i8,
diff --git a/tests/rustdoc-json/attrs/repr_c.rs b/tests/rustdoc-json/attrs/repr_c.rs
index 609d33d94de..e6219413f30 100644
--- a/tests/rustdoc-json/attrs/repr_c.rs
+++ b/tests/rustdoc-json/attrs/repr_c.rs
@@ -1,16 +1,16 @@
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='ReprCStruct')].attrs" '["#[attr = Repr([ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '["#[repr(C)]"]'
 #[repr(C)]
 pub struct ReprCStruct(pub i64);
 
-//@ is "$.index[*][?(@.name=='ReprCEnum')].attrs" '["#[attr = Repr([ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '["#[repr(C)]"]'
 #[repr(C)]
 pub enum ReprCEnum {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='ReprCUnion')].attrs" '["#[attr = Repr([ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '["#[repr(C)]"]'
 #[repr(C)]
 pub union ReprCUnion {
     pub left: i64,
diff --git a/tests/rustdoc-json/attrs/repr_combination.rs b/tests/rustdoc-json/attrs/repr_combination.rs
index 662bfef67cb..0e8e2ef0d83 100644
--- a/tests/rustdoc-json/attrs/repr_combination.rs
+++ b/tests/rustdoc-json/attrs/repr_combination.rs
@@ -1,34 +1,35 @@
 #![no_std]
 
 // Combinations of `#[repr(..)]` attributes.
+// Rustdoc JSON emits normalized output, regardless of the original source.
 
-//@ is "$.index[*][?(@.name=='ReprCI8')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I8))])]\n"]'
+//@ is "$.index[?(@.name=='ReprCI8')].attrs" '["#[repr(C, i8)]"]'
 #[repr(C, i8)]
 pub enum ReprCI8 {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='SeparateReprCI16')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I16))])]\n"]'
+//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '["#[repr(C, i16)]"]'
 #[repr(C)]
 #[repr(i16)]
 pub enum SeparateReprCI16 {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='ReversedReprCUsize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize)), ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '["#[repr(C, usize)]"]'
 #[repr(usize, C)]
 pub enum ReversedReprCUsize {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='ReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(1 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '["#[repr(C, packed(1))]"]'
 #[repr(C, packed)]
 pub struct ReprCPacked {
     a: i8,
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='SeparateReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(2 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '["#[repr(C, packed(2))]"]'
 #[repr(C)]
 #[repr(packed(2))]
 pub struct SeparateReprCPacked {
@@ -36,21 +37,21 @@ pub struct SeparateReprCPacked {
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='ReversedReprCPacked')].attrs" '["#[attr = Repr([ReprPacked(Align(2 bytes)), ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '["#[repr(C, packed(2))]"]'
 #[repr(packed(2), C)]
 pub struct ReversedReprCPacked {
     a: i8,
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='ReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '["#[repr(C, align(16))]"]'
 #[repr(C, align(16))]
 pub struct ReprCAlign {
     a: i8,
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='SeparateReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(2 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '["#[repr(C, align(2))]"]'
 #[repr(C)]
 #[repr(align(2))]
 pub struct SeparateReprCAlign {
@@ -58,20 +59,20 @@ pub struct SeparateReprCAlign {
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='ReversedReprCAlign')].attrs" '["#[attr = Repr([ReprAlign(Align(2 bytes)), ReprC])]\n"]'
+//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '["#[repr(C, align(2))]"]'
 #[repr(align(2), C)]
 pub struct ReversedReprCAlign {
     a: i8,
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='AlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes)), ReprInt(SignedInt(Isize))])]\n"]'
+//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]'
 #[repr(C, align(16), isize)]
 pub enum AlignedExplicitRepr {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprInt(SignedInt(Isize)), ReprC, ReprAlign(Align(16 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]'
 #[repr(isize, C, align(16))]
 pub enum ReorderedAlignedExplicitRepr {
     First,
diff --git a/tests/rustdoc-json/attrs/repr_int_enum.rs b/tests/rustdoc-json/attrs/repr_int_enum.rs
index 2ad57de2798..9b09f341d4f 100644
--- a/tests/rustdoc-json/attrs/repr_int_enum.rs
+++ b/tests/rustdoc-json/attrs/repr_int_enum.rs
@@ -1,18 +1,18 @@
 #![no_std]
 
-//@ is "$.index[*][?(@.name=='I8')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I8))])]\n"]'
+//@ is "$.index[?(@.name=='I8')].attrs" '["#[repr(i8)]"]'
 #[repr(i8)]
 pub enum I8 {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='I32')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]'
+//@ is "$.index[?(@.name=='I32')].attrs" '["#[repr(i32)]"]'
 #[repr(i32)]
 pub enum I32 {
     First,
 }
 
-//@ is "$.index[*][?(@.name=='Usize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize))])]\n"]'
+//@ is "$.index[?(@.name=='Usize')].attrs" '["#[repr(usize)]"]'
 #[repr(usize)]
 pub enum Usize {
     First,
diff --git a/tests/rustdoc-json/attrs/repr_packed.rs b/tests/rustdoc-json/attrs/repr_packed.rs
index 33acc23b7c8..9f3fd86c4b0 100644
--- a/tests/rustdoc-json/attrs/repr_packed.rs
+++ b/tests/rustdoc-json/attrs/repr_packed.rs
@@ -1,16 +1,16 @@
 #![no_std]
 
 // Note the normalization:
-// `#[repr(packed)]` in has the implict "1" in rustdoc JSON.
-
-//@ is "$.index[*][?(@.name=='Packed')].attrs" '["#[attr = Repr([ReprPacked(Align(1 bytes))])]\n"]'
+// `#[repr(packed)]` in source becomes `#[repr(packed(1))]` in rustdoc JSON.
+//
+//@ is "$.index[?(@.name=='Packed')].attrs" '["#[repr(packed(1))]"]'
 #[repr(packed)]
 pub struct Packed {
     a: i8,
     b: i64,
 }
 
-//@ is "$.index[*][?(@.name=='PackedAligned')].attrs" '["#[attr = Repr([ReprPacked(Align(4 bytes))])]\n"]'
+//@ is "$.index[?(@.name=='PackedAligned')].attrs" '["#[repr(packed(4))]"]'
 #[repr(packed(4))]
 pub struct PackedAligned {
     a: i8,
diff --git a/tests/rustdoc-json/attrs/repr_transparent.rs b/tests/rustdoc-json/attrs/repr_transparent.rs
index ef6e69f8703..1e634ca901d 100644
--- a/tests/rustdoc-json/attrs/repr_transparent.rs
+++ b/tests/rustdoc-json/attrs/repr_transparent.rs
@@ -1,22 +1,37 @@
 #![no_std]
 
-// Rustdoc JSON currently includes `#[repr(transparent)]`
-// even if the transparency is not part of the public API
+// Rustdoc JSON *only* includes `#[repr(transparent)]`
+// if the transparency is public API:
+// - if a non-1-ZST field exists, it has to be public
+// - otherwise, all fields are 1-ZST and at least one of them is public
 //
-// https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
+// More info: https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
 
-//@ is "$.index[*][?(@.name=='Transparent')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]'
+// Here, the non-1-ZST field is public.
+// We expect `#[repr(transparent)]` in the attributes.
+//
+//@ is "$.index[?(@.name=='Transparent')].attrs" '["#[repr(transparent)]"]'
 #[repr(transparent)]
 pub struct Transparent(pub i64);
 
-//@ is "$.index[*][?(@.name=='TransparentNonPub')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]'
+// Here the non-1-ZST field isn't public, so the attribute isn't included.
+//
+//@ has "$.index[?(@.name=='TransparentNonPub')]"
+//@ is "$.index[?(@.name=='TransparentNonPub')].attrs" '[]'
 #[repr(transparent)]
 pub struct TransparentNonPub(i64);
 
-//@ is "$.index[*][?(@.name=='AllZst')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]'
+// Only 1-ZST fields here, and one of them is public.
+// We expect `#[repr(transparent)]` in the attributes.
+//
+//@ is "$.index[?(@.name=='AllZst')].attrs" '["#[repr(transparent)]"]'
 #[repr(transparent)]
 pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ());
 
-//@ is "$.index[*][?(@.name=='AllZstNotPublic')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]'
+// Only 1-ZST fields here but none of them are public.
+// The attribute isn't included.
+//
+//@ has "$.index[?(@.name=='AllZstNotPublic')]"
+//@ is "$.index[?(@.name=='AllZstNotPublic')].attrs" '[]'
 #[repr(transparent)]
 pub struct AllZstNotPublic<'a>(core::marker::PhantomData<&'a ()>, ());
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index bf0983e66a1..d500bf5af6b 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.type.resolved_path"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\"
+//@ has "$.index[?(@.name=='Error')].inner.assoc_type"
+//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path"
+//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs
index 249e35b7243..e68df7e9c61 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 06a240404fb..c7f164f3408 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 bf2bce85108..3743b13fec8 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 7508490d666..c84181334e3 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -3,40 +3,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 6f66495bed2..acf58048d3a 100644
--- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
+++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
@@ -1,15 +1,15 @@
 #[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 8e7985f07f4..d8b92cfabb3 100644
--- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
+++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
@@ -1,10 +1,10 @@
 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 f2bed77902b..ea669e6a0b3 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -1,13 +1,13 @@
 #[repr(i32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]'
+//@ 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 201c1cdc88e..1b8e791eb23 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -1,13 +1,13 @@
 #[repr(u32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(U32))])]\n"]'
+//@ 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 6aec6960b5f..6ecd98fadf5 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 b353678ac92..07ee0e62ea9 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 a78be200b41..e8560687954 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 517a53828b7..3c011858630 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -1,27 +1,27 @@
 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": [], "has_stripped_fields": false}'
+    //@ set Named = "$.index[?(@.name=='Named')].id"
+    //@ is "$.index[?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": 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.has_stripped_fields" 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.has_stripped_fields" 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 2184f58b1da..cd9d2ce0b8a 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.has_stripped_fields" 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.has_stripped_fields" 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 3ac7a3ce0fc..aa25625b94c 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 2631b43da8e..18f21ff0903 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.use)].id"
-//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color
-//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true
+//@ set use_Color = "$.index[?(@.inner.use)].id"
+//@ is "$.index[?(@.inner.use)].inner.use.id" $Color
+//@ is "$.index[?(@.inner.use)].inner.use.is_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 6d3322e0ba9..26cca0743d9 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.use)].id"
-//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None
+//@ set use_None = "$.index[?(@.inner.use)].id"
+//@ is "$.index[?(@.inner.use)].inner.use.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 a9ad61b9fe3..14e07b4123e 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.use[?(@.name == 'Red')]"
+//@ has "$.index[?(@.inner.use.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 6ebe28c94ca..dd11c0963ee 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 44a0c946711..730689c8afa 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 04f0cbb40c4..0fc06920e4b 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 13a967bd35e..34150c0fe89 100644
--- a/tests/rustdoc-json/fn_pointer/abi.rs
+++ b/tests/rustdoc-json/fn_pointer/abi.rs
@@ -1,22 +1,22 @@
 #![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 c974b472297..960b91e7d8e 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -1,8 +1,8 @@
-//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"'
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.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.sig.inputs[*]" 1
+//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"'
+//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.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 398e31f72db..769749d0dd4 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,9 +1,9 @@
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false
+//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false
+//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false
 pub type FnPointer = fn();
 
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false
+//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true
+//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false
 pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs
index 68957f79952..7277bb1f59a 100644
--- a/tests/rustdoc-json/fns/abi.rs
+++ b/tests/rustdoc-json/fns/abi.rs
@@ -1,22 +1,22 @@
 #![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 ddfd4ccf90d..e7c6a2981ac 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -4,30 +4,30 @@
 
 use std::future::Future;
 
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false
+//@ is "$.index[?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[?(@.name=='get_int')].inner.function.header.is_async" false
 pub fn get_int() -> i32 {
     42
 }
 
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true
+//@ is "$.index[?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[?(@.name=='get_int_async')].inner.function.header.is_async" true
 pub async fn get_int_async() -> i32 {
     42
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive"  \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false
+//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
+//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive"  \"i32\"
+//@ is "$.index[?(@.name=='get_int_future')].inner.function.header.is_async" false
 pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true
+//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
+//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
+//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.header.is_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 8e9085640e0..d90bb83d98f 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.sig.is_c_variadic" false
+    //@ is "$.index[?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false
     pub fn not_variadic(_: i32);
-    //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true
+    //@ is "$.index[?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true
     pub fn variadic(_: i32, ...);
 }
diff --git a/tests/rustdoc-json/fns/extern_safe.rs b/tests/rustdoc-json/fns/extern_safe.rs
index b00f9f50bd2..bc217ae914c 100644
--- a/tests/rustdoc-json/fns/extern_safe.rs
+++ b/tests/rustdoc-json/fns/extern_safe.rs
@@ -1,17 +1,17 @@
 extern "C" {
-    //@ is "$.index[*][?(@.name=='f1')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='f1')].inner.function.header.is_unsafe" true
     pub fn f1();
 
     // items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers
 }
 
 unsafe extern "C" {
-    //@ is "$.index[*][?(@.name=='f4')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='f4')].inner.function.header.is_unsafe" true
     pub fn f4();
 
-    //@ is "$.index[*][?(@.name=='f5')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='f5')].inner.function.header.is_unsafe" true
     pub unsafe fn f5();
 
-    //@ is "$.index[*][?(@.name=='f6')].inner.function.header.is_unsafe" false
+    //@ is "$.index[?(@.name=='f6')].inner.function.header.is_unsafe" false
     pub safe fn f6();
 }
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index 6a7124976f8..2ea68173d68 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -1,58 +1,58 @@
-//@ 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.sig.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.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.sig.inputs[*]" 1
+//@ is "$.index[?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[?(@.name=='generics')].inner.function.sig.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.sig.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"'
-//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.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.sig.inputs[*]" 1
+//@ is "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"'
+//@ count "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1
+//@ is "$.index[?(@.name=='impl_trait')].inner.function.sig.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, "is_synthetic": false}}'
-//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.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, "is_synthetic": false}}'
+//@ count "$.index[?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3
+//@ is "$.index[?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[?(@.name=='where_clase')].inner.function.sig.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 90e17525c44..a0d4c745599 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -1,11 +1,11 @@
-//@ 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.sig.inputs" []
-//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo
+//@ is "$.index[?(@.name=='get_foo')].inner.function.sig.inputs" []
+//@ count "$.index[?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1
+//@ is "$.index[?(@.name=='get_foo')].inner.function.sig.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 b953094b5de..3efd917309a 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -1,20 +1,20 @@
-//@ 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.is_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.sig.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.is_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.sig.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.is_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.sig.inputs[*]" 1
-//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"'
-//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.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.is_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.sig.inputs[*]" 1
+//@ is    "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"'
+//@ is    "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.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 d2a00f47438..059318a4295 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.sig.inputs[0][0]" '"(x, _)"'
+//@ is "$.index[?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"'
 pub fn fst<X, Y>((x, _): (X, Y)) -> X {
     x
 }
 
-//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is "$.index[?(@.name=='drop_int')].inner.function.sig.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 67e49f0780a..7d93a3bf243 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.is_async" false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const"  false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false
+//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_async" false
+//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_const"  false
+//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false
 pub fn nothing_fn() {}
 
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async"  false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const"  false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true
+//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_async"  false
+//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_const"  false
+//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true
 pub unsafe fn unsafe_fn() {}
 
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async"  false
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const"  true
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false
+//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_async"  false
+//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_const"  true
+//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_unsafe" false
 pub const fn const_fn() {}
 
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async"  true
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const"  false
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false
+//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_async"  true
+//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_const"  false
+//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_unsafe" false
 pub async fn async_fn() {}
 
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async"  true
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const"  false
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true
+//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_async"  true
+//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_const"  false
+//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true
 pub async unsafe fn async_unsafe_fn() {}
 
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async"  false
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const"  true
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true
+//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_async"  false
+//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_const"  true
+//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_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 d60c4b68258..0aa1db47b7f 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.sig.output.resolved_path.id" $foo
+//@ is "$.index[?(@.name=='demo')].inner.function.sig.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 d1172b35fda..5218cc886e3 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -1,32 +1,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.sig.output.qualified_path.args.angle_bracketed.args[*]" 1
-    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
-    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\"
+    //@ count "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1
+    //@ count "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[?(@.name=='lending_next')].inner.function.sig.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.sig.output.qualified_path.args.angle_bracketed.args[*]" 0
-    //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
-    //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\"
+    //@ count "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0
+    //@ count "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[?(@.name=='next')].inner.function.sig.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 e7a5d2a78c1..90bda1644ff 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 b63e5dadd9e..6887f9ff63d 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.use)].inner.use.name" \"*\"
+//@ has "$.index[?(@.name=='glob')]"
+//@ has "$.index[?(@.inner.use)].inner.use.name" \"*\"
 
 mod m1 {
     pub fn f() {}
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
index fc12fc87e8d..742a46e8967 100644
--- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -4,25 +4,25 @@ pub struct AlwaysTrue;
 
 /// impl IntoIterator
 impl IntoIterator for AlwaysTrue {
-    //@ set Item = '$.index[*][?(@.docs=="type Item")].id'
+    //@ set Item = '$.index[?(@.docs=="type Item")].id'
     /// type Item
     type Item = bool;
 
-    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"'
-    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'
+    //@ count '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
+    //@ is    '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"'
+    //@ count '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
+    //@ is    '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
+    //@ is    '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'
 
-    //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id'
+    //@ set IntoIter = '$.index[?(@.docs=="type IntoIter")].id'
     /// type IntoIter
     type IntoIter = impl Iterator<Item = bool>;
 
-    //@ set into_iter = '$.index[*][?(@.docs=="fn into_iter")].id'
+    //@ set into_iter = '$.index[?(@.docs=="fn into_iter")].id'
     /// fn into_iter
     fn into_iter(self) -> Self::IntoIter {
         std::iter::repeat(true)
     }
 }
 
-//@ ismany '$.index[*][?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter
+//@ ismany '$.index[?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter
diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs
index 06be95099b4..37adb514f55 100644
--- a/tests/rustdoc-json/impl-trait-precise-capturing.rs
+++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs
@@ -1,4 +1,4 @@
-//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0].lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1].param" \"T\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2].param" \"N\"
+//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0].lifetime" \"\'a\"
+//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1].param" \"T\"
+//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2].param" \"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 f37dae4c1ed..f94f7338480 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.is_synthetic==true)].span" null
+// is "$.index[?(@.inner.impl.is_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 de92dafae0b..24ee6cf6670 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 1347f954cad..e46b158d802 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.use.id"
+//@ set ForeignTrait = "$.index[?(@.docs=='ForeignTrait id hack')].inner.use.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 293dd965804..680ea175d0b 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 77ee717b03a..82d59b97b01 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 80c47eee6cb..a3b145adb86 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 32b9abb0717..02262d9b65f 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.use)].id"
+//@ set import = "$.index[?(@.inner.use)].id"
 pub use bar::Baz;
 
 //@ is "$.index[*].inner.module.items[*]" $import
 //@ is "$.index[*].inner.use.id" $baz
-//@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl
-//@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit
+//@ 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 4a313044920..54ec08135be 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 d3f2180f22c..afb29fd6316 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 a3f05818842..7fc3f70fe5a 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 cd89c475348..86c72a580b2 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.use.id"
+//@ set ForeignStruct = "$.index[?(@.docs=='ForeignStruct id hack')].inner.use.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 1d141d6e4de..876a7912f09 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 8c1eb044eae..859c0cb8ec8 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 56d930ca5c4..a5ab3ec8a1b 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/impls/pub_for_hidden_private.rs b/tests/rustdoc-json/impls/pub_for_hidden_private.rs
index 261ffbfeb4a..eb89219022c 100644
--- a/tests/rustdoc-json/impls/pub_for_hidden_private.rs
+++ b/tests/rustdoc-json/impls/pub_for_hidden_private.rs
@@ -5,6 +5,6 @@ pub trait TheTrait {}
 #[doc(hidden)]
 struct Value {}
 
-//@ has '$.index[*][?(@.docs=="THE IMPL")]'
+//@ has '$.index[?(@.docs=="THE IMPL")]'
 /// THE IMPL
 impl TheTrait for Value {}
diff --git a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs
index 0fbb4df0028..17cb07f3571 100644
--- a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs
+++ b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs
@@ -1,15 +1,15 @@
-//@ set t1 = '$.index[*][?(@.name=="T1")].id'
+//@ set t1 = '$.index[?(@.name=="T1")].id'
 pub trait T1 {}
 
-//@ set t2 = '$.index[*][?(@.name=="T2")].id'
+//@ set t2 = '$.index[?(@.name=="T2")].id'
 pub trait T2 {}
 
 /// Fun impl
 impl T1 for dyn T2 {}
 
-//@ set impl = '$.index[*][?(@.docs=="Fun impl")].id'
-//@ is '$.index[*][?(@.name=="T1")].inner.trait.implementations[*]' $impl
-//@ is '$.index[*][?(@.name=="T2")].inner.trait.implementations' []
+//@ set impl = '$.index[?(@.docs=="Fun impl")].id'
+//@ is '$.index[?(@.name=="T1")].inner.trait.implementations[*]' $impl
+//@ is '$.index[?(@.name=="T2")].inner.trait.implementations' []
 
-//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.trait.id' $t1
-//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2
+//@ is '$.index[?(@.docs=="Fun impl")].inner.impl.trait.id' $t1
+//@ is '$.index[?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2
diff --git a/tests/rustdoc-json/intra-doc-links/foreign_variant.rs b/tests/rustdoc-json/intra-doc-links/foreign_variant.rs
index 251c4884fbb..b3e6f51d23c 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 00987d93c1e..e2d00ee64e9 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 c3f9df95a8f..97a643490e6 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 8a2130f1978..566b2c68bd5 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=='break')]"
-//@ !has "$.index[*][?(@.name=='bar')]"
+//@ !has "$.index[?(@.name=='break')]"
+//@ !has "$.index[?(@.name=='bar')]"
 #[doc(keyword = "break")]
 /// hello
 mod bar {}
diff --git a/tests/rustdoc-json/keyword_private.rs b/tests/rustdoc-json/keyword_private.rs
index 2a13bf10d5d..fea546c9fb6 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=='break')]"
-//@ has "$.index[*][?(@.name=='bar')]"
-//@ is   "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]'
-//@ is   "$.index[*][?(@.name=='bar')].docs" '"hello"'
+//@ !has "$.index[?(@.name=='break')]"
+//@ has "$.index[?(@.name=='bar')]"
+//@ is   "$.index[?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]'
+//@ is   "$.index[?(@.name=='bar')].docs" '"hello"'
 #[doc(keyword = "break")]
 /// hello
 mod bar {}
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 2d4e098d696..50cf084c398 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -1,24 +1,24 @@
-//@ 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.sig.inputs[*]" 2
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"'
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"'
+//@ count "$.index[?(@.name=='longest')].inner.function.sig.inputs[*]" 2
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"'
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"'
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\"
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\"
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false
+//@ is "$.index[?(@.name=='longest')].inner.function.sig.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 257e43985ac..f191b386c6c 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -1,16 +1,16 @@
-//@ 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.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.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.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false
+//@ is "$.index[?(@.name=='foo')].inner.function.sig.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 55ff5250541..dc9f57ff8a1 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_param.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_param.rs
@@ -1,6 +1,6 @@
-//@ 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 5158ff118a0..48faf8ff830 100644
--- a/tests/rustdoc-json/lifetime/outlives_in_where.rs
+++ b/tests/rustdoc-json/lifetime/outlives_in_where.rs
@@ -1,20 +1,20 @@
-//@ 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 dac02a6ce3c..fa2387ddf67 100644
--- a/tests/rustdoc-json/methods/abi.rs
+++ b/tests/rustdoc-json/methods/abi.rs
@@ -1,50 +1,50 @@
 #![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 ba7c2e60936..b1d9f0c1af3 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.is_async" false
-    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const"  true
-    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false
+    //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_async" false
+    //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_const"  true
+    //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_unsafe" false
     pub const fn const_meth() {}
 
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async"  false
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const"  false
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false
+    //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false
     pub fn nothing_meth() {}
 
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async"  false
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const"  false
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true
     pub unsafe fn unsafe_meth() {}
 
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async"  true
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const"  false
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false
+    //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_async"  true
+    //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_unsafe" false
     pub async fn async_meth() {}
 
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async"  true
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const"  false
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_async"  true
+    //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true
     pub async unsafe fn async_unsafe_meth() {}
 
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async"  false
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const"  true
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true
+    //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_const"  true
+    //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_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 10ec2831c21..8cc564706d6 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -2,31 +2,31 @@
 //@ 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
+//@ 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.use)].inner.use.is_glob" false
-    //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"'
-    //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false
-    //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id
-    //@ set l4_use_id = "$.index[*][?(@.inner.use)].id"
+    //@ is "$.index[?(@.inner.use)].inner.use.is_glob" false
+    //@ is "$.index[?(@.inner.use)].inner.use.source" '"l3::L4"'
+    //@ is "$.index[?(@.inner.use)].inner.use.is_glob" false
+    //@ is "$.index[?(@.inner.use)].inner.use.id" $l4_id
+    //@ set l4_use_id = "$.index[?(@.inner.use)].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 7c518a8f5a7..84318821c50 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -5,11 +5,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, "is_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, "is_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 3454f421636..4d4339ceb23 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/path_name.rs b/tests/rustdoc-json/path_name.rs
index a1b3ae294fa..dcfaa0607c4 100644
--- a/tests/rustdoc-json/path_name.rs
+++ b/tests/rustdoc-json/path_name.rs
@@ -19,49 +19,49 @@ pub use priv_mod::{InPrivMod, InPrivMod as InPrivMod2};
 use pub_mod::InPubMod as InPubMod3;
 pub use pub_mod::{InPubMod, InPubMod as InPubMod2};
 
-//@ is "$.index[*][?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
+//@ is "$.index[?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
 pub type T0 = priv_mod::InPrivMod;
-//@ is "$.index[*][?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"'
+//@ is "$.index[?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"'
 pub type T1 = InPrivMod;
-//@ is "$.index[*][?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"'
+//@ is "$.index[?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"'
 pub type T2 = InPrivMod2;
-//@ is "$.index[*][?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
+//@ is "$.index[?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
 pub type T3 = InPrivMod3;
 
-//@ is "$.index[*][?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
+//@ is "$.index[?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
 pub type U0 = pub_mod::InPubMod;
-//@ is "$.index[*][?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"'
+//@ is "$.index[?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"'
 pub type U1 = InPubMod;
-//@ is "$.index[*][?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"'
+//@ is "$.index[?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"'
 pub type U2 = InPubMod2;
-//@ is "$.index[*][?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
+//@ is "$.index[?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
 pub type U3 = InPubMod3;
 
 // Check we only have paths for structs at their original path
-//@ ismany "$.paths[*][?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]'
+//@ ismany "$.paths[?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]'
 
 pub use defines_and_reexports::{InPrivMod as XPrivMod, InPubMod as XPubMod};
 use defines_and_reexports::{InPrivMod as XPrivMod2, InPubMod as XPubMod2};
 
-//@ is "$.index[*][?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"'
+//@ is "$.index[?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"'
 pub type X0 = defines_and_reexports::m1::InPubMod;
-//@ is "$.index[*][?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
+//@ is "$.index[?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
 pub type X1 = defines_and_reexports::InPubMod;
-//@ is "$.index[*][?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"'
+//@ is "$.index[?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"'
 pub type X2 = defines_and_reexports::InPubMod2;
-//@ is "$.index[*][?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"'
+//@ is "$.index[?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"'
 pub type X3 = XPubMod;
 // N.B. This isn't the path as used *or* the original path!
-//@ is "$.index[*][?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
+//@ is "$.index[?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
 pub type X4 = XPubMod2;
 
-//@ is "$.index[*][?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
+//@ is "$.index[?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
 pub type Y1 = defines_and_reexports::InPrivMod;
-//@ is "$.index[*][?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"'
+//@ is "$.index[?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"'
 pub type Y2 = defines_and_reexports::InPrivMod2;
-//@ is "$.index[*][?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"'
+//@ is "$.index[?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"'
 pub type Y3 = XPrivMod;
-//@ is "$.index[*][?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
+//@ is "$.index[?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
 pub type Y4 = XPrivMod2;
 
 // For foreign items, $.paths contains the *origional* path, even if it's not publicly
@@ -74,9 +74,9 @@ pub type Y4 = XPrivMod2;
 
 // Tests for the example in the docs of Path::name.
 // If these change, chage the docs.
-//@ is "$.index[*][?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"'
+//@ is "$.index[?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"'
 pub type Vec1 = std::vec::Vec<i32>;
-//@ is "$.index[*][?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"'
+//@ is "$.index[?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"'
 pub type Vec2 = Vec<i32>;
-//@ is "$.index[*][?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"'
+//@ is "$.index[?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"'
 pub type Vec3 = std::prelude::v1::Vec<i32>;
diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs
index b10ae45f3ec..b58120bae05 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 58c222ce4f0..a1f0ebd11b6 100644
--- a/tests/rustdoc-json/primitives/primitive_impls.rs
+++ b/tests/rustdoc-json/primitives/primitive_impls.rs
@@ -4,26 +4,26 @@
 #![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"
 
 #[lang = "sized"]
 trait Sized {}
 
 /// 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 {}
 
@@ -31,7 +31,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 5e5f3974ab3..ae0306843c5 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 21ef5ab7196..a0d34218b80 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 d4cdef84de8..2991cc1e47c 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -5,15 +5,15 @@
 #[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.use[?(@.name=='my_i32')].id" null
+//@ is "$.index[?(@.inner.use.name=='my_i32')].inner.use.id" null
 pub use i32 as my_i32;
-//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null
+//@ is "$.index[?(@.inner.use.name=='u32')].inner.use.id" null
 pub use u32;
diff --git a/tests/rustdoc-json/pub_mod_in_private_mod.rs b/tests/rustdoc-json/pub_mod_in_private_mod.rs
index 112ab9c68f0..8b31ad0bcfe 100644
--- a/tests/rustdoc-json/pub_mod_in_private_mod.rs
+++ b/tests/rustdoc-json/pub_mod_in_private_mod.rs
@@ -1,6 +1,6 @@
 // See https://github.com/rust-lang/rust/issues/101105
 
-//@ !has "$.index[*][?(@.name=='nucleus')]"
+//@ !has "$.index[?(@.name=='nucleus')]"
 mod corpus {
     pub mod nucleus {}
 }
diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
index 4debd395496..f7067857ddf 100644
--- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
+++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
@@ -4,7 +4,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 4efacd283ef..746749e0204 100644
--- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
+++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
@@ -2,5 +2,5 @@
 
 #![crate_name = "export_extern_crate_as_self"]
 
-//@ 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 dfe6e7a03b1..8a4388feaca 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.use)].inner.use.name' \"enum_with_discriminant\"
-//@ set use = '$.index[*][?(@.inner.use)].id'
-//@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
+//@ !has '$.index[?(@.docs == "Should not be inlined")]'
+//@ is '$.index[?(@.inner.use)].inner.use.name' \"enum_with_discriminant\"
+//@ set use = '$.index[?(@.inner.use)].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 8142c35f4c7..48de1b5e772 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.use[?(@.name=='m1')].id" $m1
-//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true
+//@ set m1_use = "$.index[?(@.docs=='m1 re-export')].id"
+//@ is "$.index[?(@.inner.use.name=='m1')].inner.use.id" $m1
+//@ is "$.index[?(@.inner.use.name=='m1')].inner.use.is_glob" true
 /// m1 re-export
 pub use m1::*;
-//@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
-//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2
-//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true
+//@ set m2_use = "$.index[?(@.docs=='m2 re-export')].id"
+//@ is "$.index[?(@.inner.use.name=='m2')].inner.use.id" $m2
+//@ is "$.index[?(@.inner.use.name=='m2')].inner.use.is_glob" true
 /// m2 re-export
 pub use m2::*;
 
-//@ ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use
+//@ ismany "$.index[?(@.name=='glob_collision')].inner.module.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 ee1779407f4..69c0c0e6d5f 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.use)].inner.use.id" $m1
+//@ is "$.index[?(@.inner.use)].inner.use.id" $m1
 pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index 98be4773941..ccc6faffc8e 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.use)].inner.use.is_glob" true
-//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id
-//@ set use_id = "$.index[*][?(@.inner.use)].id"
-//@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
+//@ is "$.index[?(@.inner.use)].inner.use.is_glob" true
+//@ is "$.index[?(@.inner.use)].inner.use.id" $mod1_id
+//@ set use_id = "$.index[?(@.inner.use)].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 2084ffc356e..f232914787b 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.use.name" \"mod2\"
+    //@ set mod2_use_id = "$.index[?(@.docs=='Mod2 re-export')].id"
+    //@ is "$.index[?(@.docs=='Mod2 re-export')].inner.use.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.use.name" \"mod1\"
+//@ set mod1_use_id = "$.index[?(@.docs=='Mod1 re-export')].id"
+//@ is "$.index[?(@.docs=='Mod1 re-export')].inner.use.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 a1d2080c068..005004e3b86 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[?(@.use.source=='foo::Foo')]"
+//@ has "$.index[*].inner.use.source" '"foo::Foo"'
 pub use foo::Foo;
 
 pub mod bar {
-    //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]"
+    //@ has "$.index[*].inner.use.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 7d26d2a970d..54dda2a3cd0 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[?(@.use.source=='foo::Bar')].use.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.use.source=='foo::Bar')].inner.use.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[?(@.use.source=='crate::foo::Bar')].use.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.use.source=='crate::foo::Bar')].inner.use.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 f182208c341..0bd37768255 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 d0ce95749f1..59e5fff59c9 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[?(@.use.name=='x')].use.source" '"m1::x"'
-//@ !has "$.index[*][?(@.name=='m1')]"
+//@ has "$.index[?(@.name=='x' && @.inner.function)]"
+//@ has "$.index[?(@.inner.use.name=='x')].inner.use.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 fdf8cda103b..6b5d03e207e 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -5,19 +5,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.use.id"
+//@ set crate_use_id = "$.index[?(@.docs=='Hack A')].id"
+//@ set foo_id = "$.index[?(@.docs=='Hack A')].inner.use.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.use.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.use.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.use)].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.use)].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 049100d7f49..79af40b83a4 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -1,21 +1,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.use.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\"
-//@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
+//@ is "$.index[?(@.docs=='First re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[?(@.docs=='First re-export')].inner.use.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.use.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\"
-//@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
+//@ is "$.index[?(@.docs=='Second re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[?(@.docs=='Second re-export')].inner.use.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 e021b51ab4b..129ccb7e2eb 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 25edd5dbb28..56922340a6f 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 80f171da888..119e699d815 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[?(@.use.name=='UsedHidden')]"
-//@ has "$.index[*][?(@.name=='Hidden')]"
+//@ has "$.index[*].inner.use.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 3f13f305d64..0494dff5bca 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.use)].inner.use.name" \"NewName\"
+//@ is "$.index[?(@.inner.use)].inner.use.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 81c003a51c4..a3d712358f2 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[?(@.use.name=='Public')]"
-//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\"
+//@ set import_id = "$.index[?(@.docs=='Re-export')].id"
+//@ !has "$.index[?(@.inner.use.name=='Public')]"
+//@ is "$.index[?(@.inner.use.name=='NewName')].inner.use.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 760e2c6f775..6e7ad3393e5 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[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct
-//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct
+//@ ismany "$.index[?(@.inner.use.name == 'Foo')].inner.use.id" $foo_fn $foo_struct
+//@ ismany "$.index[?(@.inner.use.name == 'Bar')].inner.use.id" $foo_fn $foo_struct
 
-//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2
-//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2
+//@ count "$.index[?(@.inner.use.name == 'Foo')]" 2
+//@ count "$.index[?(@.inner.use.name == 'Bar')]" 2
 pub use Foo as Bar;
 pub use nested::Foo;
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 f313171afa5..05b55c7b12a 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
@@ -3,17 +3,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[?(@.use.name=='Trait')].use.id" $trait_id
+//@ set export_id = "$.index[?(@.docs=='First re-export')].id"
+//@ is "$.index[?(@.inner.use.name=='Trait')].inner.use.id" $trait_id
 /// First re-export
 pub use inner::Trait;
-//@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
-//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id
+//@ set reexport_id = "$.index[?(@.docs=='Second re-export')].id"
+//@ is "$.index[?(@.inner.use.name=='Reexport')].inner.use.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 405d57d342e..40be1708dc6 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -1,20 +1,20 @@
 //@ 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.use)].inner.use.name" \"Public\"
-//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id
-//@ set use_id = "$.index[*][?(@.inner.use)].id"
+//@ is "$.index[?(@.inner.use)].inner.use.name" \"Public\"
+//@ is "$.index[?(@.inner.use)].inner.use.id" $pub_id
+//@ set use_id = "$.index[?(@.inner.use)].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
 
 // Test for https://github.com/rust-lang/rust/issues/135309
-//@ has  "$.paths[*][?(@.kind=='module')].path" '["simple_private"]'
+//@ has  "$.paths[?(@.kind=='module')].path" '["simple_private"]'
 //@ !has "$.paths[*].path"                      '["simple_private", "inner"]'
-//@ has  "$.paths[*][?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]'
+//@ has  "$.paths[?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]'
 //@ !has "$.paths[*].path"                      '["simple_private", "Public"]'
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index f1335828314..cdb6c0dc88a 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -1,21 +1,21 @@
 //@ 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.use.source" \"inner::Public\"
+//@ set import_id = "$.index[?(@.docs=='Outer')].id"
+//@ is "$.index[?(@.docs=='Outer')].inner.use.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
 
-//@ has  "$.paths[*][?(@.kind=='module')].path" '["simple_public"]'
-//@ has  "$.paths[*][?(@.kind=='module')].path" '["simple_public", "inner"]'
-//@ has  "$.paths[*][?(@.kind=='struct')].path" '["simple_public", "inner", "Public"]'
+//@ has  "$.paths[?(@.kind=='module')].path" '["simple_public"]'
+//@ has  "$.paths[?(@.kind=='module')].path" '["simple_public", "inner"]'
+//@ has  "$.paths[?(@.kind=='struct')].path" '["simple_public", "inner", "Public"]'
 //@ !has "$.paths[*].path"                      '["simple_public", "Public"]'
diff --git a/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs b/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs
index 59699e4861b..89591690bca 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-type-notation.rs b/tests/rustdoc-json/return-type-notation.rs
index 2219642bfc5..7943991616b 100644
--- a/tests/rustdoc-json/return-type-notation.rs
+++ b/tests/rustdoc-json/return-type-notation.rs
@@ -8,8 +8,8 @@ pub trait Foo {
     async fn bar();
 }
 
-//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.args.angle_bracketed.constraints[0].args" '"return_type_notation"'
-//@ ismany "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[*].bound_predicate.type.qualified_path.args" '"return_type_notation"' '"return_type_notation"'
+//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.args.angle_bracketed.constraints[0].args" '"return_type_notation"'
+//@ ismany "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[*].bound_predicate.type.qualified_path.args" '"return_type_notation"' '"return_type_notation"'
 pub fn foo<T: Foo<bar(..): Send>>()
 where
     <T as Foo>::bar(..): 'static,
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index 214fda14aca..8fbdb6be5c9 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -1,13 +1,13 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/96161>.
 
 mod secret {
-    //@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id"
+    //@ set struct_secret = "$.index[?(@.name == 'Secret' && @.inner.struct)].id"
     pub struct Secret;
 }
 
-//@ has "$.index[*][?(@.name=='get_secret')].inner.function"
-//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"'
-//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret
+//@ has "$.index[?(@.name=='get_secret')].inner.function"
+//@ is "$.index[?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"'
+//@ is "$.index[?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs
index 9e0265da8e2..5be13c8b8fc 100644
--- a/tests/rustdoc-json/statics/extern.rs
+++ b/tests/rustdoc-json/statics/extern.rs
@@ -1,38 +1,38 @@
 //@ edition: 2021
 
 extern "C" {
-    //@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
+    //@ is '$.index[?(@.name=="A")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="A")].inner.static.is_mutable' false
     pub static A: i32;
-    //@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
+    //@ is '$.index[?(@.name=="B")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="B")].inner.static.is_mutable' true
     pub static mut B: i32;
 
     // items in unadorned `extern` blocks cannot have safety qualifiers
 }
 
 unsafe extern "C" {
-    //@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false
+    //@ is '$.index[?(@.name=="C")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="C")].inner.static.is_mutable' false
     pub static C: i32;
-    //@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true
+    //@ is '$.index[?(@.name=="D")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="D")].inner.static.is_mutable' true
     pub static mut D: i32;
 
-    //@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe'  false
-    //@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false
+    //@ is '$.index[?(@.name=="E")].inner.static.is_unsafe'  false
+    //@ is '$.index[?(@.name=="E")].inner.static.is_mutable' false
     pub safe static E: i32;
-    //@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe'  false
-    //@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true
+    //@ is '$.index[?(@.name=="F")].inner.static.is_unsafe'  false
+    //@ is '$.index[?(@.name=="F")].inner.static.is_mutable' true
     pub safe static mut F: i32;
 
-    //@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false
+    //@ is '$.index[?(@.name=="G")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="G")].inner.static.is_mutable' false
     pub unsafe static G: i32;
-    //@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe'  true
-    //@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true
+    //@ is '$.index[?(@.name=="H")].inner.static.is_unsafe'  true
+    //@ is '$.index[?(@.name=="H")].inner.static.is_mutable' true
     pub unsafe static mut H: i32;
 }
 
-//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""'
-//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"'
+//@ ismany '$.index[?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""'
+//@ ismany '$.index[?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"'
diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs
index a8af23cc87d..497a134c503 100644
--- a/tests/rustdoc-json/statics/statics.rs
+++ b/tests/rustdoc-json/statics/statics.rs
@@ -1,12 +1,12 @@
-//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"'
-//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
-//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"'
-//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false
+//@ is '$.index[?(@.name=="A")].inner.static.type.primitive' '"i32"'
+//@ is '$.index[?(@.name=="A")].inner.static.is_mutable' false
+//@ is '$.index[?(@.name=="A")].inner.static.expr' '"5"'
+//@ is '$.index[?(@.name=="A")].inner.static.is_unsafe' false
 pub static A: i32 = 5;
 
-//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"'
-//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
+//@ is '$.index[?(@.name=="B")].inner.static.type.primitive' '"u32"'
+//@ is '$.index[?(@.name=="B")].inner.static.is_mutable' true
 // Expr value isn't gaurenteed, it'd be fine to change it.
-//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"'
-//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false
+//@ is '$.index[?(@.name=="B")].inner.static.expr' '"_"'
+//@ is '$.index[?(@.name=="B")].inner.static.is_unsafe' false
 pub static mut B: u32 = 2 + 3;
diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs
index d0db9c6588b..ba6644190a2 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 7e556df777f..eb1740676a6 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 67d2a4a7a8c..501044f62cc 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.has_stripped_fields" 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.has_stripped_fields" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 4573adc73fa..e62fb27ae86 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.has_stripped_fields" 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.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index 30013021abe..127f9ed1972 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.has_stripped_fields" 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.has_stripped_fields" 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 91079a30d42..181d5ea0de2 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.has_stripped_fields" 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.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/tuple.rs b/tests/rustdoc-json/structs/tuple.rs
index 6c8dc79dfe2..115ce29bd70 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 137915e6c05..af5b57fb133 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 11af26e6ea3..b97a17cc46a 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 ad6af65c0e0..6a961725206 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 3e7f175a5a1..979b002d0ee 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.has_stripped_fields" 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.has_stripped_fields" 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 fe99292456d..4e856bda296 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -1,9 +1,9 @@
-//@ 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.has_stripped_fields" 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.has_stripped_fields" 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 d9ef256b106..e7a586ee95a 100644
--- a/tests/rustdoc-json/trait_alias.rs
+++ b/tests/rustdoc-json/trait_alias.rs
@@ -1,17 +1,17 @@
 #![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.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ is "$.index[?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
 pub fn f() -> impl StrLike {
     "heya"
 }
 
-//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ !is "$.index[?(@.name=='g')].inner.function.sig.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 95e0f97b52c..d17988474f9 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 9fdb763b61e..499acefedb7 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_dyn_compatible.rs b/tests/rustdoc-json/traits/is_dyn_compatible.rs
index bccf94d17d6..b172b53807b 100644
--- a/tests/rustdoc-json/traits/is_dyn_compatible.rs
+++ b/tests/rustdoc-json/traits/is_dyn_compatible.rs
@@ -1,19 +1,19 @@
 #![no_std]
 
-//@ has "$.index[*][?(@.name=='FooDynIncompatible')]"
-//@ is "$.index[*][?(@.name=='FooDynIncompatible')].inner.trait.is_dyn_compatible" false
+//@ has "$.index[?(@.name=='FooDynIncompatible')]"
+//@ is "$.index[?(@.name=='FooDynIncompatible')].inner.trait.is_dyn_compatible" false
 pub trait FooDynIncompatible {
     fn foo() -> Self;
 }
 
-//@ has "$.index[*][?(@.name=='BarDynIncompatible')]"
-//@ is "$.index[*][?(@.name=='BarDynIncompatible')].inner.trait.is_dyn_compatible" false
+//@ has "$.index[?(@.name=='BarDynIncompatible')]"
+//@ is "$.index[?(@.name=='BarDynIncompatible')].inner.trait.is_dyn_compatible" false
 pub trait BarDynIncompatible<T> {
     fn foo(i: T);
 }
 
-//@ has "$.index[*][?(@.name=='FooDynCompatible')]"
-//@ is "$.index[*][?(@.name=='FooDynCompatible')].inner.trait.is_dyn_compatible" true
+//@ has "$.index[?(@.name=='FooDynCompatible')]"
+//@ is "$.index[?(@.name=='FooDynCompatible')].inner.trait.is_dyn_compatible" true
 pub trait FooDynCompatible {
     fn foo(&self);
 }
diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs
index ce0642278e0..1e11abaecdf 100644
--- a/tests/rustdoc-json/traits/private_supertrait.rs
+++ b/tests/rustdoc-json/traits/private_supertrait.rs
@@ -1,9 +1,9 @@
-//@ !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/self.rs b/tests/rustdoc-json/traits/self.rs
index efd9efd556f..018bda9cc3c 100644
--- a/tests/rustdoc-json/traits/self.rs
+++ b/tests/rustdoc-json/traits/self.rs
@@ -7,29 +7,29 @@ pub struct Foo;
 // Each assertion matches 3 times, and should be the same each time.
 
 impl Foo {
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
+    //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+    //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
     pub fn by_ref(&self) {}
 
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true
+    //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+    //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true
     pub fn by_exclusive_ref(&mut self) {}
 
-    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
     pub fn by_value(self) {}
 
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
+    //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
+    //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
     pub fn with_lifetime<'a>(&'a self) {}
 
-    //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"'
     pub fn build() -> Self {
         Self
     }
diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs
index 4b6199d4b26..3accb0ff858 100644
--- a/tests/rustdoc-json/traits/supertrait.rs
+++ b/tests/rustdoc-json/traits/supertrait.rs
@@ -1,20 +1,20 @@
-//@ 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 137b8947e23..497930a67c8 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -2,25 +2,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.sig.inputs[0][1].impl_trait"
-//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.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.sig.inputs[0][1].impl_trait"
+//@ is "$.index[?(@.name=='takes_alias')].inner.function.sig.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 3a93bcaefd4..52983527f08 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 d8686d4e2fb..4e533a67f8b 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -1,45 +1,45 @@
 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.path" \"Box\"
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
-//@ 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.path" '"Fn"'
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"'
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"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.path" \"Box\"
+//@ is    "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
+//@ 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.path" '"Fn"'
+//@ is    "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"'
+//@ is    "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"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.is_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.path" '"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.is_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.path" '"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.path" '"Send"'
-//@ is    "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"'
+//@ is    "$.index[?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"'
+//@ is    "$.index[?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"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 97e1c3760ee..7963690e448 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" \"extern_type\"
+//@ is "$.index[?(@.docs=='No inner information')].name" '"Foo"'
+//@ is "$.index[?(@.docs=='No inner information')].inner" \"extern_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index aaa716bf11f..10e95cc5e56 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -1,24 +1,24 @@
-//@ 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.sig.inputs[*]" 1
-//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.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.sig.inputs[*]" 1
+//@ is     "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is     "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.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.sig.inputs[*]" 1
-//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.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.sig.inputs[*]" 1
+//@ is    "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is    "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.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 2d2ce9cd103..26a232a1562 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -1,31 +1,31 @@
-//@ 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.path" \"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.path" \"Result\"
-//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
-//@ 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.path" \"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.path" \"Result\"
+//@ is    "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
+//@ 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 08b35b90a2b..68b7a556a69 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -1,5 +1,5 @@
-//@ 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),
@@ -8,12 +8,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.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
-//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.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.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"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.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+//@ count "$.index[?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+//@ is "$.index[?(@.name=='dynfn')].inner.function.sig.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.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"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 e26f8f7c651..e96a92f7cfb 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -1,23 +1,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.sig.output.qualified_path.name' '"Metadata"'
-//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner
+//@ is '$.index[?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"'
+//@ is '$.index[?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null
+//@ is '$.index[?(@.name=="create")].inner.function.sig.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.type.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.type.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 22c9c9c1149..20354909f8e 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -1,17 +1,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.sig.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+//@ count "$.index[?(@.name=='user')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"'
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null
+//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.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 501694dce8b..934daba11bb 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -1,15 +1,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.sig.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
-//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
-//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null
+//@ count "$.index[?(@.name=='test')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
+//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"'
+//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null
 pub fn test(_: Parametrized<i32>::Proj) {}
 
 /// param_bool
@@ -24,10 +24,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 2f2b4c42d44..7fd23a48040 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.sig.output.resolved_path.id" $IntVec
+//@ is "$.index[?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec
 pub fn f() -> IntVec {
     vec![0; 32]
 }
 
-//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec
+//@ !is "$.index[?(@.name=='g')].inner.function.sig.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 a1616f62751..b3a07a13bc8 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 989a025f669..6f398cc23f6 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 7f135a72dec..24ee47f1957 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.sig.output.resolved_path"
-//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union
+//@ has "$.index[?(@.name=='make_int_union')].inner.function.sig.output.resolved_path"
+//@ is "$.index[?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union
 pub fn make_int_union(int: i32) -> Union {
     Union { int }
 }
diff --git a/tests/rustdoc-ui/coverage/html.rs b/tests/rustdoc-ui/coverage/html.rs
index 41e1ce1609d..7fd080f0758 100644
--- a/tests/rustdoc-ui/coverage/html.rs
+++ b/tests/rustdoc-ui/coverage/html.rs
@@ -2,3 +2,5 @@
 
 /// Foo
 pub struct Xo;
+
+//~? ERROR `--output-format=html` is not supported for the `--show-coverage` option
diff --git a/tests/rustdoc-ui/deprecated-attrs.rs b/tests/rustdoc-ui/deprecated-attrs.rs
index 3b59e05a012..0ae65a5eaf7 100644
--- a/tests/rustdoc-ui/deprecated-attrs.rs
+++ b/tests/rustdoc-ui/deprecated-attrs.rs
@@ -19,3 +19,7 @@
 //~| NOTE see issue #44136
 //~| NOTE no longer functions
 //~| NOTE `doc(plugins)` is now a no-op
+
+//~? WARN the `passes` flag no longer functions
+//~? NOTE see issue #44136
+//~? HELP you may want to use --document-private-items
diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
new file mode 100644
index 00000000000..e3420dc0789
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
@@ -0,0 +1,16 @@
+// Ensure that `doc(cfg())` respects `check-cfg`
+// Currently not properly working
+#![feature(doc_cfg)]
+#![deny(unexpected_cfgs)]
+
+//@revisions: no_check cfg_empty cfg_foo
+//@[cfg_empty] compile-flags: --check-cfg cfg()
+//@[cfg_foo] compile-flags: --check-cfg cfg(foo)
+
+//@[no_check] check-pass
+//@[cfg_empty] check-pass
+//@[cfg_empty] known-bug: #138358
+//@[cfg_foo] check-pass
+
+#[doc(cfg(foo))]
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs
new file mode 100644
index 00000000000..14c2e83ec85
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-unstable.rs
@@ -0,0 +1,10 @@
+// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))`
+#![feature(doc_cfg)]
+
+// `cfg_boolean_literals`
+#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change
+pub fn cfg_boolean_literals() {}
+
+// `cfg_version`
+#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change
+pub fn cfg_sanitize() {}
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr
new file mode 100644
index 00000000000..54de3b178ed
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr
@@ -0,0 +1,23 @@
+error[E0658]: `cfg(false)` is experimental and subject to change
+  --> $DIR/doc-cfg-unstable.rs:5:11
+   |
+LL | #[doc(cfg(false))]
+   |           ^^^^^
+   |
+   = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
+   = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `cfg(sanitize)` is experimental and subject to change
+  --> $DIR/doc-cfg-unstable.rs:9:11
+   |
+LL | #[doc(cfg(sanitize = "thread"))]
+   |           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #39699 <https://github.com/rust-lang/rust/issues/39699> for more information
+   = help: add `#![feature(cfg_sanitize)]` 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 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/rustdoc-ui/doctest-output.rs b/tests/rustdoc-ui/doctest-output.rs
index 720f2952980..28364c3a3ea 100644
--- a/tests/rustdoc-ui/doctest-output.rs
+++ b/tests/rustdoc-ui/doctest-output.rs
@@ -1 +1,3 @@
 //@ compile-flags:-Z unstable-options --show-coverage --output-format=doctest
+
+//~? ERROR `--output-format=doctest` is not supported for the `--show-coverage` option
diff --git a/tests/rustdoc-ui/doctest/display-output.stdout b/tests/rustdoc-ui/doctest/display-output.stdout
index ad25d1ce541..45e107b2c70 100644
--- a/tests/rustdoc-ui/doctest/display-output.stdout
+++ b/tests/rustdoc-ui/doctest/display-output.stdout
@@ -6,7 +6,7 @@ successes:
 
 ---- $DIR/display-output.rs - foo (line 9) stdout ----
 warning: unused variable: `x`
-  --> $DIR/display-output.rs:11:5
+  --> $DIR/display-output.rs:12:5
    |
 LL | let x = 12;
    |     ^ help: if this is intentional, prefix it with an underscore: `_x`
@@ -19,13 +19,13 @@ LL | #![warn(unused)]
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: unused variable: `x`
-  --> $DIR/display-output.rs:13:8
+  --> $DIR/display-output.rs:14:8
    |
 LL | fn foo(x: &dyn std::fmt::Display) {}
    |        ^ help: if this is intentional, prefix it with an underscore: `_x`
 
 warning: function `foo` is never used
-  --> $DIR/display-output.rs:13:4
+  --> $DIR/display-output.rs:14:4
    |
 LL | fn foo(x: &dyn std::fmt::Display) {}
    |    ^^^
diff --git a/tests/rustdoc-ui/doctest/extern-crate.rs b/tests/rustdoc-ui/doctest/extern-crate.rs
new file mode 100644
index 00000000000..0415d33bb72
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/extern-crate.rs
@@ -0,0 +1,23 @@
+//@ check-pass
+//@ compile-flags:--test --test-args=--test-threads=1
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+// This test ensures that crate imports are placed outside of the `main` function
+// so they work all the time (even in 2015 edition).
+
+/// ```rust
+/// #![feature(test)]
+///
+/// extern crate test;
+/// use test::Bencher;
+///
+/// #[bench]
+/// fn bench_xor_1000_ints(b: &mut Bencher) {
+///     b.iter(|| {
+///         (0..1000).fold(0, |old, new| old ^ new);
+///     });
+/// }
+/// ```
+///
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/doctest/extern-crate.stdout b/tests/rustdoc-ui/doctest/extern-crate.stdout
new file mode 100644
index 00000000000..b103343afdd
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/extern-crate.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/extern-crate.rs - foo (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/per-target-ignores.rs b/tests/rustdoc-ui/doctest/per-target-ignores.rs
new file mode 100644
index 00000000000..3dea7099b4b
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/per-target-ignores.rs
@@ -0,0 +1,14 @@
+//@ only-aarch64
+//@ compile-flags:--test
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ check-pass
+
+///```ignore-x86_64
+/// assert!(cfg!(not(target_arch = "x86_64")));
+///```
+pub fn foo() -> u8 {
+    4
+}
+
+fn main() {}
diff --git a/tests/rustdoc-ui/doctest/per-target-ignores.stdout b/tests/rustdoc-ui/doctest/per-target-ignores.stdout
new file mode 100644
index 00000000000..fe7282144dd
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/per-target-ignores.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/per-target-ignores.rs - foo (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/extract-doctests.stdout b/tests/rustdoc-ui/extract-doctests.stdout
index fa8604cae94..b11531b844e 100644
--- a/tests/rustdoc-ui/extract-doctests.stdout
+++ b/tests/rustdoc-ui/extract-doctests.stdout
@@ -1 +1 @@
-{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":"#![allow(unused)]\nfn main() {\nlet\n}","name":"$DIR/extract-doctests.rs - (line 13)"}]}
\ No newline at end of file
+{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]}
\ No newline at end of file
diff --git a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs
index babdbd0a692..9d6ec0caf9f 100644
--- a/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs
+++ b/tests/rustdoc-ui/generate-link-to-definition/generate-link-to-definition-opt.rs
@@ -5,3 +5,5 @@
 //@ check-pass
 
 pub fn f() {}
+
+//~? WARN `--generate-link-to-definition` option can only be used with HTML output format
diff --git a/tests/rustdoc-ui/include-str-bare-urls.rs b/tests/rustdoc-ui/include-str-bare-urls.rs
index c452c88cdd3..f80e28e8ca7 100644
--- a/tests/rustdoc-ui/include-str-bare-urls.rs
+++ b/tests/rustdoc-ui/include-str-bare-urls.rs
@@ -13,3 +13,5 @@
 
 #![deny(rustdoc::bare_urls)]
 #![doc=include_str!("auxiliary/include-str-bare-urls.md")]
+
+//~? ERROR this URL is not a hyperlink
diff --git a/tests/rustdoc-ui/lints/check.rs b/tests/rustdoc-ui/lints/check.rs
index 61c9f188952..0943f9f6053 100644
--- a/tests/rustdoc-ui/lints/check.rs
+++ b/tests/rustdoc-ui/lints/check.rs
@@ -12,3 +12,5 @@
 pub fn foo() {}
 //~^ WARN
 //~^^ WARN
+
+//~? WARN no documentation found for this crate's top-level module
diff --git a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
index a05b5169989..c0d2515998f 100644
--- a/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
+++ b/tests/rustdoc-ui/remap-path-prefix-invalid-doctest.stdout
@@ -5,11 +5,11 @@ test remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) .
 failures:
 
 ---- remapped_path/remap-path-prefix-invalid-doctest.rs - SomeStruct (line 10) stdout ----
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `is`
+error: expected one of `!` or `::`, found `is`
   --> remapped_path/remap-path-prefix-invalid-doctest.rs:11:6
    |
 LL | this is not real code
-   |      ^^ expected one of 8 possible tokens
+   |      ^^ expected one of `!` or `::`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/rustdoc-ui/remap-path-prefix-lint.rs b/tests/rustdoc-ui/remap-path-prefix-lint.rs
index f27863e825d..d003e19f200 100644
--- a/tests/rustdoc-ui/remap-path-prefix-lint.rs
+++ b/tests/rustdoc-ui/remap-path-prefix-lint.rs
@@ -8,3 +8,5 @@
 
 /// </script>
 pub struct Bar;
+
+//~? ERROR unopened HTML tag `script`
diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs
index 4fb5c9ab36f..c8e82d3a20b 100644
--- a/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs
+++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-fail-if-type-error.rs
@@ -5,3 +5,5 @@ pub fn foo() {
   INVALID_FUNC();
   //~^ ERROR could not resolve path
 }
+
+//~? ERROR Compilation failed, aborting rustdoc
diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs
index df7b41e20f6..3db7924dbe1 100644
--- a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs
+++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-1.rs
@@ -1 +1,3 @@
 //@ compile-flags: -Z unstable-options --scrape-examples-target-crate foobar
+
+//~? ERROR must use --scrape-examples-output-path and --scrape-examples-target-crate together
diff --git a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs
index ef270a08f48..7b6a30291ce 100644
--- a/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs
+++ b/tests/rustdoc-ui/scrape-examples/scrape-examples-wrong-options-2.rs
@@ -1 +1,3 @@
 //@ compile-flags: -Z unstable-options --scrape-examples-output-path ex.calls
+
+//~? ERROR must use --scrape-examples-output-path and --scrape-examples-target-crate together
diff --git a/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs b/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs
index 62d3d955855..42847203d48 100644
--- a/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs
+++ b/tests/rustdoc-ui/use_both_out_dir_and_output_options.rs
@@ -1 +1,3 @@
 //@ compile-flags: --output ./foo
+
+//~? ERROR cannot use both 'out-dir' and 'output' at once
diff --git a/tests/rustdoc/deref/deref-methods-24686-target.rs b/tests/rustdoc/deref/deref-methods-24686-target.rs
new file mode 100644
index 00000000000..e019488ca80
--- /dev/null
+++ b/tests/rustdoc/deref/deref-methods-24686-target.rs
@@ -0,0 +1,27 @@
+#![crate_name = "foo"]
+
+// test for https://github.com/rust-lang/rust/issues/24686
+use std::ops::Deref;
+
+pub struct Foo<T>(T);
+impl Foo<i32> {
+    pub fn get_i32(&self) -> i32 { self.0 }
+}
+impl Foo<u32> {
+    pub fn get_u32(&self) -> u32 { self.0 }
+}
+
+// Note that the same href is used both on the method itself,
+// and on the sidebar items.
+//@ has foo/struct.Bar.html
+//@ has - '//a[@href="#method.get_i32"]' 'get_i32'
+//@ !has - '//a[@href="#method.get_u32"]' 'get_u32'
+//@ count - '//ul[@class="block deref-methods"]//a' 1
+//@ count - '//a[@href="#method.get_i32"]' 2
+pub struct Bar(Foo<i32>);
+impl Deref for Bar {
+    type Target = Foo<i32>;
+    fn deref(&self) -> &Foo<i32> {
+        &self.0
+    }
+}
diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs
index db2d1669df6..65dad2a5195 100644
--- a/tests/rustdoc/playground.rs
+++ b/tests/rustdoc/playground.rs
@@ -24,4 +24,4 @@
 
 //@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
 //@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
new file mode 100644
index 00000000000..3fdd65d6c87
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Z unstable-options
+//@ ignore-stage1
+
+#![feature(rustc_private)]
+#![deny(rustc::usage_of_type_ir_traits)]
+
+extern crate rustc_type_ir;
+
+use rustc_type_ir::Interner;
+
+fn foo<I: Interner>(cx: I, did: I::DefId) {
+    let _ = cx.trait_is_unsafe(did);
+    //~^ ERROR do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr
new file mode 100644
index 00000000000..df29a494558
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-traits.stderr
@@ -0,0 +1,15 @@
+error: do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
+  --> $DIR/import-of-type-ir-traits.rs:12:13
+   |
+LL |     let _ = cx.trait_is_unsafe(did);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler
+note: the lint level is defined here
+  --> $DIR/import-of-type-ir-traits.rs:5:9
+   |
+LL | #![deny(rustc::usage_of_type_ir_traits)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 37e328a315f..4a866560e79 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -114,7 +114,6 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                     rules: BlockCheckMode::Default,
                     span: DUMMY_SP,
                     tokens: None,
-                    could_be_bare_literal: false,
                 });
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
             }
diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
index cffb41742b4..0a579a07cef 100644
--- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
@@ -18,6 +18,7 @@ extern crate stable_mir;
 
 use rustc_smir::rustc_internal;
 use stable_mir::mir::MirVisitor;
+use stable_mir::mir::MutMirVisitor;
 use stable_mir::*;
 use std::collections::HashSet;
 use std::io::Write;
@@ -99,6 +100,83 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> {
     }
 }
 
+fn test_mut_visitor() -> ControlFlow<()> {
+    let main_fn = stable_mir::entry_fn();
+    let mut main_body = main_fn.unwrap().expect_body();
+    let locals = main_body.locals().to_vec();
+    let mut main_visitor = TestMutVisitor::collect(locals);
+    main_visitor.visit_body(&mut main_body);
+    assert!(main_visitor.ret_val.is_some());
+    assert!(main_visitor.args.is_empty());
+    assert!(main_visitor.tys.contains(&main_visitor.ret_val.unwrap().ty));
+    assert!(!main_visitor.calls.is_empty());
+
+    let exit_fn = main_visitor.calls.last().unwrap();
+    assert!(exit_fn.mangled_name().contains("exit_fn"), "Unexpected last function: {exit_fn:?}");
+
+    let mut exit_body = exit_fn.body().unwrap();
+    let locals = exit_body.locals().to_vec();
+    let mut exit_visitor = TestMutVisitor::collect(locals);
+    exit_visitor.visit_body(&mut exit_body);
+    assert!(exit_visitor.ret_val.is_some());
+    assert_eq!(exit_visitor.args.len(), 1);
+    assert!(exit_visitor.tys.contains(&exit_visitor.ret_val.unwrap().ty));
+    assert!(exit_visitor.tys.contains(&exit_visitor.args[0].ty));
+    ControlFlow::Continue(())
+}
+
+struct TestMutVisitor {
+    locals: Vec<mir::LocalDecl>,
+    pub tys: HashSet<ty::Ty>,
+    pub ret_val: Option<mir::LocalDecl>,
+    pub args: Vec<mir::LocalDecl>,
+    pub calls: Vec<mir::mono::Instance>,
+}
+
+impl TestMutVisitor {
+    fn collect(locals: Vec<mir::LocalDecl>) -> TestMutVisitor {
+        let visitor = TestMutVisitor {
+            locals: locals,
+            tys: Default::default(),
+            ret_val: None,
+            args: vec![],
+            calls: vec![],
+        };
+        visitor
+    }
+}
+
+impl mir::MutMirVisitor for TestMutVisitor {
+    fn visit_ty(&mut self, ty: &mut ty::Ty, _location: mir::visit::Location) {
+        self.tys.insert(*ty);
+        self.super_ty(ty)
+    }
+
+    fn visit_ret_decl(&mut self, local: mir::Local, decl: &mut mir::LocalDecl) {
+        assert!(local == mir::RETURN_LOCAL);
+        assert!(self.ret_val.is_none());
+        self.ret_val = Some(decl.clone());
+        self.super_ret_decl(local, decl);
+    }
+
+    fn visit_arg_decl(&mut self, local: mir::Local, decl: &mut mir::LocalDecl) {
+        self.args.push(decl.clone());
+        assert_eq!(local, self.args.len());
+        self.super_arg_decl(local, decl);
+    }
+
+    fn visit_terminator(&mut self, term: &mut mir::Terminator, location: mir::visit::Location) {
+        if let mir::TerminatorKind::Call { func, .. } = &mut term.kind {
+            let ty::TyKind::RigidTy(ty) = func.ty(&self.locals).unwrap().kind() else {
+                unreachable!()
+            };
+            let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() };
+            self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap());
+        }
+        self.super_terminator(term, location);
+    }
+}
+
 /// This test will generate and analyze a dummy crate using the stable mir.
 /// For that, it will first write the dummy crate into a file.
 /// Then it will create a `StableMir` using custom arguments and then
@@ -113,7 +191,8 @@ fn main() {
         CRATE_NAME.to_string(),
         path.to_string(),
     ];
-    run!(args, test_visitor).unwrap();
+    run!(args.clone(), test_visitor).unwrap();
+    run!(args, test_mut_visitor).unwrap();
 }
 
 fn generate_input(path: &str) -> std::io::Result<()> {
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 64e65ece85d..be649029c86 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -62,7 +62,6 @@
 //@[nvptx64] needs-llvm-components: nvptx
 #![feature(no_core, rustc_attrs, lang_items)]
 #![feature(unsized_fn_params, transparent_unions)]
-#![no_std]
 #![no_core]
 #![allow(unused, improper_ctypes_definitions, internal_features)]
 
diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs
index acab74300b8..fa4b3ba3054 100644
--- a/tests/ui/abi/simd-abi-checks-avx.rs
+++ b/tests/ui/abi/simd-abi-checks-avx.rs
@@ -1,6 +1,7 @@
 //@ only-x86_64
 //@ build-pass
 //@ ignore-pass (test emits codegen-time warnings)
+//@ compile-flags: -C target-feature=-avx
 
 #![feature(avx512_target_feature)]
 #![feature(portable_simd)]
diff --git a/tests/ui/abi/simd-abi-checks-avx.stderr b/tests/ui/abi/simd-abi-checks-avx.stderr
index 0dddc7dfa1c..5419970f809 100644
--- a/tests/ui/abi/simd-abi-checks-avx.stderr
+++ b/tests/ui/abi/simd-abi-checks-avx.stderr
@@ -1,5 +1,5 @@
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:64:11
+  --> $DIR/simd-abi-checks-avx.rs:65:11
    |
 LL |         f(g());
    |           ^^^ function called here
@@ -10,7 +10,7 @@ LL |         f(g());
    = note: `#[warn(abi_unsupported_vector_types)]` on by default
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:64:9
+  --> $DIR/simd-abi-checks-avx.rs:65:9
    |
 LL |         f(g());
    |         ^^^^^^ function called here
@@ -20,7 +20,7 @@ LL |         f(g());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:72:14
+  --> $DIR/simd-abi-checks-avx.rs:73:14
    |
 LL |         gavx(favx());
    |              ^^^^^^ function called here
@@ -30,7 +30,7 @@ LL |         gavx(favx());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:72:9
+  --> $DIR/simd-abi-checks-avx.rs:73:9
    |
 LL |         gavx(favx());
    |         ^^^^^^^^^^^^ function called here
@@ -40,7 +40,7 @@ LL |         gavx(favx());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:84:19
+  --> $DIR/simd-abi-checks-avx.rs:85:19
    |
 LL |         w(Wrapper(g()));
    |                   ^^^ function called here
@@ -50,7 +50,7 @@ LL |         w(Wrapper(g()));
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:84:9
+  --> $DIR/simd-abi-checks-avx.rs:85:9
    |
 LL |         w(Wrapper(g()));
    |         ^^^^^^^^^^^^^^^ function called here
@@ -60,7 +60,7 @@ LL |         w(Wrapper(g()));
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:100:9
+  --> $DIR/simd-abi-checks-avx.rs:101:9
    |
 LL |         some_extern();
    |         ^^^^^^^^^^^^^ function called here
@@ -70,7 +70,7 @@ LL |         some_extern();
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:27:1
+  --> $DIR/simd-abi-checks-avx.rs:28:1
    |
 LL | unsafe extern "C" fn g() -> __m256 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -80,7 +80,7 @@ LL | unsafe extern "C" fn g() -> __m256 {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:21:1
+  --> $DIR/simd-abi-checks-avx.rs:22:1
    |
 LL | unsafe extern "C" fn f(_: __m256) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -90,7 +90,7 @@ LL | unsafe extern "C" fn f(_: __m256) {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:15:1
+  --> $DIR/simd-abi-checks-avx.rs:16:1
    |
 LL | unsafe extern "C" fn w(_: Wrapper) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -100,7 +100,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:57:8
+  --> $DIR/simd-abi-checks-avx.rs:58:8
    |
 LL |     || g()
    |        ^^^ function called here
@@ -113,7 +113,7 @@ warning: 11 warnings emitted
 
 Future incompatibility report: Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:64:11
+  --> $DIR/simd-abi-checks-avx.rs:65:11
    |
 LL |         f(g());
    |           ^^^ function called here
@@ -125,7 +125,7 @@ LL |         f(g());
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:64:9
+  --> $DIR/simd-abi-checks-avx.rs:65:9
    |
 LL |         f(g());
    |         ^^^^^^ function called here
@@ -137,7 +137,7 @@ LL |         f(g());
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:72:14
+  --> $DIR/simd-abi-checks-avx.rs:73:14
    |
 LL |         gavx(favx());
    |              ^^^^^^ function called here
@@ -149,7 +149,7 @@ LL |         gavx(favx());
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:72:9
+  --> $DIR/simd-abi-checks-avx.rs:73:9
    |
 LL |         gavx(favx());
    |         ^^^^^^^^^^^^ function called here
@@ -161,7 +161,7 @@ LL |         gavx(favx());
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:84:19
+  --> $DIR/simd-abi-checks-avx.rs:85:19
    |
 LL |         w(Wrapper(g()));
    |                   ^^^ function called here
@@ -173,7 +173,7 @@ LL |         w(Wrapper(g()));
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:84:9
+  --> $DIR/simd-abi-checks-avx.rs:85:9
    |
 LL |         w(Wrapper(g()));
    |         ^^^^^^^^^^^^^^^ function called here
@@ -185,7 +185,7 @@ LL |         w(Wrapper(g()));
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:100:9
+  --> $DIR/simd-abi-checks-avx.rs:101:9
    |
 LL |         some_extern();
    |         ^^^^^^^^^^^^^ function called here
@@ -197,7 +197,7 @@ LL |         some_extern();
 
 Future breakage diagnostic:
 warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:27:1
+  --> $DIR/simd-abi-checks-avx.rs:28:1
    |
 LL | unsafe extern "C" fn g() -> __m256 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -209,7 +209,7 @@ LL | unsafe extern "C" fn g() -> __m256 {
 
 Future breakage diagnostic:
 warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:21:1
+  --> $DIR/simd-abi-checks-avx.rs:22:1
    |
 LL | unsafe extern "C" fn f(_: __m256) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -221,7 +221,7 @@ LL | unsafe extern "C" fn f(_: __m256) {
 
 Future breakage diagnostic:
 warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:15:1
+  --> $DIR/simd-abi-checks-avx.rs:16:1
    |
 LL | unsafe extern "C" fn w(_: Wrapper) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -233,7 +233,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) {
 
 Future breakage diagnostic:
 warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:57:8
+  --> $DIR/simd-abi-checks-avx.rs:58:8
    |
 LL |     || g()
    |        ^^^ function called here
diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs
index 424ac00edcf..3743c75bf1e 100644
--- a/tests/ui/abi/simd-abi-checks-s390x.rs
+++ b/tests/ui/abi/simd-abi-checks-s390x.rs
@@ -1,7 +1,7 @@
 //@ add-core-stubs
 //@ revisions: z10 z13_no_vector z13_soft_float
 //@ build-fail
-//@[z10] compile-flags: --target s390x-unknown-linux-gnu
+//@[z10] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10
 //@[z10] needs-llvm-components: systemz
 //@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector
 //@[z13_no_vector] needs-llvm-components: systemz
diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs
index adbda369b6a..78f30d50d8c 100644
--- a/tests/ui/asm/inline-syntax.rs
+++ b/tests/ui/asm/inline-syntax.rs
@@ -58,3 +58,8 @@ pub fn main() {
 global_asm!(".intel_syntax noprefix", "nop");
 //[x86_64]~^ WARN avoid using `.intel_syntax`
 // Global assembly errors don't have line numbers, so no error on ARM.
+
+//[arm_llvm_18]~? ERROR unknown directive
+//[arm_llvm_18]~? ERROR unknown directive
+//[arm]~? ERROR unknown directive
+//[arm]~? ERROR unknown directive
diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs
new file mode 100644
index 00000000000..afe1a389147
--- /dev/null
+++ b/tests/ui/asm/naked-functions-target-feature.rs
@@ -0,0 +1,21 @@
+//@ build-pass
+//@ needs-asm-support
+
+#![feature(naked_functions, naked_functions_target_feature)]
+#![crate_type = "lib"]
+
+use std::arch::{asm, naked_asm};
+
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse2")]
+#[naked]
+pub unsafe extern "C" fn compatible_target_feature() {
+    naked_asm!("");
+}
+
+#[cfg(target_arch = "aarch64")]
+#[target_feature(enable = "neon")]
+#[naked]
+pub unsafe extern "C" fn compatible_target_feature() {
+    naked_asm!("");
+}
diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs
index e7e5d84f2a5..3d4d414539c 100644
--- a/tests/ui/asm/naked-functions.rs
+++ b/tests/ui/asm/naked-functions.rs
@@ -230,13 +230,6 @@ pub unsafe extern "C" fn compatible_codegen_attributes() {
     naked_asm!("", options(raw));
 }
 
-#[cfg(target_arch = "x86_64")]
-#[target_feature(enable = "sse2")]
-#[naked]
-pub unsafe extern "C" fn compatible_target_feature() {
-    naked_asm!("");
-}
-
 #[doc = "foo bar baz"]
 /// a doc comment
 // a normal comment
diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr
index 372d379de5a..64304be9d6b 100644
--- a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.stderr
+++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr
@@ -1,12 +1,12 @@
 error[E0283]: type annotations needed
-  --> $DIR/dedup-normalized-2-higher-ranked.rs:23:5
+  --> $DIR/dedup-normalized-2-higher-ranked.rs:28:5
    |
 LL |     impls(rigid);
    |     ^^^^^ cannot infer type of the type parameter `U` declared on the function `impls`
    |
    = note: cannot satisfy `for<'b> <P as Trait>::Rigid: Bound<'b, _>`
 note: required by a bound in `impls`
-  --> $DIR/dedup-normalized-2-higher-ranked.rs:20:13
+  --> $DIR/dedup-normalized-2-higher-ranked.rs:25:13
    |
 LL | fn impls<T: for<'b> Bound<'b, U>, U>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls`
diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs
index 9224d47d30f..32b8c689248 100644
--- a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs
+++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.rs
@@ -1,3 +1,8 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
 // We try to prove `for<'b> T::Rigid: Bound<'b, ?0>` and have 2 candidates from where-clauses:
 //
 // - `for<'a> Bound<'a, String>`
@@ -21,7 +26,7 @@ fn impls<T: for<'b> Bound<'b, U>, U>(_: T) {}
 
 fn test<P: Trait>(rigid: P::Rigid) {
     impls(rigid);
-    //~^ ERROR type annotations needed
+    //[current]~^ ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
deleted file mode 100644
index 9082044fe06..00000000000
--- a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/bound-lifetime-constrained.rs:48:1
-   |
-LL | fn main() { }
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs
index 1dc3b2f5c2b..3a5a77f57f2 100644
--- a/tests/ui/associated-types/bound-lifetime-constrained.rs
+++ b/tests/ui/associated-types/bound-lifetime-constrained.rs
@@ -1,7 +1,7 @@
 //@ revisions: func object clause ok
+//@[ok] check-pass
 
 #![allow(dead_code)]
-#![feature(rustc_attrs)]
 
 trait Foo<'a> {
     type Item;
@@ -44,5 +44,4 @@ fn clause2<T>() where T: for<'a> Fn() -> <() as Foo<'a>>::Item {
     //[clause]~^ ERROR `Output` references lifetime `'a`
 }
 
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
deleted file mode 100644
index 435e224bd89..00000000000
--- a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/bound-lifetime-in-binding-only.rs:71:1
-   |
-LL | fn main() { }
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
index e973e58b629..2401fe0ef1f 100644
--- a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
+++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs
@@ -1,7 +1,7 @@
 //@ revisions: angle paren ok elision
+//@[ok] check-pass
 
 #![allow(dead_code)]
-#![feature(rustc_attrs)]
 #![feature(unboxed_closures)]
 
 trait Foo {
@@ -67,5 +67,4 @@ fn ok2<T: for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() {
 fn ok3<T>() where for<'a> Parameterized<'a>: Foo<Item=&'a i32> {
 }
 
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
deleted file mode 100644
index 1815a7be7ee..00000000000
--- a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/bound-lifetime-in-return-only.rs:49:1
-   |
-LL | fn main() { }
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.rs b/tests/ui/associated-types/bound-lifetime-in-return-only.rs
index bf3aa6149cc..8a28f5b7786 100644
--- a/tests/ui/associated-types/bound-lifetime-in-return-only.rs
+++ b/tests/ui/associated-types/bound-lifetime-in-return-only.rs
@@ -1,7 +1,7 @@
 //@ revisions: sig local structure ok elision
+//@[ok] check-pass
 
 #![allow(dead_code)]
-#![feature(rustc_attrs)]
 #![feature(unboxed_closures)]
 
 trait Foo {
@@ -45,5 +45,4 @@ fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) {
 fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) {
 }
 
-#[rustc_error]
-fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error]
+fn main() { }
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index f5e696b7ac1..f79afc89d10 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -36,11 +36,18 @@ LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
+
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/issue-59324.rs:24:29
    |
-help: consider further restricting type parameter `Bug` with trait `Foo`
+LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
    |
-LL | pub trait ThriftService<Bug: NotFoo + Foo>:
-   |                                     +++++
+help: this trait has no implementations, consider adding one
+  --> $DIR/issue-59324.rs:3:1
+   |
+LL | pub trait Foo: NotFoo {
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
   --> $DIR/issue-59324.rs:16:5
@@ -51,18 +58,11 @@ LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
-
-error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:24:29
    |
-LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
-   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
-   |
-help: this trait has no implementations, consider adding one
-  --> $DIR/issue-59324.rs:3:1
+help: consider further restricting type parameter `Bug` with trait `Foo`
    |
-LL | pub trait Foo: NotFoo {
-   | ^^^^^^^^^^^^^^^^^^^^^
+LL | pub trait ThriftService<Bug: NotFoo + Foo>:
+   |                                     +++++
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
   --> $DIR/issue-59324.rs:20:10
diff --git a/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs
new file mode 100644
index 00000000000..ecfc06d2bad
--- /dev/null
+++ b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ compile-flags: -Zinline-mir -Zvalidate-mir
+//@ edition: 2024
+
+// See comment below.
+
+use std::future::Future;
+use std::pin::pin;
+use std::task::{Context, Waker};
+
+fn call_once<T>(f: impl FnOnce() -> T) -> T { f() }
+
+fn main() {
+    let x = async || {};
+    // We first inline `call_once<{async closure}>`.
+    //
+    // This gives us a future whose type is the "FnOnce" flavor of the async closure's
+    // child coroutine. The body of this coroutine is synthetic, which we synthesize in
+    // the by-move body query.
+    let fut = pin!(call_once(x));
+    // We then try to inline that body in this poll call.
+    //
+    // The inliner does some inlinability checks; one of these checks involves checking
+    // the body for the `#[rustc_no_mir_inline]` attribute. Since the synthetic body had
+    // no HIR synthesized, but it's still a local def id, we end up ICEing in the
+    // `local_def_id_to_hir_id` call when trying to read its attrs.
+    fut.poll(&mut Context::from_waker(Waker::noop()));
+}
diff --git a/tests/ui/attributes/crate-name-empty.rs b/tests/ui/attributes/crate-name-empty.rs
new file mode 100644
index 00000000000..dfba77a52de
--- /dev/null
+++ b/tests/ui/attributes/crate-name-empty.rs
@@ -0,0 +1,5 @@
+// Ensure we reject `#![crate_name = ""]`.
+
+#![crate_name = ""] //~ ERROR crate name must not be empty
+
+fn main() {}
diff --git a/tests/ui/attributes/crate-name-empty.stderr b/tests/ui/attributes/crate-name-empty.stderr
new file mode 100644
index 00000000000..509a42d05f7
--- /dev/null
+++ b/tests/ui/attributes/crate-name-empty.stderr
@@ -0,0 +1,8 @@
+error: crate name must not be empty
+  --> $DIR/crate-name-empty.rs:3:1
+   |
+LL | #![crate_name = ""]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/dont-dup-expr-attrs.rs b/tests/ui/attributes/dont-dup-expr-attrs.rs
new file mode 100644
index 00000000000..21da6820a53
--- /dev/null
+++ b/tests/ui/attributes/dont-dup-expr-attrs.rs
@@ -0,0 +1,133 @@
+//@ check-pass
+//
+// During development of #124141 at one point expression on attributes were
+// being duplicated and `m1` caused an exponential blowup that caused OOM.
+// The number of recursive calls depends on the number of doc comments on the
+// expr block. On each recursive call, the `#[allow(deprecated)]` attribute(s) on
+// the `0` somehow get duplicated, resulting in 1, 2, 4, 8, ... identical
+// attributes.
+//
+// After the fix, the code compiles quickly and normally.
+
+macro_rules! m1 {
+    ($(#[$meta:meta])* { $e:expr }) => {
+        m1! { expr: { $e }, unprocessed: [$(#[$meta])*] }
+    };
+
+    (expr: { $e:expr }, unprocessed: [ #[$meta:meta] $($metas:tt)* ]) => {
+        m1! { expr: { $e }, unprocessed: [ $($metas)* ] }
+    };
+
+    (expr: { $e:expr }, unprocessed: []) => {
+        { $e }
+    }
+}
+
+macro_rules! m2 {
+    ($(#[$meta:meta])* { $e:stmt }) => {
+        m2! { stmt: { $e }, unprocessed: [$(#[$meta])*] }
+    };
+
+    (stmt: { $e:stmt }, unprocessed: [ #[$meta:meta] $($metas:tt)* ]) => {
+        m2! { stmt: { $e }, unprocessed: [ $($metas)* ] }
+    };
+
+    (stmt: { $e:stmt }, unprocessed: []) => {
+        { $e }
+    }
+}
+
+macro_rules! m3 {
+    ($(#[$meta:meta])* { $e:item }) => {
+        m3! { item: { $e }, unprocessed: [$(#[$meta])*] }
+    };
+
+    (item: { $e:item }, unprocessed: [ #[$meta:meta] $($metas:tt)* ]) => {
+        m3! { item: { $e }, unprocessed: [ $($metas)* ] }
+    };
+
+    (item: { $e:item }, unprocessed: []) => {
+        { $e }
+    }
+}
+
+fn main() {
+    // Each additional doc comment line doubles the compile time.
+    m1!(
+        /// a1
+        /// a2
+        /// a3
+        /// a4
+        /// a5
+        /// a6
+        /// a7
+        /// a8
+        /// a9
+        /// a10
+        /// a11
+        /// a12
+        /// a13
+        /// a14
+        /// a15
+        /// a16
+        /// a17
+        /// a18
+        /// a19
+        /// a20
+        {
+            #[allow(deprecated)] 0
+        }
+    );
+
+    m2!(
+        /// a1
+        /// a2
+        /// a3
+        /// a4
+        /// a5
+        /// a6
+        /// a7
+        /// a8
+        /// a9
+        /// a10
+        /// a11
+        /// a12
+        /// a13
+        /// a14
+        /// a15
+        /// a16
+        /// a17
+        /// a18
+        /// a19
+        /// a20
+        {
+            #[allow(deprecated)] let x = 5
+        }
+    );
+
+    m3!(
+        /// a1
+        /// a2
+        /// a3
+        /// a4
+        /// a5
+        /// a6
+        /// a7
+        /// a8
+        /// a9
+        /// a10
+        /// a11
+        /// a12
+        /// a13
+        /// a14
+        /// a15
+        /// a16
+        /// a17
+        /// a18
+        /// a19
+        /// a20
+        {
+            #[allow(deprecated)] struct S;
+        }
+    );
+}
diff --git a/tests/ui/attributes/inner-attr-metavar.rs b/tests/ui/attributes/inner-attr-metavar.rs
new file mode 100644
index 00000000000..345121c252e
--- /dev/null
+++ b/tests/ui/attributes/inner-attr-metavar.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+//
+// During `Nonterminal` removal (#124141) there was at one point a problem with
+// calling from_ast on expressions with inner attributes within metavars -- the
+// inner attributes were being inserted in the wrong place in `from_ast`. This
+// test covers that case.
+
+macro_rules! m3 { ($e:expr) => {} }
+macro_rules! m2 { ($e:expr) => { m3!($e); } }
+macro_rules! m1 { ($e:expr) => { m2!($e); } }
+
+m1!({ #![allow(unused)] 0 });
+
+fn main() {}
diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs
index 83c8f00999a..004a8a23fd6 100644
--- a/tests/ui/attributes/nonterminal-expansion.rs
+++ b/tests/ui/attributes/nonterminal-expansion.rs
@@ -5,8 +5,7 @@
 macro_rules! pass_nonterminal {
     ($n:expr) => {
         #[repr(align($n))]
-        //~^ ERROR expected unsuffixed literal, found expression `n!()`
-        //~^^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693]
+        //~^ ERROR expected unsuffixed literal, found `expr` metavariable
         struct S;
     };
 }
@@ -16,5 +15,6 @@ macro_rules! n {
 }
 
 pass_nonterminal!(n!());
+//~^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693]
 
 fn main() {}
diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr
index 8a85731bd5a..9c6cb98f619 100644
--- a/tests/ui/attributes/nonterminal-expansion.stderr
+++ b/tests/ui/attributes/nonterminal-expansion.stderr
@@ -1,4 +1,4 @@
-error: expected unsuffixed literal, found expression `n!()`
+error: expected unsuffixed literal, found `expr` metavariable
   --> $DIR/nonterminal-expansion.rs:7:22
    |
 LL |         #[repr(align($n))]
@@ -10,15 +10,10 @@ LL | pass_nonterminal!(n!());
    = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument
-  --> $DIR/nonterminal-expansion.rs:7:22
+  --> $DIR/nonterminal-expansion.rs:17:19
    |
-LL |         #[repr(align($n))]
-   |                      ^^
-...
 LL | pass_nonterminal!(n!());
-   | ----------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                   ^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
index 6f323d91227..9d323bf0324 100644
--- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
+++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
@@ -1,6 +1,5 @@
-#![feature(rustc_attrs)]
 #![allow(dead_code)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     // Original borrow ends at end of function
     let mut x = 1;
     let y = &mut x;
diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
index db73d4c04ac..444a74cbfcf 100644
--- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
+++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:7:13
    |
 LL |     let y = &mut x;
    |             ------ mutable borrow occurs here
@@ -11,7 +11,7 @@ LL |     y.use_mut();
    |     - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:20:21
    |
 LL |             let y = &x;
    |                     -- immutable borrow occurs here
@@ -23,7 +23,7 @@ LL |             y.use_ref();
    |             - immutable borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:35:17
    |
 LL |         let y = &mut x;
    |                 ------ first mutable borrow occurs here
diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.rs b/tests/ui/borrowck/mut-borrow-outside-loop.rs
index c02bfbf8739..3cc362def38 100644
--- a/tests/ui/borrowck/mut-borrow-outside-loop.rs
+++ b/tests/ui/borrowck/mut-borrow-outside-loop.rs
@@ -1,6 +1,6 @@
 // ensure borrowck messages are correct outside special case
-#![feature(rustc_attrs)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+
+fn main() {
     let mut void = ();
 
     let first = &mut void;
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs
deleted file mode 100644
index cfc0a97989d..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Combination of `ptr-to-trait-obj-wrap.rs` and `ptr-to-trait-obj-add-auto.rs`.
-//
-// Checks that you *can't* add auto traits to trait object in pointer casts involving wrapping said
-// traits structures.
-
-trait A {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap(a: *const W<dyn A>) -> *const (dyn A + Send) {
-    a as _
-    //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn unwrap_nested(a: *const W<W<dyn A>>) -> *const W<dyn A + Send> {
-    a as _
-    //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn rewrap(a: *const W<dyn A>) -> *const X<dyn A + Send> {
-    a as _
-    //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn rewrap_nested(a: *const W<W<dyn A>>) -> *const W<X<dyn A + Send>> {
-    a as _
-    //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn wrap(a: *const dyn A) -> *const W<dyn A + Send> {
-    a as _
-    //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr
deleted file mode 100644
index 42cdbc34ee8..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
-  --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:12:5
-   |
-LL |     a as _
-   |     ^^^^^^ unsupported cast
-   |
-   = note: this could allow UB elsewhere
-   = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
-  --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:17:5
-   |
-LL |     a as _
-   |     ^^^^^^ unsupported cast
-   |
-   = note: this could allow UB elsewhere
-   = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
-  --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:22:5
-   |
-LL |     a as _
-   |     ^^^^^^ unsupported cast
-   |
-   = note: this could allow UB elsewhere
-   = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
-  --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:27:5
-   |
-LL |     a as _
-   |     ^^^^^^ unsupported cast
-   |
-   = note: this could allow UB elsewhere
-   = help: use `transmute` if you're sure this is sound
-
-error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast
-  --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:32:5
-   |
-LL |     a as _
-   |     ^^^^^^ unsupported cast
-   |
-   = note: this could allow UB elsewhere
-   = help: use `transmute` if you're sure this is sound
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0804`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs
deleted file mode 100644
index ebe7a06a7a1..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Combination of `ptr-to-trait-obj-different-args.rs` and `ptr-to-trait-obj-wrap.rs`.
-//
-// Checks that you *can't* change type arguments of trait objects in pointer casts involving
-// wrapping said traits structures.
-
-trait A<T> {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap<F, G>(a: *const W<dyn A<F>>) -> *const dyn A<G> {
-    a as _
-    //~^ error casting `*const W<(dyn A<F> + 'static)>` as `*const dyn A<G>` is invalid
-}
-
-fn unwrap_nested<F, G>(a: *const W<W<dyn A<F>>>) -> *const W<dyn A<G>> {
-    a as _
-    //~^ error casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<dyn A<G>>` is invalid
-}
-
-fn rewrap<F, G>(a: *const W<dyn A<F>>) -> *const X<dyn A<G>> {
-    a as _
-    //~^ error: casting `*const W<(dyn A<F> + 'static)>` as `*const X<dyn A<G>>` is invalid
-}
-
-fn rewrap_nested<F, G>(a: *const W<W<dyn A<F>>>) -> *const W<X<dyn A<G>>> {
-    a as _
-    //~^ error: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<X<dyn A<G>>>` is invalid
-}
-
-fn wrap<F, G>(a: *const dyn A<F>) -> *const W<dyn A<G>> {
-    a as _
-    //~^ error: casting `*const (dyn A<F> + 'static)` as `*const W<dyn A<G>>` is invalid
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr
deleted file mode 100644
index 4f85b208d05..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0606]: casting `*const W<(dyn A<F> + 'static)>` as `*const dyn A<G>` is invalid
-  --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:12:5
-   |
-LL |     a as _
-   |     ^^^^^^
-   |
-   = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<dyn A<G>>` is invalid
-  --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:17:5
-   |
-LL |     a as _
-   |     ^^^^^^
-   |
-   = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<(dyn A<F> + 'static)>` as `*const X<dyn A<G>>` is invalid
-  --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:22:5
-   |
-LL |     a as _
-   |     ^^^^^^
-   |
-   = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const W<W<(dyn A<F> + 'static)>>` as `*const W<X<dyn A<G>>>` is invalid
-  --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:27:5
-   |
-LL |     a as _
-   |     ^^^^^^
-   |
-   = note: the trait objects may have different vtables
-
-error[E0606]: casting `*const (dyn A<F> + 'static)` as `*const W<dyn A<G>>` is invalid
-  --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:32:5
-   |
-LL |     a as _
-   |     ^^^^^^
-   |
-   = note: the trait objects may have different vtables
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs
deleted file mode 100644
index b0941277d01..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Combination of `ptr-to-trait-obj-different-regions-misc.rs` and `ptr-to-trait-obj-wrap.rs`.
-//
-// Checks that you *can't* change lifetime arguments of trait objects in pointer casts involving
-// wrapping said traits structures.
-
-trait A<'a> {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
-    a as _
-    //~^ error
-    //~| error
-}
-
-fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
-    a as _
-    //~^ error
-    //~| error
-}
-
-fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
-    a as _
-    //~^ error: lifetime may not live long enough
-    //~| error: lifetime may not live long enough
-}
-
-fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
-    a as _
-    //~^ error: lifetime may not live long enough
-    //~| error: lifetime may not live long enough
-}
-
-fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
-    a as _
-    //~^ error: lifetime may not live long enough
-    //~| error: lifetime may not live long enough
-}
-
-fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr
deleted file mode 100644
index 17a0ca3c34f..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr
+++ /dev/null
@@ -1,140 +0,0 @@
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5
-   |
-LL | fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5
-   |
-LL | fn unwrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const dyn A<'b> {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5
-   |
-LL | fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
-   |                  --  -- lifetime `'b` defined here
-   |                  |
-   |                  lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5
-   |
-LL | fn unwrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<dyn A<'b>> {
-   |                  --  -- lifetime `'b` defined here
-   |                  |
-   |                  lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5
-   |
-LL | fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5
-   |
-LL | fn rewrap<'a, 'b>(a: *const W<dyn A<'a>>) -> *const X<dyn A<'b>> {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5
-   |
-LL | fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
-   |                  --  -- lifetime `'b` defined here
-   |                  |
-   |                  lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5
-   |
-LL | fn rewrap_nested<'a, 'b>(a: *const W<W<dyn A<'a>>>) -> *const W<X<dyn A<'b>>> {
-   |                  --  -- lifetime `'b` defined here
-   |                  |
-   |                  lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5
-   |
-LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
-   |         --  -- lifetime `'b` defined here
-   |         |
-   |         lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
-   |
-   = help: consider adding the following bound: `'b: 'a`
-
-error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5
-   |
-LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W<dyn A<'b>> {
-   |         --  -- lifetime `'b` defined here
-   |         |
-   |         lifetime `'a` defined here
-LL |     a as _
-   |     ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
-   |
-   = help: consider adding the following bound: `'a: 'b`
-
-help: `'b` and `'a` must be the same: replace one with the other
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors
-
diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap.rs b/tests/ui/cast/ptr-to-trait-obj-wrap.rs
deleted file mode 100644
index 9809ea80f95..00000000000
--- a/tests/ui/cast/ptr-to-trait-obj-wrap.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Checks that various casts of pointers to trait objects wrapped in structures
-// work. Note that the metadata doesn't change when a DST is wrapped in a
-// structure, so these casts *are* fine.
-//
-//@ check-pass
-
-trait A {}
-
-struct W<T: ?Sized>(T);
-struct X<T: ?Sized>(T);
-
-fn unwrap(a: *const W<dyn A>) -> *const dyn A {
-    a as _
-}
-
-fn unwrap_nested(a: *const W<W<dyn A>>) -> *const W<dyn A> {
-    a as _
-}
-
-fn rewrap(a: *const W<dyn A>) -> *const X<dyn A> {
-    a as _
-}
-
-fn rewrap_nested(a: *const W<W<dyn A>>) -> *const W<X<dyn A>> {
-    a as _
-}
-
-fn wrap(a: *const dyn A) -> *const W<dyn A> {
-    a as _
-}
-
-fn main() {}
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
index cae9c65cb45..e9661abf3ab 100644
--- a/tests/ui/cfg/disallowed-cli-cfgs.rs
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -37,3 +37,5 @@
 //@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh
 
 fn main() {}
+
+//~? ERROR unexpected `--cfg
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index e7b8f355057..b07d630e5f5 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value`
 LL | #[cfg(target_vendor = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 95af0a90929..80f8f36c23f 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value`
 LL | #[cfg(target_vendor = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 95af0a90929..80f8f36c23f 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value`
 LL | #[cfg(target_vendor = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs
index c6b1218ce27..3bea128e3e4 100644
--- a/tests/ui/check-cfg/invalid-arguments.rs
+++ b/tests/ui/check-cfg/invalid-arguments.rs
@@ -36,3 +36,5 @@
 //@ [unsafe_attr]compile-flags: --check-cfg=unsafe(cfg(foo))
 
 fn main() {}
+
+//~? ERROR invalid `--check-cfg` argument
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index a9d67481ba1..aa5fd09c0c7 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -17,11 +17,16 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `aes`
 `altivec`
 `alu32`
+`amx-avx512`
 `amx-bf16`
 `amx-complex`
 `amx-fp16`
+`amx-fp8`
 `amx-int8`
+`amx-movrs`
+`amx-tf32`
 `amx-tile`
+`amx-transpose`
 `atomics`
 `avx`
 `avx2`
@@ -152,6 +157,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `mclass`
 `mops`
 `movbe`
+`movrs`
 `mp`
 `mp1e2`
 `msa`
@@ -245,6 +251,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `trustzone`
 `ual`
 `unaligned-scalar-mem`
+`unaligned-vector-mem`
 `v`
 `v5te`
 `v6`
@@ -317,6 +324,11 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `zfinx`
 `zhinx`
 `zhinxmin`
+`zicntr`
+`zicsr`
+`zifencei`
+`zihintpause`
+`zihpm`
 `zk`
 `zkn`
 `zknd`
@@ -325,7 +337,42 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `zkr`
 `zks`
 `zksed`
-`zksh`, and `zkt`
+`zksh`
+`zkt`
+`zvbb`
+`zvbc`
+`zve32f`
+`zve32x`
+`zve64d`
+`zve64f`
+`zve64x`
+`zvfh`
+`zvfhmin`
+`zvkb`
+`zvkg`
+`zvkn`
+`zvknc`
+`zvkned`
+`zvkng`
+`zvknha`
+`zvknhb`
+`zvks`
+`zvksc`
+`zvksed`
+`zvksg`
+`zvksh`
+`zvkt`
+`zvl1024b`
+`zvl128b`
+`zvl16384b`
+`zvl2048b`
+`zvl256b`
+`zvl32768b`
+`zvl32b`
+`zvl4096b`
+`zvl512b`
+`zvl64b`
+`zvl65536b`, and `zvl8192b`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index ba1900fcddb..4636b6945d0 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
+   = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/closures/upvar-or-pattern-issue-138958.rs b/tests/ui/closures/upvar-or-pattern-issue-138958.rs
new file mode 100644
index 00000000000..fe9ebc0a7e6
--- /dev/null
+++ b/tests/ui/closures/upvar-or-pattern-issue-138958.rs
@@ -0,0 +1,11 @@
+//@ edition:2024
+//@ check-pass
+
+pub fn f(x: (u32, u32)) {
+    let _ = || {
+        let ((0, a) | (a, _)) = x;
+        a
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs
index cff20dd9bd6..a446395de20 100644
--- a/tests/ui/codegen/duplicated-path-in-error.rs
+++ b/tests/ui/codegen/duplicated-path-in-error.rs
@@ -5,3 +5,5 @@
 // the path of the dylib.
 
 fn main() {}
+
+//~? ERROR couldn't load codegen backend /non-existing-one.so
diff --git a/tests/ui/codegen/empty-static-libs-issue-108825.rs b/tests/ui/codegen/empty-static-libs-issue-108825.rs
new file mode 100644
index 00000000000..46bd6d6b2da
--- /dev/null
+++ b/tests/ui/codegen/empty-static-libs-issue-108825.rs
@@ -0,0 +1,16 @@
+//! Test that linking a no_std application still outputs the
+//! `native-static-libs: ` note, even though it is empty.
+
+//@ compile-flags: -Cpanic=abort --print=native-static-libs
+//@ build-pass
+//@ error-pattern: note: native-static-libs:
+//@ dont-check-compiler-stderr (libcore links `/defaultlib:msvcrt` or `/defaultlib:libcmt` on MSVC)
+//@ ignore-pass (the note is emitted later in the compilation pipeline, needs build)
+
+#![crate_type = "staticlib"]
+#![no_std]
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
deleted file mode 100644
index eda83e999a5..00000000000
--- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//@ 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/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
deleted file mode 100644
index c7f46318aae..00000000000
--- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-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/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
deleted file mode 100644
index a02ff30918d..00000000000
--- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-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/codemap_tests/issue-11715.rs b/tests/ui/codemap_tests/issue-11715.rs
index 617d57ff75a..d0daaf444b3 100644
--- a/tests/ui/codemap_tests/issue-11715.rs
+++ b/tests/ui/codemap_tests/issue-11715.rs
@@ -1,5 +1,4 @@
-#![feature(rustc_attrs)]
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     let mut x = "foo";
     let y = &mut x;
     let z = &mut x; //~ ERROR cannot borrow
diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr
index 5d0cf718761..6b330560adb 100644
--- a/tests/ui/codemap_tests/issue-11715.stderr
+++ b/tests/ui/codemap_tests/issue-11715.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/issue-11715.rs:5:13
+  --> $DIR/issue-11715.rs:4:13
    |
 LL |     let y = &mut x;
    |             ------ first mutable borrow occurs here
diff --git a/tests/ui/coercion/struct-coerce-vec-to-slice.rs b/tests/ui/coercion/struct-coerce-vec-to-slice.rs
new file mode 100644
index 00000000000..9ef20ac4ea6
--- /dev/null
+++ b/tests/ui/coercion/struct-coerce-vec-to-slice.rs
@@ -0,0 +1,20 @@
+//! Regression test that ensures struct field literals can be coerced into slice and `Box` types
+
+//@ check-pass
+
+struct Thing1<'a> {
+    baz: &'a [Box<isize>],
+    bar: Box<u64>,
+}
+
+struct Thing2<'a> {
+    baz: &'a [Box<isize>],
+    bar: u64,
+}
+
+pub fn main() {
+    let _a = Thing1 { baz: &[], bar: Box::new(32) };
+    let _b = Thing1 { baz: &Vec::new(), bar: Box::new(32) };
+    let _c = Thing2 { baz: &[], bar: 32 };
+    let _d = Thing2 { baz: &Vec::new(), bar: 32 };
+}
diff --git a/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs
new file mode 100644
index 00000000000..0b8ec7dc07a
--- /dev/null
+++ b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs
@@ -0,0 +1,16 @@
+//! Regression test to check that literal expressions in a struct field can be coerced to the
+//! expected field type, including block expressions.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/31260>
+
+//@ check-pass
+
+pub struct Struct<K: 'static> {
+    pub field: K,
+}
+
+static STRUCT: Struct<&'static [u8]> = Struct { field: { &[1] } };
+
+static STRUCT2: Struct<&'static [u8]> = Struct { field: &[1] };
+
+fn main() {}
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
index 9a041557c7c..47418b4e091 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
@@ -28,8 +28,7 @@ struct S9;
 macro_rules! generate_s10 {
     ($expr: expr) => {
         #[cfg(feature = $expr)]
-        //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
-        //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")`
+        //~^ ERROR expected unsuffixed literal, found `expr` metavariable
         struct S10;
     }
 }
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index 21a3712d939..66ce2ee9858 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")]
    |           |
    |           help: consider removing the prefix
 
-error: expected unsuffixed literal, found expression `concat!("nonexistent")`
+error: expected unsuffixed literal, found `expr` metavariable
   --> $DIR/cfg-attr-syntax-validation.rs:30:25
    |
 LL |         #[cfg(feature = $expr)]
@@ -65,19 +65,7 @@ LL | generate_s10!(concat!("nonexistent"));
    |
    = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected unsuffixed literal, found expression `concat!("nonexistent")`
-  --> $DIR/cfg-attr-syntax-validation.rs:30:25
-   |
-LL |         #[cfg(feature = $expr)]
-   |                         ^^^^^
-...
-LL | generate_s10!(concat!("nonexistent"));
-   | ------------------------------------- in this macro invocation
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-   = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0537, E0565.
 For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
index 794e6fad3fc..7c42be3ed4d 100644
--- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
@@ -1,11 +1,12 @@
 // This was triggering an assertion failure in `NodeRange::new`.
 
+//@ check-pass
+
 #![feature(cfg_eval)]
 #![feature(stmt_expr_attributes)]
 
 fn f() -> u32 {
     #[cfg_eval] #[cfg(not(FALSE))] 0
-    //~^ ERROR removing an expression is not supported in this position
 }
 
 fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
deleted file mode 100644
index 0699e182bd5..00000000000
--- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: removing an expression is not supported in this position
-  --> $DIR/invalid-node-range-issue-129166.rs:7:17
-   |
-LL |     #[cfg_eval] #[cfg(not(FALSE))] 0
-   |                 ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.rs b/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.rs
new file mode 100644
index 00000000000..231bb5252de
--- /dev/null
+++ b/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.rs
@@ -0,0 +1,41 @@
+// compile-flags: -Znext-solver
+
+// Test for a weird diagnostics corner case. In the error reporting code, when reporting
+// fulfillment errors for goals A and B, we try to see if elaborating A will result in
+// another goal that can equate with B. That would signal that B is "implied by" A,
+// allowing us to skip reporting it, which is beneficial for cutting down on the number
+// of diagnostics we report. In the new trait solver especially, but even in the old trait
+// solver through things like defining opaque type usages, this `can_equate` call was not
+// properly taking the param-env of the goals, resulting in nested obligations that had
+// empty param-envs. If one of these nested obligations was a `ConstParamHasTy` goal, then
+// we would ICE, since those goals are particularly strict about the param-env they're
+// evaluated in.
+
+// This is morally a fix for <https://github.com/rust-lang/rust/issues/139314>, but that
+// repro uses details about how defining usages in the `check_opaque_well_formed` code
+// can spring out of type equality, and will likely stop failing soon coincidentally once
+// we start using `PostBorrowck` mode in that check.
+
+trait Foo: Baz<()> {}
+trait Baz<T> {}
+
+trait IdentityWithConstArgGoal<const N: usize> {
+    type Assoc;
+}
+impl<T, const N: usize> IdentityWithConstArgGoal<N> for T {
+    type Assoc = T;
+}
+
+fn unsatisfied<T, const N: usize>()
+where
+    T: Foo,
+    T: Baz<<T as IdentityWithConstArgGoal<N>>::Assoc>,
+{
+}
+
+fn test<const N: usize>() {
+    unsatisfied::<(), N>();
+    //~^ ERROR the trait bound `(): Foo` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.stderr b/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.stderr
new file mode 100644
index 00000000000..77bba494552
--- /dev/null
+++ b/tests/ui/const-generics/const-param-has-ty-goal-in-error-implies.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/const-param-has-ty-goal-in-error-implies.rs:37:19
+   |
+LL |     unsatisfied::<(), N>();
+   |                   ^^ the trait `Foo` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/const-param-has-ty-goal-in-error-implies.rs:19:1
+   |
+LL | trait Foo: Baz<()> {}
+   | ^^^^^^^^^^^^^^^^^^
+note: required by a bound in `unsatisfied`
+  --> $DIR/const-param-has-ty-goal-in-error-implies.rs:31:8
+   |
+LL | fn unsatisfied<T, const N: usize>()
+   |    ----------- required by a bound in this function
+LL | where
+LL |     T: Foo,
+   |        ^^^ required by this bound in `unsatisfied`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr
index 0c3e455eb2d..95821526835 100644
--- a/tests/ui/consts/assoc-const-elided-lifetime.stderr
+++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr
@@ -35,8 +35,6 @@ note: cannot automatically infer `'static` because of other lifetimes in scope
    |
 LL | impl<'a> Foo<'a> {
    |      ^^
-LL |     const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
-   |                    ^^
 help: use the `'static` lifetime
    |
 LL |     const BAR: &'static () = &();
diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs
index 40be4d195d4..1211a150f7d 100644
--- a/tests/ui/consts/async-block.rs
+++ b/tests/ui/consts/async-block.rs
@@ -2,8 +2,8 @@
 
 //@ edition:2018
 //@ revisions: with_feature without_feature
+//@[with_feature] check-pass
 
-#![feature(rustc_attrs)]
 #![cfg_attr(with_feature, feature(const_async_blocks))]
 
 use std::future::Future;
@@ -15,5 +15,4 @@ const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 };
 static _FUT: &(dyn Future<Output = ()> + Sync) = &async {};
 //[without_feature]~^ `async` block
 
-#[rustc_error]
-fn main() {} //[with_feature]~ fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr
deleted file mode 100644
index 8228fa29edf..00000000000
--- a/tests/ui/consts/async-block.with_feature.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/async-block.rs:19:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/consts/const-eval/const_fn_ptr.rs b/tests/ui/consts/const-eval/const_fn_ptr.rs
index f8a2658f31e..1d65eedb93d 100644
--- a/tests/ui/consts/const-eval/const_fn_ptr.rs
+++ b/tests/ui/consts/const-eval/const_fn_ptr.rs
@@ -34,3 +34,5 @@ fn main() {
     let z = foo(double, 2);
     assert_eq!(z, 4);
 }
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs
index a0f804722db..00bf0ed0eba 100644
--- a/tests/ui/consts/const-eval/const_fn_ptr_fail.rs
+++ b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs
@@ -10,3 +10,5 @@ const fn bar(x: usize) -> usize {
 }
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs
index 7db8c6e81ab..c6ae3af4427 100644
--- a/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs
+++ b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs
@@ -24,3 +24,5 @@ fn main() {
     assert_eq!(Y, 4);
     assert_eq!(Z, 4);
 }
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/const-eval/issue-85155.rs b/tests/ui/consts/const-eval/issue-85155.rs
index 95253a0b288..cb5b3a08375 100644
--- a/tests/ui/consts/const-eval/issue-85155.rs
+++ b/tests/ui/consts/const-eval/issue-85155.rs
@@ -19,3 +19,6 @@ fn main() {
     post_monomorphization_error::stdarch_intrinsic::<2>();
     //~^ NOTE the above error was encountered while instantiating
 }
+
+//~? ERROR evaluation of `post_monomorphization_error::ValidateConstImm::<2, 0, 1>::VALID` failed
+//~? NOTE erroneous constant encountered
diff --git a/tests/ui/consts/const_in_pattern/arrays-and-slices.rs b/tests/ui/consts/const_in_pattern/arrays-and-slices.rs
new file mode 100644
index 00000000000..bb38490206b
--- /dev/null
+++ b/tests/ui/consts/const_in_pattern/arrays-and-slices.rs
@@ -0,0 +1,53 @@
+//! Tests that arrays and slices in constants aren't interchangeable when used as patterns.
+
+#[derive(PartialEq, Eq)]
+struct SomeStruct<T: ?Sized>(T);
+
+const BSTR_SIZED: &'static [u8; 3] = b"012";
+const BSTR_UNSIZED: &'static [u8] = BSTR_SIZED;
+const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
+const STRUCT_UNSIZED: &'static SomeStruct<[u8]> = STRUCT_SIZED;
+
+fn type_mismatches() {
+    // Test that array consts can't be used where a slice pattern is expected. This helps ensure
+    // that `const_to_pat` won't produce irrefutable `thir::PatKind::Array` patterns when matching
+    // on slices, which would result in missing length checks.
+    // See also `tests/ui/match/pattern-deref-miscompile.rs`, which tests that byte string literal
+    // patterns check slices' length appropriately when matching on slices.
+    match BSTR_UNSIZED {
+        BSTR_SIZED => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match STRUCT_UNSIZED {
+        STRUCT_SIZED => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+
+    // Test that slice consts can't be used where an array pattern is expected.
+    match BSTR_UNSIZED {
+        BSTR_SIZED => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    // If the types matched here, this would still error, since unsized structs aren't permitted in
+    // constant patterns. See the `invalid_patterns` test below.
+    match STRUCT_UNSIZED {
+        STRUCT_SIZED => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+}
+
+fn invalid_patterns() {
+    // Test that unsized structs containing slices can't be used as patterns.
+    // See `tests/ui/consts/issue-87046.rs` for an example with `str`.
+    match STRUCT_UNSIZED {
+        STRUCT_UNSIZED => {}
+        //~^ ERROR: cannot use unsized non-slice type `SomeStruct<[u8]>` in constant patterns
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/consts/const_in_pattern/arrays-and-slices.stderr b/tests/ui/consts/const_in_pattern/arrays-and-slices.stderr
new file mode 100644
index 00000000000..412caf60f7d
--- /dev/null
+++ b/tests/ui/consts/const_in_pattern/arrays-and-slices.stderr
@@ -0,0 +1,84 @@
+error[E0308]: mismatched types
+  --> $DIR/arrays-and-slices.rs:18:9
+   |
+LL | const BSTR_SIZED: &'static [u8; 3] = b"012";
+   | ---------------------------------- constant defined here
+...
+LL |     match BSTR_UNSIZED {
+   |           ------------ this expression has type `&[u8]`
+LL |         BSTR_SIZED => {}
+   |         ^^^^^^^^^^
+   |         |
+   |         expected `&[u8]`, found `&[u8; 3]`
+   |         `BSTR_SIZED` is interpreted as a constant, not a new binding
+   |         help: introduce a new binding instead: `other_bstr_sized`
+   |
+   = note: expected reference `&[u8]`
+              found reference `&'static [u8; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/arrays-and-slices.rs:23:9
+   |
+LL | const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
+   | ------------------------------------------------ constant defined here
+...
+LL |     match STRUCT_UNSIZED {
+   |           -------------- this expression has type `&SomeStruct<[u8]>`
+LL |         STRUCT_SIZED => {}
+   |         ^^^^^^^^^^^^
+   |         |
+   |         expected `&SomeStruct<[u8]>`, found `&SomeStruct<[u8; 3]>`
+   |         `STRUCT_SIZED` is interpreted as a constant, not a new binding
+   |         help: introduce a new binding instead: `other_struct_sized`
+   |
+   = note: expected reference `&SomeStruct<[u8]>`
+              found reference `&'static SomeStruct<[u8; 3]>`
+
+error[E0308]: mismatched types
+  --> $DIR/arrays-and-slices.rs:30:9
+   |
+LL | const BSTR_SIZED: &'static [u8; 3] = b"012";
+   | ---------------------------------- constant defined here
+...
+LL |     match BSTR_UNSIZED {
+   |           ------------ this expression has type `&[u8]`
+LL |         BSTR_SIZED => {}
+   |         ^^^^^^^^^^
+   |         |
+   |         expected `&[u8]`, found `&[u8; 3]`
+   |         `BSTR_SIZED` is interpreted as a constant, not a new binding
+   |         help: introduce a new binding instead: `other_bstr_sized`
+   |
+   = note: expected reference `&[u8]`
+              found reference `&'static [u8; 3]`
+
+error[E0308]: mismatched types
+  --> $DIR/arrays-and-slices.rs:37:9
+   |
+LL | const STRUCT_SIZED: &'static SomeStruct<[u8; 3]> = &SomeStruct(*BSTR_SIZED);
+   | ------------------------------------------------ constant defined here
+...
+LL |     match STRUCT_UNSIZED {
+   |           -------------- this expression has type `&SomeStruct<[u8]>`
+LL |         STRUCT_SIZED => {}
+   |         ^^^^^^^^^^^^
+   |         |
+   |         expected `&SomeStruct<[u8]>`, found `&SomeStruct<[u8; 3]>`
+   |         `STRUCT_SIZED` is interpreted as a constant, not a new binding
+   |         help: introduce a new binding instead: `other_struct_sized`
+   |
+   = note: expected reference `&SomeStruct<[u8]>`
+              found reference `&'static SomeStruct<[u8; 3]>`
+
+error: cannot use unsized non-slice type `SomeStruct<[u8]>` in constant patterns
+  --> $DIR/arrays-and-slices.rs:47:9
+   |
+LL | const STRUCT_UNSIZED: &'static SomeStruct<[u8]> = STRUCT_SIZED;
+   | ----------------------------------------------- constant defined here
+...
+LL |         STRUCT_UNSIZED => {}
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs
deleted file mode 100644
index 4fe4b0d33c8..00000000000
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(inline_const_pat)]
-
-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
deleted file mode 100644
index b22f99f40d3..00000000000
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0015]: cannot call non-const closure in constants
-  --> $DIR/invalid-inline-const-in-match-arm.rs:5:17
-   |
-LL |         const { (|| {})() } => {}
-   |                 ^^^^^^^^^
-   |
-   = note: closures need an RFC before allowed to be called in constants
-   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
-
-error: could not evaluate constant pattern
-  --> $DIR/invalid-inline-const-in-match-arm.rs:5:9
-   |
-LL |         const { (|| {})() } => {}
-   |         ^^^^^^^^^^^^^^^^^^^ could not evaluate constant
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.rs b/tests/ui/consts/miri_unleashed/abi-mismatch.rs
index ea640ae78d5..0a2b3f3abd6 100644
--- a/tests/ui/consts/miri_unleashed/abi-mismatch.rs
+++ b/tests/ui/consts/miri_unleashed/abi-mismatch.rs
@@ -13,3 +13,5 @@ static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn
 //~| NOTE calling a function with calling convention C using calling convention Rust
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/assoc_const.rs b/tests/ui/consts/miri_unleashed/assoc_const.rs
index 96b47ff4e5e..812207ee809 100644
--- a/tests/ui/consts/miri_unleashed/assoc_const.rs
+++ b/tests/ui/consts/miri_unleashed/assoc_const.rs
@@ -28,3 +28,5 @@ fn main() {
     // this test only causes errors due to the line below, so post-monomorphization
     let y = <String as Bar<Vec<u32>, String>>::F;
 }
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/box.rs b/tests/ui/consts/miri_unleashed/box.rs
index 89df4526b07..1539083f09c 100644
--- a/tests/ui/consts/miri_unleashed/box.rs
+++ b/tests/ui/consts/miri_unleashed/box.rs
@@ -9,3 +9,5 @@ static TEST_BAD: &mut i32 = {
     //~^ ERROR could not evaluate static initializer
     //~| NOTE calling non-const function `Box::<i32>::new`
 };
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs
index a6691fa2a2f..fdccc17ab49 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs
@@ -31,3 +31,5 @@ const REF_IMMUT: &u8 = &MY_STATIC;
 const READ_IMMUT: u8 = *REF_IMMUT;
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/inline_asm.rs b/tests/ui/consts/miri_unleashed/inline_asm.rs
index 8627a6bf887..f1ce613b16e 100644
--- a/tests/ui/consts/miri_unleashed/inline_asm.rs
+++ b/tests/ui/consts/miri_unleashed/inline_asm.rs
@@ -11,3 +11,5 @@ static TEST_BAD: () = {
     //~^ ERROR could not evaluate static initializer
     //~| NOTE inline assembly is not supported
 };
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs
index 039d0fadfcc..e7fc5699236 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references.rs
+++ b/tests/ui/consts/miri_unleashed/mutable_references.rs
@@ -114,3 +114,5 @@ fn main() {
     }
     *OH_YES = 99; //~ ERROR cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
 }
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/non_const_fn.rs b/tests/ui/consts/miri_unleashed/non_const_fn.rs
index d3ffb61af11..201647ac8d8 100644
--- a/tests/ui/consts/miri_unleashed/non_const_fn.rs
+++ b/tests/ui/consts/miri_unleashed/non_const_fn.rs
@@ -9,3 +9,5 @@ static C: () = foo();
 //~| NOTE calling non-const function `foo`
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/ptr_arith.rs b/tests/ui/consts/miri_unleashed/ptr_arith.rs
index 6dd8ab11e7c..4e118322079 100644
--- a/tests/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/tests/ui/consts/miri_unleashed/ptr_arith.rs
@@ -21,3 +21,5 @@ static PTR_INT_TRANSMUTE: () = unsafe {
 // their `PartialEq` impl is non-`const`.
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs
index 126d78158fe..7fa173d8d9d 100644
--- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs
+++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs
@@ -38,3 +38,5 @@ static RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
 //~^ ERROR mutable pointer in final value
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/tls.rs b/tests/ui/consts/miri_unleashed/tls.rs
index b0c6c088361..ab23a524998 100644
--- a/tests/ui/consts/miri_unleashed/tls.rs
+++ b/tests/ui/consts/miri_unleashed/tls.rs
@@ -23,3 +23,5 @@ static TEST_BAD_REF: () = {
 };
 
 fn main() {}
+
+//~? WARN skipping const checks
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
index 95d59f9b894..ccf63f86fcf 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs
@@ -16,7 +16,7 @@ impl Bar for Foo<'_> {
     const STATIC: &str = "";
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
     //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| ERROR const not compatible with trait
+    //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
 }
 
 fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
index ec01225c6bf..33873f5c5a5 100644
--- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
+++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr
@@ -39,21 +39,15 @@ help: use the `'static` lifetime
 LL |     const STATIC: &'static str = "";
    |                    +++++++
 
-error[E0308]: const not compatible with trait
-  --> $DIR/elided-lifetime.rs:16:5
+error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+  --> $DIR/elided-lifetime.rs:16:17
    |
+LL |     const STATIC: &str;
+   |                 - lifetimes in impl do not match this const in trait
+...
 LL |     const STATIC: &str = "";
-   |     ^^^^^^^^^^^^^^^^^^ lifetime mismatch
-   |
-   = note: expected reference `&'static _`
-              found reference `&_`
-note: the anonymous lifetime as defined here...
-  --> $DIR/elided-lifetime.rs:16:19
-   |
-LL |     const STATIC: &str = "";
-   |                   ^
-   = note: ...does not necessarily outlive the static lifetime
+   |                 ^ lifetimes do not match const in trait
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
index 025fda4df58..1e12259e483 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs
@@ -9,7 +9,7 @@ impl Bar<'_> for A {
     const STATIC: &str = "";
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
     //~| WARN this was previously accepted by the compiler but is being phased out
-    //~| ERROR const not compatible with trait
+    //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration
 }
 
 struct B;
@@ -17,4 +17,17 @@ impl Bar<'static> for B {
     const STATIC: &str = "";
 }
 
+struct C;
+impl Bar<'_> for C {
+    // make  ^^ not cause
+    const STATIC: &'static str = {
+        struct B;
+        impl Bar<'static> for B {
+            const STATIC: &str = "";
+            //            ^ to emit a future incompat warning
+        }
+        ""
+    };
+}
+
 fn main() {}
diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
index b8e2f412b49..116f28e8484 100644
--- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
+++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr
@@ -21,25 +21,15 @@ help: use the `'static` lifetime
 LL |     const STATIC: &'static str = "";
    |                    +++++++
 
-error[E0308]: const not compatible with trait
-  --> $DIR/static-trait-impl.rs:9:5
+error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration
+  --> $DIR/static-trait-impl.rs:9:17
    |
+LL |     const STATIC: &'a str;
+   |                 - lifetimes in impl do not match this const in trait
+...
 LL |     const STATIC: &str = "";
-   |     ^^^^^^^^^^^^^^^^^^ lifetime mismatch
-   |
-   = note: expected reference `&_`
-              found reference `&_`
-note: the anonymous lifetime as defined here...
-  --> $DIR/static-trait-impl.rs:9:19
-   |
-LL |     const STATIC: &str = "";
-   |                   ^
-note: ...does not necessarily outlive the anonymous lifetime as defined here
-  --> $DIR/static-trait-impl.rs:8:10
-   |
-LL | impl Bar<'_> for A {
-   |          ^^
+   |                 ^ lifetimes do not match const in trait
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.current.stderr
index 3cc4377514a..02bcaee8015 100644
--- a/tests/ui/consts/too_generic_eval_ice.stderr
+++ b/tests/ui/consts/too_generic_eval_ice.current.stderr
@@ -1,5 +1,5 @@
 error: constant expression depends on a generic parameter
-  --> $DIR/too_generic_eval_ice.rs:7:13
+  --> $DIR/too_generic_eval_ice.rs:11:13
    |
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |             ^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    = note: this may fail depending on what value the parameter takes
 
 error: constant expression depends on a generic parameter
-  --> $DIR/too_generic_eval_ice.rs:7:9
+  --> $DIR/too_generic_eval_ice.rs:11:9
    |
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |         ^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    = note: this may fail depending on what value the parameter takes
 
 error: constant expression depends on a generic parameter
-  --> $DIR/too_generic_eval_ice.rs:7:30
+  --> $DIR/too_generic_eval_ice.rs:11:30
    |
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |                              ^^
@@ -23,7 +23,7 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    = note: this may fail depending on what value the parameter takes
 
 error[E0277]: can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]`
-  --> $DIR/too_generic_eval_ice.rs:7:30
+  --> $DIR/too_generic_eval_ice.rs:11:30
    |
 LL |         [5; Self::HOST_SIZE] == [6; 0]
    |                              ^^ no implementation for `[{integer}; Self::HOST_SIZE] == [{integer}; 0]`
diff --git a/tests/ui/consts/too_generic_eval_ice.next.stderr b/tests/ui/consts/too_generic_eval_ice.next.stderr
new file mode 100644
index 00000000000..01da33241c8
--- /dev/null
+++ b/tests/ui/consts/too_generic_eval_ice.next.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `the constant `Self::HOST_SIZE` can be evaluated`
+  --> $DIR/too_generic_eval_ice.rs:11:13
+   |
+LL |         [5; Self::HOST_SIZE] == [6; 0]
+   |             ^^^^^^^^^^^^^^^ cannot satisfy `the constant `Self::HOST_SIZE` can be evaluated`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/consts/too_generic_eval_ice.rs b/tests/ui/consts/too_generic_eval_ice.rs
index 0d46a4c8276..ff741cdcf20 100644
--- a/tests/ui/consts/too_generic_eval_ice.rs
+++ b/tests/ui/consts/too_generic_eval_ice.rs
@@ -1,3 +1,7 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 pub struct Foo<A, B>(A, B);
 
 impl<A, B> Foo<A, B> {
@@ -5,10 +9,11 @@ impl<A, B> Foo<A, B> {
 
     pub fn crash() -> bool {
         [5; Self::HOST_SIZE] == [6; 0]
-        //~^ ERROR constant expression depends on a generic parameter
-        //~| ERROR constant expression depends on a generic parameter
-        //~| ERROR constant expression depends on a generic parameter
-        //~| ERROR can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]`
+        //[current]~^ ERROR constant expression depends on a generic parameter
+        //[current]~| ERROR constant expression depends on a generic parameter
+        //[current]~| ERROR constant expression depends on a generic parameter
+        //[current]~| ERROR can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]`
+        //[next]~^^^^^ ERROR type annotations needed
     }
 }
 
diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr
index 31a635b57e5..f24db78415e 100644
--- a/tests/ui/coverage-attr/name-value.stderr
+++ b/tests/ui/coverage-attr/name-value.stderr
@@ -44,6 +44,21 @@ LL + #[coverage(on)]
    |
 
 error: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:26:1
+   |
+LL | #[coverage = "off"]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+help: the following are the possible correct uses
+   |
+LL - #[coverage = "off"]
+LL + #[coverage(off)]
+   |
+LL - #[coverage = "off"]
+LL + #[coverage(on)]
+   |
+
+error: malformed `coverage` attribute input
   --> $DIR/name-value.rs:29:5
    |
 LL |     #[coverage = "off"]
@@ -59,7 +74,7 @@ LL +     #[coverage(on)]
    |
 
 error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:26:1
+  --> $DIR/name-value.rs:35:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^
@@ -104,7 +119,7 @@ LL +     #[coverage(on)]
    |
 
 error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:35:1
+  --> $DIR/name-value.rs:50:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^
@@ -149,21 +164,6 @@ LL +     #[coverage(on)]
    |
 
 error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:50:1
-   |
-LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL - #[coverage = "off"]
-LL + #[coverage(off)]
-   |
-LL - #[coverage = "off"]
-LL + #[coverage(on)]
-   |
-
-error: malformed `coverage` attribute input
   --> $DIR/name-value.rs:64:1
    |
 LL | #[coverage = "off"]
diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr
index 612301885dc..2773db9c857 100644
--- a/tests/ui/coverage-attr/word-only.stderr
+++ b/tests/ui/coverage-attr/word-only.stderr
@@ -38,6 +38,19 @@ LL | #[coverage(on)]
    |           ++++
 
 error: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:26:1
+   |
+LL | #[coverage]
+   | ^^^^^^^^^^^
+   |
+help: the following are the possible correct uses
+   |
+LL | #[coverage(off)]
+   |           +++++
+LL | #[coverage(on)]
+   |           ++++
+
+error: malformed `coverage` attribute input
   --> $DIR/word-only.rs:29:5
    |
 LL |     #[coverage]
@@ -51,7 +64,7 @@ LL |     #[coverage(on)]
    |               ++++
 
 error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:26:1
+  --> $DIR/word-only.rs:35:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^
@@ -90,7 +103,7 @@ LL |     #[coverage(on)]
    |               ++++
 
 error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:35:1
+  --> $DIR/word-only.rs:50:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^
@@ -129,19 +142,6 @@ LL |     #[coverage(on)]
    |               ++++
 
 error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:50:1
-   |
-LL | #[coverage]
-   | ^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL | #[coverage(off)]
-   |           +++++
-LL | #[coverage(on)]
-   |           ++++
-
-error: malformed `coverage` attribute input
   --> $DIR/word-only.rs:64:1
    |
 LL | #[coverage]
diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs
index 289767b1f69..57b55e9437b 100644
--- a/tests/ui/custom_test_frameworks/full.rs
+++ b/tests/ui/custom_test_frameworks/full.rs
@@ -25,4 +25,17 @@ impl example_runner::Testable for IsFoo {
 const TEST_1: IsFoo = IsFoo("hello");
 
 #[test_case]
-const TEST_2: IsFoo = IsFoo("foo");
+static TEST_2: IsFoo = IsFoo("foo");
+
+// FIXME: `test_case` is currently ignored on anything other than
+// fn/const/static. This should be an error. Compare this with `#[test]` and
+// #[bench] whose expanders emit "error: expected a non-associated function,
+// found […]" if applied to invalid items.
+#[test_case]
+struct _S;
+
+// FIXME: as above.
+#[test_case]
+impl _S {
+    fn _f() {}
+}
diff --git a/tests/ui/dep-graph/dep-graph-dump.rs b/tests/ui/dep-graph/dep-graph-dump.rs
index 7aede27d125..5dc05045e82 100644
--- a/tests/ui/dep-graph/dep-graph-dump.rs
+++ b/tests/ui/dep-graph/dep-graph-dump.rs
@@ -4,3 +4,5 @@
 //@ compile-flags: -Z dump-dep-graph
 
 fn main() {}
+
+//~? ERROR can't dump dependency graph without `-Z query-dep-graph`
diff --git a/tests/ui/deprecation/deprecated_ar.rs b/tests/ui/deprecation/deprecated_ar.rs
index 404d062e6a4..00862d2c00a 100644
--- a/tests/ui/deprecation/deprecated_ar.rs
+++ b/tests/ui/deprecation/deprecated_ar.rs
@@ -2,3 +2,5 @@
 //@ compile-flags: -Car=foo
 
 fn main() {}
+
+//~? WARN `-C ar`: this option is deprecated and does nothing
diff --git a/tests/ui/deprecation/deprecated_inline_threshold.rs b/tests/ui/deprecation/deprecated_inline_threshold.rs
index b54fa36397a..284a6d6798e 100644
--- a/tests/ui/deprecation/deprecated_inline_threshold.rs
+++ b/tests/ui/deprecation/deprecated_inline_threshold.rs
@@ -6,3 +6,9 @@
 //@[no_val] compile-flags: -Cinline-threshold
 
 fn main() {}
+
+//[good_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing
+//[bad_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing
+//[bad_val]~? ERROR incorrect value `asd` for codegen option `inline-threshold`
+//[no_val]~? WARN `-C inline-threshold`: this option is deprecated and does nothing
+//[no_val]~? ERROR codegen option `inline-threshold` requires a number
diff --git a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
index 62584ec23e3..e014c7e80af 100644
--- a/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
+++ b/tests/ui/deprecation/deprecated_no_stack_check_opt.rs
@@ -2,3 +2,5 @@
 //@ compile-flags: -Cno-stack-check
 
 fn main() {}
+
+//~? WARN `-C no-stack-check`: this option is deprecated and does nothing
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
index 8980ef9c422..f928e112289 100644
--- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
@@ -13,14 +13,16 @@
 //! - Original impl PR: <https://github.com/rust-lang/rust/pull/21248>.
 //! - RFC 507 "Release channels":
 //!   <https://github.com/rust-lang/rfcs/blob/c017755b9bfa0421570d92ba38082302e0f3ad4f/text/0507-release-channels.md>.
-#![feature(rustc_attrs)]
 
 //@ revisions: without_flag with_flag
 
+//@ check-pass
+//@ compile-flags: -Zunleash-the-miri-inside-of-you
 //@[with_flag] compile-flags: -Awarnings
 
-//@ check-pass
+fn non_constant() {}
+const fn constant() { non_constant() }
 
-#[rustc_error(warn)]
 fn main() {}
-//[without_flag]~^ WARN unexpected annotation used with `#[rustc_error(...)]`!
+
+//[without_flag]~? WARN skipping const checks
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
index 3f33ccbd1c9..08ae11fc18a 100644
--- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
@@ -1,8 +1,10 @@
-warning: unexpected annotation used with `#[rustc_error(...)]`!
-  --> $DIR/allow-non-lint-warnings.rs:25:1
+warning: skipping const checks
    |
-LL | fn main() {}
-   | ^^^^^^^^^
+help: skipping check that does not even have a feature gate
+  --> $DIR/allow-non-lint-warnings.rs:24:23
+   |
+LL | const fn constant() { non_constant() }
+   |                       ^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.rs b/tests/ui/diagnostic_namespace/suggest_typos.rs
index 6fa4f800462..8d1dc6f59da 100644
--- a/tests/ui/diagnostic_namespace/suggest_typos.rs
+++ b/tests/ui/diagnostic_namespace/suggest_typos.rs
@@ -16,4 +16,9 @@ trait Y{}
 //~^^HELP an attribute with a similar name exists
 trait Z{}
 
+#[diagnostic::dont_recommend]
+//~^ERROR unknown diagnostic attribute
+//~^^HELP an attribute with a similar name exists
+impl X for u8 {}
+
 fn main(){}
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.stderr b/tests/ui/diagnostic_namespace/suggest_typos.stderr
index 86d778c6ec0..1f19fd4bbcf 100644
--- a/tests/ui/diagnostic_namespace/suggest_typos.stderr
+++ b/tests/ui/diagnostic_namespace/suggest_typos.stderr
@@ -37,5 +37,17 @@ help: an attribute with a similar name exists
 LL | #[diagnostic::on_unimplemented]
    |                  ++
 
-error: aborting due to 3 previous errors
+error: unknown diagnostic attribute
+  --> $DIR/suggest_typos.rs:19:15
+   |
+LL | #[diagnostic::dont_recommend]
+   |               ^^^^^^^^^^^^^^
+   |
+help: an attribute with a similar name exists
+   |
+LL - #[diagnostic::dont_recommend]
+LL + #[diagnostic::do_not_recommend]
+   |
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/did_you_mean/recursion_limit_deref.rs b/tests/ui/did_you_mean/recursion_limit_deref.rs
index af4c4ddda69..e53007388af 100644
--- a/tests/ui/did_you_mean/recursion_limit_deref.rs
+++ b/tests/ui/did_you_mean/recursion_limit_deref.rs
@@ -51,3 +51,6 @@ fn main() {
     let x: &Bottom = &t; //~ ERROR mismatched types
     //~^ error recursion limit
 }
+
+//~? ERROR reached the recursion limit finding the struct tail for `K`
+//~? ERROR reached the recursion limit finding the struct tail for `Bottom`
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
index c3dfcfb19cb..f8d2755b9d7 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -28,3 +28,5 @@ pub fn check_async() {
 
     let _recovery_witness: () = 0; //~ ERROR mismatched types
 }
+
+//~? ERROR macro expansion ends with an incomplete expression
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
index 1447c49ef71..f4438472a0e 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -39,3 +39,5 @@ pub fn check_async() {
 
     let _recovery_witness: () = 0; //~ ERROR mismatched types
 }
+
+//~? ERROR macro expansion ends with an incomplete expression
diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs
index d8ae12d200f..0b527baaafe 100644
--- a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs
+++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs
@@ -2,3 +2,5 @@
 
 extern crate bad_main_functions;
 pub use bad_main_functions::boilerplate as main;
+
+//~? ERROR `main` function has wrong type
diff --git a/tests/ui/errors/wrong-target-spec.rs b/tests/ui/errors/wrong-target-spec.rs
index bc9038c1fab..9b31c943e3e 100644
--- a/tests/ui/errors/wrong-target-spec.rs
+++ b/tests/ui/errors/wrong-target-spec.rs
@@ -6,3 +6,5 @@
 //@ compile-flags: --target x86_64_unknown-linux-musl
 
 fn main() {}
+
+//~? ERROR Error loading target specification: Could not find specification for target "x86_64_unknown-linux-musl"
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
index 2c130664e9a..f9b5176d78a 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.rs
@@ -17,4 +17,13 @@ impl Mop {
     //~| ERROR: unconstrained opaque type
 }
 
+fn funky(_: [(); {
+    impl Foo for fn() {
+        type Bar = impl Sized;
+        //~^ ERROR: `impl Trait` in associated types is unstable
+        //~| ERROR: unconstrained opaque type
+    }
+    0
+}]) {}
+
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
index 7dfd79c7286..01d25c16228 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
@@ -18,6 +18,16 @@ LL |     type Bop = impl std::fmt::Debug;
    = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
+error[E0658]: `impl Trait` in associated types is unstable
+  --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20
+   |
+LL |         type Bar = impl Sized;
+   |                    ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error[E0658]: inherent associated types are unstable
   --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5
    |
@@ -44,6 +54,14 @@ LL |     type Bop = impl std::fmt::Debug;
    |
    = note: `Bop` must be used in combination with a concrete type within the same impl
 
-error: aborting due to 5 previous errors
+error: unconstrained opaque type
+  --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:22:20
+   |
+LL |         type Bar = impl Sized;
+   |                    ^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same impl
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs b/tests/ui/feature-gates/feature-gate-inline_const_pat.rs
deleted file mode 100644
index 3d0df289fb7..00000000000
--- a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let const { () } = ();
-    //~^ ERROR inline-const in pattern position is experimental [E0658]
-}
diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr
deleted file mode 100644
index 7d7376fa818..00000000000
--- a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/feature-gate-inline_const_pat.rs:2:9
-   |
-LL |     let const { () } = ();
-   |         ^^^^^
-   |
-   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
-   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs
index c12ff5b04dc..8e11a05c89b 100644
--- a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs
+++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs
@@ -7,3 +7,5 @@
 extern "C" {}
 
 fn main() {}
+
+//[in_flag]~? ERROR unknown linking modifier `link-arg`
diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs
new file mode 100644
index 00000000000..738cab5a06d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "movrs")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr
new file mode 100644
index 00000000000..16fe7aaead5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `movrs` is currently unstable
+  --> $DIR/feature-gate-movrs_target_feature.rs:2:18
+   |
+LL | #[target_feature(enable = "movrs")]
+   |                  ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #137976 <https://github.com/rust-lang/rust/issues/137976> for more information
+   = help: add `#![feature(movrs_target_feature)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs
new file mode 100644
index 00000000000..0d3af4c5fe0
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs
@@ -0,0 +1,15 @@
+//@ needs-asm-support
+//@ only-x86_64
+
+#![feature(naked_functions)]
+
+use std::arch::naked_asm;
+
+#[naked]
+#[target_feature(enable = "avx2")]
+//~^ ERROR: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions
+extern "C" fn naked() {
+    unsafe { naked_asm!("") }
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr
new file mode 100644
index 00000000000..b0592d08046
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions
+  --> $DIR/feature-gate-naked_functions_target_feature.rs:9:1
+   |
+LL | #[target_feature(enable = "avx2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #138568 <https://github.com/rust-lang/rust/issues/138568> for more information
+   = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
index c2965e42f27..c5859eec8db 100644
--- a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
+++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
@@ -7,3 +7,5 @@
 extern "C" {}
 
 fn main() {}
+
+//[in_flag]~? ERROR linking modifier `as-needed` is unstable
diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs
deleted file mode 100644
index 308b41dfc68..00000000000
--- a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-trait Foo {
-    fn test() -> impl Sized + use<Self>;
-    //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position
-}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr
deleted file mode 100644
index b2c6bf61124..00000000000
--- a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31
-   |
-LL |     fn test() -> impl Sized + use<Self>;
-   |                               ^^^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
index 7ae4a8d911b..025b4b52f12 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
@@ -1,7 +1,6 @@
 // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
 
 #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
index 8c3a8eb2df8..0f760e0602d 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -7,18 +7,9 @@ LL | #[rustc_variance]
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-  --> $DIR/feature-gate-rustc-attrs-1.rs:4:1
-   |
-LL | #[rustc_error]
-   | ^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
               (note that the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized)
-  --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
+  --> $DIR/feature-gate-rustc-attrs-1.rs:4:1
    |
 LL | #[rustc_nonnull_optimization_guaranteed]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,6 +17,6 @@ LL | #[rustc_nonnull_optimization_guaranteed]
    = help: add `#![feature(rustc_attrs)]` 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 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index ec70a20844a..d332fba0623 100644
--- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -1,38 +1,42 @@
-//@ check-pass
-#![feature(type_alias_impl_trait)]
 use std::fmt::Debug;
 
-type Foo = impl Debug;
+type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
 
 struct Bar(Foo);
-#[define_opaque(Foo)]
+#[define_opaque(Foo)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
 fn define() -> Bar {
     Bar(42)
 }
 
-type Foo2 = impl Debug;
+type Foo2 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
 
-#[define_opaque(Foo2)]
+#[define_opaque(Foo2)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
 fn define2() {
     let x = || -> Foo2 { 42 };
 }
 
-type Foo3 = impl Debug;
+type Foo3 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
 
-#[define_opaque(Foo3)]
+#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
 fn define3(x: Foo3) {
     let y: i32 = x;
 }
-#[define_opaque(Foo3)]
+#[define_opaque(Foo3)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
 fn define3_1() {
     define3(42)
 }
 
-type Foo4 = impl Debug;
+type Foo4 = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
 
-#[define_opaque(Foo4)]
+#[define_opaque(Foo4)] //~ ERROR use of unstable library feature `type_alias_impl_trait`
 fn define4(_: Foo4) {
     let y: Foo4 = 42;
 }
 
+type Foo5 = [(); {
+    type Foo = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
+    //~^ ERROR unconstrained opaque type
+    0
+}];
+
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
new file mode 100644
index 00000000000..bab60eb4293
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
@@ -0,0 +1,111 @@
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:6:3
+   |
+LL | #[define_opaque(Foo)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:13:3
+   |
+LL | #[define_opaque(Foo2)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:20:3
+   |
+LL | #[define_opaque(Foo3)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:3
+   |
+LL | #[define_opaque(Foo3)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:31:3
+   |
+LL | #[define_opaque(Foo4)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:3:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:11:13
+   |
+LL | type Foo2 = impl Debug;
+   |             ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:13
+   |
+LL | type Foo3 = impl Debug;
+   |             ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13
+   |
+LL | type Foo4 = impl Debug;
+   |             ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `impl Trait` in type aliases is unstable
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16
+   |
+LL |     type Foo = impl Debug;
+   |                ^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` 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: unconstrained opaque type
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:37:16
+   |
+LL |     type Foo = impl Debug;
+   |                ^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same crate
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fmt/fmt_debug/invalid.rs b/tests/ui/fmt/fmt_debug/invalid.rs
index 09cb46f1ea6..f2652fe277d 100644
--- a/tests/ui/fmt/fmt_debug/invalid.rs
+++ b/tests/ui/fmt/fmt_debug/invalid.rs
@@ -2,3 +2,5 @@
 //@ failure-status: 1
 fn main() {
 }
+
+//~? ERROR incorrect value `invalid-value` for unstable option `fmt-debug`
diff --git a/tests/ui/fn/bad-turbofish-hints-issue-121901.rs b/tests/ui/fn/bad-turbofish-hints-issue-121901.rs
new file mode 100644
index 00000000000..1425e576d75
--- /dev/null
+++ b/tests/ui/fn/bad-turbofish-hints-issue-121901.rs
@@ -0,0 +1,8 @@
+// Regression test for the parser wrongfully suggesting turbofish syntax in below syntax errors
+
+type One = for<'a> fn(Box<dyn Send + 'a);
+//~^ ERROR: expected one of `+`, `,`, or `>`, found `)`
+type Two = for<'a> fn(Box<dyn Send + 'a>>);
+//~^ ERROR: unmatched angle bracket
+
+fn main() {}
diff --git a/tests/ui/fn/bad-turbofish-hints-issue-121901.stderr b/tests/ui/fn/bad-turbofish-hints-issue-121901.stderr
new file mode 100644
index 00000000000..aacb326f8a2
--- /dev/null
+++ b/tests/ui/fn/bad-turbofish-hints-issue-121901.stderr
@@ -0,0 +1,25 @@
+error: expected one of `+`, `,`, or `>`, found `)`
+  --> $DIR/bad-turbofish-hints-issue-121901.rs:3:40
+   |
+LL | type One = for<'a> fn(Box<dyn Send + 'a);
+   |                                        ^ expected one of `+`, `,`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type One = for<'a> fn(Box<dyn Send + 'a>);
+   |                                        +
+
+error: unmatched angle bracket
+  --> $DIR/bad-turbofish-hints-issue-121901.rs:5:41
+   |
+LL | type Two = for<'a> fn(Box<dyn Send + 'a>>);
+   |                                         ^
+   |
+help: remove extra angle bracket
+   |
+LL - type Two = for<'a> fn(Box<dyn Send + 'a>>);
+LL + type Two = for<'a> fn(Box<dyn Send + 'a>);
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/fn/trait-fn-generic-mismatch.rs b/tests/ui/fn/trait-fn-generic-mismatch.rs
new file mode 100644
index 00000000000..dc8222e967e
--- /dev/null
+++ b/tests/ui/fn/trait-fn-generic-mismatch.rs
@@ -0,0 +1,12 @@
+fn retry() -> impl Sized {}
+
+struct Core<T>(T);
+
+impl Core<XXX> { //~ ERROR cannot find type `XXX` in this scope
+    pub fn spawn(self) {}
+}
+
+fn main() {
+    let core = Core(1);
+    core.spawn(retry()); //~ ERROR this method takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/fn/trait-fn-generic-mismatch.stderr b/tests/ui/fn/trait-fn-generic-mismatch.stderr
new file mode 100644
index 00000000000..8384d74e225
--- /dev/null
+++ b/tests/ui/fn/trait-fn-generic-mismatch.stderr
@@ -0,0 +1,32 @@
+error[E0412]: cannot find type `XXX` in this scope
+  --> $DIR/trait-fn-generic-mismatch.rs:5:11
+   |
+LL | impl Core<XXX> {
+   |           ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<XXX> Core<XXX> {
+   |     +++++
+
+error[E0061]: this method takes 0 arguments but 1 argument was supplied
+  --> $DIR/trait-fn-generic-mismatch.rs:11:10
+   |
+LL |     core.spawn(retry());
+   |          ^^^^^ ------- unexpected argument of type `impl Sized`
+   |
+note: method defined here
+  --> $DIR/trait-fn-generic-mismatch.rs:6:12
+   |
+LL |     pub fn spawn(self) {}
+   |            ^^^^^
+help: remove the extra argument
+   |
+LL -     core.spawn(retry());
+LL +     core.spawn();
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0412.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
index f943ea0271d..f79001ff1f1 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 #![allow(non_contiguous_range_endpoints)]
-#![feature(inline_const_pat)]
-
 fn main() {
     let mut if_lettable = vec![];
     let mut first_or = vec![];
@@ -16,7 +14,6 @@ fn main() {
         match x {
             1 | -3..0 => first_or.push(x),
             y @ (0..5 | 6) => or_two.push(y),
-            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
             y => bottom.push(y),
@@ -25,6 +22,6 @@ fn main() {
     assert_eq!(if_lettable, [-1, 0, 2, 4]);
     assert_eq!(first_or, [-3, -2, -1, 1]);
     assert_eq!(or_two, [0, 2, 3, 4, 6]);
-    assert_eq!(range_from, [-5, -4, 7]);
+    assert_eq!(range_from, [-5, -4, 5, 7]);
     assert_eq!(bottom, [-7, -6]);
 }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
index 4d7c9f10261..c5705d5db60 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
@@ -18,8 +18,6 @@ fn main() {
             //~^ error: expected a pattern range bound, found an expression
             1 | -3..0 => first_or.push(x),
             y @ (0..5 | 6) => or_two.push(y),
-            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-            //~^ error: inline-const in pattern position is experimental [E0658]
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
             y => bottom.push(y),
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index 62be2ef7a4d..5cd98faa8ab 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -11,10 +11,6 @@ LL +         const VAL: /* Type */ = 5+1;
 LL ~         match x as i32 {
 LL ~             0..VAL => errors_only.push(x),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |             0..const { 5+1 } => errors_only.push(x),
-   |                +++++++     +
 
 error[E0408]: variable `n` is not bound in all patterns
   --> $DIR/range_pat_interactions1.rs:10:25
@@ -24,17 +20,6 @@ LL |         if let n @ 2..3|4 = x {
    |                |
    |                variable not in all patterns
 
-error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions1.rs:21:20
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                    ^^^^^
-   |
-   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
-   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0408, E0658.
-For more information about an error, try `rustc --explain E0408`.
+For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
deleted file mode 100644
index 0dbdb8fe7b6..00000000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-fn main() {
-    let mut first_or = Vec::<i32>::new();
-    let mut or_two = Vec::<i32>::new();
-    let mut range_from = Vec::<i32>::new();
-    let mut bottom = Vec::<i32>::new();
-    let mut errors_only = Vec::<i32>::new();
-
-    for x in -9 + 1..=(9 - 2) {
-        match x as i32 {
-            0..=(5+1) => errors_only.push(x),
-            //~^ error: expected a pattern range bound, found an expression
-            //~| error: range pattern bounds cannot have parentheses
-            1 | -3..0 => first_or.push(x),
-            y @ (0..5 | 6) => or_two.push(y),
-            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-            //~^ error: inline-const in pattern position is experimental
-            y @ -5.. => range_from.push(y),
-            y @ ..-7 => assert_eq!(y, -8),
-            y => bottom.push(y),
-        }
-    }
-}
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
deleted file mode 100644
index dbe7f4482ee..00000000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error: range pattern bounds cannot have parentheses
-  --> $DIR/range_pat_interactions2.rs:10:17
-   |
-LL |             0..=(5+1) => errors_only.push(x),
-   |                 ^   ^
-   |
-help: remove these parentheses
-   |
-LL -             0..=(5+1) => errors_only.push(x),
-LL +             0..=5+1 => errors_only.push(x),
-   |
-
-error: expected a pattern range bound, found an expression
-  --> $DIR/range_pat_interactions2.rs:10:18
-   |
-LL |             0..=(5+1) => errors_only.push(x),
-   |                  ^^^ not a pattern
-   |
-   = note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
-help: consider extracting the expression into a `const`
-   |
-LL +         const VAL: /* Type */ = 5+1;
-LL ~         match x as i32 {
-LL ~             0..=(VAL) => errors_only.push(x),
-   |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |             0..=(const { 5+1 }) => errors_only.push(x),
-   |                  +++++++     +
-
-error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions2.rs:15:20
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                    ^^^^^
-   |
-   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
-   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
deleted file mode 100644
index 2f2778095cf..00000000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-fn main() {
-    let mut first_or = Vec::<i32>::new();
-    let mut or_two = Vec::<i32>::new();
-    let mut range_from = Vec::<i32>::new();
-    let mut bottom = Vec::<i32>::new();
-
-    for x in -9 + 1..=(9 - 2) {
-        match x as i32 {
-            8.. => bottom.push(x),
-            1 | -3..0 => first_or.push(x),
-            y @ (0..5 | 6) => or_two.push(y),
-            y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-            //~^ inline-const in pattern position is experimental
-            y @ -5.. => range_from.push(y),
-            y @ ..-7 => assert_eq!(y, -8),
-            y => bottom.push(y),
-        }
-    }
-}
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
deleted file mode 100644
index dc7dc0efa7a..00000000000
--- a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: inline-const in pattern position is experimental
-  --> $DIR/range_pat_interactions3.rs:12:20
-   |
-LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
-   |                    ^^^^^
-   |
-   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
-   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/define-via-const.rs b/tests/ui/impl-trait/define-via-const.rs
new file mode 100644
index 00000000000..a4b9123654c
--- /dev/null
+++ b/tests/ui/impl-trait/define-via-const.rs
@@ -0,0 +1,12 @@
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Closure = impl Fn(u32) -> u32;
+
+#[define_opaque(Closure)]
+const ADDER: Closure = |x| x + 1;
+
+fn main() {
+    let z = (ADDER)(1);
+}
diff --git a/tests/ui/impl-trait/define-via-extern.rs b/tests/ui/impl-trait/define-via-extern.rs
new file mode 100644
index 00000000000..599c31ff917
--- /dev/null
+++ b/tests/ui/impl-trait/define-via-extern.rs
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+
+type Hi = impl Sized;
+
+extern "C" {
+    #[define_opaque(Hi)] fn foo();
+    //~^ ERROR only functions, statics, and consts can define opaque types
+
+    #[define_opaque(Hi)] static HI: Hi;
+    //~^ ERROR only functions, statics, and consts can define opaque types
+}
+
+#[define_opaque(Hi)]
+fn main() {
+    let _: Hi = 0;
+}
diff --git a/tests/ui/impl-trait/define-via-extern.stderr b/tests/ui/impl-trait/define-via-extern.stderr
new file mode 100644
index 00000000000..4a0ca5edd47
--- /dev/null
+++ b/tests/ui/impl-trait/define-via-extern.stderr
@@ -0,0 +1,14 @@
+error: only functions, statics, and consts can define opaque types
+  --> $DIR/define-via-extern.rs:6:5
+   |
+LL |     #[define_opaque(Hi)] fn foo();
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: only functions, statics, and consts can define opaque types
+  --> $DIR/define-via-extern.rs:9:5
+   |
+LL |     #[define_opaque(Hi)] static HI: Hi;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
index 2f17c0ff508..776bb7278ce 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
@@ -2,8 +2,7 @@
 use std::fmt::Debug;
 
 fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-    //~^ ERROR cannot resolve opaque type
-    //~| WARNING elided lifetime has a name
+    //~^ WARNING elided lifetime has a name
     |x| x
     //~^ ERROR expected generic lifetime parameter, found `'_`
 }
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
index 91550f0e284..209186db4cc 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
@@ -7,24 +7,14 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
    = note: `#[warn(elided_named_lifetimes)]` on by default
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/impl-fn-predefined-lifetimes.rs:7:9
+  --> $DIR/impl-fn-predefined-lifetimes.rs:6:9
    |
 LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
    |                                                -- this generic parameter must be used with a generic lifetime parameter
-...
+LL |
 LL |     |x| x
    |         ^
 
-error[E0720]: cannot resolve opaque type
-  --> $DIR/impl-fn-predefined-lifetimes.rs:4:35
-   |
-LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
-   |                                   ^^^^^^^^^^^^^^^ recursive opaque type
-...
-LL |     |x| x
-   |     ----- returning here with type `{closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8}`
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-Some errors have detailed explanations: E0720, E0792.
-For more information about an error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs
index 2c277aee06d..89fe3c1509c 100644
--- a/tests/ui/impl-trait/impl_trait_projections.rs
+++ b/tests/ui/impl-trait/impl_trait_projections.rs
@@ -35,4 +35,9 @@ fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
     panic!()
 }
 
+fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::<impl Sized>] {
+    //~^ ERROR `impl Trait` is not allowed in paths
+    loop {}
+}
+
 fn main() {}
diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr
index 5e0b80fcd59..21f45613938 100644
--- a/tests/ui/impl-trait/impl_trait_projections.stderr
+++ b/tests/ui/impl-trait/impl_trait_projections.stderr
@@ -30,6 +30,14 @@ LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: aborting due to 4 previous errors
+error[E0562]: `impl Trait` is not allowed in paths
+  --> $DIR/impl_trait_projections.rs:38:68
+   |
+LL | fn parametrized_value_in_anon_const_is_disallowed() -> [(); None::<impl Sized>] {
+   |                                                                    ^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs
index 47198d51150..20b0e60702f 100644
--- a/tests/ui/impl-trait/in-trait/dump.rs
+++ b/tests/ui/impl-trait/in-trait/dump.rs
@@ -1,6 +1,6 @@
 //@ compile-flags: -Zverbose-internals
 
-#![feature(precise_capturing_in_traits, rustc_attrs)]
+#![feature(rustc_attrs)]
 #![rustc_hidden_type_of_opaques]
 
 trait Foo {
diff --git a/tests/ui/impl-trait/in-trait/refine-captures.rs b/tests/ui/impl-trait/in-trait/refine-captures.rs
index e7dffcb52aa..199cc464c4e 100644
--- a/tests/ui/impl-trait/in-trait/refine-captures.rs
+++ b/tests/ui/impl-trait/in-trait/refine-captures.rs
@@ -1,5 +1,3 @@
-#![feature(precise_capturing_in_traits)]
-
 trait LifetimeParam<'a> {
     fn test() -> impl Sized;
 }
diff --git a/tests/ui/impl-trait/in-trait/refine-captures.stderr b/tests/ui/impl-trait/in-trait/refine-captures.stderr
index 166991894d1..6f213f16144 100644
--- a/tests/ui/impl-trait/in-trait/refine-captures.stderr
+++ b/tests/ui/impl-trait/in-trait/refine-captures.stderr
@@ -1,5 +1,5 @@
 warning: impl trait in impl method captures fewer lifetimes than in trait
-  --> $DIR/refine-captures.rs:8:31
+  --> $DIR/refine-captures.rs:6:31
    |
 LL |     fn test() -> impl Sized + use<> {}
    |                               ^^^^^
@@ -13,7 +13,7 @@ LL |     fn test() -> impl Sized + use<'a> {}
    |                                   ++
 
 warning: impl trait in impl method captures fewer lifetimes than in trait
-  --> $DIR/refine-captures.rs:22:31
+  --> $DIR/refine-captures.rs:20:31
    |
 LL |     fn test() -> impl Sized + use<> {}
    |                               ^^^^^
@@ -26,7 +26,7 @@ LL |     fn test() -> impl Sized + use<'a> {}
    |                                   ++
 
 warning: impl trait in impl method captures fewer lifetimes than in trait
-  --> $DIR/refine-captures.rs:27:31
+  --> $DIR/refine-captures.rs:25:31
    |
 LL |     fn test() -> impl Sized + use<'b> {}
    |                               ^^^^^^^
@@ -39,7 +39,7 @@ LL |     fn test() -> impl Sized + use<'a, 'b> {}
    |                                    ++++
 
 error: `impl Trait` must mention all type parameters in scope in `use<...>`
-  --> $DIR/refine-captures.rs:32:18
+  --> $DIR/refine-captures.rs:30:18
    |
 LL | impl<T> TypeParam<T> for u64 {
    |      - type parameter is implicitly captured by this `impl Trait`
diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs
index cd2f43fca9a..c0f569c690a 100644
--- a/tests/ui/impl-trait/in-trait/variance.rs
+++ b/tests/ui/impl-trait/in-trait/variance.rs
@@ -1,4 +1,4 @@
-#![feature(rustc_attrs, precise_capturing_in_traits)]
+#![feature(rustc_attrs)]
 #![allow(internal_features)]
 #![rustc_variance_of_opaques]
 
diff --git a/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs
new file mode 100644
index 00000000000..ab54d5f87ba
--- /dev/null
+++ b/tests/ui/impl-trait/inside-item-nested-in-anon-const.rs
@@ -0,0 +1,25 @@
+// Ensure we don't misclassify `impl Trait` as TAIT/ATPIT if located inside an anon const in a
+// type alias/assoc type.
+// issue: <https://github.com/rust-lang/rust/issues/139055>
+//@ check-pass
+#![forbid(unstable_features)]
+
+struct Girder<const N: usize>;
+
+type Alias = Girder<{
+    fn pass(input: impl Sized) -> impl Sized { input }
+    0
+}>;
+
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for () {
+    type Assoc = [(); {
+        fn pass(input: impl Sized) -> impl Sized { input }
+        0
+    }];
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index c1176255f24..9e8ea439dde 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -40,7 +40,6 @@ impl Context {
         f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
     ) -> TransactionResult<O> {
         //~^ ERROR expected generic lifetime parameter, found `'_`
-        //~| ERROR: item does not constrain
         let mut conn = Connection {};
         let mut transaction = TestTransaction { conn: &mut conn };
         f(&mut transaction).await
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 11e23d97d72..80aa5d75c3c 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -24,26 +24,6 @@ note: this opaque type is supposed to be constrained
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `TransactionFuture::{opaque#0}`
-  --> $DIR/issue-86800.rs:41:31
-   |
-LL |       ) -> TransactionResult<O> {
-   |  _______________________________^
-LL | |
-LL | |
-LL | |         let mut conn = Connection {};
-LL | |         let mut transaction = TestTransaction { conn: &mut conn };
-LL | |         f(&mut transaction).await
-LL | |     }
-   | |_____^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/issue-86800.rs:21:34
-   |
-LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/issue-86800.rs:31:5
    |
@@ -62,13 +42,12 @@ LL |   type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionRe
 LL |       ) -> TransactionResult<O> {
    |  _______________________________^
 LL | |
-LL | |
 LL | |         let mut conn = Connection {};
 LL | |         let mut transaction = TestTransaction { conn: &mut conn };
 LL | |         f(&mut transaction).await
 LL | |     }
    | |_____^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
index 6c2477c9744..1b52b170201 100644
--- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
@@ -1,5 +1,3 @@
-#![feature(precise_capturing_in_traits)]
-
 fn type_param<T>() -> impl Sized + use<> {}
 //~^ ERROR `impl Trait` must mention all type parameters in scope
 
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
index 93b44a0c18c..93c35203f1d 100644
--- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
@@ -1,5 +1,5 @@
 error: `impl Trait` must mention all type parameters in scope in `use<...>`
-  --> $DIR/forgot-to-capture-type.rs:3:23
+  --> $DIR/forgot-to-capture-type.rs:1:23
    |
 LL | fn type_param<T>() -> impl Sized + use<> {}
    |               -       ^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | fn type_param<T>() -> impl Sized + use<> {}
    = note: currently, all type parameters are required to be mentioned in the precise captures list
 
 error: `impl Trait` must mention the `Self` type of the trait in `use<...>`
-  --> $DIR/forgot-to-capture-type.rs:7:17
+  --> $DIR/forgot-to-capture-type.rs:5:17
    |
 LL | trait Foo {
    | --------- `Self` type parameter is implicitly captured by this `impl Trait`
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs
index 32dc0927317..2385827db22 100644
--- a/tests/ui/impl-trait/precise-capturing/redundant.rs
+++ b/tests/ui/impl-trait/precise-capturing/redundant.rs
@@ -1,6 +1,5 @@
 //@ edition: 2024
 
-#![feature(precise_capturing_in_traits)]
 #![deny(impl_trait_redundant_captures)]
 
 fn hello<'a>() -> impl Sized + use<'a> {}
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr
index 5c8b35c2285..c9f84d360e3 100644
--- a/tests/ui/impl-trait/precise-capturing/redundant.stderr
+++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr
@@ -1,5 +1,5 @@
 error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:6:19
+  --> $DIR/redundant.rs:5:19
    |
 LL | fn hello<'a>() -> impl Sized + use<'a> {}
    |                   ^^^^^^^^^^^^^-------
@@ -7,13 +7,13 @@ LL | fn hello<'a>() -> impl Sized + use<'a> {}
    |                                help: remove the `use<...>` syntax
    |
 note: the lint level is defined here
-  --> $DIR/redundant.rs:4:9
+  --> $DIR/redundant.rs:3:9
    |
 LL | #![deny(impl_trait_redundant_captures)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:11:27
+  --> $DIR/redundant.rs:10:27
    |
 LL |     fn inherent(&self) -> impl Sized + use<'_> {}
    |                           ^^^^^^^^^^^^^-------
@@ -21,7 +21,7 @@ LL |     fn inherent(&self) -> impl Sized + use<'_> {}
    |                                        help: remove the `use<...>` syntax
 
 error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:16:22
+  --> $DIR/redundant.rs:15:22
    |
 LL |     fn in_trait() -> impl Sized + use<'a, Self>;
    |                      ^^^^^^^^^^^^^-------------
@@ -29,7 +29,7 @@ LL |     fn in_trait() -> impl Sized + use<'a, Self>;
    |                                   help: remove the `use<...>` syntax
 
 error: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:20:22
+  --> $DIR/redundant.rs:19:22
    |
 LL |     fn in_trait() -> impl Sized + use<'a> {}
    |                      ^^^^^^^^^^^^^-------
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
index b39c1408c05..f6126c03339 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
@@ -2,8 +2,6 @@
 // trait definition, which is not allowed. Due to the default lifetime capture
 // rules of RPITITs, this is only doable if we use precise capturing.
 
-#![feature(precise_capturing_in_traits)]
-
 pub trait Foo {
     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
 }
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
index 45f755d3cc1..d9066018880 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
@@ -1,5 +1,5 @@
 error: return type captures more lifetimes than trait definition
-  --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40
+  --> $DIR/rpitit-captures-more-method-lifetimes.rs:10:40
    |
 LL |     fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {}
    |            ---                         ^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {}
    |            this lifetime was captured
    |
 note: hidden type must only reference lifetimes captured by this impl trait
-  --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40
+  --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40
    |
 LL |     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
    |                                        ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
index b16b0522d6e..115cab1cb99 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
@@ -1,5 +1,3 @@
-#![feature(precise_capturing_in_traits)]
-
 struct Invariant<'a>(&'a mut &'a mut ());
 
 trait Trait {
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
index 360f0d7e7f3..123e0acf171 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
@@ -1,5 +1,5 @@
 error: return type captures more lifetimes than trait definition
-  --> $DIR/rpitit-impl-captures-too-much.rs:10:39
+  --> $DIR/rpitit-impl-captures-too-much.rs:8:39
    |
 LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
    |                               -- this lifetime was captured
@@ -8,7 +8,7 @@ LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {}
    |                                       ^^^^^^^^^^^^^^^^^^^^
    |
 note: hidden type must only reference lifetimes captured by this impl trait
-  --> $DIR/rpitit-impl-captures-too-much.rs:6:39
+  --> $DIR/rpitit-impl-captures-too-much.rs:4:39
    |
 LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs b/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs
index 6f7e1a0eaef..6fc129a6480 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-outlives-2.rs
@@ -2,8 +2,6 @@
 
 // Ensure that we skip uncaptured args from RPITITs when comptuing outlives.
 
-#![feature(precise_capturing_in_traits)]
-
 struct Invariant<T>(*mut T);
 
 trait Foo {
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs b/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs
index 94d81d766f7..616368d25cf 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-outlives.rs
@@ -3,8 +3,6 @@
 // Ensure that we skip uncaptured args from RPITITs when collecting the regions
 // to enforce member constraints in opaque type inference.
 
-#![feature(precise_capturing_in_traits)]
-
 struct Invariant<T>(*mut T);
 
 trait Foo {
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs
index 3f887e8e47f..91c52817d85 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs
@@ -3,8 +3,6 @@
 // To fix this soundly, we need to make sure that all the trait header args
 // remain captured, since they affect trait selection.
 
-#![feature(precise_capturing_in_traits)]
-
 fn eq_types<T>(_: T, _: T) {}
 
 trait TraitLt<'a: 'a> {
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
index 498eae54a1c..ff461e81079 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
@@ -1,5 +1,5 @@
 error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
-  --> $DIR/rpitit.rs:11:19
+  --> $DIR/rpitit.rs:9:19
    |
 LL | trait TraitLt<'a: 'a> {
    |               -- all lifetime parameters originating from a trait are captured implicitly
@@ -7,7 +7,7 @@ LL |     fn hello() -> impl Sized + use<Self>;
    |                   ^^^^^^^^^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/rpitit.rs:15:5
+  --> $DIR/rpitit.rs:13:5
    |
 LL |   fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () {
    |               --  -- lifetime `'b` defined here
@@ -24,7 +24,7 @@ LL | |     );
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/rpitit.rs:15:5
+  --> $DIR/rpitit.rs:13:5
    |
 LL |   fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () {
    |               --  -- lifetime `'b` defined here
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs
index 15985da50b5..66fbfc78043 100644
--- a/tests/ui/impl-trait/precise-capturing/self-capture.rs
+++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![feature(precise_capturing_in_traits)]
-
 trait Foo {
     fn bar<'a>() -> impl Sized + use<Self>;
 }
diff --git a/tests/ui/imports/glob-resolve1.stderr b/tests/ui/imports/glob-resolve1.stderr
index 75e65681c3a..23b0db0fa46 100644
--- a/tests/ui/imports/glob-resolve1.stderr
+++ b/tests/ui/imports/glob-resolve1.stderr
@@ -58,6 +58,11 @@ error[E0425]: cannot find function `import` in this scope
 LL |     import();
    |     ^^^^^^ not found in this scope
    |
+note: function `bar::import` exists but is inaccessible
+  --> $DIR/glob-resolve1.rs:7:5
+   |
+LL |     fn fpriv() {}
+   |     ^^^^^^^^^^ not accessible
 help: consider importing this function
    |
 LL + use other::import;
diff --git a/tests/ui/imports/issue-4366-2.stderr b/tests/ui/imports/issue-4366-2.stderr
index 412423f4d59..b1c0092b05d 100644
--- a/tests/ui/imports/issue-4366-2.stderr
+++ b/tests/ui/imports/issue-4366-2.stderr
@@ -16,6 +16,11 @@ error[E0423]: expected function, found module `foo`
 LL |     foo();
    |     ^^^ not a function
    |
+note: function `m1::foo` exists but is inaccessible
+  --> $DIR/issue-4366-2.rs:21:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^ not accessible
 help: consider importing this function instead
    |
 LL + use foo::foo;
diff --git a/tests/ui/imports/issue-4366.stderr b/tests/ui/imports/issue-4366.stderr
index e63399d554e..54b7f31b231 100644
--- a/tests/ui/imports/issue-4366.stderr
+++ b/tests/ui/imports/issue-4366.stderr
@@ -4,6 +4,11 @@ error[E0425]: cannot find function `foo` in this scope
 LL |         fn sub() -> isize { foo(); 1 }
    |                             ^^^ not found in this scope
    |
+note: function `m1::foo` exists but is inaccessible
+  --> $DIR/issue-4366.rs:23:5
+   |
+LL |     fn foo() {}
+   |     ^^^^^^^^ not accessible
 help: consider importing this function
    |
 LL +         use foo::foo;
diff --git a/tests/ui/imports/show-private-items-issue-138626.rs b/tests/ui/imports/show-private-items-issue-138626.rs
new file mode 100644
index 00000000000..d9708fc33c2
--- /dev/null
+++ b/tests/ui/imports/show-private-items-issue-138626.rs
@@ -0,0 +1,19 @@
+pub mod one {
+    mod foo {
+        pub struct Foo;
+    }
+
+    pub use self::foo::Foo;
+}
+
+pub mod two {
+    mod foo {
+        mod bar {
+            pub struct Foo;
+        }
+    }
+
+    pub use crate::two::foo::Foo; //~ ERROR unresolved import `crate::two::foo::Foo` [E0432]
+}
+
+fn main() {}
diff --git a/tests/ui/imports/show-private-items-issue-138626.stderr b/tests/ui/imports/show-private-items-issue-138626.stderr
new file mode 100644
index 00000000000..b664462daed
--- /dev/null
+++ b/tests/ui/imports/show-private-items-issue-138626.stderr
@@ -0,0 +1,20 @@
+error[E0432]: unresolved import `crate::two::foo::Foo`
+  --> $DIR/show-private-items-issue-138626.rs:16:13
+   |
+LL |     pub use crate::two::foo::Foo;
+   |             ^^^^^^^^^^^^^^^^^^^^ no `Foo` in `two::foo`
+   |
+note: struct `two::foo::bar::Foo` exists but is inaccessible
+  --> $DIR/show-private-items-issue-138626.rs:12:13
+   |
+LL |             pub struct Foo;
+   |             ^^^^^^^^^^^^^^^ not accessible
+help: consider importing this struct through its public re-export instead
+   |
+LL -     pub use crate::two::foo::Foo;
+LL +     pub use one::Foo;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr
index 7d09af9a7d4..7770cc8a720 100644
--- a/tests/ui/infinite/infinite-autoderef.stderr
+++ b/tests/ui/infinite/infinite-autoderef.stderr
@@ -1,8 +1,8 @@
 error[E0275]: overflow assigning `Box<_>` to `_`
-  --> $DIR/infinite-autoderef.rs:16:13
+  --> $DIR/infinite-autoderef.rs:16:22
    |
 LL |         x = Box::new(x);
-   |             ^^^^^^^^^^^
+   |                      ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/infinite/infinite-struct.rs b/tests/ui/infinite/infinite-struct.rs
index 62f9702b9f4..fd47a4ec9cc 100644
--- a/tests/ui/infinite/infinite-struct.rs
+++ b/tests/ui/infinite/infinite-struct.rs
@@ -15,3 +15,5 @@ struct Foo { //~ ERROR has infinite size
 struct Bar<T>([T; 1]);
 
 fn main() {}
+
+//~? ERROR reached the recursion limit finding the struct tail for `Take`
diff --git a/tests/ui/inline-const/collect-scopes-in-pat.rs b/tests/ui/inline-const/collect-scopes-in-pat.rs
deleted file mode 100644
index 16baf920f58..00000000000
--- a/tests/ui/inline-const/collect-scopes-in-pat.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ compile-flags: -Zlint-mir
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
-    match 1 {
-        const {
-            || match 0 {
-                x => 0,
-            };
-            0
-        } => (),
-        _ => (),
-    }
-}
diff --git a/tests/ui/inline-const/const-block-pat-liveness.rs b/tests/ui/inline-const/const-block-pat-liveness.rs
deleted file mode 100644
index 26393a4f65b..00000000000
--- a/tests/ui/inline-const/const-block-pat-liveness.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! This test used to ICE because const blocks didn't have a body
-//! anymore, making a lot of logic very fragile around handling the
-//! HIR of a const block.
-//! https://github.com/rust-lang/rust/issues/125846
-
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
-    match 0 {
-        const {
-            let a = 10_usize;
-            *&a
-        }
-        | _ => {}
-    }
-}
diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs
deleted file mode 100644
index 889c015e9ac..00000000000
--- a/tests/ui/inline-const/const-match-pat-generic.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![feature(inline_const_pat)]
-
-// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
-
-fn foo<const V: usize>() {
-    match 0 {
-        const { V } => {},
-        //~^ ERROR constant pattern cannot depend on generic parameters
-        _ => {},
-    }
-}
-
-const fn f(x: usize) -> usize {
-    x + 1
-}
-
-fn bar<const V: usize>() {
-    match 0 {
-        const { f(V) } => {},
-        //~^ ERROR constant pattern cannot depend on generic parameters
-        _ => {},
-    }
-}
-
-fn main() {
-    foo::<1>();
-    bar::<1>();
-}
diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr
deleted file mode 100644
index 7d9e1d9e407..00000000000
--- a/tests/ui/inline-const/const-match-pat-generic.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0158]: constant pattern cannot depend on generic parameters
-  --> $DIR/const-match-pat-generic.rs:7:9
-   |
-LL |         const { V } => {},
-   |         ^^^^^^^^^^^ `const` depends on a generic parameter
-
-error[E0158]: constant pattern cannot depend on generic parameters
-  --> $DIR/const-match-pat-generic.rs:19:9
-   |
-LL |         const { f(V) } => {},
-   |         ^^^^^^^^^^^^^^ `const` depends on a generic parameter
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs
deleted file mode 100644
index 3d3533839bc..00000000000
--- a/tests/ui/inline-const/const-match-pat-inference.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ check-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
-    match 1u64 {
-        0 => (),
-        const { 0 + 1 } => (),
-        const { 2 - 1 } ..= const { u64::MAX } => (),
-    }
-}
diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs
deleted file mode 100644
index 7f450ebe6fc..00000000000
--- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-#![feature(inline_const_pat)]
-
-use std::marker::PhantomData;
-
-#[derive(PartialEq, Eq)]
-pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
-
-#[derive(PartialEq, Eq)]
-pub struct CovariantRef<'a, T: ?Sized>(&'a T);
-
-impl<'a, T: ?Sized> InvariantRef<'a, T> {
-    pub const fn new(r: &'a T) -> Self {
-        InvariantRef(r, PhantomData)
-    }
-}
-
-impl<'a> InvariantRef<'a, ()> {
-    pub const NEW: Self = InvariantRef::new(&());
-}
-
-impl<'a> CovariantRef<'a, ()> {
-    pub const NEW: Self = CovariantRef(&());
-}
-
-fn match_invariant_ref<'a>() {
-    let y = ();
-    match InvariantRef::new(&y) {
-        //~^ ERROR `y` does not live long enough [E0597]
-        const { InvariantRef::<'a>::NEW } => (),
-    }
-}
-
-fn match_covariant_ref<'a>() {
-    // Unclear if we should error here (should we be able to subtype the type of
-    // `y.0`), but using the associated const directly in the pattern also
-    // errors.
-    let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),);
-    //~^ ERROR lifetime may not live long enough
-    match y.0 {
-        const { CovariantRef::<'a>::NEW } => (),
-    }
-}
-
-fn main() {
-    match_invariant_ref();
-    match_covariant_ref();
-}
diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
deleted file mode 100644
index 7eea1846057..00000000000
--- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0597]: `y` does not live long enough
-  --> $DIR/const-match-pat-lifetime-err.rs:27:29
-   |
-LL | fn match_invariant_ref<'a>() {
-   |                        -- lifetime `'a` defined here
-LL |     let y = ();
-   |         - binding `y` declared here
-LL |     match InvariantRef::new(&y) {
-   |                             ^^ borrowed value does not live long enough
-LL |
-LL |         const { InvariantRef::<'a>::NEW } => (),
-   |                 ----------------------- using this value as a constant requires that `y` is borrowed for `'a`
-LL |     }
-LL | }
-   | - `y` dropped here while still borrowed
-
-error: lifetime may not live long enough
-  --> $DIR/const-match-pat-lifetime-err.rs:37:12
-   |
-LL | fn match_covariant_ref<'a>() {
-   |                        -- lifetime `'a` defined here
-...
-LL |     let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),);
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs
deleted file mode 100644
index 7f1011ea240..00000000000
--- a/tests/ui/inline-const/const-match-pat-lifetime.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ run-pass
-
-#![feature(inline_const_pat)]
-
-use std::marker::PhantomData;
-
-// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
-fn issue_78174() {
-    match "foo" {
-        const { concat!("fo", "o") } => (),
-        _ => unreachable!(),
-    }
-}
-
-#[derive(PartialEq, Eq)]
-pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
-
-impl<'a, T: ?Sized> InvariantRef<'a, T> {
-    pub const fn new(r: &'a T) -> Self {
-        InvariantRef(r, PhantomData)
-    }
-}
-
-fn match_invariant_ref<'a>() {
-    match const { InvariantRef::<'a, _>::new(&()) } {
-        const { InvariantRef::<'a, ()>::new(&()) } => {
-        }
-    }
-}
-
-fn main() {
-    issue_78174();
-    match_invariant_ref();
-}
diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs
deleted file mode 100644
index 7202c0c0452..00000000000
--- a/tests/ui/inline-const/const-match-pat-range.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//@ build-pass
-
-#![feature(inline_const_pat)]
-
-fn main() {
-    const N: u32 = 10;
-    let x: u32 = 3;
-
-    match x {
-        1 ..= const { N + 1 } => {},
-        _ => {},
-    }
-
-    match x {
-        const { N - 1 } ..= 10 => {},
-        _ => {},
-    }
-
-    match x {
-        const { N - 1 } ..= const { N + 1 } => {},
-        _ => {},
-    }
-
-    match x {
-        .. const { N + 1 } => {},
-        _ => {},
-    }
-
-    match x {
-        const { N - 1 } .. => {},
-        _ => {},
-    }
-
-    match x {
-        ..= const { N + 1 } => {},
-        _ => {}
-    }
-}
diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs
deleted file mode 100644
index 1580ef25812..00000000000
--- a/tests/ui/inline-const/const-match-pat.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ run-pass
-
-#![feature(inline_const_pat)]
-const MMIO_BIT1: u8 = 4;
-const MMIO_BIT2: u8 = 5;
-
-fn main() {
-    let s = match read_mmio() {
-        0 => "FOO",
-        const { 1 << MMIO_BIT1 } => "BAR",
-        const { 1 << MMIO_BIT2 } => "BAZ",
-        _ => unreachable!(),
-    };
-
-    assert_eq!("BAZ", s);
-}
-
-fn read_mmio() -> i32 {
-    1 << 5
-}
diff --git a/tests/ui/inline-const/in-pat-recovery.rs b/tests/ui/inline-const/in-pat-recovery.rs
new file mode 100644
index 00000000000..0d912af0981
--- /dev/null
+++ b/tests/ui/inline-const/in-pat-recovery.rs
@@ -0,0 +1,11 @@
+// While `feature(inline_const_pat)` has been removed from the
+// compiler, we should still make sure that the resulting error
+// message is acceptable.
+fn main() {
+    match 1 {
+        const { 1 + 7 } => {}
+        //~^ `inline_const_pat` has been removed
+        2 => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/inline-const/in-pat-recovery.stderr b/tests/ui/inline-const/in-pat-recovery.stderr
new file mode 100644
index 00000000000..e1f2e681e77
--- /dev/null
+++ b/tests/ui/inline-const/in-pat-recovery.stderr
@@ -0,0 +1,10 @@
+error: `inline_const_pat` has been removed
+  --> $DIR/in-pat-recovery.rs:6:15
+   |
+LL |         const { 1 + 7 } => {}
+   |               ^^^^^^^^^
+   |
+   = help: use a named `const`-item or an `if`-guard instead
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/inline-const/pat-match-fndef.rs b/tests/ui/inline-const/pat-match-fndef.rs
deleted file mode 100644
index 013a4a67561..00000000000
--- a/tests/ui/inline-const/pat-match-fndef.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(inline_const_pat)]
-
-fn uwu() {}
-
-fn main() {
-    let x = [];
-    match x[123] {
-        const { uwu } => {}
-        //~^ ERROR `fn() {uwu}` cannot be used in patterns
-        _ => {}
-    }
-}
diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr
deleted file mode 100644
index 220437a0491..00000000000
--- a/tests/ui/inline-const/pat-match-fndef.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fn item `fn() {uwu}` cannot be used in patterns
-  --> $DIR/pat-match-fndef.rs:8:9
-   |
-LL |         const { uwu } => {}
-   |         ^^^^^^^^^^^^^ fn item can't be used in patterns
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs
deleted file mode 100644
index b906def7029..00000000000
--- a/tests/ui/inline-const/pat-unsafe-err.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(inline_const_pat)]
-
-const unsafe fn require_unsafe() -> usize {
-    1
-}
-
-fn main() {
-    match () {
-        const {
-            require_unsafe();
-            //~^ ERROR [E0133]
-        } => (),
-    }
-
-    match 1 {
-        const {
-            require_unsafe()
-            //~^ ERROR [E0133]
-        }..=4 => (),
-        _ => (),
-    }
-}
diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr
deleted file mode 100644
index 786c7f31ccc..00000000000
--- a/tests/ui/inline-const/pat-unsafe-err.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
-  --> $DIR/pat-unsafe-err.rs:10:13
-   |
-LL |             require_unsafe();
-   |             ^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
-  --> $DIR/pat-unsafe-err.rs:17:13
-   |
-LL |             require_unsafe()
-   |             ^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs
deleted file mode 100644
index 4b05f3a1cdd..00000000000
--- a/tests/ui/inline-const/pat-unsafe.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//@ check-pass
-
-#![warn(unused_unsafe)]
-#![feature(inline_const_pat)]
-
-const unsafe fn require_unsafe() -> usize {
-    1
-}
-
-fn main() {
-    unsafe {
-        match () {
-            const {
-                require_unsafe();
-                unsafe {}
-                //~^ WARNING unnecessary `unsafe` block
-            } => (),
-        }
-
-        match 1 {
-            const {
-                unsafe {}
-                //~^ WARNING unnecessary `unsafe` block
-                require_unsafe()
-            }..=4 => (),
-            _ => (),
-        }
-    }
-}
diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr
deleted file mode 100644
index 59460271ac0..00000000000
--- a/tests/ui/inline-const/pat-unsafe.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-warning: unnecessary `unsafe` block
-  --> $DIR/pat-unsafe.rs:15:17
-   |
-LL |                 unsafe {}
-   |                 ^^^^^^ unnecessary `unsafe` block
-   |
-note: the lint level is defined here
-  --> $DIR/pat-unsafe.rs:3:9
-   |
-LL | #![warn(unused_unsafe)]
-   |         ^^^^^^^^^^^^^
-
-warning: unnecessary `unsafe` block
-  --> $DIR/pat-unsafe.rs:22:17
-   |
-LL |                 unsafe {}
-   |                 ^^^^^^ unnecessary `unsafe` block
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/instrument-coverage/bad-value.rs b/tests/ui/instrument-coverage/bad-value.rs
index 34417385291..d44f982ea46 100644
--- a/tests/ui/instrument-coverage/bad-value.rs
+++ b/tests/ui/instrument-coverage/bad-value.rs
@@ -3,3 +3,6 @@
 //@ [bad] compile-flags: -Cinstrument-coverage=bad-value
 
 fn main() {}
+
+//[blank]~? ERROR incorrect value `` for codegen option `instrument-coverage`
+//[bad]~? ERROR incorrect value `bad-value` for codegen option `instrument-coverage`
diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs
index 7615a0fb275..c3eae9625da 100644
--- a/tests/ui/instrument-coverage/coverage-options.rs
+++ b/tests/ui/instrument-coverage/coverage-options.rs
@@ -17,3 +17,5 @@
 //@ [bad] compile-flags: -Zcoverage-options=bad
 
 fn main() {}
+
+//[bad]~? ERROR incorrect value `bad` for unstable option `coverage-options`
diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
index b4025080034..2a39d579c51 100644
--- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
+++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
@@ -15,3 +15,7 @@
 
 #[lang = "sized"]
 trait Sized {}
+
+//[BADFLAGS]~? ERROR incorrect value `leaf` for unstable option `branch-protection`
+//[BADFLAGSPC]~? ERROR incorrect value `pc` for unstable option `branch-protection`
+//[BADTARGET]~? ERROR `-Zbranch-protection` is only supported on aarch64
diff --git a/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs
index ddb46e59711..832821c9c88 100644
--- a/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs
+++ b/tests/ui/invalid-compile-flags/invalid-llvm-passes.rs
@@ -2,3 +2,5 @@
 //@ compile-flags: -Cpasses=unknown-pass
 
 fn main() {}
+
+//~? ERROR failed to run LLVM passes: unknown pass name 'unknown-pass'
diff --git a/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs b/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs
index b1ac4a4ae21..0e80b1dd178 100644
--- a/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs
+++ b/tests/ui/invalid-compile-flags/need-crate-arg-ignore-tidy$x.rs
@@ -1,2 +1,5 @@
 // issue: 113981
+
 pub fn main() {}
+
+//~? ERROR invalid character '$' in crate name: `need_crate_arg_ignore_tidy$x`
diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr
index 05d42247d41..8abaee5056b 100644
--- a/tests/ui/invalid-compile-flags/print-without-arg.stderr
+++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr
@@ -1,5 +1,5 @@
 error: Argument to option 'print' missing
        Usage:
-           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
+           --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
                                Compiler information to print on stdout
 
diff --git a/tests/ui/invalid-compile-flags/print.rs b/tests/ui/invalid-compile-flags/print.rs
index 0d0a9d22750..4665bb2c536 100644
--- a/tests/ui/invalid-compile-flags/print.rs
+++ b/tests/ui/invalid-compile-flags/print.rs
@@ -1 +1,3 @@
 //@ compile-flags: --print yyyy
+
+//~? ERROR unknown print request: `yyyy`
diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr
index 4ea06a06539..e3374eb1e6e 100644
--- a/tests/ui/invalid-compile-flags/print.stderr
+++ b/tests/ui/invalid-compile-flags/print.stderr
@@ -1,5 +1,5 @@
 error: unknown print request: `yyyy`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 
diff --git a/tests/ui/invalid-module-declaration/invalid-module-declaration.rs b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs
index 254d810d79d..1c6c282f4b7 100644
--- a/tests/ui/invalid-module-declaration/invalid-module-declaration.rs
+++ b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs
@@ -3,3 +3,5 @@ mod auxiliary {
 }
 
 fn main() {}
+
+//~? ERROR file not found for module `baz`
diff --git a/tests/ui/issues/issue-28777.rs b/tests/ui/issues/issue-28777.rs
deleted file mode 100644
index f67e11e3694..00000000000
--- a/tests/ui/issues/issue-28777.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ run-pass
-#![allow(unused_braces)]
-fn main() {
-    let v1 = { 1 + {2} * {3} };
-    let v2 =   1 + {2} * {3}  ;
-
-    assert_eq!(7, v1);
-    assert_eq!(7, v2);
-
-    let v3;
-    v3 = { 1 + {2} * {3} };
-    let v4;
-    v4 = 1 + {2} * {3};
-    assert_eq!(7, v3);
-    assert_eq!(7, v4);
-
-    let v5 = { 1 + {2} * 3 };
-    assert_eq!(7, v5);
-
-    let v9 = { 1 + if 1 > 2 {1} else {2} * {3} };
-    assert_eq!(7, v9);
-}
diff --git a/tests/ui/issues/issue-31260.rs b/tests/ui/issues/issue-31260.rs
deleted file mode 100644
index 5e9fffb195c..00000000000
--- a/tests/ui/issues/issue-31260.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ check-pass
-#![allow(dead_code)]
-pub struct Struct<K: 'static> {
-    pub field: K,
-}
-
-static STRUCT: Struct<&'static [u8]> = Struct {
-    field: {&[1]}
-};
-
-static STRUCT2: Struct<&'static [u8]> = Struct {
-    field: &[1]
-};
-
-fn main() {}
diff --git a/tests/ui/issues/issue-9382.rs b/tests/ui/issues/issue-9382.rs
deleted file mode 100644
index 27f9ab57743..00000000000
--- a/tests/ui/issues/issue-9382.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-
-// Tests for a previous bug that occurred due to an interaction
-// between struct field initialization and the auto-coercion
-// from a vector to a slice. The drop glue was being invoked on
-// the temporary slice with a wrong type, triggering an LLVM assert.
-
-
-struct Thing1<'a> {
-    baz: &'a [Box<isize>],
-    bar: Box<u64>,
-}
-
-struct Thing2<'a> {
-    baz: &'a [Box<isize>],
-    bar: u64,
-}
-
-pub fn main() {
-    let _t1_fixed = Thing1 {
-        baz: &[],
-        bar: Box::new(32),
-    };
-    Thing1 {
-        baz: &Vec::new(),
-        bar: Box::new(32),
-    };
-    let _t2_fixed = Thing2 {
-        baz: &[],
-        bar: 32,
-    };
-    Thing2 {
-        baz: &Vec::new(),
-        bar: 32,
-    };
-}
diff --git a/tests/ui/lang-items/lang-item-generic-requirements.rs b/tests/ui/lang-items/lang-item-generic-requirements.rs
index 0f982df61e8..90ed5f3f0ef 100644
--- a/tests/ui/lang-items/lang-item-generic-requirements.rs
+++ b/tests/ui/lang-items/lang-item-generic-requirements.rs
@@ -59,3 +59,5 @@ fn ice() {
 
 // use `start`
 fn main() {}
+
+//~? ERROR requires `copy` lang_item
diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs
index f6c1df55988..f144094d43f 100644
--- a/tests/ui/layout/reprc-power-alignment.rs
+++ b/tests/ui/layout/reprc-power-alignment.rs
@@ -148,5 +148,29 @@ pub struct I {
     d: f32,
     e: f64,
 }
-
+#[repr(C)]
+pub struct J {
+    a: u8,
+    b: I,
+}
+// The lint also ignores diagnosing #[repr(align(n))].
+#[repr(C, align(8))]
+pub struct K {
+    a: u8,
+    b: u8,
+    c: f64,
+    d: f32,
+    e: f64,
+}
+#[repr(C)]
+pub struct L {
+    a: u8,
+    b: K,
+}
+#[repr(C, align(8))]
+pub struct M {
+    a: u8,
+    b: K,
+    c: L,
+}
 fn main() { }
diff --git a/tests/ui/link-native-libs/modifiers-bad.rs b/tests/ui/link-native-libs/modifiers-bad.rs
index 185201e0d84..4d6c8a278d4 100644
--- a/tests/ui/link-native-libs/modifiers-bad.rs
+++ b/tests/ui/link-native-libs/modifiers-bad.rs
@@ -9,3 +9,8 @@
 // Tests various illegal values for the "modifier" part of an `-l` flag.
 
 fn main() {}
+
+//[blank]~? ERROR invalid linking modifier syntax, expected '+' or '-' prefix
+//[no-prefix]~? ERROR invalid linking modifier syntax, expected '+' or '-' prefix
+//[prefix-only]~? ERROR unknown linking modifier ``
+//[unknown]~? ERROR unknown linking modifier `ferris`
diff --git a/tests/ui/link-native-libs/modifiers-override-2.rs b/tests/ui/link-native-libs/modifiers-override-2.rs
index a462a741ac6..d132f2419d8 100644
--- a/tests/ui/link-native-libs/modifiers-override-2.rs
+++ b/tests/ui/link-native-libs/modifiers-override-2.rs
@@ -1,3 +1,5 @@
 //@ compile-flags:-lstatic:+whole-archive,-whole-archive=foo
 
 fn main() {}
+
+//~? ERROR multiple `whole-archive` modifiers in a single `-l` option
diff --git a/tests/ui/link-native-libs/msvc-non-utf8-output.rs b/tests/ui/link-native-libs/msvc-non-utf8-output.rs
index 03b1f6516ab..5cc4cd9a3d6 100644
--- a/tests/ui/link-native-libs/msvc-non-utf8-output.rs
+++ b/tests/ui/link-native-libs/msvc-non-utf8-output.rs
@@ -3,3 +3,5 @@
 //@ only-msvc
 //@ normalize-stderr: "(?:.|\n)*(⦺ⅈ⽯⭏⽽◃⡽⚞)(?:.|\n)*" -> "$1"
 pub fn main() {}
+
+//~? ERROR linking with `
diff --git a/tests/ui/linkage-attr/link-self-contained-consistency.rs b/tests/ui/linkage-attr/link-self-contained-consistency.rs
index def63233e94..08227433891 100644
--- a/tests/ui/linkage-attr/link-self-contained-consistency.rs
+++ b/tests/ui/linkage-attr/link-self-contained-consistency.rs
@@ -8,3 +8,6 @@
 // ignore-tidy-linelength
 
 fn main() {}
+
+//[one]~? ERROR some `-C link-self-contained` components were both enabled and disabled: linker
+//[many]~? ERROR some `-C link-self-contained` components were both enabled and disabled: crto, linker
diff --git a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
index b43df634112..23848056ee1 100644
--- a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
+++ b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
@@ -22,3 +22,5 @@ fn main() {
        println!("{:p}", &dep1::collision);
     }
 }
+
+//~? ERROR symbol `collision` is already defined
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
index e69a4537935..92cb60bb16d 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs
@@ -19,3 +19,5 @@ extern "C" {
 pub fn lib_main() {
     unsafe { f(42); }
 }
+
+//~? ERROR Dlltool could not create import library with
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs
index 057242246f0..0c78d799bad 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs
@@ -10,3 +10,5 @@ extern "C" {
 pub fn lib_main() {
     unsafe { f(42); }
 }
+
+//~? ERROR Error calling dlltool 'does_not_exist.exe': program not found
diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs
deleted file mode 100644
index e2d8c90edcc..00000000000
--- a/tests/ui/lint/dead-code/anon-const-in-pat.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-//@ check-pass
-#![feature(inline_const_pat)]
-#![deny(dead_code)]
-
-const fn one() -> i32 {
-    1
-}
-
-const fn two() -> i32 {
-    2
-}
-
-const fn three() -> i32 {
-    3
-}
-
-fn inline_const() {
-    // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern
-    match 1 {
-        const { one() } => {}
-        _ => {}
-    }
-}
-
-fn inline_const_range() {
-    match 1 {
-        1 ..= const { two() } => {}
-        _ => {}
-    }
-}
-
-struct S<const C: i32>;
-
-fn const_generic_arg() {
-    match S::<3> {
-        S::<{three()}> => {}
-    }
-}
-
-fn main() {
-    inline_const();
-    inline_const_range();
-    const_generic_arg();
-}
diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs
index d0f26a87385..3cb4b91ff2b 100644
--- a/tests/ui/lint/expansion-time.rs
+++ b/tests/ui/lint/expansion-time.rs
@@ -31,3 +31,5 @@ fn main() {
     // WARN see in the stderr file, the warning points to the included file.
     include!("expansion-time-include.rs");
 }
+
+//~? WARN include macro expected single expression in source
diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs
index 90303a1fc3d..5d4133d6c77 100644
--- a/tests/ui/lint/inert-attr-macro.rs
+++ b/tests/ui/lint/inert-attr-macro.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 
+#![feature(cfg_boolean_literals)]
 #![warn(unused)]
 
 macro_rules! foo {
@@ -17,4 +18,10 @@ fn main() {
     // This does work, since the attribute is on a parent
     // of the macro invocation.
     #[allow(warnings)] { #[inline] foo!(); }
+
+    // Ok, `cfg` and `cfg_attr` are expanded eagerly and do not warn.
+    #[cfg(true)] foo!();
+    #[cfg(false)] foo!();
+    #[cfg_attr(true, cfg(true))] foo!();
+    #[cfg_attr(false, nonexistent)] foo!();
 }
diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr
index 5ccb4ffe792..b85b0319e71 100644
--- a/tests/ui/lint/inert-attr-macro.stderr
+++ b/tests/ui/lint/inert-attr-macro.stderr
@@ -1,41 +1,41 @@
 warning: unused attribute `inline`
-  --> $DIR/inert-attr-macro.rs:10:5
+  --> $DIR/inert-attr-macro.rs:11:5
    |
 LL |     #[inline] foo!();
    |     ^^^^^^^^^
    |
 note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:10:15
+  --> $DIR/inert-attr-macro.rs:11:15
    |
 LL |     #[inline] foo!();
    |               ^^^
 note: the lint level is defined here
-  --> $DIR/inert-attr-macro.rs:3:9
+  --> $DIR/inert-attr-macro.rs:4:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
 
 warning: unused attribute `allow`
-  --> $DIR/inert-attr-macro.rs:14:5
+  --> $DIR/inert-attr-macro.rs:15:5
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:14:34
+  --> $DIR/inert-attr-macro.rs:15:34
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                                  ^^^
 
 warning: unused attribute `inline`
-  --> $DIR/inert-attr-macro.rs:14:24
+  --> $DIR/inert-attr-macro.rs:15:24
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                        ^^^^^^^^^
    |
 note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:14:34
+  --> $DIR/inert-attr-macro.rs:15:34
    |
 LL |     #[allow(warnings)] #[inline] foo!();
    |                                  ^^^
diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs
new file mode 100644
index 00000000000..69e322ef513
--- /dev/null
+++ b/tests/ui/lint/inline-exported.rs
@@ -0,0 +1,30 @@
+//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`,
+//! because `#[inline]` is ignored for such functions.
+
+#![crate_type = "lib"]
+
+#![feature(linkage)]
+#![feature(naked_functions)]
+#![deny(unused_attributes)]
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[no_mangle]
+fn no_mangle() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[export_name = "export_name"]
+fn export_name() {}
+
+#[inline]
+//~^ ERROR: `#[inline]` is ignored on externally exported functions
+#[linkage = "external"]
+fn external_linkage() {}
+
+#[inline]
+fn normal() {}
+
+#[inline]
+#[linkage = "internal"] // not exported
+fn internal_linkage() {}
diff --git a/tests/ui/lint/inline-exported.stderr b/tests/ui/lint/inline-exported.stderr
new file mode 100644
index 00000000000..dcf63cc4090
--- /dev/null
+++ b/tests/ui/lint/inline-exported.stderr
@@ -0,0 +1,31 @@
+error: `#[inline]` is ignored on externally exported functions
+  --> $DIR/inline-exported.rs:10:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+note: the lint level is defined here
+  --> $DIR/inline-exported.rs:8:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: `#[inline]` is ignored on externally exported functions
+  --> $DIR/inline-exported.rs:15:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: `#[inline]` is ignored on externally exported functions
+  --> $DIR/inline-exported.rs:20:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
new file mode 100644
index 00000000000..7948f0d86d0
--- /dev/null
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -0,0 +1,136 @@
+// check-fail
+// run-rustfix
+
+use std::ptr;
+use std::mem;
+
+unsafe fn null_ptr() {
+    ptr::write(
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+        ptr::null_mut() as *mut u32,
+        mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+    );
+
+    let null_ptr = ptr::null_mut();
+    ptr::write(
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+        null_ptr as *mut u32,
+        mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+    );
+
+    let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::copy::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    ptr::copy::<usize>(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    ptr::copy_nonoverlapping::<usize>(
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+        ptr::NonNull::dangling().as_ptr(),
+        ptr::null_mut(),
+        0
+    );
+
+    #[derive(Copy, Clone)]
+    struct A(usize);
+    let mut v = A(200);
+
+    let _a: A = ptr::read(ptr::null());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _a: A = ptr::read(ptr::null_mut());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    let _a: A = ptr::read_unaligned(ptr::null());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _a: A = ptr::read_unaligned(ptr::null_mut());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    let _a: A = ptr::read_volatile(ptr::null());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    let _a: A = ptr::read_volatile(ptr::null_mut());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    let _a: A = ptr::replace(ptr::null_mut(), v);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::swap::<A>(ptr::null_mut(), &mut v);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    ptr::swap::<A>(&mut v, ptr::null_mut());
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::write(ptr::null_mut(), v);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::write_unaligned(ptr::null_mut(), v);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::write_volatile(ptr::null_mut(), v);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    // with indirections
+    let const_ptr = null_ptr as *const u8;
+    let _a: u8 = ptr::read(const_ptr);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+}
+
+unsafe fn zst() {
+    struct Zst; // zero-sized type
+
+    std::slice::from_raw_parts::<()>(ptr::null(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+    std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
+    //~^ ERROR calling this function with a null pointer is undefined behavior
+
+    ptr::read::<()>(ptr::null());
+    ptr::read::<Zst>(ptr::null());
+
+    ptr::write(ptr::null_mut(), ());
+    ptr::write(ptr::null_mut(), Zst);
+
+    ptr::copy(ptr::null::<()>(), ptr::null_mut::<()>(), 1);
+    ptr::copy(ptr::null::<Zst>(), ptr::null_mut::<Zst>(), 1);
+}
+
+unsafe fn not_invalid() {
+    // Simplified false-positive from std quicksort implementation
+
+    let mut a = ptr::null_mut();
+    let mut b = ();
+
+    loop {
+        if false {
+            break;
+        }
+
+        a = &raw mut b;
+    }
+
+    ptr::write(a, ());
+}
+
+fn main() {}
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
new file mode 100644
index 00000000000..f95bc2afa82
--- /dev/null
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -0,0 +1,330 @@
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:8:5
+   |
+LL | /     ptr::write(
+LL | |
+LL | |         ptr::null_mut() as *mut u32,
+   | |         --------------- null pointer originates from here
+LL | |         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+LL | |     );
+   | |_____^
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+   = note: `#[deny(invalid_null_arguments)]` on by default
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:15:5
+   |
+LL | /     ptr::write(
+LL | |
+LL | |         null_ptr as *mut u32,
+LL | |         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
+LL | |     );
+   | |_____^
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+note: null pointer originates from here
+  --> $DIR/invalid_null_args.rs:14:20
+   |
+LL |     let null_ptr = ptr::null_mut();
+   |                    ^^^^^^^^^^^^^^^
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:21:23
+   |
+LL |     let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+   |                                                  |
+   |                                                  null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:23:23
+   |
+LL |     let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                                  |
+   |                                                  null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:25:23
+   |
+LL |     let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^
+   |                                                  |
+   |                                                  null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:27:23
+   |
+LL |     let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^
+   |                                                                 |
+   |                                                                 null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:30:23
+   |
+LL |     let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                                      |
+   |                                                      null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:33:5
+   |
+LL |     ptr::copy::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        |
+   |                        null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:35:5
+   |
+LL |     ptr::copy::<usize>(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                                           |
+   |                                                           null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:38:5
+   |
+LL |     ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       |
+   |                                       null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:40:5
+   |
+LL | /     ptr::copy_nonoverlapping::<usize>(
+LL | |
+LL | |         ptr::NonNull::dangling().as_ptr(),
+LL | |         ptr::null_mut(),
+   | |         --------------- null pointer originates from here
+LL | |         0
+LL | |     );
+   | |_____^
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:51:17
+   |
+LL |     let _a: A = ptr::read(ptr::null());
+   |                 ^^^^^^^^^^-----------^
+   |                           |
+   |                           null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:53:17
+   |
+LL |     let _a: A = ptr::read(ptr::null_mut());
+   |                 ^^^^^^^^^^---------------^
+   |                           |
+   |                           null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:56:17
+   |
+LL |     let _a: A = ptr::read_unaligned(ptr::null());
+   |                 ^^^^^^^^^^^^^^^^^^^^-----------^
+   |                                     |
+   |                                     null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:58:17
+   |
+LL |     let _a: A = ptr::read_unaligned(ptr::null_mut());
+   |                 ^^^^^^^^^^^^^^^^^^^^---------------^
+   |                                     |
+   |                                     null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:61:17
+   |
+LL |     let _a: A = ptr::read_volatile(ptr::null());
+   |                 ^^^^^^^^^^^^^^^^^^^-----------^
+   |                                    |
+   |                                    null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:63:17
+   |
+LL |     let _a: A = ptr::read_volatile(ptr::null_mut());
+   |                 ^^^^^^^^^^^^^^^^^^^---------------^
+   |                                    |
+   |                                    null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:66:17
+   |
+LL |     let _a: A = ptr::replace(ptr::null_mut(), v);
+   |                 ^^^^^^^^^^^^^---------------^^^^
+   |                              |
+   |                              null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:69:5
+   |
+LL |     ptr::swap::<A>(ptr::null_mut(), &mut v);
+   |     ^^^^^^^^^^^^^^^---------------^^^^^^^^^
+   |                    |
+   |                    null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:71:5
+   |
+LL |     ptr::swap::<A>(&mut v, ptr::null_mut());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^
+   |                            |
+   |                            null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:74:5
+   |
+LL |     ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
+   |                                   |
+   |                                   null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:76:5
+   |
+LL |     ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                           |
+   |                                           null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:79:5
+   |
+LL |     ptr::write(ptr::null_mut(), v);
+   |     ^^^^^^^^^^^---------------^^^^
+   |                |
+   |                null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:82:5
+   |
+LL |     ptr::write_unaligned(ptr::null_mut(), v);
+   |     ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                          |
+   |                          null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:85:5
+   |
+LL |     ptr::write_volatile(ptr::null_mut(), v);
+   |     ^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                         |
+   |                         null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:88:5
+   |
+LL |     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
+   |                               |
+   |                               null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:93:18
+   |
+LL |     let _a: u8 = ptr::read(const_ptr);
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+note: null pointer originates from here
+  --> $DIR/invalid_null_args.rs:14:20
+   |
+LL |     let null_ptr = ptr::null_mut();
+   |                    ^^^^^^^^^^^^^^^
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:100:5
+   |
+LL |     std::slice::from_raw_parts::<()>(ptr::null(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+   |                                      |
+   |                                      null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:102:5
+   |
+LL |     std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
+   |                                       |
+   |                                       null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:104:5
+   |
+LL |     std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                          |
+   |                                          null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
+  --> $DIR/invalid_null_args.rs:106:5
+   |
+LL |     std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
+   |                                           |
+   |                                           null pointer originates from here
+   |
+   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
+
+error: aborting due to 31 previous errors
+
diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr
index 3a2c392fd03..c678562ab54 100644
--- a/tests/ui/lint/linker-warning.stderr
+++ b/tests/ui/lint/linker-warning.stderr
@@ -16,7 +16,7 @@ warning: unused attribute
 LL | #![allow(linker_messages)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
-   = note: the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked
+   = note: the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/lint/lint-unexported-no-mangle.rs b/tests/ui/lint/lint-unexported-no-mangle.rs
index 63eeb3374d2..65a7fd9d769 100644
--- a/tests/ui/lint/lint-unexported-no-mangle.rs
+++ b/tests/ui/lint/lint-unexported-no-mangle.rs
@@ -27,3 +27,10 @@ fn main() {
     foo();
     bar();
 }
+
+//~? WARN lint `private_no_mangle_fns` has been removed
+//~? WARN lint `private_no_mangle_statics` has been removed
+//~? WARN lint `private_no_mangle_fns` has been removed
+//~? WARN lint `private_no_mangle_statics` has been removed
+//~? WARN lint `private_no_mangle_fns` has been removed
+//~? WARN lint `private_no_mangle_statics` has been removed
diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.fixed b/tests/ui/lint/unused/lint-unused-imports-self-single.fixed
new file mode 100644
index 00000000000..361548bfdc1
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-imports-self-single.fixed
@@ -0,0 +1,29 @@
+//@ run-rustfix
+
+#![deny(unused_imports)]
+#![allow(unreachable_code)]
+
+use std::collections::{self as coll};
+//~^ ERROR unused import: `HashMap`
+
+//~^ ERROR unused import: `self as std_io`
+
+use std::sync::Mutex;
+//~^ ERROR unused import: `self as std_sync`
+
+use std::sync::mpsc::Sender;
+//~^ ERROR unused import: `self as std_sync_mpsc`
+
+use std::collections::hash_map::{self as std_coll_hm};
+//~^ ERROR unused import: `Keys`
+
+use std::borrow::Cow;
+//~^ ERROR unused import: `self`
+
+fn main() {
+    let _ = coll::BTreeSet::<String>::default();
+    let _ = Mutex::new(String::new());
+    let _: Cow<'static, str> = "foo".into();
+    let _: Sender<u32> = todo!();
+    let _: std_coll_hm::Entry<'static, u32, u32> = todo!();
+}
diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.rs b/tests/ui/lint/unused/lint-unused-imports-self-single.rs
new file mode 100644
index 00000000000..d03d3822e04
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-imports-self-single.rs
@@ -0,0 +1,30 @@
+//@ run-rustfix
+
+#![deny(unused_imports)]
+#![allow(unreachable_code)]
+
+use std::collections::{HashMap, self as coll};
+//~^ ERROR unused import: `HashMap`
+
+use std::io::{self as std_io};
+//~^ ERROR unused import: `self as std_io`
+
+use std::sync::{Mutex, self as std_sync};
+//~^ ERROR unused import: `self as std_sync`
+
+use std::sync::{mpsc::{self as std_sync_mpsc, Sender}};
+//~^ ERROR unused import: `self as std_sync_mpsc`
+
+use std::collections::{hash_map::{self as std_coll_hm, Keys}};
+//~^ ERROR unused import: `Keys`
+
+use std::borrow::{self, Cow};
+//~^ ERROR unused import: `self`
+
+fn main() {
+    let _ = coll::BTreeSet::<String>::default();
+    let _ = Mutex::new(String::new());
+    let _: Cow<'static, str> = "foo".into();
+    let _: Sender<u32> = todo!();
+    let _: std_coll_hm::Entry<'static, u32, u32> = todo!();
+}
diff --git a/tests/ui/lint/unused/lint-unused-imports-self-single.stderr b/tests/ui/lint/unused/lint-unused-imports-self-single.stderr
new file mode 100644
index 00000000000..70a9b78a664
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-imports-self-single.stderr
@@ -0,0 +1,44 @@
+error: unused import: `HashMap`
+  --> $DIR/lint-unused-imports-self-single.rs:6:24
+   |
+LL | use std::collections::{HashMap, self as coll};
+   |                        ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-unused-imports-self-single.rs:3:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused import: `self as std_io`
+  --> $DIR/lint-unused-imports-self-single.rs:9:15
+   |
+LL | use std::io::{self as std_io};
+   |               ^^^^^^^^^^^^^^
+
+error: unused import: `self as std_sync`
+  --> $DIR/lint-unused-imports-self-single.rs:12:24
+   |
+LL | use std::sync::{Mutex, self as std_sync};
+   |                        ^^^^^^^^^^^^^^^^
+
+error: unused import: `self as std_sync_mpsc`
+  --> $DIR/lint-unused-imports-self-single.rs:15:24
+   |
+LL | use std::sync::{mpsc::{self as std_sync_mpsc, Sender}};
+   |                        ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused import: `Keys`
+  --> $DIR/lint-unused-imports-self-single.rs:18:56
+   |
+LL | use std::collections::{hash_map::{self as std_coll_hm, Keys}};
+   |                                                        ^^^^
+
+error: unused import: `self`
+  --> $DIR/lint-unused-imports-self-single.rs:21:19
+   |
+LL | use std::borrow::{self, Cow};
+   |                   ^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs
new file mode 100644
index 00000000000..1fe81679e65
--- /dev/null
+++ b/tests/ui/lint/wasm_c_abi_transition.rs
@@ -0,0 +1,41 @@
+//@ compile-flags: --target wasm32-unknown-unknown
+//@ needs-llvm-components: webassembly
+//@ add-core-stubs
+//@ build-fail
+
+#![feature(no_core)]
+#![no_core]
+#![crate_type = "lib"]
+#![deny(wasm_c_abi)]
+
+extern crate minicore;
+use minicore::*;
+
+pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {}
+
+#[repr(C)]
+pub struct MyType(i32, i32);
+pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition
+//~^WARN: previously accepted
+
+// This one is ABI-safe as it only wraps a single field,
+// and the return type can be anything.
+#[repr(C)]
+pub struct MySafeType(i32);
+pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} }
+
+// This one not ABI-safe due to the alignment.
+#[repr(C, align(16))]
+pub struct MyAlignedType(i32);
+pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition
+//~^WARN: previously accepted
+
+// Check call-site warning
+extern "C" {
+    fn other_fun(x: MyType);
+}
+
+pub fn call_other_fun(x: MyType) {
+    unsafe { other_fun(x) } //~ERROR: wasm ABI transition
+    //~^WARN: previously accepted
+}
diff --git a/tests/ui/lint/wasm_c_abi_transition.stderr b/tests/ui/lint/wasm_c_abi_transition.stderr
new file mode 100644
index 00000000000..389710d5cb3
--- /dev/null
+++ b/tests/ui/lint/wasm_c_abi_transition.stderr
@@ -0,0 +1,85 @@
+error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:18:1
+   |
+LL | pub extern "C" fn my_fun(_x: MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:30:1
+   |
+LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
+error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:39:14
+   |
+LL |     unsafe { other_fun(x) }
+   |              ^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
+error: aborting due to 3 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:18:1
+   |
+LL | pub extern "C" fn my_fun(_x: MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+Future breakage diagnostic:
+error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:30:1
+   |
+LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+Future breakage diagnostic:
+error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:39:14
+   |
+LL |     unsafe { other_fun(x) }
+   |              ^^^^^^^^^^^^
+   |
+   = 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 #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
diff --git a/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs
index f742cd78697..2f0aeb0b7ba 100644
--- a/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs
+++ b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs
@@ -1,3 +1,5 @@
 //@ compile-flags: -C lto -C embed-bitcode=no
 
 fn main() {}
+
+//~? ERROR options `-C embed-bitcode=no` and `-C lto` are incompatible
diff --git a/tests/ui/macros/include-single-expr.rs b/tests/ui/macros/include-single-expr.rs
index c501f5d97ca..e3ab1257b42 100644
--- a/tests/ui/macros/include-single-expr.rs
+++ b/tests/ui/macros/include-single-expr.rs
@@ -1,6 +1,6 @@
-//@ error-pattern include macro expected single expression
-
 fn main() {
     include!("include-single-expr-helper.rs");
     include!("include-single-expr-helper-1.rs");
 }
+
+//~? ERROR include macro expected single expression
diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs
index b0a7f3e4650..a03ede20c54 100644
--- a/tests/ui/macros/nonterminal-matching.rs
+++ b/tests/ui/macros/nonterminal-matching.rs
@@ -29,8 +29,8 @@ macro_rules! foo {
     (ident $x:ident) => { bar!(ident $x); };
     (lifetime $x:lifetime) => { bar!(lifetime $x); };
     (tt $x:tt) => { bar!(tt $x); };
-    (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3`
-    (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4`
+    (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected `expr` metavariable
+    (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected `literal` metavariable
     (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable
     (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable
 }
diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr
index 2d9252fbfc1..d0156141566 100644
--- a/tests/ui/macros/nonterminal-matching.stderr
+++ b/tests/ui/macros/nonterminal-matching.stderr
@@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {});
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected expression `3`
+error: no rules expected `expr` metavariable
   --> $DIR/nonterminal-matching.rs:32:35
    |
 LL |     (expr $x:expr) => { bar!(expr $x); };
@@ -45,7 +45,7 @@ LL |     (expr 3) => {};
    = help: try using `:tt` instead in the macro definition
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: no rules expected literal `4`
+error: no rules expected `literal` metavariable
   --> $DIR/nonterminal-matching.rs:33:44
    |
 LL |     (literal $x:literal) => { bar!(literal $x); };
diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs
deleted file mode 100644
index b2febe29210..00000000000
--- a/tests/ui/match/issue-112438.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-pass
-#![feature(inline_const_pat)]
-#![allow(dead_code)]
-fn foo<const V: usize>() {
-    match 0 {
-        const { 1 << 5 } | _ => {}
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs
index 46d4239886d..678cedf016b 100644
--- a/tests/ui/match/validate-range-endpoints.rs
+++ b/tests/ui/match/validate-range-endpoints.rs
@@ -1,4 +1,3 @@
-#![feature(inline_const_pat)]
 #![allow(overlapping_range_endpoints)]
 
 fn main() {
@@ -17,8 +16,6 @@ fn main() {
         // There isn't really a way to detect these
         1..=TOO_BIG => {}
         //~^ ERROR lower range bound must be less than or equal to upper
-        1..=const { 256 } => {}
-        //~^ ERROR lower range bound must be less than or equal to upper
         _ => {}
     }
 
diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr
index 2d0538804a3..6a8a81a1cc6 100644
--- a/tests/ui/match/validate-range-endpoints.stderr
+++ b/tests/ui/match/validate-range-endpoints.stderr
@@ -1,59 +1,53 @@
 error: literal out of range for `u8`
-  --> $DIR/validate-range-endpoints.rs:7:12
+  --> $DIR/validate-range-endpoints.rs:6:12
    |
 LL |         1..257 => {}
    |            ^^^ this value does not fit into the type `u8` whose range is `0..=255`
 
 error: literal out of range for `u8`
-  --> $DIR/validate-range-endpoints.rs:9:13
+  --> $DIR/validate-range-endpoints.rs:8:13
    |
 LL |         1..=256 => {}
    |             ^^^ this value does not fit into the type `u8` whose range is `0..=255`
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/validate-range-endpoints.rs:18:9
+  --> $DIR/validate-range-endpoints.rs:17:9
    |
 LL |         1..=TOO_BIG => {}
    |         ^^^^^^^^^^^ lower bound larger than upper bound
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/validate-range-endpoints.rs:20:9
-   |
-LL |         1..=const { 256 } => {}
-   |         ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
-
 error: literal out of range for `u64`
-  --> $DIR/validate-range-endpoints.rs:26:32
+  --> $DIR/validate-range-endpoints.rs:23:32
    |
 LL |         10000000000000000000..=99999999999999999999 => {}
    |                                ^^^^^^^^^^^^^^^^^^^^ this value does not fit into the type `u64` whose range is `0..=18446744073709551615`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:32:12
+  --> $DIR/validate-range-endpoints.rs:29:12
    |
 LL |         0..129 => {}
    |            ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:34:13
+  --> $DIR/validate-range-endpoints.rs:31:13
    |
 LL |         0..=128 => {}
    |             ^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:36:9
+  --> $DIR/validate-range-endpoints.rs:33:9
    |
 LL |         -129..0 => {}
    |         ^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error: literal out of range for `i8`
-  --> $DIR/validate-range-endpoints.rs:38:9
+  --> $DIR/validate-range-endpoints.rs:35:9
    |
 LL |         -10000..=-20 => {}
    |         ^^^^^^ this value does not fit into the type `i8` whose range is `-128..=127`
 
 error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
-  --> $DIR/validate-range-endpoints.rs:49:11
+  --> $DIR/validate-range-endpoints.rs:46:11
    |
 LL |     match 0i8 {
    |           ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered
@@ -66,7 +60,7 @@ LL +         i8::MIN..=-17_i8 | 1_i8..=i8::MAX => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` not covered
-  --> $DIR/validate-range-endpoints.rs:53:11
+  --> $DIR/validate-range-endpoints.rs:50:11
    |
 LL |     match 0i8 {
    |           ^^^ pattern `i8::MIN..=-17_i8` not covered
@@ -78,7 +72,7 @@ LL ~         -10000.. => {},
 LL +         i8::MIN..=-17_i8 => todo!()
    |
 
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0004, E0030.
 For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/mir-dataflow/inits-1.rs b/tests/ui/mir-dataflow/inits-1.rs
index 8fb1d4bc736..3331809f359 100644
--- a/tests/ui/mir-dataflow/inits-1.rs
+++ b/tests/ui/mir-dataflow/inits-1.rs
@@ -51,3 +51,5 @@ fn main() {
     foo(true, &mut S(13), S(14), S(15));
     foo(false, &mut S(13), S(14), S(15));
 }
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir-dataflow/liveness-enum.rs b/tests/ui/mir-dataflow/liveness-enum.rs
index 5eb04ae8c8d..515f36698fb 100644
--- a/tests/ui/mir-dataflow/liveness-enum.rs
+++ b/tests/ui/mir-dataflow/liveness-enum.rs
@@ -20,3 +20,5 @@ fn foo() -> Option<i32> {
 }
 
 fn main() {}
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir-dataflow/liveness-projection.rs b/tests/ui/mir-dataflow/liveness-projection.rs
index 486f31b635d..edea6ee60f6 100644
--- a/tests/ui/mir-dataflow/liveness-projection.rs
+++ b/tests/ui/mir-dataflow/liveness-projection.rs
@@ -30,3 +30,5 @@ fn foo() {
 }
 
 fn main() {}
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir-dataflow/liveness-ptr.rs b/tests/ui/mir-dataflow/liveness-ptr.rs
index 786da523a33..704949aa9c8 100644
--- a/tests/ui/mir-dataflow/liveness-ptr.rs
+++ b/tests/ui/mir-dataflow/liveness-ptr.rs
@@ -26,3 +26,5 @@ fn foo() -> i32 {
 }
 
 fn main() {}
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir-dataflow/uninits-1.rs b/tests/ui/mir-dataflow/uninits-1.rs
index c2b4284a7b4..c689512833d 100644
--- a/tests/ui/mir-dataflow/uninits-1.rs
+++ b/tests/ui/mir-dataflow/uninits-1.rs
@@ -49,3 +49,5 @@ fn main() {
     foo(true, &mut S(13), S(14), S(15));
     foo(false, &mut S(13), S(14), S(15));
 }
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir-dataflow/uninits-2.rs b/tests/ui/mir-dataflow/uninits-2.rs
index c584ee74afb..04daf78e56f 100644
--- a/tests/ui/mir-dataflow/uninits-2.rs
+++ b/tests/ui/mir-dataflow/uninits-2.rs
@@ -22,3 +22,5 @@ fn main() {
     foo(&mut S(13));
     foo(&mut S(13));
 }
+
+//~? ERROR stop_after_dataflow ended compilation
diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs
index 957e7d4d96d..405ada77183 100644
--- a/tests/ui/mir/enable_passes_validation.rs
+++ b/tests/ui/mir/enable_passes_validation.rs
@@ -19,3 +19,6 @@
 //@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored
 
 fn main() {}
+
+//[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes`
+//[unprefixed]~? ERROR incorrect value `CheckAlignment` for unstable option `mir-enable-passes`
diff --git a/tests/ui/mir/inline-causes-trimmed-paths.rs b/tests/ui/mir/inline-causes-trimmed-paths.rs
new file mode 100644
index 00000000000..d626ab4e1d9
--- /dev/null
+++ b/tests/ui/mir/inline-causes-trimmed-paths.rs
@@ -0,0 +1,36 @@
+//@ build-pass
+//@ compile-flags: -Zinline-mir
+
+trait Storage {
+    type Buffer: ?Sized;
+}
+
+struct Array<const N: usize>;
+impl<const N: usize> Storage for Array<N> {
+    type Buffer = [(); N];
+}
+
+struct Slice;
+impl Storage for Slice {
+    type Buffer = [()];
+}
+
+struct Wrap<S: Storage> {
+    _b: S::Buffer,
+}
+
+fn coerce<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice>
+where
+    Array<N>: Storage,
+{
+    coerce_again(this)
+}
+
+fn coerce_again<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice> {
+    this
+}
+
+fn main() {
+    let inner: Wrap<Array<1>> = Wrap { _b: [(); 1] };
+    let _: &Wrap<Slice> = coerce(&inner);
+}
diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs
index 9b247fa5434..4bc481b82e5 100644
--- a/tests/ui/mir/issue-75053.rs
+++ b/tests/ui/mir/issue-75053.rs
@@ -1,6 +1,7 @@
+//@ check-pass
 //@ compile-flags: -Z mir-opt-level=3
 
-#![feature(type_alias_impl_trait, rustc_attrs)]
+#![feature(type_alias_impl_trait)]
 
 use std::marker::PhantomData;
 
@@ -43,8 +44,6 @@ impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
     }
 }
 
-#[rustc_error]
 fn main() {
-    //~^ ERROR
     let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
 }
diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr
deleted file mode 100644
index 91032bc3797..00000000000
--- a/tests/ui/mir/issue-75053.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-75053.rs:47:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/mir/var_debug_ref.rs b/tests/ui/mir/var_debug_ref.rs
new file mode 100644
index 00000000000..1dcf38b5bb9
--- /dev/null
+++ b/tests/ui/mir/var_debug_ref.rs
@@ -0,0 +1,24 @@
+// Regression test for #138942, where a function was incorrectly internalized, despite the fact
+// that it was referenced by a var debug info from another code generation unit.
+//
+//@ build-pass
+//@ revisions: limited full
+//@ compile-flags: -Ccodegen-units=4
+//@[limited] compile-flags: -Cdebuginfo=limited
+//@[full]    compile-flags: -Cdebuginfo=full
+trait Fun {
+    const FUN: &'static fn();
+}
+impl Fun for () {
+    const FUN: &'static fn() = &(detail::f as fn());
+}
+mod detail {
+    // Place `f` in a distinct module to generate a separate code generation unit.
+    #[inline(never)]
+    pub(super) fn f() {}
+}
+fn main() {
+    // SingleUseConsts represents "x" using VarDebugInfoContents::Const.
+    // It is the only reference to `f` remaining.
+    let x = <() as ::Fun>::FUN;
+}
diff --git a/tests/ui/missing/missing-allocator.rs b/tests/ui/missing/missing-allocator.rs
index 3a65e657d0b..60aa9fcc898 100644
--- a/tests/ui/missing/missing-allocator.rs
+++ b/tests/ui/missing/missing-allocator.rs
@@ -16,3 +16,5 @@ fn oom(_: core::alloc::Layout) -> ! {
 }
 
 extern crate alloc;
+
+//~? ERROR no global memory allocator found but one is required
diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs
index 4ff975af67d..b1ac0756688 100644
--- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs
+++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs
@@ -1,2 +1,4 @@
 mod foo;
 fn main() {}
+
+//~? ERROR file not found for module `missing`
diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs
index 9ebb4f1bdbd..987fe1166d7 100644
--- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs
+++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs
@@ -1,2 +1,4 @@
 mod foo_inline;
 fn main() {}
+
+//~? ERROR file not found for module `missing`
diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs
index 1ec460a8735..9289a8e870a 100644
--- a/tests/ui/occurs-check-2.rs
+++ b/tests/ui/occurs-check-2.rs
@@ -4,6 +4,6 @@ fn main() {
     let g;
 
     g = f;
-    f = Box::new(g);
     //~^ ERROR overflow assigning `Box<_>` to `_`
+    f = Box::new(g);
 }
diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr
index 54307a6c547..5f296967f30 100644
--- a/tests/ui/occurs-check-2.stderr
+++ b/tests/ui/occurs-check-2.stderr
@@ -1,8 +1,8 @@
 error[E0275]: overflow assigning `Box<_>` to `_`
-  --> $DIR/occurs-check-2.rs:7:9
+  --> $DIR/occurs-check-2.rs:6:9
    |
-LL |     f = Box::new(g);
-   |         ^^^^^^^^^^^
+LL |     g = f;
+   |         ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr
index 77b67ec1a62..eb05c94957c 100644
--- a/tests/ui/occurs-check-3.stderr
+++ b/tests/ui/occurs-check-3.stderr
@@ -1,8 +1,8 @@
 error[E0275]: overflow assigning `Clam<_>` to `_`
-  --> $DIR/occurs-check-3.rs:6:9
+  --> $DIR/occurs-check-3.rs:6:17
    |
 LL |     c = Clam::A(c);
-   |         ^^^^^^^^^^
+   |                 ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr
index 30468d68cbd..ea7c541abc1 100644
--- a/tests/ui/occurs-check.stderr
+++ b/tests/ui/occurs-check.stderr
@@ -1,8 +1,8 @@
 error[E0275]: overflow assigning `Box<_>` to `_`
-  --> $DIR/occurs-check.rs:3:9
+  --> $DIR/occurs-check.rs:3:18
    |
 LL |     f = Box::new(f);
-   |         ^^^^^^^^^^^
+   |                  ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.rs b/tests/ui/panic-handler/panic-handler-wrong-location.rs
index 49685ee4592..c91580ae0c4 100644
--- a/tests/ui/panic-handler/panic-handler-wrong-location.rs
+++ b/tests/ui/panic-handler/panic-handler-wrong-location.rs
@@ -6,3 +6,5 @@
 #[panic_handler] //~ ERROR `panic_impl` lang item must be applied to a function
 #[no_mangle]
 static X: u32 = 42;
+
+//~? ERROR `#[panic_handler]` function required, but not found
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs
index 2d0c6dbb50a..937390a6da5 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.rs
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs
@@ -2,7 +2,6 @@ macro_rules! mac {
     ($attr_item: meta) => {
         #[cfg($attr_item)]
         //~^ ERROR expected unsuffixed literal, found `meta` metavariable
-        //~| ERROR expected unsuffixed literal, found `meta` metavariable
         struct S;
     }
 }
@@ -11,7 +10,6 @@ mac!(an(arbitrary token stream));
 
 #[cfg(feature = -1)]
 //~^ ERROR expected unsuffixed literal, found `-`
-//~| ERROR expected unsuffixed literal, found `-`
 fn handler() {}
 
 fn main() {}
diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
index dea574fd36d..9c6ab5adadf 100644
--- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr
+++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr
@@ -1,5 +1,5 @@
 error: expected unsuffixed literal, found `-`
-  --> $DIR/attr-bad-meta-4.rs:12:17
+  --> $DIR/attr-bad-meta-4.rs:11:17
    |
 LL | #[cfg(feature = -1)]
    |                 ^
@@ -15,25 +15,5 @@ LL | mac!(an(arbitrary token stream));
    |
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected unsuffixed literal, found `meta` metavariable
-  --> $DIR/attr-bad-meta-4.rs:3:15
-   |
-LL |         #[cfg($attr_item)]
-   |               ^^^^^^^^^^
-...
-LL | mac!(an(arbitrary token stream));
-   | -------------------------------- in this macro invocation
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-   = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: expected unsuffixed literal, found `-`
-  --> $DIR/attr-bad-meta-4.rs:12:17
-   |
-LL | #[cfg(feature = -1)]
-   |                 ^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/closure-return-syntax.rs b/tests/ui/parser/closure-return-syntax.rs
index c6a08abeff4..6865d8c5393 100644
--- a/tests/ui/parser/closure-return-syntax.rs
+++ b/tests/ui/parser/closure-return-syntax.rs
@@ -1,7 +1,21 @@
 // Test that we cannot parse a closure with an explicit return type
 // unless it uses braces.
 
-fn main() {
+fn needs_braces_1() {
     let x = || -> i32 22;
     //~^ ERROR expected `{`, found `22`
 }
+
+// Check other delimiters too.
+
+fn needs_braces_2() {
+        let x = || -> (i32, i32) (1, 2);
+        //~^ ERROR expected `{`, found `(`
+}
+
+fn needs_braces_3() {
+        let c = || -> [i32; 2] [1, 2];
+        //~^ ERROR expected `{`, found `[`
+}
+
+fn main() {}
diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr
index aacc31ed871..763f19ccc64 100644
--- a/tests/ui/parser/closure-return-syntax.stderr
+++ b/tests/ui/parser/closure-return-syntax.stderr
@@ -2,12 +2,40 @@ error: expected `{`, found `22`
   --> $DIR/closure-return-syntax.rs:5:23
    |
 LL |     let x = || -> i32 22;
-   |                       ^^ expected `{`
+   |                   --- ^^
+   |                   |
+   |                   explicit return type requires closure body to be enclosed in braces
    |
-help: you might have meant to write this as part of a block
+help: wrap the expression in curly braces
    |
 LL |     let x = || -> i32 { 22 };
    |                       +    +
 
-error: aborting due to 1 previous error
+error: expected `{`, found `(`
+  --> $DIR/closure-return-syntax.rs:12:34
+   |
+LL |         let x = || -> (i32, i32) (1, 2);
+   |                       ---------- ^
+   |                       |
+   |                       explicit return type requires closure body to be enclosed in braces
+   |
+help: wrap the expression in curly braces
+   |
+LL |         let x = || -> (i32, i32) { (1, 2) };
+   |                                  +        +
+
+error: expected `{`, found `[`
+  --> $DIR/closure-return-syntax.rs:17:32
+   |
+LL |         let c = || -> [i32; 2] [1, 2];
+   |                       -------- ^
+   |                       |
+   |                       explicit return type requires closure body to be enclosed in braces
+   |
+help: wrap the expression in curly braces
+   |
+LL |         let c = || -> [i32; 2] { [1, 2] };
+   |                                +        +
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs
index a4e9134218c..12b6c98705c 100644
--- a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs
+++ b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs
@@ -12,6 +12,8 @@ macro_rules! abi_from_lit_frag {
             fn _import();
         }
 
+        unsafe extern $abi {}
+
         extern $abi fn _export() {}
 
         type _PTR = extern $abi fn();
@@ -24,6 +26,8 @@ macro_rules! abi_from_expr_frag {
             fn _import();
         }
 
+        unsafe extern $abi {}
+
         extern $abi fn _export() {}
 
         type _PTR = extern $abi fn();
diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs
index 990f2926dc8..bf7163039c4 100644
--- a/tests/ui/parser/float-field-interpolated.rs
+++ b/tests/ui/parser/float-field-interpolated.rs
@@ -5,10 +5,10 @@ macro_rules! generate_field_accesses {
         let s = S(0, (0, 0));
 
         s.$a; // OK
-        { s.$b; } //~ ERROR unexpected token: `1.1`
-                  //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1`
-        { s.$c; } //~ ERROR unexpected token: `1.1`
-                  //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1`
+        { s.$b; } //~ ERROR unexpected token: `literal` metavariable
+                  //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable
+        { s.$c; } //~ ERROR unexpected token: `expr` metavariable
+                  //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable
     };
 }
 
diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr
index 2a1a4926cb3..e2b7e3a7dbe 100644
--- a/tests/ui/parser/float-field-interpolated.stderr
+++ b/tests/ui/parser/float-field-interpolated.stderr
@@ -1,4 +1,4 @@
-error: unexpected token: `1.1`
+error: unexpected token: `literal` metavariable
   --> $DIR/float-field-interpolated.rs:8:13
    |
 LL |         { s.$b; }
@@ -9,7 +9,7 @@ LL |     generate_field_accesses!(1.1, 1.1, 1.1);
    |
    = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1`
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable
   --> $DIR/float-field-interpolated.rs:8:13
    |
 LL |         { s.$b; }
@@ -20,7 +20,7 @@ LL |     generate_field_accesses!(1.1, 1.1, 1.1);
    |
    = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: unexpected token: `1.1`
+error: unexpected token: `expr` metavariable
   --> $DIR/float-field-interpolated.rs:10:13
    |
 LL |         { s.$c; }
@@ -31,7 +31,7 @@ LL |     generate_field_accesses!(1.1, 1.1, 1.1);
    |
    = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1`
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable
   --> $DIR/float-field-interpolated.rs:10:13
    |
 LL |         { s.$c; }
diff --git a/tests/ui/parser/issues/issue-103451.rs b/tests/ui/parser/issues/issue-103451.rs
index 6b0928229e9..687dbc632d6 100644
--- a/tests/ui/parser/issues/issue-103451.rs
+++ b/tests/ui/parser/issues/issue-103451.rs
@@ -1,4 +1,4 @@
-//@ error-pattern: this file contains an unclosed delimiter
 struct R { }
+//~vv ERROR this file contains an unclosed delimiter
 struct S {
     x: [u8; R
diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs
index 7200ea1f1dd..dcc03fec545 100644
--- a/tests/ui/parser/issues/issue-10636-2.rs
+++ b/tests/ui/parser/issues/issue-10636-2.rs
@@ -1,7 +1,7 @@
-//@ error-pattern: mismatched closing delimiter: `}`
 // FIXME(31528) we emit a bunch of silly errors here due to continuing past the
 // first one. This would be easy-ish to address by better recovery in tokenisation.
 
+//~vvvvv ERROR mismatched closing delimiter: `}`
 pub fn trace_option(option: Option<isize>) {
     option.map(|some| 42;
 
diff --git a/tests/ui/parser/issues/issue-111692.rs b/tests/ui/parser/issues/issue-111692.rs
deleted file mode 100644
index 56096f706a8..00000000000
--- a/tests/ui/parser/issues/issue-111692.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-mod module {
-    #[derive(Eq, PartialEq)]
-    pub struct Type {
-        pub x: u8,
-        pub y: u8,
-    }
-
-    pub const C: u8 = 32u8;
-}
-
-fn test(x: module::Type) {
-    if x == module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
-    }
-}
-
-fn test2(x: module::Type) {
-    if x ==module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
-    }
-}
-
-
-fn test3(x: module::Type) {
-    if x == Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
-    }
-}
-
-fn test4(x: module::Type) {
-    if x == demo_module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
-    }
-}
-
-fn main() { }
diff --git a/tests/ui/parser/issues/issue-111692.stderr b/tests/ui/parser/issues/issue-111692.stderr
deleted file mode 100644
index 068b0483b0f..00000000000
--- a/tests/ui/parser/issues/issue-111692.stderr
+++ /dev/null
@@ -1,46 +0,0 @@
-error: invalid struct literal
-  --> $DIR/issue-111692.rs:12:21
-   |
-LL |     if x == module::Type { x: module::C, y: 1 } {
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: you might need to surround the struct literal with parentheses
-   |
-LL |     if x == (module::Type { x: module::C, y: 1 }) {
-   |             +                                   +
-
-error: invalid struct literal
-  --> $DIR/issue-111692.rs:17:20
-   |
-LL |     if x ==module::Type { x: module::C, y: 1 } {
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: you might need to surround the struct literal with parentheses
-   |
-LL |     if x ==(module::Type { x: module::C, y: 1 }) {
-   |            +                                   +
-
-error: invalid struct literal
-  --> $DIR/issue-111692.rs:23:13
-   |
-LL |     if x == Type { x: module::C, y: 1 } {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: you might need to surround the struct literal with parentheses
-   |
-LL |     if x == (Type { x: module::C, y: 1 }) {
-   |             +                           +
-
-error: invalid struct literal
-  --> $DIR/issue-111692.rs:28:26
-   |
-LL |     if x == demo_module::Type { x: module::C, y: 1 } {
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: you might need to surround the struct literal with parentheses
-   |
-LL |     if x == (demo_module::Type { x: module::C, y: 1 }) {
-   |             +                                        +
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr
index 2af57a52035..e96c004fb35 100644
--- a/tests/ui/parser/issues/issue-24375.stderr
+++ b/tests/ui/parser/issues/issue-24375.stderr
@@ -16,10 +16,6 @@ LL +     const VAL: /* Type */ = tmp[0];
 LL ~     match z {
 LL ~         VAL => {}
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { tmp[0] } => {}
-   |         +++++++        +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
index 7952d29c260..0c0fbd7d592 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
@@ -1,5 +1,4 @@
 // Fixed in #66054.
 // ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
 #[Ѕ
\ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
index 14f5469f6af..28fd78d660d 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4
+  --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
    |
 LL | #[Ѕ
    |  - ^
diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs
index a219f662cf7..a8c7d6eb9fd 100644
--- a/tests/ui/parser/issues/issue-62524.rs
+++ b/tests/ui/parser/issues/issue-62524.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-trailing-newlines
-//@ error-pattern: aborting due to 1 previous error
+
 #![allow(uncommon_codepoints)]
 
+//~vv ERROR this file contains an unclosed delimiter
 y![
 Ϥ,
\ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr
index d83a49aedd6..c1ff6e7e715 100644
--- a/tests/ui/parser/issues/issue-62524.stderr
+++ b/tests/ui/parser/issues/issue-62524.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62524.rs:6:3
+  --> $DIR/issue-62524.rs:7:3
    |
 LL | y![
    |   - unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs
index 9f196e4b0d6..4a8a1684a41 100644
--- a/tests/ui/parser/issues/issue-62554.rs
+++ b/tests/ui/parser/issues/issue-62554.rs
@@ -1,5 +1,4 @@
-//@ error-pattern:this file contains an unclosed delimiter
-
 fn main() {}
 
+//~v ERROR this file contains an unclosed delimiter
 fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr
index d4aaef16181..50515c4c574 100644
--- a/tests/ui/parser/issues/issue-62554.stderr
+++ b/tests/ui/parser/issues/issue-62554.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:5:89
+  --> $DIR/issue-62554.rs:4:89
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
    |               -                       -         -                  -                  -^
diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs
index 5b1627a2553..c49cbe4b934 100644
--- a/tests/ui/parser/issues/issue-62894.rs
+++ b/tests/ui/parser/issues/issue-62894.rs
@@ -1,6 +1,6 @@
 // Regression test for #62894, shouldn't crash.
-//@ error-pattern: this file contains an unclosed delimiter
 
+//~vvv ERROR this file contains an unclosed delimiter
 fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs
index 5c666d802fe..a091e4eec1d 100644
--- a/tests/ui/parser/issues/issue-62973.rs
+++ b/tests/ui/parser/issues/issue-62973.rs
@@ -1,8 +1,10 @@
 // ignore-tidy-trailing-newlines
-//@ error-pattern: aborting due to 3 previous errors
 
 fn main() {}
 
+//~vvv ERROR mismatched closing delimiter: `)`
+//~vv ERROR mismatched closing delimiter: `)`
+//~vvv ERROR this file contains an unclosed delimiter
 fn p() { match s { v, E { [) {) }
 
 
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 493183988e1..ea3e2bebee4 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -1,5 +1,5 @@
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-62973.rs:6:27
+  --> $DIR/issue-62973.rs:8:27
    |
 LL | fn p() { match s { v, E { [) {) }
    |                           ^^ mismatched closing delimiter
@@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) }
    |                           unclosed delimiter
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-62973.rs:6:30
+  --> $DIR/issue-62973.rs:8:30
    |
 LL | fn p() { match s { v, E { [) {) }
    |                              ^^ mismatched closing delimiter
@@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) }
    |                              unclosed delimiter
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62973.rs:8:2
+  --> $DIR/issue-62973.rs:10:2
    |
 LL | fn p() { match s { v, E { [) {) }
    |        -         -         -  - missing open `(` for this delimiter
diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs
index 3be9606b4ed..48abe639e8d 100644
--- a/tests/ui/parser/issues/issue-63116.rs
+++ b/tests/ui/parser/issues/issue-63116.rs
@@ -1,3 +1,4 @@
 // fixed by #66361
-//@ error-pattern: aborting due to 2 previous errors
+//~vv ERROR mismatched closing delimiter: `]`
+//~v ERROR this file contains an unclosed delimiter
 impl W <s(f;Y(;]
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index e0f7dd176ce..e5bad84d112 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -1,5 +1,5 @@
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-63116.rs:3:14
+  --> $DIR/issue-63116.rs:4:14
    |
 LL | impl W <s(f;Y(;]
    |              ^ ^ mismatched closing delimiter
@@ -7,7 +7,7 @@ LL | impl W <s(f;Y(;]
    |              unclosed delimiter
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-63116.rs:3:18
+  --> $DIR/issue-63116.rs:4:18
    |
 LL | impl W <s(f;Y(;]
    |          -     -^
diff --git a/tests/ui/parser/issues/issue-63135.rs b/tests/ui/parser/issues/issue-63135.rs
index 112dd4c83dd..63eca5b87ef 100644
--- a/tests/ui/parser/issues/issue-63135.rs
+++ b/tests/ui/parser/issues/issue-63135.rs
@@ -1,3 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
 fn i(n{...,f #
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index d6275901a53..061ec170388 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-63135.rs:3:16
+  --> $DIR/issue-63135.rs:2:16
    |
 LL | fn i(n{...,f #
    |     - -       ^
diff --git a/tests/ui/parser/issues/issue-81804.rs b/tests/ui/parser/issues/issue-81804.rs
index 7c9e6e90582..57951ca5c4b 100644
--- a/tests/ui/parser/issues/issue-81804.rs
+++ b/tests/ui/parser/issues/issue-81804.rs
@@ -1,6 +1,5 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: this file contains an unclosed delimiter
-
 fn main() {}
 
+//~vv ERROR mismatched closing delimiter: `}`
+//~v ERROR this file contains an unclosed delimiter
 fn p([=(}
diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr
index 6caaaa792b1..f12c6a61ce5 100644
--- a/tests/ui/parser/issues/issue-81804.stderr
+++ b/tests/ui/parser/issues/issue-81804.stderr
@@ -1,5 +1,5 @@
 error: mismatched closing delimiter: `}`
-  --> $DIR/issue-81804.rs:6:8
+  --> $DIR/issue-81804.rs:5:8
    |
 LL | fn p([=(}
    |        ^^ mismatched closing delimiter
@@ -7,7 +7,7 @@ LL | fn p([=(}
    |        unclosed delimiter
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-81804.rs:6:11
+  --> $DIR/issue-81804.rs:5:11
    |
 LL | fn p([=(}
    |     --   ^
diff --git a/tests/ui/parser/issues/issue-81827.rs b/tests/ui/parser/issues/issue-81827.rs
index a2bd345fc05..7dfeec13022 100644
--- a/tests/ui/parser/issues/issue-81827.rs
+++ b/tests/ui/parser/issues/issue-81827.rs
@@ -1,10 +1,7 @@
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: mismatched closing delimiter: `]`
-
 #![crate_name="0"]
 
-
-
 fn main() {}
 
+//~vv ERROR mismatched closing delimiter: `]`
+//~v ERROR this file contains an unclosed delimiter
 fn r()->i{0|{#[cfg(r(0{]0
diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr
index d12c74b4a34..986ed6b7e70 100644
--- a/tests/ui/parser/issues/issue-81827.stderr
+++ b/tests/ui/parser/issues/issue-81827.stderr
@@ -1,5 +1,5 @@
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-81827.rs:10:23
+  --> $DIR/issue-81827.rs:7:23
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
    |               -       ^^ mismatched closing delimiter
@@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0
    |               closing delimiter possibly meant for this
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-81827.rs:10:27
+  --> $DIR/issue-81827.rs:7:27
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
    |          -  -          - ^
diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs
index bced05e684a..6baf882701d 100644
--- a/tests/ui/parser/issues/issue-84104.rs
+++ b/tests/ui/parser/issues/issue-84104.rs
@@ -1,2 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
 #[i=i::<ښܖ<
diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs
index 560475bd32c..452279021ab 100644
--- a/tests/ui/parser/issues/issue-84148-2.rs
+++ b/tests/ui/parser/issues/issue-84148-2.rs
@@ -1,2 +1,2 @@
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
 fn f(t:for<>t?
diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs
index ecc50481f65..0dd18435ce3 100644
--- a/tests/ui/parser/issues/issue-88770.rs
+++ b/tests/ui/parser/issues/issue-88770.rs
@@ -1,7 +1,6 @@
 // Regression test for the ICE described in #88770.
 
-//@ error-pattern:this file contains an unclosed delimiter
-
+//~vvvv ERROR this file contains an unclosed delimiter
 fn m(){print!("",(c for&g
 u
 e
diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr
index 5b54072d009..137cfea7e1d 100644
--- a/tests/ui/parser/issues/issue-88770.stderr
+++ b/tests/ui/parser/issues/issue-88770.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-88770.rs:8:3
+  --> $DIR/issue-88770.rs:7:3
    |
 LL | fn m(){print!("",(c for&g
    |       -      -   - unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-94340.rs b/tests/ui/parser/issues/issue-94340.rs
index d0fb84a689a..4f3dbc6acdd 100644
--- a/tests/ui/parser/issues/issue-94340.rs
+++ b/tests/ui/parser/issues/issue-94340.rs
@@ -6,3 +6,6 @@
 include!("auxiliary/issue-94340-inc.rs");
 
 fn main() {}
+
+//~? ERROR an inner attribute is not permitted in this context
+//~? ERROR an inner attribute is not permitted in this context
diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs
index e93000193b6..b4140613cba 100644
--- a/tests/ui/parser/macro/trait-non-item-macros.rs
+++ b/tests/ui/parser/macro/trait-non-item-macros.rs
@@ -1,7 +1,7 @@
 macro_rules! bah {
     ($a:expr) => {
         $a
-    }; //~^ ERROR macro expansion ignores expression `2` and any tokens following
+    }; //~^ ERROR macro expansion ignores `expr` metavariable and any tokens following
 }
 
 trait Bar {
diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr
index 1a828483778..62b42fa8b8d 100644
--- a/tests/ui/parser/macro/trait-non-item-macros.stderr
+++ b/tests/ui/parser/macro/trait-non-item-macros.stderr
@@ -1,4 +1,4 @@
-error: macro expansion ignores expression `2` and any tokens following
+error: macro expansion ignores `expr` metavariable and any tokens following
   --> $DIR/trait-non-item-macros.rs:3:9
    |
 LL |         $a
diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs
index 9c57b0ebcfc..85191931664 100644
--- a/tests/ui/parser/mbe_missing_right_paren.rs
+++ b/tests/ui/parser/mbe_missing_right_paren.rs
@@ -1,3 +1,3 @@
 // ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
+//~v ERROR this file contains an unclosed delimiter
 macro_rules! abc(ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs
deleted file mode 100644
index 8be7c9ee8ac..00000000000
--- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-pub struct Example { a: i32 }
-
-impl Example {
-    fn is_pos(&self) -> bool { self.a > 0 }
-}
-
-fn one() -> i32 { 1 }
-
-fn main() {
-    if Example { a: one(), }.is_pos() { //~ ERROR invalid struct literal
-        println!("Positive!");
-    }
-}
diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr
deleted file mode 100644
index f7822ba1124..00000000000
--- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: invalid struct literal
-  --> $DIR/method-call-on-struct-literal-in-if-condition.rs:10:8
-   |
-LL |     if Example { a: one(), }.is_pos() {
-   |        ^^^^^^^^^^^^^^^^^^^^^
-   |
-help: you might need to surround the struct literal with parentheses
-   |
-LL |     if (Example { a: one(), }).is_pos() {
-   |        +                     +
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs
index bbf4519a713..311a16c214c 100644
--- a/tests/ui/parser/missing_right_paren.rs
+++ b/tests/ui/parser/missing_right_paren.rs
@@ -1,4 +1,3 @@
 // ignore-tidy-trailing-newlines
-//@ error-pattern: this file contains an unclosed delimiter
-//@ error-pattern: aborting due to 1 previous error
+//~v ERROR this file contains an unclosed delimiter
 fn main((ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr
index 4815f04fbce..97ccb40a5a2 100644
--- a/tests/ui/parser/missing_right_paren.stderr
+++ b/tests/ui/parser/missing_right_paren.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/missing_right_paren.rs:4:11
+  --> $DIR/missing_right_paren.rs:3:11
    |
 LL | fn main((ؼ
    |        -- ^
diff --git a/tests/ui/parser/operator-precedence-braces-exprs.rs b/tests/ui/parser/operator-precedence-braces-exprs.rs
new file mode 100644
index 00000000000..d6f44ef879c
--- /dev/null
+++ b/tests/ui/parser/operator-precedence-braces-exprs.rs
@@ -0,0 +1,28 @@
+//! Regression test for ensuring that operator precedence is correctly handled in the presence of
+//! braces
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/28777>
+
+//@ run-pass
+
+#[allow(unused_braces)]
+fn main() {
+    let v1 = { 1 + { 2 } * { 3 } };
+    let v2 = 1 + { 2 } * { 3 };
+
+    assert_eq!(7, v1);
+    assert_eq!(7, v2);
+
+    let v3;
+    v3 = { 1 + { 2 } * { 3 } };
+    let v4;
+    v4 = 1 + { 2 } * { 3 };
+    assert_eq!(7, v3);
+    assert_eq!(7, v4);
+
+    let v5 = { 1 + { 2 } * 3 };
+    assert_eq!(7, v5);
+
+    let v9 = { 1 + if 1 > 2 { 1 } else { 2 } * { 3 } };
+    assert_eq!(7, v9);
+}
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
index dcc1945d569..69bc5107cca 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.stderr
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -17,10 +17,6 @@ LL ~     match 0 {
 LL |         x => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.y } => (),
-   |         +++++++     +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:6:9
@@ -42,10 +38,6 @@ LL |         x => (),
 LL |         x.y => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.0 } => (),
-   |         +++++++     +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:7:9
@@ -68,10 +60,6 @@ LL |         x.y => (),
 LL |         x.0 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x._0 } => (),
-   |         +++++++      +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:8:9
@@ -94,10 +82,6 @@ LL |         x => (),
 LL |         x._0 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.0.1 } => (),
-   |         +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:9:9
@@ -120,10 +104,6 @@ LL |         x => (),
 LL |         x.0.1 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.4.y.17.__z } => (),
-   |         +++++++              +
 
 error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
   --> $DIR/recover-pat-exprs.rs:12:12
@@ -173,10 +153,6 @@ LL +     const VAL: /* Type */ = x[0];
 LL ~     match 0 {
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x[0] } => (),
-   |         +++++++      +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:24:9
@@ -197,10 +173,6 @@ LL ~     match 0 {
 LL |         x[0] => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x[..] } => (),
-   |         +++++++       +
 
 error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
   --> $DIR/recover-pat-exprs.rs:27:12
@@ -247,10 +219,6 @@ LL +     const VAL: /* Type */ = x.f();
 LL ~     match 0 {
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.f() } => (),
-   |         +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:38:9
@@ -271,10 +239,6 @@ LL ~     match 0 {
 LL |         x.f() => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x._f() } => (),
-   |         +++++++        +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:39:9
@@ -296,10 +260,6 @@ LL |         x.f() => (),
 LL |         x._f() => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x? } => (),
-   |         +++++++    +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:40:9
@@ -322,10 +282,6 @@ LL |         x._f() => (),
 LL |         x? => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { ().f() } => (),
-   |         +++++++        +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:41:9
@@ -348,10 +304,6 @@ LL |         x.f() => (),
 LL |         ().f() => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { (0, x)?.f() } => (),
-   |         +++++++             +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:42:9
@@ -374,10 +326,6 @@ LL |         x.f() => (),
 LL |         (0, x)?.f() => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.f().g() } => (),
-   |         +++++++           +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:43:9
@@ -400,10 +348,6 @@ LL |         x.f() => (),
 LL |         x.f().g() => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { 0.f()?.g()?? } => (),
-   |         +++++++              +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:50:9
@@ -423,10 +367,6 @@ LL +     const VAL: /* Type */ = x as usize;
 LL ~     match 0 {
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x as usize } => (),
-   |         +++++++            +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:51:9
@@ -447,10 +387,6 @@ LL ~     match 0 {
 LL |         x as usize => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { 0 as usize } => (),
-   |         +++++++            +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:52:9
@@ -472,10 +408,6 @@ LL |         x as usize => (),
 LL |         0 as usize => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.f().0.4 as f32 } => (),
-   |         +++++++                  +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:59:9
@@ -495,10 +427,6 @@ LL +     const VAL: /* Type */ = 1 + 1;
 LL ~     match 0 {
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { 1 + 1 } => (),
-   |         +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:60:9
@@ -519,10 +447,6 @@ LL ~     match 0 {
 LL |         1 + 1 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { (1 + 2) * 3 } => (),
-   |         +++++++             +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:63:9
@@ -545,10 +469,6 @@ LL |         1 + 1 => (),
 LL |
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.0 > 2 } => (),
-   |         +++++++         +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:64:9
@@ -571,10 +491,6 @@ LL |         1 + 1 => (),
 LL |         x.0 > 2 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { x.0 == 2 } => (),
-   |         +++++++          +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:69:13
@@ -594,10 +510,6 @@ LL +     const VAL: /* Type */ = y.0 > 2;
 LL ~     match (0, 0) {
 LL ~         (x, VAL) if x != 0 => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (x, const { y.0 > 2 }) if x != 0 => (),
-   |             +++++++         +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:70:13
@@ -618,10 +530,6 @@ LL ~     match (0, 0) {
 LL |         (x, y.0 > 2) if x != 0 => (),
 LL ~         (x, VAL) if x != 0 || x != 1 => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (x, const { y.0 > 2 }) if x != 0 || x != 1 => (),
-   |             +++++++         +
 
 error: left-hand side of `@` must be a binding
   --> $DIR/recover-pat-exprs.rs:83:9
@@ -658,10 +566,6 @@ LL +     const VAL: /* Type */ = u8::MAX.abs();
 LL ~     match u8::MAX {
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { u8::MAX.abs() } => (),
-   |         +++++++               +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:86:17
@@ -684,10 +588,6 @@ LL |         u8::MAX.abs() => (),
 LL |
 LL ~         z @ w @ VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         z @ w @ const { v.u() } => (),
-   |                 +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:88:9
@@ -710,10 +610,6 @@ LL |         u8::MAX.abs() => (),
 LL |
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { y.ilog(3) } => (),
-   |         +++++++           +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:90:9
@@ -736,10 +632,6 @@ LL |         u8::MAX.abs() => (),
 LL |
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { n + 1 } => (),
-   |         +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:92:10
@@ -762,10 +654,6 @@ LL |         u8::MAX.abs() => (),
 LL |
 LL ~         (VAL) => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (const { "".f() + 14 * 8 }) => (),
-   |          +++++++                 +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:95:9
@@ -788,10 +676,6 @@ LL |         u8::MAX.abs() => (),
 LL |         0 | ((1) | 2) | 3 => (),
 LL ~         VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { f?() } => (),
-   |         +++++++      +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:101:9
diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr
index 0c65b16dd95..ec7fcda3497 100644
--- a/tests/ui/parser/recover/recover-pat-issues.stderr
+++ b/tests/ui/parser/recover/recover-pat-issues.stderr
@@ -16,10 +16,6 @@ LL +     const VAL: /* Type */ = "hi".to_owned();
 LL ~     match foo {
 LL ~         Foo(VAL) => true,
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         Foo(const { "hi".to_owned() }) => true,
-   |             +++++++                 +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-issues.rs:14:20
@@ -39,10 +35,6 @@ LL +     const BAZ: /* Type */ = "hi".to_owned();
 LL ~     match bar {
 LL ~         Bar { baz: BAZ } => true,
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         Bar { baz: const { "hi".to_owned() } } => true,
-   |                    +++++++                 +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-issues.rs:25:11
@@ -62,10 +54,6 @@ LL +     const VAL: /* Type */ = "foo".to_string();
 LL ~     match foo.as_slice() {
 LL ~         &[VAL] => {}
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         &[const { "foo".to_string() }] => {}
-   |           +++++++                   +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-issues.rs:36:17
@@ -79,10 +67,6 @@ help: consider extracting the expression into a `const`
 LL +     const VAL: /* Type */ = MAGIC.0 as usize;
 LL ~     if let Some(VAL) = None::<usize> {}
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |     if let Some(const { MAGIC.0 as usize }) = None::<usize> {}
-   |                 +++++++                  +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-issues.rs:41:13
@@ -96,10 +80,6 @@ help: consider extracting the expression into a `const`
 LL +     const VAL: /* Type */ = -1.some(4);
 LL ~     if let (VAL) = (0, Some(4)) {}
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |     if let (const { -1.some(4) }) = (0, Some(4)) {}
-   |             +++++++            +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-issues.rs:44:13
@@ -113,10 +93,6 @@ help: consider extracting the expression into a `const`
 LL +     const VAL: /* Type */ = -1.Some(4);
 LL ~     if let (VAL) = (0, Some(4)) {}
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |     if let (const { -1.Some(4) }) = (0, Some(4)) {}
-   |             +++++++            +
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr
index 55252729d7b..ab79e4ebcae 100644
--- a/tests/ui/parser/recover/recover-pat-lets.stderr
+++ b/tests/ui/parser/recover/recover-pat-lets.stderr
@@ -34,10 +34,6 @@ help: consider extracting the expression into a `const`
 LL +     const VAL: /* Type */ = 1 + 1;
 LL ~     let Some(VAL) = x else {
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |     let Some(const { 1 + 1 }) = x else {
-   |              +++++++       +
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-lets.rs:17:17
@@ -51,10 +47,6 @@ help: consider extracting the expression into a `const`
 LL +     const VAL: /* Type */ = 1 + 1;
 LL ~     if let Some(VAL) = x {
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |     if let Some(const { 1 + 1 }) = x {
-   |                 +++++++       +
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr
index e8f323596d0..6c17182618b 100644
--- a/tests/ui/parser/recover/recover-pat-ranges.stderr
+++ b/tests/ui/parser/recover/recover-pat-ranges.stderr
@@ -98,10 +98,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         ..=VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         ..=const { 1 + 2 } => (),
-   |            +++++++       +
 
 error: expected a pattern range bound, found an expression
   --> $DIR/recover-pat-ranges.rs:15:10
@@ -119,10 +115,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         (VAL).. => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (const { -4 + 0 }).. => (),
-   |          +++++++        +
 
 error: expected a pattern range bound, found an expression
   --> $DIR/recover-pat-ranges.rs:18:10
@@ -140,10 +132,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         (VAL)...1 * 2 => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (const { 1 + 4 })...1 * 2 => (),
-   |          +++++++       +
 
 error: expected a pattern range bound, found an expression
   --> $DIR/recover-pat-ranges.rs:18:19
@@ -161,10 +149,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         (1 + 4)...VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         (1 + 4)...const { 1 * 2 } => (),
-   |                   +++++++       +
 
 error: expected a pattern range bound, found an expression
   --> $DIR/recover-pat-ranges.rs:24:9
@@ -182,10 +166,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         VAL..="y".z() => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         const { 0.x() }..="y".z() => (),
-   |         +++++++       +
 
 error: expected a pattern range bound, found an expression
   --> $DIR/recover-pat-ranges.rs:24:17
@@ -203,10 +183,6 @@ LL |         0..=1 => (),
 LL |
 LL ~         0.x()..=VAL => (),
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         0.x()..=const { "y".z() } => (),
-   |                 +++++++         +
 
 warning: `...` range patterns are deprecated
   --> $DIR/recover-pat-ranges.rs:18:16
diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr
index f939e513370..ebc1cbf7d59 100644
--- a/tests/ui/parser/recover/recover-pat-wildcards.stderr
+++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr
@@ -84,10 +84,6 @@ LL +     const VAL: /* Type */ = 2 + _;
 LL ~     match 9 {
 LL ~         4..=(VAL) => ()
    |
-help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
-   |
-LL |         4..=(const { 2 + _ }) => ()
-   |              +++++++       +
 
 error: aborting due to 11 previous errors
 
diff --git a/tests/ui/parser/struct-literal-in-for.rs b/tests/ui/parser/struct-literal-in-for.rs
deleted file mode 100644
index 3227ae37bfd..00000000000
--- a/tests/ui/parser/struct-literal-in-for.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-struct Foo {
-    x: isize,
-}
-
-impl Foo {
-    fn hi(&self) -> bool {
-        true
-    }
-}
-
-fn main() {
-    for x in Foo { //~ ERROR struct literals are not allowed here
-        x: 3       //~^ ERROR `bool` is not an iterator
-    }.hi() {
-        println!("yo");
-    }
-}
diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr
deleted file mode 100644
index 1c91eba68e3..00000000000
--- a/tests/ui/parser/struct-literal-in-for.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-for.rs:12:14
-   |
-LL |       for x in Foo {
-   |  ______________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     for x in (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error[E0277]: `bool` is not an iterator
-  --> $DIR/struct-literal-in-for.rs:12:14
-   |
-LL |       for x in Foo {
-   |  ______________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |__________^ `bool` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `bool`
-   = note: required for `bool` to implement `IntoIterator`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/parser/struct-literal-in-if.rs b/tests/ui/parser/struct-literal-in-if.rs
deleted file mode 100644
index c4a253c3da2..00000000000
--- a/tests/ui/parser/struct-literal-in-if.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-struct Foo {
-    x: isize,
-}
-
-impl Foo {
-    fn hi(&self) -> bool {
-        true
-    }
-}
-
-fn main() {
-    if Foo { //~ ERROR struct literals are not allowed here
-        x: 3
-    }.hi() {
-        println!("yo");
-    }
-    if let true = Foo { //~ ERROR struct literals are not allowed here
-        x: 3
-    }.hi() {
-        println!("yo");
-    }
-}
diff --git a/tests/ui/parser/struct-literal-in-if.stderr b/tests/ui/parser/struct-literal-in-if.stderr
deleted file mode 100644
index 8b72469fcf5..00000000000
--- a/tests/ui/parser/struct-literal-in-if.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-if.rs:12:8
-   |
-LL |       if Foo {
-   |  ________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     if (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-if.rs:17:19
-   |
-LL |       if let true = Foo {
-   |  ___________________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     if let true = (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.rs b/tests/ui/parser/struct-literal-in-match-discriminant.rs
deleted file mode 100644
index ce132df5a88..00000000000
--- a/tests/ui/parser/struct-literal-in-match-discriminant.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-struct Foo {
-    x: isize,
-}
-
-fn main() {
-    match Foo { //~ ERROR struct literals are not allowed here
-        x: 3
-    } {
-        Foo {
-            x: x
-        } => {}
-    }
-}
diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.stderr b/tests/ui/parser/struct-literal-in-match-discriminant.stderr
deleted file mode 100644
index 5177f5f126e..00000000000
--- a/tests/ui/parser/struct-literal-in-match-discriminant.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-match-discriminant.rs:6:11
-   |
-LL |       match Foo {
-   |  ___________^
-LL | |         x: 3
-LL | |     } {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     match (Foo {
-LL |         x: 3
-LL ~     }) {
-   |
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/parser/struct-literal-in-while.rs b/tests/ui/parser/struct-literal-in-while.rs
deleted file mode 100644
index 86931f7888d..00000000000
--- a/tests/ui/parser/struct-literal-in-while.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-struct Foo {
-    x: isize,
-}
-
-impl Foo {
-    fn hi(&self) -> bool {
-        true
-    }
-}
-
-fn main() {
-    while Foo { //~ ERROR struct literals are not allowed here
-        x: 3
-    }.hi() {
-        println!("yo");
-    }
-    while let true = Foo { //~ ERROR struct literals are not allowed here
-        x: 3
-    }.hi() {
-        println!("yo");
-    }
-}
diff --git a/tests/ui/parser/struct-literal-in-while.stderr b/tests/ui/parser/struct-literal-in-while.stderr
deleted file mode 100644
index 13d003608a1..00000000000
--- a/tests/ui/parser/struct-literal-in-while.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-while.rs:12:11
-   |
-LL |       while Foo {
-   |  ___________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     while (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-in-while.rs:17:22
-   |
-LL |       while let true = Foo {
-   |  ______________________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     while let true = (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.rs b/tests/ui/parser/struct-literal-restrictions-in-lamda.rs
deleted file mode 100644
index e185153dcf6..00000000000
--- a/tests/ui/parser/struct-literal-restrictions-in-lamda.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-struct Foo {
-    x: isize,
-}
-
-impl Foo {
-    fn hi(&self) -> bool {
-        true
-    }
-}
-
-fn main() {
-    while || Foo { //~ ERROR struct literals are not allowed here
-        x: 3       //~^ ERROR mismatched types
-    }.hi() {
-        println!("yo");
-    }
-}
diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr
deleted file mode 100644
index c715486e2da..00000000000
--- a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14
-   |
-LL |       while || Foo {
-   |  ______________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |_____^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~     while || (Foo {
-LL |         x: 3
-LL ~     }).hi() {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/struct-literal-restrictions-in-lamda.rs:12:11
-   |
-LL |       while || Foo {
-   |  ___________^
-LL | |         x: 3
-LL | |     }.hi() {
-   | |__________^ expected `bool`, found closure
-   |
-   = note: expected type `bool`
-           found closure `{closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13}`
-help: use parentheses to call this closure
-   |
-LL ~     while (|| Foo {
-LL |         x: 3
-LL ~     }.hi())() {
-   |
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/struct-literal-variant-in-if.rs b/tests/ui/parser/struct-literal-variant-in-if.rs
deleted file mode 100644
index 4ef8effaf1f..00000000000
--- a/tests/ui/parser/struct-literal-variant-in-if.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-enum E {
-    V { field: bool },
-    I { field1: bool, field2: usize },
-    J { field: isize },
-    K { field: &'static str},
-}
-fn test_E(x: E) {
-    let field = true;
-    if x == E::V { field } {}
-    //~^ ERROR expected value, found struct variant `E::V`
-    //~| ERROR mismatched types
-    if x == E::I { field1: true, field2: 42 } {}
-    //~^ ERROR struct literals are not allowed here
-    if x == E::V { field: false } {}
-    //~^ ERROR struct literals are not allowed here
-    if x == E::J { field: -42 } {}
-    //~^ ERROR struct literals are not allowed here
-    if x == E::K { field: "" } {}
-    //~^ ERROR struct literals are not allowed here
-    let y: usize = ();
-    //~^ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/tests/ui/parser/struct-literal-variant-in-if.stderr b/tests/ui/parser/struct-literal-variant-in-if.stderr
deleted file mode 100644
index 15f059f145b..00000000000
--- a/tests/ui/parser/struct-literal-variant-in-if.stderr
+++ /dev/null
@@ -1,76 +0,0 @@
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-variant-in-if.rs:13:13
-   |
-LL |     if x == E::I { field1: true, field2: 42 } {}
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: surround the struct literal with parentheses
-   |
-LL |     if x == (E::I { field1: true, field2: 42 }) {}
-   |             +                                 +
-
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-variant-in-if.rs:15:13
-   |
-LL |     if x == E::V { field: false } {}
-   |             ^^^^^^^^^^^^^^^^^^^^^
-   |
-help: surround the struct literal with parentheses
-   |
-LL |     if x == (E::V { field: false }) {}
-   |             +                     +
-
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-variant-in-if.rs:17:13
-   |
-LL |     if x == E::J { field: -42 } {}
-   |             ^^^^^^^^^^^^^^^^^^^
-   |
-help: surround the struct literal with parentheses
-   |
-LL |     if x == (E::J { field: -42 }) {}
-   |             +                   +
-
-error: struct literals are not allowed here
-  --> $DIR/struct-literal-variant-in-if.rs:19:13
-   |
-LL |     if x == E::K { field: "" } {}
-   |             ^^^^^^^^^^^^^^^^^^
-   |
-help: surround the struct literal with parentheses
-   |
-LL |     if x == (E::K { field: "" }) {}
-   |             +                  +
-
-error[E0533]: expected value, found struct variant `E::V`
-  --> $DIR/struct-literal-variant-in-if.rs:10:13
-   |
-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
-   |
-LL |     if x == E::V { field } {}
-   |     ---------------^^^^^--
-   |     |              |
-   |     |              expected `()`, found `bool`
-   |     expected this to be `()`
-
-error[E0308]: mismatched types
-  --> $DIR/struct-literal-variant-in-if.rs:21:20
-   |
-LL |     let y: usize = ();
-   |            -----   ^^ expected `usize`, found `()`
-   |            |
-   |            expected due to this
-
-error: aborting due to 7 previous errors
-
-Some errors have detailed explanations: E0308, E0533.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/struct-literals-in-invalid-places.rs b/tests/ui/parser/struct-literals-in-invalid-places.rs
new file mode 100644
index 00000000000..eed51b94583
--- /dev/null
+++ b/tests/ui/parser/struct-literals-in-invalid-places.rs
@@ -0,0 +1,92 @@
+fn main() {
+    if Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        println!("yo");
+    }
+    if let true = Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        println!("yo");
+    }
+
+    for x in Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        //~^ ERROR `bool` is not an iterator
+        println!("yo");
+    }
+
+    while Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        println!("yo");
+    }
+    while let true = Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        println!("yo");
+    }
+
+    match Foo { x: 3 } { //~ ERROR struct literals are not allowed here
+        Foo { x: x } => {}
+    }
+
+    let _ = |x: E| {
+        let field = true;
+        if x == E::V { field } {}
+        //~^ ERROR expected value, found struct variant `E::V`
+        //~| ERROR mismatched types
+        if x == E::I { field1: true, field2: 42 } {}
+        //~^ ERROR struct literals are not allowed here
+        if x == E::V { field: false } {}
+        //~^ ERROR struct literals are not allowed here
+        if x == E::J { field: -42 } {}
+        //~^ ERROR struct literals are not allowed here
+        if x == E::K { field: "" } {}
+        //~^ ERROR struct literals are not allowed here
+        let y: usize = ();
+        //~^ ERROR mismatched types
+    };
+
+    // Regression test for <https://github.com/rust-lang/rust/issues/43412>.
+    while || Foo { x: 3 }.hi() { //~ ERROR struct literals are not allowed here
+        //~^ ERROR mismatched types
+        println!("yo");
+    }
+
+    // This uses `one()` over `1` as token `one` may begin a type and thus back when type ascription
+    // `$expr : $ty` still existed, `{ x: one` could've been the start of a block expr which used to
+    // make the compiler take a different execution path. Now it no longer makes a difference tho.
+
+    // Regression test for <https://github.com/rust-lang/rust/issues/82051>.
+    if Foo { x: one(), }.hi() { //~ ERROR struct literals are not allowed here
+        println!("Positive!");
+    }
+
+    const FOO: Foo = Foo { x: 1 };
+    // Below, test that we correctly parenthesize the struct literals.
+
+    // Regression test for <https://github.com/rust-lang/rust/issues/112278>.
+    if FOO == self::Foo { x: one() } {} //~ ERROR struct literals are not allowed here
+
+    if FOO == Foo::<> { x: one() } {} //~ ERROR struct literals are not allowed here
+
+    fn env<T: Trait<Out = Foo>>() {
+        if FOO == <T as Trait>::Out { x: one() } {} //~ ERROR struct literals are not allowed here
+        //~^ ERROR usage of qualified paths in this context is experimental
+    }
+}
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+    x: isize,
+}
+
+impl Foo {
+    fn hi(&self) -> bool {
+        true
+    }
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+enum E {
+    V { field: bool },
+    I { field1: bool, field2: usize },
+    J { field: isize },
+    K { field: &'static str},
+}
+
+fn one() -> isize { 1 }
+
+trait Trait { type Out; }
diff --git a/tests/ui/parser/struct-literals-in-invalid-places.stderr b/tests/ui/parser/struct-literals-in-invalid-places.stderr
new file mode 100644
index 00000000000..39dc2d2efb7
--- /dev/null
+++ b/tests/ui/parser/struct-literals-in-invalid-places.stderr
@@ -0,0 +1,234 @@
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:2:8
+   |
+LL |     if Foo { x: 3 }.hi() {
+   |        ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     if (Foo { x: 3 }).hi() {
+   |        +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:5:19
+   |
+LL |     if let true = Foo { x: 3 }.hi() {
+   |                   ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     if let true = (Foo { x: 3 }).hi() {
+   |                   +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:9:14
+   |
+LL |     for x in Foo { x: 3 }.hi() {
+   |              ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     for x in (Foo { x: 3 }).hi() {
+   |              +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:14:11
+   |
+LL |     while Foo { x: 3 }.hi() {
+   |           ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     while (Foo { x: 3 }).hi() {
+   |           +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:17:22
+   |
+LL |     while let true = Foo { x: 3 }.hi() {
+   |                      ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     while let true = (Foo { x: 3 }).hi() {
+   |                      +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:21:11
+   |
+LL |     match Foo { x: 3 } {
+   |           ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     match (Foo { x: 3 }) {
+   |           +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:30:17
+   |
+LL |         if x == E::I { field1: true, field2: 42 } {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |         if x == (E::I { field1: true, field2: 42 }) {}
+   |                 +                                 +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:32:17
+   |
+LL |         if x == E::V { field: false } {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |         if x == (E::V { field: false }) {}
+   |                 +                     +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:34:17
+   |
+LL |         if x == E::J { field: -42 } {}
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |         if x == (E::J { field: -42 }) {}
+   |                 +                   +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:36:17
+   |
+LL |         if x == E::K { field: "" } {}
+   |                 ^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |         if x == (E::K { field: "" }) {}
+   |                 +                  +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:43:14
+   |
+LL |     while || Foo { x: 3 }.hi() {
+   |              ^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     while || (Foo { x: 3 }).hi() {
+   |              +            +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:53:8
+   |
+LL |     if Foo { x: one(), }.hi() {
+   |        ^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     if (Foo { x: one(), }).hi() {
+   |        +                 +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:61:15
+   |
+LL |     if FOO == self::Foo { x: one() } {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     if FOO == (self::Foo { x: one() }) {}
+   |               +                      +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:63:15
+   |
+LL |     if FOO == Foo::<> { x: one() } {}
+   |               ^^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |     if FOO == (Foo::<> { x: one() }) {}
+   |               +                    +
+
+error: struct literals are not allowed here
+  --> $DIR/struct-literals-in-invalid-places.rs:66:19
+   |
+LL |         if FOO == <T as Trait>::Out { x: one() } {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: surround the struct literal with parentheses
+   |
+LL |         if FOO == (<T as Trait>::Out { x: one() }) {}
+   |                   +                              +
+
+error[E0658]: usage of qualified paths in this context is experimental
+  --> $DIR/struct-literals-in-invalid-places.rs:66:19
+   |
+LL |         if FOO == <T as Trait>::Out { x: one() } {}
+   |                   ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
+   = help: add `#![feature(more_qualified_paths)]` 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[E0277]: `bool` is not an iterator
+  --> $DIR/struct-literals-in-invalid-places.rs:9:14
+   |
+LL |     for x in Foo { x: 3 }.hi() {
+   |              ^^^^^^^^^^^^^^^^^ `bool` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `bool`
+   = note: required for `bool` to implement `IntoIterator`
+
+error[E0533]: expected value, found struct variant `E::V`
+  --> $DIR/struct-literals-in-invalid-places.rs:27:17
+   |
+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-literals-in-invalid-places.rs:27:24
+   |
+LL |         if x == E::V { field } {}
+   |         ---------------^^^^^--
+   |         |              |
+   |         |              expected `()`, found `bool`
+   |         expected this to be `()`
+   |
+help: you might have meant to return this value
+   |
+LL |         if x == E::V { return field; } {}
+   |                        ++++++      +
+
+error[E0308]: mismatched types
+  --> $DIR/struct-literals-in-invalid-places.rs:38:24
+   |
+LL |         let y: usize = ();
+   |                -----   ^^ expected `usize`, found `()`
+   |                |
+   |                expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/struct-literals-in-invalid-places.rs:43:11
+   |
+LL |     while || Foo { x: 3 }.hi() {
+   |           ^^^^^^^^^^^^^^^^^^^^ expected `bool`, found closure
+   |
+   = note: expected type `bool`
+           found closure `{closure@$DIR/struct-literals-in-invalid-places.rs:43:11: 43:13}`
+help: use parentheses to call this closure
+   |
+LL |     while (|| Foo { x: 3 }.hi())() {
+   |           +                    +++
+
+error: aborting due to 21 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0533, E0658.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs
index fec168afba1..18d7061d69c 100644
--- a/tests/ui/parser/type-ascription-in-pattern.rs
+++ b/tests/ui/parser/type-ascription-in-pattern.rs
@@ -1,11 +1,10 @@
 fn foo(x: bool) -> i32 {
-    match x {
+    match x { //~ ERROR struct literals are not allowed here
         x: i32 => x, //~ ERROR expected
-        //~^ ERROR mismatched types
-        true => 42.,
-        false => 0.333,
+        true => 42., //~ ERROR expected identifier
+        false => 0.333, //~ ERROR expected identifier
     }
-}
+} //~ ERROR expected one of
 
 fn main() {
     match foo(true) {
diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr
index 09190754993..135879f208b 100644
--- a/tests/ui/parser/type-ascription-in-pattern.stderr
+++ b/tests/ui/parser/type-ascription-in-pattern.stderr
@@ -1,18 +1,64 @@
-error: expected one of `@` or `|`, found `:`
-  --> $DIR/type-ascription-in-pattern.rs:3:10
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, `}`, or an operator, found `=>`
+  --> $DIR/type-ascription-in-pattern.rs:3:16
    |
+LL |     match x {
+   |           - while parsing this struct
 LL |         x: i32 => x,
-   |          ^ --- specifying the type of a pattern isn't supported
-   |          |
-   |          expected one of `@` or `|`
+   |               -^^ expected one of 8 possible tokens
+   |               |
+   |               help: try adding a comma: `,`
+
+error: expected identifier, found keyword `true`
+  --> $DIR/type-ascription-in-pattern.rs:4:9
    |
-help: maybe write a path separator here
+LL |     match x {
+   |           - while parsing this struct
+LL |         x: i32 => x,
+LL |         true => 42.,
+   |         ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `false`
+  --> $DIR/type-ascription-in-pattern.rs:5:9
    |
-LL |         x::i32 => x,
-   |          ~~
+LL |     match x {
+   |           - while parsing this struct
+...
+LL |         false => 0.333,
+   |         ^^^^^ expected identifier, found keyword
+
+error: struct literals are not allowed here
+  --> $DIR/type-ascription-in-pattern.rs:2:11
+   |
+LL |       match x {
+   |  ___________^
+LL | |         x: i32 => x,
+LL | |         true => 42.,
+LL | |         false => 0.333,
+LL | |     }
+   | |_____^
+   |
+help: surround the struct literal with parentheses
+   |
+LL ~     match (x {
+LL |         x: i32 => x,
+LL |         true => 42.,
+LL |         false => 0.333,
+LL ~     })
+   |
+
+error: expected one of `.`, `?`, `{`, or an operator, found `}`
+  --> $DIR/type-ascription-in-pattern.rs:7:1
+   |
+LL |     match x {
+   |     ----- while parsing this `match` expression
+...
+LL |     }
+   |      - expected one of `.`, `?`, `{`, or an operator
+LL | }
+   | ^ unexpected token
 
 error: expected one of `...`, `..=`, `..`, or `|`, found `:`
-  --> $DIR/type-ascription-in-pattern.rs:12:11
+  --> $DIR/type-ascription-in-pattern.rs:11:11
    |
 LL |         42: i32 => (),
    |           ^ --- specifying the type of a pattern isn't supported
@@ -20,7 +66,7 @@ LL |         42: i32 => (),
    |           expected one of `...`, `..=`, `..`, or `|`
 
 error: expected `|`, found `:`
-  --> $DIR/type-ascription-in-pattern.rs:13:10
+  --> $DIR/type-ascription-in-pattern.rs:12:10
    |
 LL |         _: f64 => (),
    |          ^ --- specifying the type of a pattern isn't supported
@@ -28,7 +74,7 @@ LL |         _: f64 => (),
    |          expected `|`
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/type-ascription-in-pattern.rs:14:10
+  --> $DIR/type-ascription-in-pattern.rs:13:10
    |
 LL |         x: i32 => (),
    |          ^ --- specifying the type of a pattern isn't supported
@@ -40,15 +86,5 @@ help: maybe write a path separator here
 LL |         x::i32 => (),
    |          ~~
 
-error[E0308]: mismatched types
-  --> $DIR/type-ascription-in-pattern.rs:3:19
-   |
-LL | fn foo(x: bool) -> i32 {
-   |                    --- expected `i32` because of return type
-LL |     match x {
-LL |         x: i32 => x,
-   |                   ^ expected `i32`, found `bool`
-
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs
index d9c936186ea..43e23a70271 100644
--- a/tests/ui/parser/unbalanced-doublequote.rs
+++ b/tests/ui/parser/unbalanced-doublequote.rs
@@ -1,6 +1,4 @@
-//@ error-pattern: unterminated double quote string
-
-
+//~vv ERROR unterminated double quote string
 fn main() {
     "
 }
diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr
index d40b982da7c..60057eddbb4 100644
--- a/tests/ui/parser/unbalanced-doublequote.stderr
+++ b/tests/ui/parser/unbalanced-doublequote.stderr
@@ -1,5 +1,5 @@
 error[E0765]: unterminated double quote string
-  --> $DIR/unbalanced-doublequote.rs:5:5
+  --> $DIR/unbalanced-doublequote.rs:3:5
    |
 LL | /     "
 LL | | }
diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.rs b/tests/ui/parser/unclosed-delimiter-in-dep.rs
index 4de83ee640a..40f517f317e 100644
--- a/tests/ui/parser/unclosed-delimiter-in-dep.rs
+++ b/tests/ui/parser/unclosed-delimiter-in-dep.rs
@@ -3,3 +3,5 @@ mod unclosed_delim_mod;
 fn main() {
     let _: usize = unclosed_delim_mod::new();
 }
+
+//~? ERROR mismatched closing delimiter: `}`
diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs
index 6679651fe47..aa52fe92ac1 100644
--- a/tests/ui/parser/use-unclosed-brace.rs
+++ b/tests/ui/parser/use-unclosed-brace.rs
@@ -1,4 +1,3 @@
-//@ error-pattern: this file contains an unclosed delimiter
 use foo::{bar, baz;
 
 use std::fmt::Display;
@@ -7,4 +6,5 @@ mod bar { }
 
 mod baz { }
 
+//~v ERROR this file contains an unclosed delimiter
 fn main() {}
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs
index cb5bc62b6b3..2d5a0b0a771 100644
--- a/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-flags.rs
@@ -1,2 +1,5 @@
 //@ compile-flags: -Z patchable-function-entry=1,2
+
 fn main() {}
+
+//~? ERROR incorrect value `1,2` for unstable option `patchable-function-entry`
diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs
index dde44dfee9c..5869767c936 100644
--- a/tests/ui/pattern/non-structural-match-types.rs
+++ b/tests/ui/pattern/non-structural-match-types.rs
@@ -1,14 +1,29 @@
 //@ edition:2021
-
-#![allow(unreachable_code)]
 #![feature(const_async_blocks)]
-#![feature(inline_const_pat)]
 
-fn main() {
-    match loop {} {
-        const { || {} } => {} //~ ERROR cannot be used in patterns
+struct AnyOption<T>(T);
+impl<T> AnyOption<T> {
+    const NONE: Option<T> = None;
+}
+
+fn uwu() {}
+fn defines() {
+    match Some(uwu) {
+        AnyOption::<_>::NONE => {}
+        //~^ ERROR constant of non-structural type
+        _ => {}
     }
-    match loop {} {
-        const { async {} } => {} //~ ERROR cannot be used in patterns
+
+    match Some(|| {}) {
+        AnyOption::<_>::NONE => {}
+        //~^ ERROR constant of non-structural type
+        _ => {}
+    }
+
+    match Some(async {}) {
+        AnyOption::<_>::NONE => {}
+        //~^ ERROR constant of non-structural type
+        _ => {}
     }
 }
+fn main() {}
diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr
index 3588751bf66..da675a9f3ff 100644
--- a/tests/ui/pattern/non-structural-match-types.stderr
+++ b/tests/ui/pattern/non-structural-match-types.stderr
@@ -1,14 +1,42 @@
-error: closure `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns
-  --> $DIR/non-structural-match-types.rs:9:9
+error: constant of non-structural type `Option<fn() {uwu}>` in a pattern
+  --> $DIR/non-structural-match-types.rs:12:9
+   |
+LL | impl<T> AnyOption<T> {
+   | --------------------
+LL |     const NONE: Option<T> = None;
+   |     --------------------- constant defined here
+...
+LL |         AnyOption::<_>::NONE => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-LL |         const { || {} } => {}
-   |         ^^^^^^^^^^^^^^^ closure can't be used in patterns
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
-error: `async` block `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
-  --> $DIR/non-structural-match-types.rs:12:9
+error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:17:16: 17:18}>` in a pattern
+  --> $DIR/non-structural-match-types.rs:18:9
+   |
+LL | impl<T> AnyOption<T> {
+   | --------------------
+LL |     const NONE: Option<T> = None;
+   |     --------------------- constant defined here
+...
+LL |         AnyOption::<_>::NONE => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+
+error: constant of non-structural type `Option<{async block@$DIR/non-structural-match-types.rs:23:16: 23:21}>` in a pattern
+  --> $DIR/non-structural-match-types.rs:24:9
+   |
+LL | impl<T> AnyOption<T> {
+   | --------------------
+LL |     const NONE: Option<T> = None;
+   |     --------------------- constant defined here
+...
+LL |         AnyOption::<_>::NONE => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-LL |         const { async {} } => {}
-   |         ^^^^^^^^^^^^^^^^^^ `async` block can't be used in patterns
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+   = note: `ResumeTy` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/pin-macro/pin_move.rs b/tests/ui/pin-macro/pin_move.rs
new file mode 100644
index 00000000000..0f6d34fad95
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.rs
@@ -0,0 +1,26 @@
+//@ edition:2024
+
+use core::marker::PhantomPinned;
+use core::pin::pin;
+
+fn a() {
+    struct NotCopy<T>(T);
+    #[allow(unused_mut)]
+    let mut pointee = NotCopy(PhantomPinned);
+    pin!(pointee);
+    let _moved = pointee;
+    //~^ ERROR use of moved value
+}
+
+fn b() {
+    struct NotCopy<T>(T);
+    let mut pointee = NotCopy(PhantomPinned);
+    pin!(*&mut pointee);
+    //~^ ERROR cannot move
+    let _moved = pointee;
+}
+
+fn main() {
+    a();
+    b();
+}
diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr
new file mode 100644
index 00000000000..c9b8ad9b202
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.stderr
@@ -0,0 +1,38 @@
+error[E0382]: use of moved value: `pointee`
+  --> $DIR/pin_move.rs:11:18
+   |
+LL |     let mut pointee = NotCopy(PhantomPinned);
+   |         ----------- move occurs because `pointee` has type `a::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+LL |     pin!(pointee);
+   |          ------- value moved here
+LL |     let _moved = pointee;
+   |                  ^^^^^^^ value used here after move
+   |
+note: if `a::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+  --> $DIR/pin_move.rs:7:5
+   |
+LL |     struct NotCopy<T>(T);
+   |     ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     pin!(pointee);
+   |          ------- you could clone this value
+
+error[E0507]: cannot move out of a mutable reference
+  --> $DIR/pin_move.rs:18:10
+   |
+LL |     pin!(*&mut pointee);
+   |          ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+   |
+note: if `b::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+  --> $DIR/pin_move.rs:16:5
+   |
+LL |     struct NotCopy<T>(T);
+   |     ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+LL |     let mut pointee = NotCopy(PhantomPinned);
+LL |     pin!(*&mut pointee);
+   |          ------------- you could clone this value
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0382, E0507.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs
index 81018e4bff3..eacaa63e543 100644
--- a/tests/ui/precondition-checks/copy-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs
index 694853f950a..1fadd90bf70 100644
--- a/tests/ui/precondition-checks/copy.rs
+++ b/tests/ui/precondition-checks/copy.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
index e14881d0290..ada8932c398 100644
--- a/tests/ui/precondition-checks/read_volatile.rs
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
 //@ revisions: null misaligned
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs
index 2808cee7b64..44afbd8174c 100644
--- a/tests/ui/precondition-checks/replace.rs
+++ b/tests/ui/precondition-checks/replace.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
 //@ revisions: null misaligned
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
index 3801639e255..9b9ded69a83 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
 //@ revisions: null misaligned toolarge
 
+#![allow(invalid_null_arguments)]
+
 fn main() {
     unsafe {
         #[cfg(null)]
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs
index a3690fa045e..96578c1eae5 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
 //@ revisions: null misaligned toolarge
 
+#![allow(invalid_null_arguments)]
+
 fn main() {
     unsafe {
         #[cfg(null)]
diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs
index 52e4a3c870b..ea1f6f36ad7 100644
--- a/tests/ui/precondition-checks/swap-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
index ac0b89b5ecf..0d5ecb014b3 100644
--- a/tests/ui/precondition-checks/write_volatile.rs
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -3,6 +3,8 @@
 //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
 //@ revisions: null misaligned
 
+#![allow(invalid_null_arguments)]
+
 use std::ptr;
 
 fn main() {
diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs
index 43a81175f94..55d768fc9e5 100644
--- a/tests/ui/precondition-checks/zero-size-null.rs
+++ b/tests/ui/precondition-checks/zero-size-null.rs
@@ -7,8 +7,10 @@ use std::ptr;
 
 fn main() {
     unsafe {
+        #[expect(invalid_null_arguments)] // false-positive, copy of 0
         ptr::copy_nonoverlapping::<u8>(ptr::null(), ptr::null_mut(), 0);
         ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123);
+        #[expect(invalid_null_arguments)] // false-positive, copy of 0
         ptr::copy::<u8>(ptr::null(), ptr::null_mut(), 0);
         ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123);
         ptr::swap::<()>(ptr::null_mut(), ptr::null_mut());
diff --git a/tests/ui/print-request/invalid-target.rs b/tests/ui/print-request/invalid-target.rs
index 52f09ea73d7..573d5493b25 100644
--- a/tests/ui/print-request/invalid-target.rs
+++ b/tests/ui/print-request/invalid-target.rs
@@ -2,3 +2,5 @@
 //@ needs-llvm-components: x86
 
 fn main() {}
+
+//~? ERROR only Apple targets currently support deployment version info
diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs
new file mode 100644
index 00000000000..420eae27ed4
--- /dev/null
+++ b/tests/ui/print-request/print-lints-help.rs
@@ -0,0 +1,7 @@
+//! Check that we point to `-Whelp` to guide the user to find the list of lints if the user requests
+//! `--print=lints` (which is not a valid print request).
+
+//@ compile-flags: --print lints
+//@ error-pattern: error: unknown print request: `lints`
+//@ error-pattern: help: use `-Whelp` to print a list of lints
+//@ error-pattern: help: for more information, see the rustc book
diff --git a/tests/ui/rustc-print-info-issue-138612.stderr b/tests/ui/print-request/print-lints-help.stderr
index 4f7ed821952..bc48b2fa73c 100644
--- a/tests/ui/rustc-print-info-issue-138612.stderr
+++ b/tests/ui/print-request/print-lints-help.stderr
@@ -1,6 +1,6 @@
 error: unknown print request: `lints`
   |
-  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+  = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
   = help: use `-Whelp` to print a list of lints
   = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
 
diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs
index b205b055569..0ec0886e941 100644
--- a/tests/ui/print-request/stability.rs
+++ b/tests/ui/print-request/stability.rs
@@ -18,10 +18,18 @@
 //@[all_target_specs_json] compile-flags: --print=all-target-specs-json
 //@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed
 
+//@ revisions: crate_root_lint_levels
+//@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels
+//@[crate_root_lint_levels] error-pattern: the `-Z unstable-options` flag must also be passed
+
 //@ revisions: check_cfg
 //@[check_cfg] compile-flags: --print=check-cfg
 //@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed
 
+//@ revisions: supported_crate_types
+//@[supported_crate_types] compile-flags: --print=supported-crate-types
+//@[supported_crate_types] error-pattern: the `-Z unstable-options` flag must also be passed
+
 //@ revisions: target_spec_json
 //@[target_spec_json] compile-flags: --print=target-spec-json
 //@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed
diff --git a/tests/ui/print-request/supported-crate-types.linux.stdout b/tests/ui/print-request/supported-crate-types.linux.stdout
new file mode 100644
index 00000000000..721adb432e7
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.linux.stdout
@@ -0,0 +1,7 @@
+bin
+cdylib
+dylib
+lib
+proc-macro
+rlib
+staticlib
diff --git a/tests/ui/print-request/supported-crate-types.musl.stdout b/tests/ui/print-request/supported-crate-types.musl.stdout
new file mode 100644
index 00000000000..1f4b991e49f
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.musl.stdout
@@ -0,0 +1,5 @@
+bin
+lib
+proc-macro
+rlib
+staticlib
diff --git a/tests/ui/print-request/supported-crate-types.rs b/tests/ui/print-request/supported-crate-types.rs
new file mode 100644
index 00000000000..c8b4c0c1a41
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.rs
@@ -0,0 +1,20 @@
+//! Basic smoke test for `--print=supported-crate-types`, which should print a newline delimited
+//! list of crate types supported by the given target. This test cherry-picks a few well-known
+//! targets as examples.
+//!
+//! Tracking issue: <https://github.com/rust-lang/rust/issues/138640>
+
+// ignore-tidy-linelength
+
+//@ check-pass
+
+//@ revisions: wasm musl linux
+
+//@[wasm] compile-flags: --target=wasm32-unknown-unknown --print=supported-crate-types -Zunstable-options
+//@[wasm] needs-llvm-components: webassembly
+
+//@[musl] compile-flags: --target=x86_64-unknown-linux-musl --print=supported-crate-types -Zunstable-options
+//@[musl] needs-llvm-components: x86
+
+//@[linux] compile-flags: --target=x86_64-unknown-linux-gnu --print=supported-crate-types -Zunstable-options
+//@[linux] needs-llvm-components: x86
diff --git a/tests/ui/print-request/supported-crate-types.wasm.stdout b/tests/ui/print-request/supported-crate-types.wasm.stdout
new file mode 100644
index 00000000000..ca1de519598
--- /dev/null
+++ b/tests/ui/print-request/supported-crate-types.wasm.stdout
@@ -0,0 +1,5 @@
+bin
+cdylib
+lib
+rlib
+staticlib
diff --git a/tests/ui/privacy/privacy-ns1.stderr b/tests/ui/privacy/privacy-ns1.stderr
index 3396330c993..c782c67e71c 100644
--- a/tests/ui/privacy/privacy-ns1.stderr
+++ b/tests/ui/privacy/privacy-ns1.stderr
@@ -7,6 +7,14 @@ LL |     pub struct Baz;
 LL |     Bar();
    |     ^^^
    |
+note: these functions exist but are inaccessible
+  --> $DIR/privacy-ns1.rs:14:5
+   |
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo3::Bar`: not accessible
 help: a unit struct with a similar name exists
    |
 LL -     Bar();
@@ -26,6 +34,14 @@ LL |     pub struct Baz;
 LL |     Bar();
    |     ^^^
    |
+note: these functions exist but are inaccessible
+  --> $DIR/privacy-ns1.rs:14:5
+   |
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo3::Bar`: not accessible
 help: a unit struct with a similar name exists
    |
 LL -     Bar();
@@ -45,6 +61,14 @@ LL |     pub struct Baz;
 LL |     let _x: Box<Bar>;
    |                 ^^^
    |
+note: these traits exist but are inaccessible
+  --> $DIR/privacy-ns1.rs:25:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^ `foo2::Bar`: not accessible
+...
+LL |     trait Bar {
+   |     ^^^^^^^^^ `foo3::Bar`: not accessible
 help: a struct with a similar name exists
    |
 LL -     let _x: Box<Bar>;
diff --git a/tests/ui/privacy/privacy-ns2.stderr b/tests/ui/privacy/privacy-ns2.stderr
index ac98682b2b3..fe1f0c9bd48 100644
--- a/tests/ui/privacy/privacy-ns2.stderr
+++ b/tests/ui/privacy/privacy-ns2.stderr
@@ -4,6 +4,14 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar
 LL |     Bar();
    |     ^^^ not a function, tuple struct or tuple variant
    |
+note: these functions exist but are inaccessible
+  --> $DIR/privacy-ns2.rs:14:5
+   |
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo3::Bar`: not accessible
 help: consider importing this function instead
    |
 LL + use foo2::Bar;
@@ -18,6 +26,14 @@ LL |     pub struct Baz;
 LL |     Bar();
    |     ^^^
    |
+note: these functions exist but are inaccessible
+  --> $DIR/privacy-ns2.rs:14:5
+   |
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo1::Bar`: not accessible
+...
+LL |     fn Bar() { }
+   |     ^^^^^^^^ `foo3::Bar`: not accessible
 help: a unit struct with a similar name exists
    |
 LL -     Bar();
@@ -34,6 +50,14 @@ error[E0573]: expected type, found function `Bar`
 LL |     let _x : Bar();
    |              ^^^^^ not a type
    |
+note: these traits exist but are inaccessible
+  --> $DIR/privacy-ns2.rs:31:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^ `foo2::Bar`: not accessible
+...
+LL |     trait Bar {
+   |     ^^^^^^^^^ `foo3::Bar`: not accessible
 help: use `=` if you meant to assign
    |
 LL -     let _x : Bar();
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
index 112eaf528be..877029f3de3 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -77,15 +77,14 @@ pub type Alias = OtherType;
 
 pub struct PublicWithPrivateImpl;
 
-// FIXME: This should trigger.
-// See https://github.com/rust-lang/rust/issues/71043
 impl OtherTrait for PublicWithPrivateImpl {}
+//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
 
 pub trait PubTraitOnPrivate {}
 
-// FIXME: This should trigger.
-// See https://github.com/rust-lang/rust/issues/71043
 impl PubTraitOnPrivate for OtherType {}
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+//~| ERROR type `OtherType` from private dependency 'priv_dep' in public interface
 
 pub struct AllowedPrivType {
     #[allow(exported_private_dependencies)]
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
index 53d461a5774..adfe13424cd 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -70,5 +70,25 @@ error: type `OtherType` from private dependency 'priv_dep' in public interface
 LL | pub type Alias = OtherType;
    | ^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:80:1
+   |
+LL | impl OtherTrait for PublicWithPrivateImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:85:1
+   |
+LL | impl PubTraitOnPrivate for OtherType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:85:1
+   |
+LL | impl PubTraitOnPrivate for OtherType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
index 1ebc396cdf5..57548f75d5e 100644
--- a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
+++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
@@ -3,7 +3,6 @@
 // priv-in-pub lint tests where the private trait bounds a public type
 
 #![crate_type = "lib"]
-#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 struct PrivTy;
diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
index ee79ce3f5d7..33f82a3a4fe 100644
--- a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
+++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
@@ -1,30 +1,30 @@
 warning: trait `PrivTr` is more private than the item `S`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:20:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:19:1
    |
 LL | pub struct S
    | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub`
    |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:10:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:9:1
    |
 LL | trait PrivTr {}
    | ^^^^^^^^^^^^
    = note: `#[warn(private_bounds)]` on by default
 
 warning: trait `PrivTr` is more private than the item `E`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:27:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:26:1
    |
 LL | pub enum E
    | ^^^^^^^^^^ enum `E` is reachable at visibility `pub`
    |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:10:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:9:1
    |
 LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 warning: trait `PrivTr` is more private than the item `f`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:34:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:33:1
    |
 LL | / pub fn f()
 LL | |
@@ -33,13 +33,13 @@ LL | |     PubTy: PrivTr
    | |_________________^ function `f` is reachable at visibility `pub`
    |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:10:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:9:1
    |
 LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 warning: trait `PrivTr` is more private than the item `S`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:41:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:40:1
    |
 LL | / impl S
 LL | |
@@ -48,13 +48,13 @@ LL | |     PubTy: PrivTr
    | |_________________^ implementation `S` is reachable at visibility `pub`
    |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:10:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:9:1
    |
 LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 warning: trait `PrivTr` is more private than the item `S::f`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:46:5
+  --> $DIR/where-pub-type-impls-priv-trait.rs:45:5
    |
 LL | /     pub fn f()
 LL | |
@@ -63,7 +63,7 @@ LL | |         PubTy: PrivTr
    | |_____________________^ associated function `S::f` is reachable at visibility `pub`
    |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:10:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:9:1
    |
 LL | trait PrivTr {}
    | ^^^^^^^^^^^^
diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs
index b4927f7a730..140dd10a7e0 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.rs
+++ b/tests/ui/proc-macro/cfg-attr-trace.rs
@@ -3,6 +3,7 @@
 //@ check-pass
 //@ proc-macro: test-macros.rs
 
+#![feature(cfg_boolean_literals)]
 #![feature(cfg_eval)]
 
 #[macro_use]
@@ -10,8 +11,13 @@ extern crate test_macros;
 
 #[cfg_eval]
 #[test_macros::print_attr]
-#[cfg_attr(FALSE, test_macros::print_attr)]
-#[cfg_attr(all(), test_macros::print_attr)]
+#[cfg_attr(false, test_macros::print_attr)]
+#[cfg_attr(true, test_macros::print_attr)]
 struct S;
 
+#[cfg_eval]
+#[test_macros::print_attr]
+#[cfg(true)]
+struct Z;
+
 fn main() {}
diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout
index 394c3887fe7..52f9ff4e05c 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.stdout
+++ b/tests/ui/proc-macro/cfg-attr-trace.stdout
@@ -4,59 +4,75 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
         spacing: Alone,
-        span: #0 bytes(271..272),
+        span: #0 bytes(305..306),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "test_macros",
-                span: #0 bytes(289..300),
+                span: #0 bytes(322..333),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #0 bytes(300..301),
+                span: #0 bytes(333..334),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #0 bytes(301..302),
+                span: #0 bytes(334..335),
             },
             Ident {
                 ident: "print_attr",
-                span: #0 bytes(302..312),
+                span: #0 bytes(335..345),
             },
         ],
-        span: #0 bytes(272..314),
+        span: #0 bytes(306..347),
     },
     Ident {
         ident: "struct",
-        span: #0 bytes(315..321),
+        span: #0 bytes(348..354),
     },
     Ident {
         ident: "S",
-        span: #0 bytes(322..323),
+        span: #0 bytes(355..356),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #0 bytes(323..324),
+        span: #0 bytes(356..357),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct S;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #0 bytes(315..321),
+        span: #0 bytes(348..354),
     },
     Ident {
         ident: "S",
-        span: #0 bytes(322..323),
+        span: #0 bytes(355..356),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #0 bytes(323..324),
+        span: #0 bytes(356..357),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): struct Z;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: #0 bytes(411..417),
+    },
+    Ident {
+        ident: "Z",
+        span: #0 bytes(418..419),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #0 bytes(419..420),
     },
 ]
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs
index d4336a7f3e1..2dcdbf3c402 100644
--- a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs
+++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs
@@ -1,6 +1,4 @@
 //@ compile-flags: -Z span-debug
-//@ error-pattern:custom inner attributes are unstable
-//@ error-pattern:inner macro attributes are unstable
 //@ proc-macro: test-macros.rs
 
 #![no_std] // Don't load unnecessary hygiene information from std
@@ -15,3 +13,6 @@ mod module_with_attrs;
 //~| ERROR custom inner attributes are unstable
 
 fn main() {}
+
+//~? ERROR custom inner attributes are unstable
+//~? ERROR inner macro attributes are unstable
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr
index 025eec24818..c0a9385f4c6 100644
--- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr
+++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr
@@ -19,7 +19,7 @@ LL | #![print_attr]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: non-inline modules in proc macro input are unstable
-  --> $DIR/inner-attr-non-inline-mod.rs:13:1
+  --> $DIR/inner-attr-non-inline-mod.rs:11:1
    |
 LL | mod module_with_attrs;
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL | mod module_with_attrs;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: custom inner attributes are unstable
-  --> $DIR/inner-attr-non-inline-mod.rs:13:1
+  --> $DIR/inner-attr-non-inline-mod.rs:11:1
    |
 LL | mod module_with_attrs;
    | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
index 450542f68c6..219794a8eb8 100644
--- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
+++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
@@ -4,35 +4,35 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "deny",
-                span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "unused_attributes",
-                        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
                     },
                 ],
-                span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
             },
         ],
-        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
     },
     Ident {
         ident: "mod",
-        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
     },
     Ident {
         ident: "module_with_attrs",
-        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
     },
     Group {
         delimiter: Brace,
@@ -40,38 +40,38 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
             Punct {
                 ch: '#',
                 spacing: Joint,
-                span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
             },
             Punct {
                 ch: '!',
                 spacing: Alone,
-                span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "rustfmt",
-                        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
                     },
                     Punct {
                         ch: ':',
                         spacing: Joint,
-                        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
                     },
                     Punct {
                         ch: ':',
                         spacing: Alone,
-                        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
                     },
                     Ident {
                         ident: "skip",
-                        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
                     },
                 ],
-                span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+                span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
             },
         ],
-        span: $DIR/inner-attr-non-inline-mod.rs:13:1: 13:23 (#0),
+        span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0),
     },
 ]
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
index c1e46b50d40..9482b2784d2 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
@@ -1,8 +1,9 @@
 PRINT-DERIVE INPUT (DISPLAY): struct
-Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
-{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
+Foo([bool; #[rustc_dummy(first)]
+#[rustc_dummy(second)] { #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
 PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct
-Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
+Foo([bool; #[rustc_dummy(first)]
+#[rustc_dummy(second)]
 { #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
@@ -53,97 +54,103 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                         ],
                         span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3),
                     },
-                    Punct {
-                        ch: '#',
-                        spacing: Alone,
-                        span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0),
-                    },
                     Group {
-                        delimiter: Bracket,
-                        stream: TokenStream [
-                            Ident {
-                                ident: "rustc_dummy",
-                                span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0),
-                            },
-                            Group {
-                                delimiter: Parenthesis,
-                                stream: TokenStream [
-                                    Ident {
-                                        ident: "second",
-                                        span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0),
-                                    },
-                                ],
-                                span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0),
-                            },
-                        ],
-                        span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0),
-                    },
-                    Group {
-                        delimiter: Brace,
+                        delimiter: None,
                         stream: TokenStream [
                             Punct {
                                 ch: '#',
-                                spacing: Joint,
-                                span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0),
-                            },
-                            Punct {
-                                ch: '!',
                                 spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0),
+                                span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "rustc_dummy",
-                                        span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0),
+                                        span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
-                                                ident: "third",
-                                                span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0),
+                                                ident: "second",
+                                                span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0),
                                             },
                                         ],
-                                        span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0),
+                                        span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0),
                                     },
                                 ],
-                                span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0),
-                            },
-                            Punct {
-                                ch: '#',
-                                spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0),
+                                span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0),
                             },
                             Group {
-                                delimiter: Bracket,
+                                delimiter: Brace,
                                 stream: TokenStream [
-                                    Ident {
-                                        ident: "rustc_dummy",
-                                        span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0),
+                                    Punct {
+                                        ch: '#',
+                                        spacing: Joint,
+                                        span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0),
+                                    },
+                                    Punct {
+                                        ch: '!',
+                                        spacing: Alone,
+                                        span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0),
                                     },
                                     Group {
-                                        delimiter: Parenthesis,
+                                        delimiter: Bracket,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "rustc_dummy",
+                                                span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0),
+                                            },
+                                            Group {
+                                                delimiter: Parenthesis,
+                                                stream: TokenStream [
+                                                    Ident {
+                                                        ident: "third",
+                                                        span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0),
+                                                    },
+                                                ],
+                                                span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0),
+                                            },
+                                        ],
+                                        span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0),
+                                    },
+                                    Punct {
+                                        ch: '#',
+                                        spacing: Alone,
+                                        span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0),
+                                    },
+                                    Group {
+                                        delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
-                                                ident: "fourth",
-                                                span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0),
+                                                ident: "rustc_dummy",
+                                                span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0),
+                                            },
+                                            Group {
+                                                delimiter: Parenthesis,
+                                                stream: TokenStream [
+                                                    Ident {
+                                                        ident: "fourth",
+                                                        span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0),
+                                                    },
+                                                ],
+                                                span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0),
                                             },
                                         ],
-                                        span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0),
+                                        span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0),
+                                    },
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "30",
+                                        suffix: None,
+                                        span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0),
                                     },
                                 ],
-                                span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0),
-                            },
-                            Literal {
-                                kind: Integer,
-                                symbol: "30",
-                                suffix: None,
-                                span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0),
+                                span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0),
                             },
                         ],
-                        span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0),
+                        span: $DIR/macro-rules-derive-cfg.rs:18:64: 18:69 (#3),
                     },
                 ],
                 span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3),
diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs
index d44f51bfd8d..25200378131 100644
--- a/tests/ui/proc-macro/no-macro-use-attr.rs
+++ b/tests/ui/proc-macro/no-macro-use-attr.rs
@@ -1,10 +1,9 @@
+//@ check-pass
 //@ proc-macro: test-macros.rs
 
-#![feature(rustc_attrs)]
 #![warn(unused_extern_crates)]
 
 extern crate test_macros;
 //~^ WARN unused extern crate
 
-#[rustc_error]
-fn main() {} //~ ERROR fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr
index 3dda3cc7d5a..4913672450a 100644
--- a/tests/ui/proc-macro/no-macro-use-attr.stderr
+++ b/tests/ui/proc-macro/no-macro-use-attr.stderr
@@ -10,11 +10,5 @@ note: the lint level is defined here
 LL | #![warn(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/no-macro-use-attr.rs:10:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error; 1 warning emitted
+warning: 1 warning emitted
 
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index c80a33206fb..6fd6cb47469 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "struct",
-                span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
             },
             Ident {
                 ident: "S",
-                span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
             },
             Punct {
                 ch: ';',
                 spacing: Alone,
-                span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4),
+                span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
             },
         ],
-        span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5),
+        span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
     },
 ]
 #![feature /* 0#0 */(prelude_import)]
@@ -59,7 +59,7 @@ macro_rules! outer
 struct S /* 0#0 */;
 macro inner /* 0#3 */ { () => { print_bang! { struct S; } } }
 
-struct S /* 0#4 */;
+struct S /* 0#5 */;
 // OK, not a duplicate definition of `S`
 
 fn main /* 0#0 */() {}
@@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt:
 crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
 crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
 crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner")
-crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
 crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
 crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
 crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented")
@@ -83,9 +83,9 @@ SyntaxContexts:
 #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
 #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
 #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
-#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
-#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
 #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
-#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
-#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
+#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
 */
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs
index de6453c6a82..70f0d5f6ea9 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.rs
+++ b/tests/ui/proc-macro/pretty-print-hack-show.rs
@@ -18,3 +18,5 @@ mod second {
 }
 
 fn main() {}
+
+//~? ERROR using an old version of `rental`
diff --git a/tests/ui/resolve/auxiliary/macro_helpers.rs b/tests/ui/resolve/auxiliary/macro_helpers.rs
new file mode 100644
index 00000000000..43aa336457d
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/macro_helpers.rs
@@ -0,0 +1,16 @@
+/* macro namespace. */
+
+extern crate proc_macro;
+use proc_macro::*;
+use std::str::FromStr;
+
+const ERROR: &str = "fn helper() { \"helper\" }";
+// https://doc.rust-lang.org/nightly/std/prelude/v1/index.html#attributes
+// NOTE: all the bang macros in std are currently unstable.
+#[proc_macro_attribute] pub fn test       // lang.
+    (_: TokenStream, _: TokenStream) -> TokenStream {
+        TokenStream::from_str("fn test_macro() { \"\" }").unwrap() }
+// https://doc.rust-lang.org/nightly/reference/attributes.html#built-in-attributes-index
+#[proc_macro_attribute] pub fn global_allocator // lang.
+    (_: TokenStream, _: TokenStream) -> TokenStream {
+        TokenStream::from_str("fn global_allocator_macro() { \"\" }").unwrap() }
diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr
index ccf03afaa19..dafa41bf312 100644
--- a/tests/ui/resolve/issue-21221-1.stderr
+++ b/tests/ui/resolve/issue-21221-1.stderr
@@ -19,6 +19,17 @@ error[E0412]: cannot find type `Mul` in this scope
 LL | fn getMul() -> Mul {
    |                ^^^ not found in this scope
    |
+note: these items exist but are inaccessible
+  --> $DIR/issue-21221-1.rs:10:5
+   |
+LL |     enum Mul {
+   |     ^^^^^^^^ `mul3::Mul`: not accessible
+...
+LL |     type Mul = String;
+   |     ^^^^^^^^^^^^^^^^^^ `mul4::Mul`: not accessible
+...
+LL |     struct Mul{
+   |     ^^^^^^^^^^ `mul5::Mul`: not accessible
 help: consider importing one of these traits
    |
 LL + use std::ops::Mul;
diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs
index 1e0772648af..cb15ec76403 100644
--- a/tests/ui/resolve/parse-error-resolve.rs
+++ b/tests/ui/resolve/parse-error-resolve.rs
@@ -5,3 +5,5 @@ fn main() {
     let _ = "" + 1; //~ ERROR E0369
     parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors
 }
+
+//~? ERROR expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
diff --git a/tests/ui/resolve/prelude-order.rs b/tests/ui/resolve/prelude-order.rs
new file mode 100644
index 00000000000..a3f194270d4
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.rs
@@ -0,0 +1,89 @@
+//@ proc-macro:macro_helpers.rs
+//@ compile-flags: --crate-type=lib
+
+/* There are 5 preludes and 3 namespaces. Test the order in which they are resolved.
+ * See https://doc.rust-lang.org/nightly/reference/names/preludes.html.
+ *
+ * Macros cannot be in the type or value namespace.
+ * Tools and extern crates cannot be in the macro or value namespace.
+ *
+ * Test the following truth tables:
+
+Type:
+| ...... |  tool  | extern | macro  | lang   | libs |
+|   tool |    N/A |                   mirror
+| extern | extern |    N/A |             universe
+|  macro |    N/A |    N/A |    N/A |
+|   lang |   tool | extern |    N/A |   N/A  |
+|   libs |   tool | extern |    N/A |   X    |  N/A |
+
+Macro:
+| ...... |  tool  | extern | macro  | lang   | libs |
+|   tool |    N/A |                   mirror
+| extern |    N/A |    N/A |             universe
+|  macro |    N/A |    N/A |    N/A |
+|   lang |    N/A |    N/A |  macro |   N/A  |
+|   libs |    N/A |    N/A |  macro |   X    | N/A  |
+
+Value: N/A. Only libs has items in the value namespace.
+
+† ambiguous
+X don't care (controlled namespace with no overlap)
+
+* Types are tested with `#[name::inner]`. Macros are tested with `#[name]`.
+* WARNING: I have found in testing that attribute macros give ambiguity errors in some contexts
+* instead of choosing a prelude. Have not been able to replicate.
+*
+* There should be 7 total tests.
+* See `rustc_resolve::ident::visit_scopes` for more information,
+* and for a definition of "controlled namespace".
+*/
+
+#![feature(register_tool)]
+
+/* tool prelude */
+#![register_tool(type_ns)] // extern prelude. type.
+#![register_tool(i8)]      // lang   prelude. type.
+#![register_tool(Sync)]    // libs   prelude. type.
+
+/* extern prelude */
+extern crate macro_helpers as type_ns; // tool prelude. type.
+extern crate macro_helpers as usize;   // lang prelude. type.
+extern crate macro_helpers as Option;  // libs prelude. type.
+
+/* macro_use prelude */
+#[macro_use]
+extern crate macro_helpers as _;
+
+/* lang and libs implicitly in scope */
+
+// tool/extern -> extern
+#[type_ns::inner] //~ ERROR could not find `inner` in `type_ns`
+fn t1() {}
+
+// tool/lang -> tool
+#[i8::inner] // ok
+fn t2() {}
+
+// tool/libs -> tool
+#[Sync::not_real] // ok
+fn t3() {}
+
+// extern/lang -> extern
+#[usize::inner] //~ ERROR could not find `inner` in `usize`
+fn e1() {} // NOTE: testing with `-> usize` isn't valid, crates aren't considered in that scope
+           // (unless they have generic arguments, for some reason.)
+
+// extern/libs -> extern
+// https://github.com/rust-lang/rust/issues/139095
+fn e2() -> Option<i32> { None } //~ ERROR: expected type, found crate
+
+// macro/libs -> macro
+#[test] //~ ERROR mismatched types
+fn m1() {}
+
+// macro/lang -> macro
+#[global_allocator] //~ ERROR mismatched types
+fn m2() {}
+
+// lang/libs: no items that currently overlap, in either macro or type ns.
diff --git a/tests/ui/resolve/prelude-order.stderr b/tests/ui/resolve/prelude-order.stderr
new file mode 100644
index 00000000000..1b9cc94285a
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.stderr
@@ -0,0 +1,47 @@
+error[E0433]: failed to resolve: could not find `inner` in `type_ns`
+  --> $DIR/prelude-order.rs:61:12
+   |
+LL | #[type_ns::inner]
+   |            ^^^^^ could not find `inner` in `type_ns`
+
+error[E0433]: failed to resolve: could not find `inner` in `usize`
+  --> $DIR/prelude-order.rs:73:10
+   |
+LL | #[usize::inner]
+   |          ^^^^^ could not find `inner` in `usize`
+
+error[E0573]: expected type, found crate `Option`
+  --> $DIR/prelude-order.rs:79:12
+   |
+LL | fn e2() -> Option<i32> { None }
+   |            ^^^^^^^^^^^ not a type
+   |
+help: consider importing this enum instead
+   |
+LL + use std::option::Option;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/prelude-order.rs:82:1
+   |
+LL | #[test]
+   | ^^^^^^^- help: try adding a return type: `-> &'static str`
+   | |
+   | expected `()`, found `&str`
+   |
+   = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/prelude-order.rs:86:1
+   |
+LL | #[global_allocator]
+   | ^^^^^^^^^^^^^^^^^^^- help: try adding a return type: `-> &'static str`
+   | |
+   | expected `()`, found `&str`
+   |
+   = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0433, E0573.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
index 08584349626..c5756269def 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature `structural_match`
-  --> $DIR/feature-gate.rs:29:6
+  --> $DIR/feature-gate.rs:27:6
    |
 LL | impl std::marker::StructuralPartialEq for Foo { }
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
index 711b07fee3b..694081654d5 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
@@ -3,11 +3,10 @@
 // used in a match.
 
 //@ revisions: with_gate no_gate
-
+//@[with_gate] check-pass
 // gate-test-structural_match
 
 #![allow(unused)]
-#![feature(rustc_attrs)]
 #![cfg_attr(with_gate, feature(structural_match))]
 
 
@@ -17,8 +16,7 @@ struct Foo {
 
 const FOO: Foo = Foo { x: 0 };
 
-#[rustc_error]
-fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
+fn main() {
     let y = Foo { x: 1 };
     match y {
         FOO => { }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
deleted file mode 100644
index 505b7d79cad..00000000000
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate.rs:21:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
index ef970ebd14b..2b21d3987b9 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
@@ -30,3 +30,5 @@ fn main() {
         (CONSTANT.file(), CONSTANT.line(), CONSTANT.column()),
     );
 }
+
+//~? WARN skipping const checks
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
index 4b2fc4a03b6..110c03d0e54 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -59,8 +59,10 @@ fn _macros() {
     }
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //~^ ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
     match () {
         #[cfg(FALSE)]
         () if let 0 = 1 => {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
index 1c710b04897..0997f0c81a0 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -124,15 +124,33 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/feature-gate.rs:62:16
+  --> $DIR/feature-gate.rs:60:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:63:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:63:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: no rules expected keyword `let`
-  --> $DIR/feature-gate.rs:70:15
+  --> $DIR/feature-gate.rs:72:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -202,7 +220,7 @@ LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:66:12
+  --> $DIR/feature-gate.rs:68:12
    |
 LL |         () if let 0 = 1 => {}
    |            ^^^^^^^^^^^^
@@ -262,6 +280,6 @@ LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    = help: add `#![feature(let_chains)]` 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 23 previous errors
+error: aborting due to 25 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr
index db32b8c1de4..817e226bc45 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr
@@ -233,7 +233,7 @@ LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:99:9
+  --> $DIR/disallowed-positions.rs:103:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -241,7 +241,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:102:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -249,7 +249,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:108:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -257,7 +257,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:106:9
+  --> $DIR/disallowed-positions.rs:110:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -265,7 +265,7 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:114:9
+  --> $DIR/disallowed-positions.rs:118:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
@@ -273,20 +273,20 @@ LL |     if (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:117:16
+  --> $DIR/disallowed-positions.rs:121:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:117:13
+  --> $DIR/disallowed-positions.rs:121:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:119:17
+  --> $DIR/disallowed-positions.rs:123:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
@@ -294,7 +294,7 @@ LL |     if (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:121:25
+  --> $DIR/disallowed-positions.rs:125:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -302,7 +302,7 @@ LL |     if true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:123:25
+  --> $DIR/disallowed-positions.rs:127:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -310,7 +310,7 @@ LL |     if true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:127:12
+  --> $DIR/disallowed-positions.rs:131:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^
@@ -318,7 +318,7 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:130:15
+  --> $DIR/disallowed-positions.rs:134:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
@@ -326,7 +326,7 @@ LL |     if true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:133:11
+  --> $DIR/disallowed-positions.rs:137:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
@@ -334,7 +334,7 @@ LL |     if ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:135:9
+  --> $DIR/disallowed-positions.rs:139:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
@@ -342,7 +342,7 @@ LL |     if (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:139:8
+  --> $DIR/disallowed-positions.rs:143:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -350,7 +350,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:142:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -358,7 +358,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:148:8
+  --> $DIR/disallowed-positions.rs:152:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -366,7 +366,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:154:8
+  --> $DIR/disallowed-positions.rs:158:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -374,7 +374,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:158:19
+  --> $DIR/disallowed-positions.rs:162:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^
@@ -382,7 +382,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:161:15
+  --> $DIR/disallowed-positions.rs:165:15
    |
 LL |     if return let 0 = 0 {}
    |               ^^^
@@ -390,7 +390,7 @@ LL |     if return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:164:21
+  --> $DIR/disallowed-positions.rs:168:21
    |
 LL |     loop { if break let 0 = 0 {} }
    |                     ^^^
@@ -398,7 +398,7 @@ LL |     loop { if break let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:167:15
+  --> $DIR/disallowed-positions.rs:171:15
    |
 LL |     if (match let 0 = 0 { _ => { false } }) {}
    |               ^^^
@@ -406,7 +406,7 @@ LL |     if (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:170:9
+  --> $DIR/disallowed-positions.rs:174:9
    |
 LL |     if (let 0 = 0, false).1 {}
    |         ^^^^^^^^^
@@ -414,7 +414,7 @@ LL |     if (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:173:9
+  --> $DIR/disallowed-positions.rs:177:9
    |
 LL |     if (let 0 = 0,) {}
    |         ^^^^^^^^^
@@ -422,7 +422,7 @@ LL |     if (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:177:13
+  --> $DIR/disallowed-positions.rs:181:13
    |
 LL |         if (let 0 = 0).await {}
    |             ^^^^^^^^^
@@ -430,7 +430,7 @@ LL |         if (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:181:12
+  --> $DIR/disallowed-positions.rs:185:12
    |
 LL |     if (|| let 0 = 0) {}
    |            ^^^
@@ -438,7 +438,7 @@ LL |     if (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:184:9
+  --> $DIR/disallowed-positions.rs:188:9
    |
 LL |     if (let 0 = 0)() {}
    |         ^^^^^^^^^
@@ -446,7 +446,7 @@ LL |     if (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:190:12
+  --> $DIR/disallowed-positions.rs:194:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -454,7 +454,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:193:12
+  --> $DIR/disallowed-positions.rs:197:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -462,7 +462,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:195:12
+  --> $DIR/disallowed-positions.rs:199:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -470,7 +470,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:197:12
+  --> $DIR/disallowed-positions.rs:201:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -478,7 +478,7 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:205:12
+  --> $DIR/disallowed-positions.rs:209:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
@@ -486,20 +486,20 @@ LL |     while (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:208:19
+  --> $DIR/disallowed-positions.rs:212:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:208:16
+  --> $DIR/disallowed-positions.rs:212:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:210:20
+  --> $DIR/disallowed-positions.rs:214:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
@@ -507,7 +507,7 @@ LL |     while (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:212:28
+  --> $DIR/disallowed-positions.rs:216:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -515,7 +515,7 @@ LL |     while true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:214:28
+  --> $DIR/disallowed-positions.rs:218:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -523,7 +523,7 @@ LL |     while true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:218:15
+  --> $DIR/disallowed-positions.rs:222:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^
@@ -531,7 +531,7 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:221:18
+  --> $DIR/disallowed-positions.rs:225:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
@@ -539,7 +539,7 @@ LL |     while true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:224:14
+  --> $DIR/disallowed-positions.rs:228:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
@@ -547,7 +547,7 @@ LL |     while ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:226:12
+  --> $DIR/disallowed-positions.rs:230:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
@@ -555,7 +555,7 @@ LL |     while (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:230:11
+  --> $DIR/disallowed-positions.rs:234:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -563,7 +563,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:233:11
+  --> $DIR/disallowed-positions.rs:237:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -571,7 +571,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:239:11
+  --> $DIR/disallowed-positions.rs:243:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -579,7 +579,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:245:11
+  --> $DIR/disallowed-positions.rs:249:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -587,7 +587,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:249:22
+  --> $DIR/disallowed-positions.rs:253:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^
@@ -595,7 +595,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:252:18
+  --> $DIR/disallowed-positions.rs:256:18
    |
 LL |     while return let 0 = 0 {}
    |                  ^^^
@@ -603,7 +603,7 @@ LL |     while return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:255:39
+  --> $DIR/disallowed-positions.rs:259:39
    |
 LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    |                                       ^^^
@@ -611,7 +611,7 @@ LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:258:18
+  --> $DIR/disallowed-positions.rs:262:18
    |
 LL |     while (match let 0 = 0 { _ => { false } }) {}
    |                  ^^^
@@ -619,7 +619,7 @@ LL |     while (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:261:12
+  --> $DIR/disallowed-positions.rs:265:12
    |
 LL |     while (let 0 = 0, false).1 {}
    |            ^^^^^^^^^
@@ -627,7 +627,7 @@ LL |     while (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:264:12
+  --> $DIR/disallowed-positions.rs:268:12
    |
 LL |     while (let 0 = 0,) {}
    |            ^^^^^^^^^
@@ -635,7 +635,7 @@ LL |     while (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:268:16
+  --> $DIR/disallowed-positions.rs:272:16
    |
 LL |         while (let 0 = 0).await {}
    |                ^^^^^^^^^
@@ -643,7 +643,7 @@ LL |         while (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:272:15
+  --> $DIR/disallowed-positions.rs:276:15
    |
 LL |     while (|| let 0 = 0) {}
    |               ^^^
@@ -651,7 +651,7 @@ LL |     while (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:275:12
+  --> $DIR/disallowed-positions.rs:279:12
    |
 LL |     while (let 0 = 0)() {}
    |            ^^^^^^^^^
@@ -659,7 +659,7 @@ LL |     while (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:292:6
+  --> $DIR/disallowed-positions.rs:296:6
    |
 LL |     &let 0 = 0;
    |      ^^^
@@ -667,7 +667,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:295:6
+  --> $DIR/disallowed-positions.rs:299:6
    |
 LL |     !let 0 = 0;
    |      ^^^
@@ -675,7 +675,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:297:6
+  --> $DIR/disallowed-positions.rs:301:6
    |
 LL |     *let 0 = 0;
    |      ^^^
@@ -683,7 +683,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:299:6
+  --> $DIR/disallowed-positions.rs:303:6
    |
 LL |     -let 0 = 0;
    |      ^^^
@@ -691,7 +691,7 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:301:13
+  --> $DIR/disallowed-positions.rs:305:13
    |
 LL |     let _ = let _ = 3;
    |             ^^^
@@ -699,7 +699,7 @@ LL |     let _ = let _ = 3;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:309:6
+  --> $DIR/disallowed-positions.rs:313:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^
@@ -707,7 +707,7 @@ LL |     (let 0 = 0)?;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:312:13
+  --> $DIR/disallowed-positions.rs:316:13
    |
 LL |     true || let 0 = 0;
    |             ^^^
@@ -715,7 +715,7 @@ LL |     true || let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:314:14
+  --> $DIR/disallowed-positions.rs:318:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^
@@ -723,7 +723,7 @@ LL |     (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:316:22
+  --> $DIR/disallowed-positions.rs:320:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^
@@ -731,7 +731,7 @@ LL |     true && (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:324:9
    |
 LL |     x = let 0 = 0;
    |         ^^^
@@ -739,7 +739,7 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:323:12
+  --> $DIR/disallowed-positions.rs:327:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^
@@ -747,7 +747,7 @@ LL |     true..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:325:8
+  --> $DIR/disallowed-positions.rs:329:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^
@@ -755,7 +755,7 @@ LL |     ..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:327:6
+  --> $DIR/disallowed-positions.rs:331:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^
@@ -763,7 +763,7 @@ LL |     (let 0 = 0)..;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:330:6
+  --> $DIR/disallowed-positions.rs:334:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^
@@ -771,7 +771,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:6
+  --> $DIR/disallowed-positions.rs:338:6
    |
 LL |     (let true = let true = true);
    |      ^^^
@@ -779,7 +779,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:17
+  --> $DIR/disallowed-positions.rs:338:17
    |
 LL |     (let true = let true = true);
    |                 ^^^
@@ -787,7 +787,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:340:25
+  --> $DIR/disallowed-positions.rs:344:25
    |
 LL |         let x = true && let y = 1;
    |                         ^^^
@@ -795,7 +795,7 @@ LL |         let x = true && let y = 1;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:346:19
+  --> $DIR/disallowed-positions.rs:350:19
    |
 LL |         [1, 2, 3][let _ = ()]
    |                   ^^^
@@ -803,7 +803,7 @@ LL |         [1, 2, 3][let _ = ()]
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:351:6
+  --> $DIR/disallowed-positions.rs:355:6
    |
 LL |     &let 0 = 0
    |      ^^^
@@ -811,7 +811,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:362:17
+  --> $DIR/disallowed-positions.rs:366:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -819,7 +819,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:367:17
+  --> $DIR/disallowed-positions.rs:371:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -827,7 +827,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:372:17
+  --> $DIR/disallowed-positions.rs:376:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -835,7 +835,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:383:17
+  --> $DIR/disallowed-positions.rs:387:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -843,7 +843,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:383:9
+  --> $DIR/disallowed-positions.rs:387:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -854,124 +854,124 @@ LL |         { true && let 1 = 1 }
    |         +                   +
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:436:22
+  --> $DIR/disallowed-positions.rs:440:22
    |
 LL |     let x = (true && let y = 1);
    |                      ^^^
@@ -979,7 +979,7 @@ LL |     let x = (true && let y = 1);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:441:20
+  --> $DIR/disallowed-positions.rs:445:20
    |
 LL |         ([1, 2, 3][let _ = ()])
    |                    ^^^
@@ -995,15 +995,51 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:91:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:91:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:130:8
+  --> $DIR/disallowed-positions.rs:134:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
@@ -1012,7 +1048,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:139:12
+  --> $DIR/disallowed-positions.rs:143:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1023,7 +1059,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:142:12
+  --> $DIR/disallowed-positions.rs:146:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1034,7 +1070,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:148:12
+  --> $DIR/disallowed-positions.rs:152:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1045,7 +1081,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:154:12
+  --> $DIR/disallowed-positions.rs:158:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1056,7 +1092,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:110:20
+  --> $DIR/disallowed-positions.rs:114:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1064,7 +1100,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:221:11
+  --> $DIR/disallowed-positions.rs:225:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
@@ -1073,7 +1109,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:230:15
+  --> $DIR/disallowed-positions.rs:234:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1084,7 +1120,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:233:15
+  --> $DIR/disallowed-positions.rs:237:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1095,7 +1131,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:239:15
+  --> $DIR/disallowed-positions.rs:243:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1106,7 +1142,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:245:15
+  --> $DIR/disallowed-positions.rs:249:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1117,7 +1153,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:201:23
+  --> $DIR/disallowed-positions.rs:205:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1125,7 +1161,7 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:330:10
+  --> $DIR/disallowed-positions.rs:334:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1136,14 +1172,14 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:305:17
+  --> $DIR/disallowed-positions.rs:309:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 121 previous errors
+error: aborting due to 125 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr
index ad16a0f8ed8..bab50c22c03 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr
@@ -233,7 +233,7 @@ LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:99:9
+  --> $DIR/disallowed-positions.rs:103:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -241,7 +241,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:102:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -249,7 +249,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:108:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -257,7 +257,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:106:9
+  --> $DIR/disallowed-positions.rs:110:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -265,7 +265,7 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:114:9
+  --> $DIR/disallowed-positions.rs:118:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
@@ -273,20 +273,20 @@ LL |     if (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:117:16
+  --> $DIR/disallowed-positions.rs:121:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:117:13
+  --> $DIR/disallowed-positions.rs:121:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:119:17
+  --> $DIR/disallowed-positions.rs:123:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
@@ -294,7 +294,7 @@ LL |     if (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:121:25
+  --> $DIR/disallowed-positions.rs:125:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -302,7 +302,7 @@ LL |     if true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:123:25
+  --> $DIR/disallowed-positions.rs:127:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -310,7 +310,7 @@ LL |     if true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:127:12
+  --> $DIR/disallowed-positions.rs:131:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^
@@ -318,7 +318,7 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:130:15
+  --> $DIR/disallowed-positions.rs:134:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
@@ -326,7 +326,7 @@ LL |     if true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:133:11
+  --> $DIR/disallowed-positions.rs:137:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
@@ -334,7 +334,7 @@ LL |     if ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:135:9
+  --> $DIR/disallowed-positions.rs:139:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
@@ -342,7 +342,7 @@ LL |     if (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:139:8
+  --> $DIR/disallowed-positions.rs:143:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -350,7 +350,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:142:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -358,7 +358,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:148:8
+  --> $DIR/disallowed-positions.rs:152:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -366,7 +366,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:154:8
+  --> $DIR/disallowed-positions.rs:158:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -374,7 +374,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:158:19
+  --> $DIR/disallowed-positions.rs:162:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^
@@ -382,7 +382,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:161:15
+  --> $DIR/disallowed-positions.rs:165:15
    |
 LL |     if return let 0 = 0 {}
    |               ^^^
@@ -390,7 +390,7 @@ LL |     if return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:164:21
+  --> $DIR/disallowed-positions.rs:168:21
    |
 LL |     loop { if break let 0 = 0 {} }
    |                     ^^^
@@ -398,7 +398,7 @@ LL |     loop { if break let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:167:15
+  --> $DIR/disallowed-positions.rs:171:15
    |
 LL |     if (match let 0 = 0 { _ => { false } }) {}
    |               ^^^
@@ -406,7 +406,7 @@ LL |     if (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:170:9
+  --> $DIR/disallowed-positions.rs:174:9
    |
 LL |     if (let 0 = 0, false).1 {}
    |         ^^^^^^^^^
@@ -414,7 +414,7 @@ LL |     if (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:173:9
+  --> $DIR/disallowed-positions.rs:177:9
    |
 LL |     if (let 0 = 0,) {}
    |         ^^^^^^^^^
@@ -422,7 +422,7 @@ LL |     if (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:177:13
+  --> $DIR/disallowed-positions.rs:181:13
    |
 LL |         if (let 0 = 0).await {}
    |             ^^^^^^^^^
@@ -430,7 +430,7 @@ LL |         if (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:181:12
+  --> $DIR/disallowed-positions.rs:185:12
    |
 LL |     if (|| let 0 = 0) {}
    |            ^^^
@@ -438,7 +438,7 @@ LL |     if (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:184:9
+  --> $DIR/disallowed-positions.rs:188:9
    |
 LL |     if (let 0 = 0)() {}
    |         ^^^^^^^^^
@@ -446,7 +446,7 @@ LL |     if (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:190:12
+  --> $DIR/disallowed-positions.rs:194:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -454,7 +454,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:193:12
+  --> $DIR/disallowed-positions.rs:197:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -462,7 +462,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:195:12
+  --> $DIR/disallowed-positions.rs:199:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -470,7 +470,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:197:12
+  --> $DIR/disallowed-positions.rs:201:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -478,7 +478,7 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:205:12
+  --> $DIR/disallowed-positions.rs:209:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
@@ -486,20 +486,20 @@ LL |     while (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:208:19
+  --> $DIR/disallowed-positions.rs:212:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:208:16
+  --> $DIR/disallowed-positions.rs:212:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:210:20
+  --> $DIR/disallowed-positions.rs:214:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
@@ -507,7 +507,7 @@ LL |     while (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:212:28
+  --> $DIR/disallowed-positions.rs:216:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -515,7 +515,7 @@ LL |     while true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:214:28
+  --> $DIR/disallowed-positions.rs:218:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -523,7 +523,7 @@ LL |     while true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:218:15
+  --> $DIR/disallowed-positions.rs:222:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^
@@ -531,7 +531,7 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:221:18
+  --> $DIR/disallowed-positions.rs:225:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
@@ -539,7 +539,7 @@ LL |     while true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:224:14
+  --> $DIR/disallowed-positions.rs:228:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
@@ -547,7 +547,7 @@ LL |     while ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:226:12
+  --> $DIR/disallowed-positions.rs:230:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
@@ -555,7 +555,7 @@ LL |     while (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:230:11
+  --> $DIR/disallowed-positions.rs:234:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -563,7 +563,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:233:11
+  --> $DIR/disallowed-positions.rs:237:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -571,7 +571,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:239:11
+  --> $DIR/disallowed-positions.rs:243:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -579,7 +579,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:245:11
+  --> $DIR/disallowed-positions.rs:249:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -587,7 +587,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:249:22
+  --> $DIR/disallowed-positions.rs:253:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^
@@ -595,7 +595,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:252:18
+  --> $DIR/disallowed-positions.rs:256:18
    |
 LL |     while return let 0 = 0 {}
    |                  ^^^
@@ -603,7 +603,7 @@ LL |     while return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:255:39
+  --> $DIR/disallowed-positions.rs:259:39
    |
 LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    |                                       ^^^
@@ -611,7 +611,7 @@ LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:258:18
+  --> $DIR/disallowed-positions.rs:262:18
    |
 LL |     while (match let 0 = 0 { _ => { false } }) {}
    |                  ^^^
@@ -619,7 +619,7 @@ LL |     while (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:261:12
+  --> $DIR/disallowed-positions.rs:265:12
    |
 LL |     while (let 0 = 0, false).1 {}
    |            ^^^^^^^^^
@@ -627,7 +627,7 @@ LL |     while (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:264:12
+  --> $DIR/disallowed-positions.rs:268:12
    |
 LL |     while (let 0 = 0,) {}
    |            ^^^^^^^^^
@@ -635,7 +635,7 @@ LL |     while (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:268:16
+  --> $DIR/disallowed-positions.rs:272:16
    |
 LL |         while (let 0 = 0).await {}
    |                ^^^^^^^^^
@@ -643,7 +643,7 @@ LL |         while (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:272:15
+  --> $DIR/disallowed-positions.rs:276:15
    |
 LL |     while (|| let 0 = 0) {}
    |               ^^^
@@ -651,7 +651,7 @@ LL |     while (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:275:12
+  --> $DIR/disallowed-positions.rs:279:12
    |
 LL |     while (let 0 = 0)() {}
    |            ^^^^^^^^^
@@ -659,7 +659,7 @@ LL |     while (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:292:6
+  --> $DIR/disallowed-positions.rs:296:6
    |
 LL |     &let 0 = 0;
    |      ^^^
@@ -667,7 +667,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:295:6
+  --> $DIR/disallowed-positions.rs:299:6
    |
 LL |     !let 0 = 0;
    |      ^^^
@@ -675,7 +675,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:297:6
+  --> $DIR/disallowed-positions.rs:301:6
    |
 LL |     *let 0 = 0;
    |      ^^^
@@ -683,7 +683,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:299:6
+  --> $DIR/disallowed-positions.rs:303:6
    |
 LL |     -let 0 = 0;
    |      ^^^
@@ -691,7 +691,7 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:301:13
+  --> $DIR/disallowed-positions.rs:305:13
    |
 LL |     let _ = let _ = 3;
    |             ^^^
@@ -699,7 +699,7 @@ LL |     let _ = let _ = 3;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:309:6
+  --> $DIR/disallowed-positions.rs:313:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^
@@ -707,7 +707,7 @@ LL |     (let 0 = 0)?;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:312:13
+  --> $DIR/disallowed-positions.rs:316:13
    |
 LL |     true || let 0 = 0;
    |             ^^^
@@ -715,7 +715,7 @@ LL |     true || let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:314:14
+  --> $DIR/disallowed-positions.rs:318:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^
@@ -723,7 +723,7 @@ LL |     (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:316:22
+  --> $DIR/disallowed-positions.rs:320:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^
@@ -731,7 +731,7 @@ LL |     true && (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:324:9
    |
 LL |     x = let 0 = 0;
    |         ^^^
@@ -739,7 +739,7 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:323:12
+  --> $DIR/disallowed-positions.rs:327:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^
@@ -747,7 +747,7 @@ LL |     true..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:325:8
+  --> $DIR/disallowed-positions.rs:329:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^
@@ -755,7 +755,7 @@ LL |     ..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:327:6
+  --> $DIR/disallowed-positions.rs:331:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^
@@ -763,7 +763,7 @@ LL |     (let 0 = 0)..;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:330:6
+  --> $DIR/disallowed-positions.rs:334:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^
@@ -771,7 +771,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:6
+  --> $DIR/disallowed-positions.rs:338:6
    |
 LL |     (let true = let true = true);
    |      ^^^
@@ -779,7 +779,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:17
+  --> $DIR/disallowed-positions.rs:338:17
    |
 LL |     (let true = let true = true);
    |                 ^^^
@@ -787,7 +787,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:340:25
+  --> $DIR/disallowed-positions.rs:344:25
    |
 LL |         let x = true && let y = 1;
    |                         ^^^
@@ -795,7 +795,7 @@ LL |         let x = true && let y = 1;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:346:19
+  --> $DIR/disallowed-positions.rs:350:19
    |
 LL |         [1, 2, 3][let _ = ()]
    |                   ^^^
@@ -803,7 +803,7 @@ LL |         [1, 2, 3][let _ = ()]
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:351:6
+  --> $DIR/disallowed-positions.rs:355:6
    |
 LL |     &let 0 = 0
    |      ^^^
@@ -811,7 +811,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:362:17
+  --> $DIR/disallowed-positions.rs:366:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -819,7 +819,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:367:17
+  --> $DIR/disallowed-positions.rs:371:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -827,7 +827,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:372:17
+  --> $DIR/disallowed-positions.rs:376:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -835,7 +835,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:383:17
+  --> $DIR/disallowed-positions.rs:387:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -843,7 +843,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:383:9
+  --> $DIR/disallowed-positions.rs:387:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -854,124 +854,124 @@ LL |         { true && let 1 = 1 }
    |         +                   +
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:436:22
+  --> $DIR/disallowed-positions.rs:440:22
    |
 LL |     let x = (true && let y = 1);
    |                      ^^^
@@ -979,7 +979,7 @@ LL |     let x = (true && let y = 1);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:441:20
+  --> $DIR/disallowed-positions.rs:445:20
    |
 LL |         ([1, 2, 3][let _ = ()])
    |                    ^^^
@@ -995,12 +995,48 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:93:16
+  --> $DIR/disallowed-positions.rs:91:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:91:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:95:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0658]: `let` expressions in this position are unstable
   --> $DIR/disallowed-positions.rs:49:8
@@ -1043,7 +1079,7 @@ LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/disallowed-positions.rs:404:8
+  --> $DIR/disallowed-positions.rs:408:8
    |
 LL |     if let Some(a) = opt && (true && true) {
    |        ^^^^^^^^^^^^^^^^^
@@ -1053,7 +1089,7 @@ LL |     if let Some(a) = opt && (true && true) {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/disallowed-positions.rs:420:28
+  --> $DIR/disallowed-positions.rs:424:28
    |
 LL |     if (true && (true)) && let Some(a) = opt {
    |                            ^^^^^^^^^^^^^^^^^
@@ -1063,7 +1099,7 @@ LL |     if (true && (true)) && let Some(a) = opt {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/disallowed-positions.rs:423:18
+  --> $DIR/disallowed-positions.rs:427:18
    |
 LL |     if (true) && let Some(a) = opt {
    |                  ^^^^^^^^^^^^^^^^^
@@ -1073,7 +1109,7 @@ LL |     if (true) && let Some(a) = opt {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/disallowed-positions.rs:426:16
+  --> $DIR/disallowed-positions.rs:430:16
    |
 LL |     if true && let Some(a) = opt {
    |                ^^^^^^^^^^^^^^^^^
@@ -1083,7 +1119,7 @@ LL |     if true && let Some(a) = opt {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/disallowed-positions.rs:431:8
+  --> $DIR/disallowed-positions.rs:435:8
    |
 LL |     if let true = (true && fun()) && (true) {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1093,7 +1129,7 @@ LL |     if let true = (true && fun()) && (true) {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:130:8
+  --> $DIR/disallowed-positions.rs:134:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
@@ -1102,7 +1138,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:139:12
+  --> $DIR/disallowed-positions.rs:143:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1113,7 +1149,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:142:12
+  --> $DIR/disallowed-positions.rs:146:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1124,7 +1160,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:148:12
+  --> $DIR/disallowed-positions.rs:152:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1135,7 +1171,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:154:12
+  --> $DIR/disallowed-positions.rs:158:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1146,7 +1182,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:110:20
+  --> $DIR/disallowed-positions.rs:114:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1154,7 +1190,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:221:11
+  --> $DIR/disallowed-positions.rs:225:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
@@ -1163,7 +1199,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:230:15
+  --> $DIR/disallowed-positions.rs:234:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1174,7 +1210,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:233:15
+  --> $DIR/disallowed-positions.rs:237:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1185,7 +1221,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:239:15
+  --> $DIR/disallowed-positions.rs:243:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1196,7 +1232,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:245:15
+  --> $DIR/disallowed-positions.rs:249:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1207,7 +1243,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:201:23
+  --> $DIR/disallowed-positions.rs:205:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1215,7 +1251,7 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:330:10
+  --> $DIR/disallowed-positions.rs:334:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1226,14 +1262,14 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:305:17
+  --> $DIR/disallowed-positions.rs:309:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 130 previous errors
+error: aborting due to 134 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0658.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr
index 2d5fd1144ad..943956feb4e 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr
@@ -233,7 +233,7 @@ LL |     while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:99:9
+  --> $DIR/disallowed-positions.rs:103:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -241,7 +241,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:102:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -249,7 +249,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:108:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -257,7 +257,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:106:9
+  --> $DIR/disallowed-positions.rs:110:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -265,7 +265,7 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:114:9
+  --> $DIR/disallowed-positions.rs:118:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
@@ -273,20 +273,20 @@ LL |     if (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:117:16
+  --> $DIR/disallowed-positions.rs:121:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:117:13
+  --> $DIR/disallowed-positions.rs:121:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:119:17
+  --> $DIR/disallowed-positions.rs:123:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
@@ -294,7 +294,7 @@ LL |     if (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:121:25
+  --> $DIR/disallowed-positions.rs:125:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -302,7 +302,7 @@ LL |     if true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:123:25
+  --> $DIR/disallowed-positions.rs:127:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -310,7 +310,7 @@ LL |     if true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:127:12
+  --> $DIR/disallowed-positions.rs:131:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^
@@ -318,7 +318,7 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:130:15
+  --> $DIR/disallowed-positions.rs:134:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
@@ -326,7 +326,7 @@ LL |     if true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:133:11
+  --> $DIR/disallowed-positions.rs:137:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
@@ -334,7 +334,7 @@ LL |     if ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:135:9
+  --> $DIR/disallowed-positions.rs:139:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
@@ -342,7 +342,7 @@ LL |     if (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:139:8
+  --> $DIR/disallowed-positions.rs:143:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -350,7 +350,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:142:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -358,7 +358,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:148:8
+  --> $DIR/disallowed-positions.rs:152:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -366,7 +366,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:154:8
+  --> $DIR/disallowed-positions.rs:158:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -374,7 +374,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:158:19
+  --> $DIR/disallowed-positions.rs:162:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^
@@ -382,7 +382,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:161:15
+  --> $DIR/disallowed-positions.rs:165:15
    |
 LL |     if return let 0 = 0 {}
    |               ^^^
@@ -390,7 +390,7 @@ LL |     if return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:164:21
+  --> $DIR/disallowed-positions.rs:168:21
    |
 LL |     loop { if break let 0 = 0 {} }
    |                     ^^^
@@ -398,7 +398,7 @@ LL |     loop { if break let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:167:15
+  --> $DIR/disallowed-positions.rs:171:15
    |
 LL |     if (match let 0 = 0 { _ => { false } }) {}
    |               ^^^
@@ -406,7 +406,7 @@ LL |     if (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:170:9
+  --> $DIR/disallowed-positions.rs:174:9
    |
 LL |     if (let 0 = 0, false).1 {}
    |         ^^^^^^^^^
@@ -414,7 +414,7 @@ LL |     if (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:173:9
+  --> $DIR/disallowed-positions.rs:177:9
    |
 LL |     if (let 0 = 0,) {}
    |         ^^^^^^^^^
@@ -422,7 +422,7 @@ LL |     if (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:177:13
+  --> $DIR/disallowed-positions.rs:181:13
    |
 LL |         if (let 0 = 0).await {}
    |             ^^^^^^^^^
@@ -430,7 +430,7 @@ LL |         if (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:181:12
+  --> $DIR/disallowed-positions.rs:185:12
    |
 LL |     if (|| let 0 = 0) {}
    |            ^^^
@@ -438,7 +438,7 @@ LL |     if (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:184:9
+  --> $DIR/disallowed-positions.rs:188:9
    |
 LL |     if (let 0 = 0)() {}
    |         ^^^^^^^^^
@@ -446,7 +446,7 @@ LL |     if (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:190:12
+  --> $DIR/disallowed-positions.rs:194:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -454,7 +454,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:193:12
+  --> $DIR/disallowed-positions.rs:197:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -462,7 +462,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:195:12
+  --> $DIR/disallowed-positions.rs:199:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -470,7 +470,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:197:12
+  --> $DIR/disallowed-positions.rs:201:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -478,7 +478,7 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:205:12
+  --> $DIR/disallowed-positions.rs:209:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
@@ -486,20 +486,20 @@ LL |     while (let 0 = 0)? {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:208:19
+  --> $DIR/disallowed-positions.rs:212:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:208:16
+  --> $DIR/disallowed-positions.rs:212:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:210:20
+  --> $DIR/disallowed-positions.rs:214:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
@@ -507,7 +507,7 @@ LL |     while (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:212:28
+  --> $DIR/disallowed-positions.rs:216:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -515,7 +515,7 @@ LL |     while true && (true || let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:214:28
+  --> $DIR/disallowed-positions.rs:218:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -523,7 +523,7 @@ LL |     while true || (true && let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:218:15
+  --> $DIR/disallowed-positions.rs:222:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^
@@ -531,7 +531,7 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:221:18
+  --> $DIR/disallowed-positions.rs:225:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
@@ -539,7 +539,7 @@ LL |     while true..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:224:14
+  --> $DIR/disallowed-positions.rs:228:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
@@ -547,7 +547,7 @@ LL |     while ..(let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:226:12
+  --> $DIR/disallowed-positions.rs:230:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
@@ -555,7 +555,7 @@ LL |     while (let 0 = 0).. {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:230:11
+  --> $DIR/disallowed-positions.rs:234:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -563,7 +563,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:233:11
+  --> $DIR/disallowed-positions.rs:237:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -571,7 +571,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:239:11
+  --> $DIR/disallowed-positions.rs:243:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -579,7 +579,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:245:11
+  --> $DIR/disallowed-positions.rs:249:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -587,7 +587,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:249:22
+  --> $DIR/disallowed-positions.rs:253:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^
@@ -595,7 +595,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:252:18
+  --> $DIR/disallowed-positions.rs:256:18
    |
 LL |     while return let 0 = 0 {}
    |                  ^^^
@@ -603,7 +603,7 @@ LL |     while return let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:255:39
+  --> $DIR/disallowed-positions.rs:259:39
    |
 LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    |                                       ^^^
@@ -611,7 +611,7 @@ LL |     'outer: loop { while break 'outer let 0 = 0 {} }
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:258:18
+  --> $DIR/disallowed-positions.rs:262:18
    |
 LL |     while (match let 0 = 0 { _ => { false } }) {}
    |                  ^^^
@@ -619,7 +619,7 @@ LL |     while (match let 0 = 0 { _ => { false } }) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:261:12
+  --> $DIR/disallowed-positions.rs:265:12
    |
 LL |     while (let 0 = 0, false).1 {}
    |            ^^^^^^^^^
@@ -627,7 +627,7 @@ LL |     while (let 0 = 0, false).1 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:264:12
+  --> $DIR/disallowed-positions.rs:268:12
    |
 LL |     while (let 0 = 0,) {}
    |            ^^^^^^^^^
@@ -635,7 +635,7 @@ LL |     while (let 0 = 0,) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:268:16
+  --> $DIR/disallowed-positions.rs:272:16
    |
 LL |         while (let 0 = 0).await {}
    |                ^^^^^^^^^
@@ -643,7 +643,7 @@ LL |         while (let 0 = 0).await {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:272:15
+  --> $DIR/disallowed-positions.rs:276:15
    |
 LL |     while (|| let 0 = 0) {}
    |               ^^^
@@ -651,7 +651,7 @@ LL |     while (|| let 0 = 0) {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:275:12
+  --> $DIR/disallowed-positions.rs:279:12
    |
 LL |     while (let 0 = 0)() {}
    |            ^^^^^^^^^
@@ -659,7 +659,7 @@ LL |     while (let 0 = 0)() {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:292:6
+  --> $DIR/disallowed-positions.rs:296:6
    |
 LL |     &let 0 = 0;
    |      ^^^
@@ -667,7 +667,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:295:6
+  --> $DIR/disallowed-positions.rs:299:6
    |
 LL |     !let 0 = 0;
    |      ^^^
@@ -675,7 +675,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:297:6
+  --> $DIR/disallowed-positions.rs:301:6
    |
 LL |     *let 0 = 0;
    |      ^^^
@@ -683,7 +683,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:299:6
+  --> $DIR/disallowed-positions.rs:303:6
    |
 LL |     -let 0 = 0;
    |      ^^^
@@ -691,7 +691,7 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:301:13
+  --> $DIR/disallowed-positions.rs:305:13
    |
 LL |     let _ = let _ = 3;
    |             ^^^
@@ -699,7 +699,7 @@ LL |     let _ = let _ = 3;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:309:6
+  --> $DIR/disallowed-positions.rs:313:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^
@@ -707,7 +707,7 @@ LL |     (let 0 = 0)?;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:312:13
+  --> $DIR/disallowed-positions.rs:316:13
    |
 LL |     true || let 0 = 0;
    |             ^^^
@@ -715,7 +715,7 @@ LL |     true || let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:314:14
+  --> $DIR/disallowed-positions.rs:318:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^
@@ -723,7 +723,7 @@ LL |     (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:316:22
+  --> $DIR/disallowed-positions.rs:320:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^
@@ -731,7 +731,7 @@ LL |     true && (true || let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:324:9
    |
 LL |     x = let 0 = 0;
    |         ^^^
@@ -739,7 +739,7 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:323:12
+  --> $DIR/disallowed-positions.rs:327:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^
@@ -747,7 +747,7 @@ LL |     true..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:325:8
+  --> $DIR/disallowed-positions.rs:329:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^
@@ -755,7 +755,7 @@ LL |     ..(let 0 = 0);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:327:6
+  --> $DIR/disallowed-positions.rs:331:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^
@@ -763,7 +763,7 @@ LL |     (let 0 = 0)..;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:330:6
+  --> $DIR/disallowed-positions.rs:334:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^
@@ -771,7 +771,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:6
+  --> $DIR/disallowed-positions.rs:338:6
    |
 LL |     (let true = let true = true);
    |      ^^^
@@ -779,7 +779,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:334:17
+  --> $DIR/disallowed-positions.rs:338:17
    |
 LL |     (let true = let true = true);
    |                 ^^^
@@ -787,7 +787,7 @@ LL |     (let true = let true = true);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:340:25
+  --> $DIR/disallowed-positions.rs:344:25
    |
 LL |         let x = true && let y = 1;
    |                         ^^^
@@ -795,7 +795,7 @@ LL |         let x = true && let y = 1;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:346:19
+  --> $DIR/disallowed-positions.rs:350:19
    |
 LL |         [1, 2, 3][let _ = ()]
    |                   ^^^
@@ -803,7 +803,7 @@ LL |         [1, 2, 3][let _ = ()]
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:351:6
+  --> $DIR/disallowed-positions.rs:355:6
    |
 LL |     &let 0 = 0
    |      ^^^
@@ -811,7 +811,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:362:17
+  --> $DIR/disallowed-positions.rs:366:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -819,7 +819,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:367:17
+  --> $DIR/disallowed-positions.rs:371:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -827,7 +827,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:372:17
+  --> $DIR/disallowed-positions.rs:376:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -835,7 +835,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:383:17
+  --> $DIR/disallowed-positions.rs:387:17
    |
 LL |         true && let 1 = 1
    |                 ^^^
@@ -843,7 +843,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:383:9
+  --> $DIR/disallowed-positions.rs:387:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -854,124 +854,124 @@ LL |         { true && let 1 = 1 }
    |         +                   +
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:393:9
+  --> $DIR/disallowed-positions.rs:397:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:397:9
+  --> $DIR/disallowed-positions.rs:401:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:9
+  --> $DIR/disallowed-positions.rs:404:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:400:32
+  --> $DIR/disallowed-positions.rs:404:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:9
+  --> $DIR/disallowed-positions.rs:412:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:408:31
+  --> $DIR/disallowed-positions.rs:412:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:9
+  --> $DIR/disallowed-positions.rs:416:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:412:31
+  --> $DIR/disallowed-positions.rs:416:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:416:9
+  --> $DIR/disallowed-positions.rs:420:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:436:22
+  --> $DIR/disallowed-positions.rs:440:22
    |
 LL |     let x = (true && let y = 1);
    |                      ^^^
@@ -979,7 +979,7 @@ LL |     let x = (true && let y = 1);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: expected expression, found `let` statement
-  --> $DIR/disallowed-positions.rs:441:20
+  --> $DIR/disallowed-positions.rs:445:20
    |
 LL |         ([1, 2, 3][let _ = ()])
    |                    ^^^
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
index 8eb8d617d58..99f99c2be72 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -90,8 +90,12 @@ fn _macros() {
     }
     use_expr!((let 0 = 1 && 0 == 0));
     //[feature,no_feature]~^ ERROR expected expression, found `let` statement
+    //[feature,no_feature]~| ERROR expected expression, found `let` statement
+    //[feature,no_feature]~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //[feature,no_feature]~^ ERROR expected expression, found `let` statement
+    //[feature,no_feature]~| ERROR expected expression, found `let` statement
+    //[feature,no_feature]~| ERROR expected expression, found `let` statement
 }
 
 #[cfg(not(nothing))]
diff --git a/tests/ui/rmeta/no_optitimized_mir.rs b/tests/ui/rmeta/no_optitimized_mir.rs
index 7d2e1b87215..c8ed00b039b 100644
--- a/tests/ui/rmeta/no_optitimized_mir.rs
+++ b/tests/ui/rmeta/no_optitimized_mir.rs
@@ -9,3 +9,5 @@ extern crate rmeta_meta;
 fn main() {
     rmeta_meta::missing_optimized_mir();
 }
+
+//~? ERROR missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta`
diff --git a/tests/ui/rmeta/no_optitimized_mir.stderr b/tests/ui/rmeta/no_optitimized_mir.stderr
index 92f22d78000..254f100aa7b 100644
--- a/tests/ui/rmeta/no_optitimized_mir.stderr
+++ b/tests/ui/rmeta/no_optitimized_mir.stderr
@@ -1,4 +1,4 @@
-error: missing optimized MIR for an item in the crate `rmeta_meta`
+error: missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta`
    |
 note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled with `--emit=metadata`?)
   --> $DIR/auxiliary/rmeta-meta.rs:10:1
diff --git a/tests/ui/runtime/on-broken-pipe/default.rs b/tests/ui/runtime/on-broken-pipe/default.rs
index c10d1cfacc0..61b7810e2a1 100644
--- a/tests/ui/runtime/on-broken-pipe/default.rs
+++ b/tests/ui/runtime/on-broken-pipe/default.rs
@@ -2,3 +2,5 @@
 //@ check-fail
 
 fn main() {}
+
+//~? ERROR incorrect value `default` for unstable option `on-broken-pipe`
diff --git a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs
index 2273291bfa7..bb49533c023 100644
--- a/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs
+++ b/tests/ui/runtime/on-broken-pipe/no-flag-arg.rs
@@ -2,3 +2,5 @@
 //@ check-fail
 
 fn main() {}
+
+//~? ERROR unstable option `on-broken-pipe` requires either `kill`, `error`, or `inherit`
diff --git a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs
index 14d0ac56b5a..c4a07932bc2 100644
--- a/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs
+++ b/tests/ui/runtime/on-broken-pipe/wrong-flag-arg.rs
@@ -2,3 +2,5 @@
 //@ check-fail
 
 fn main() {}
+
+//~? ERROR incorrect value `wrong` for unstable option `on-broken-pipe`
diff --git a/tests/ui/rustc-env/min-stack-banana.rs b/tests/ui/rustc-env/min-stack-banana.rs
index abbb6843710..dfde277714b 100644
--- a/tests/ui/rustc-env/min-stack-banana.rs
+++ b/tests/ui/rustc-env/min-stack-banana.rs
@@ -1,2 +1,5 @@
 //@ rustc-env:RUST_MIN_STACK=banana
+
 fn main() {}
+
+//~? ERROR `RUST_MIN_STACK` should be a number of bytes, but was "banana"
diff --git a/tests/ui/rustc-error.rs b/tests/ui/rustc-error.rs
deleted file mode 100644
index 69d57948fb5..00000000000
--- a/tests/ui/rustc-error.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_error]
-fn main() {
-    //~^ ERROR fatal error triggered by #[rustc_error]
-}
diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr
deleted file mode 100644
index 67451195b64..00000000000
--- a/tests/ui/rustc-error.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/rustc-error.rs:4:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rustc-print-info-issue-138612.rs b/tests/ui/rustc-print-info-issue-138612.rs
deleted file mode 100644
index 65b595635b1..00000000000
--- a/tests/ui/rustc-print-info-issue-138612.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-//@ check-fail
-//@ compile-flags: /dev/null --print lints
diff --git a/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs
index 10c5bf6ea5e..36f6e3bc95e 100644
--- a/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs
+++ b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs
@@ -6,3 +6,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`
diff --git a/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs
index 8ba13bd3639..83277da528c 100644
--- a/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs
+++ b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs
@@ -7,3 +7,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
diff --git a/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs
index c628709d7a1..db8d1161644 100644
--- a/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs
+++ b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs
@@ -10,3 +10,6 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR cfi sanitizer is not supported for this target
+//~? ERROR `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
diff --git a/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs
index a7ecefbf7ef..b9d5b9623d5 100644
--- a/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs
+++ b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs
@@ -7,3 +7,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`
diff --git a/tests/ui/sanitizer/cfi/requires-lto.rs b/tests/ui/sanitizer/cfi/requires-lto.rs
index 5a34f696e05..db83f5f6bf0 100644
--- a/tests/ui/sanitizer/cfi/requires-lto.rs
+++ b/tests/ui/sanitizer/cfi/requires-lto.rs
@@ -6,3 +6,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`
diff --git a/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs
index 954e4ec3b85..4ef5b6756a4 100644
--- a/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs
+++ b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs
@@ -6,3 +6,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
diff --git a/tests/ui/sanitizer/crt-static.rs b/tests/ui/sanitizer/crt-static.rs
index c24faeca3dc..b8bdf28351c 100644
--- a/tests/ui/sanitizer/crt-static.rs
+++ b/tests/ui/sanitizer/crt-static.rs
@@ -4,3 +4,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR sanitizer is incompatible with statically linked libc
diff --git a/tests/ui/sanitizer/split-lto-unit-requires-lto.rs b/tests/ui/sanitizer/split-lto-unit-requires-lto.rs
index 35e610f0307..1d08ca7423f 100644
--- a/tests/ui/sanitizer/split-lto-unit-requires-lto.rs
+++ b/tests/ui/sanitizer/split-lto-unit-requires-lto.rs
@@ -6,3 +6,5 @@
 #![feature(no_core)]
 #![no_core]
 #![no_main]
+
+//~? ERROR `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`
diff --git a/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs
new file mode 100644
index 00000000000..2bc70de2a34
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/rust/issues/138937>.
+
+// Previously, we'd take the normalized param env's clauses which included
+// `<PF as TraitC>::Value = i32`, which comes from the supertraits of `TraitD`
+// after normalizing `<PF as TraitC>::Value = <PF as TraitD>::Scalar`. Since
+// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd
+// end up with both versions of this predicate (normalized and unnormalized).
+// Since these projections preds are not equal, we'd fail with ambiguity.
+
+trait TraitB<T> {}
+
+trait TraitC: TraitB<Self::Value> {
+    type Value;
+}
+
+trait TraitD: TraitC<Value = Self::Scalar> {
+    type Scalar;
+}
+
+trait TraitE {
+    fn apply<PF: TraitD<Scalar = i32>>(&self);
+}
+
+fn main() {}
diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs
new file mode 100644
index 00000000000..2a2a6c0737d
--- /dev/null
+++ b/tests/ui/simd/empty-simd-vector-in-operand.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #134224.
+//@ only-x86_64
+
+#![feature(repr_simd)]
+
+#[repr(simd)]
+struct A();
+//~^ ERROR SIMD vector cannot be empty
+
+fn main() {
+    unsafe {
+        std::arch::asm!("{}", in(xmm_reg) A());
+        //~^ use of empty SIMD vector `A`
+    }
+}
diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr
new file mode 100644
index 00000000000..7210dddd461
--- /dev/null
+++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr
@@ -0,0 +1,15 @@
+error[E0075]: SIMD vector cannot be empty
+  --> $DIR/empty-simd-vector-in-operand.rs:7:1
+   |
+LL | struct A();
+   | ^^^^^^^^
+
+error: use of empty SIMD vector `A`
+  --> $DIR/empty-simd-vector-in-operand.rs:12:43
+   |
+LL |         std::arch::asm!("{}", in(xmm_reg) A());
+   |                                           ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0075`.
diff --git a/tests/ui/sized/dont-incompletely-prefer-built-in.rs b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
new file mode 100644
index 00000000000..f5bf0c8915e
--- /dev/null
+++ b/tests/ui/sized/dont-incompletely-prefer-built-in.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+struct W<T: ?Sized>(T);
+
+fn is_sized<T: Sized>(x: *const T) {}
+
+fn dummy<T: ?Sized>() -> *const T { todo!() }
+
+fn non_param_where_bound<T: ?Sized>()
+where
+    W<T>: Sized,
+{
+    let x: *const W<_> = dummy();
+    is_sized::<W<_>>(x);
+    let _: *const W<T> = x;
+}
+
+fn main() {}
diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs
index c4bb16f44bd..2e8252169b7 100644
--- a/tests/ui/span/range-2.rs
+++ b/tests/ui/span/range-2.rs
@@ -1,6 +1,6 @@
 // Test range syntax - borrow errors.
-#![feature(rustc_attrs)]
-pub fn main() { #![rustc_error] // rust-lang/rust#49855
+
+pub fn main() {
     let r = {
         let a = 42;
         let b = 42;
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
index 60ccaa872e7..fe6c353e8f8 100644
--- a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs
@@ -1,7 +1,6 @@
-#![feature(rustc_attrs)]
 use std::ops::FnMut;
 
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     let mut f;
     {
         let c = 1;
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
index 225f83b6e66..bb6298211bc 100644
--- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `c` does not live long enough
-  --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21
+  --> $DIR/regionck-unboxed-closure-lifetimes.rs:7:21
    |
 LL |         let c = 1;
    |             - binding `c` declared here
diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout
index 21df1fd3954..12e7a5530ac 100644
--- a/tests/ui/stable-mir-print/async-closure.stdout
+++ b/tests/ui/stable-mir-print/async-closure.stdout
@@ -56,7 +56,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
         unreachable;
     }
 }
-fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
+fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
     let mut _0: Poll<()>;
     let  _3: i32;
     let mut _4: &i32;
diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs
index 9205d4052ad..dc61e35a089 100644
--- a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs
+++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs
@@ -17,3 +17,7 @@ trait Sized {}
 trait Copy {}
 
 pub fn main(){}
+
+//[all]~? WARN `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored
+//[strong]~? WARN `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored
+//[basic]~? WARN `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index dbc9e7d254c..24e38948647 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -10,9 +10,9 @@ ast-stats-1 - DocComment                32 ( 0.5%)             1
 ast-stats-1 - Normal                    32 ( 0.5%)             1
 ast-stats-1 WherePredicate            72 ( 1.1%)             1            72
 ast-stats-1 - BoundPredicate            72 ( 1.1%)             1
+ast-stats-1 ForeignItem               80 ( 1.2%)             1            80
+ast-stats-1 - Fn                        80 ( 1.2%)             1
 ast-stats-1 Local                     80 ( 1.2%)             1            80
-ast-stats-1 ForeignItem               88 ( 1.3%)             1            88
-ast-stats-1 - Fn                        88 ( 1.3%)             1
 ast-stats-1 Arm                       96 ( 1.4%)             2            48
 ast-stats-1 FnDecl                   120 ( 1.8%)             5            24
 ast-stats-1 Param                    160 ( 2.4%)             4            40
@@ -23,37 +23,37 @@ ast-stats-1 - Expr                      96 ( 1.4%)             3
 ast-stats-1 Block                    192 ( 2.9%)             6            32
 ast-stats-1 FieldDef                 208 ( 3.1%)             2           104
 ast-stats-1 Variant                  208 ( 3.1%)             2           104
-ast-stats-1 AssocItem                352 ( 5.3%)             4            88
-ast-stats-1 - Fn                       176 ( 2.6%)             2
-ast-stats-1 - Type                     176 ( 2.6%)             2
-ast-stats-1 GenericBound             352 ( 5.3%)             4            88
-ast-stats-1 - Trait                    352 ( 5.3%)             4
-ast-stats-1 GenericParam             480 ( 7.2%)             5            96
+ast-stats-1 AssocItem                320 ( 4.8%)             4            80
+ast-stats-1 - Fn                       160 ( 2.4%)             2
+ast-stats-1 - Type                     160 ( 2.4%)             2
+ast-stats-1 GenericBound             352 ( 5.2%)             4            88
+ast-stats-1 - Trait                    352 ( 5.2%)             4
+ast-stats-1 GenericParam             480 ( 7.1%)             5            96
 ast-stats-1 Pat                      504 ( 7.5%)             7            72
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Wild                      72 ( 1.1%)             1
-ast-stats-1 - Ident                    360 ( 5.4%)             5
+ast-stats-1 - Ident                    360 ( 5.3%)             5
 ast-stats-1 Expr                     576 ( 8.6%)             8            72
 ast-stats-1 - Match                     72 ( 1.1%)             1
 ast-stats-1 - Path                      72 ( 1.1%)             1
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Lit                      144 ( 2.1%)             2
 ast-stats-1 - Block                    216 ( 3.2%)             3
-ast-stats-1 PathSegment              744 (11.1%)            31            24
-ast-stats-1 Ty                       896 (13.4%)            14            64
+ast-stats-1 PathSegment              744 (11.0%)            31            24
+ast-stats-1 Ty                       896 (13.3%)            14            64
 ast-stats-1 - Ptr                       64 ( 1.0%)             1
 ast-stats-1 - Ref                       64 ( 1.0%)             1
 ast-stats-1 - ImplicitSelf             128 ( 1.9%)             2
 ast-stats-1 - Path                     640 ( 9.5%)            10
-ast-stats-1 Item                   1_224 (18.3%)             9           136
-ast-stats-1 - Enum                     136 ( 2.0%)             1
-ast-stats-1 - ForeignMod               136 ( 2.0%)             1
-ast-stats-1 - Impl                     136 ( 2.0%)             1
-ast-stats-1 - Trait                    136 ( 2.0%)             1
-ast-stats-1 - Fn                       272 ( 4.1%)             2
-ast-stats-1 - Use                      408 ( 6.1%)             3
+ast-stats-1 Item                   1_296 (19.2%)             9           144
+ast-stats-1 - Enum                     144 ( 2.1%)             1
+ast-stats-1 - ForeignMod               144 ( 2.1%)             1
+ast-stats-1 - Impl                     144 ( 2.1%)             1
+ast-stats-1 - Trait                    144 ( 2.1%)             1
+ast-stats-1 - Fn                       288 ( 4.3%)             2
+ast-stats-1 - Use                      432 ( 6.4%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_704                   116
+ast-stats-1 Total                  6_736                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -61,12 +61,12 @@ ast-stats-2 ----------------------------------------------------------------
 ast-stats-2 Crate                     40 ( 0.5%)             1            40
 ast-stats-2 GenericArgs               40 ( 0.5%)             1            40
 ast-stats-2 - AngleBracketed            40 ( 0.5%)             1
-ast-stats-2 ExprField                 48 ( 0.7%)             1            48
+ast-stats-2 ExprField                 48 ( 0.6%)             1            48
 ast-stats-2 WherePredicate            72 ( 1.0%)             1            72
 ast-stats-2 - BoundPredicate            72 ( 1.0%)             1
+ast-stats-2 ForeignItem               80 ( 1.1%)             1            80
+ast-stats-2 - Fn                        80 ( 1.1%)             1
 ast-stats-2 Local                     80 ( 1.1%)             1            80
-ast-stats-2 ForeignItem               88 ( 1.2%)             1            88
-ast-stats-2 - Fn                        88 ( 1.2%)             1
 ast-stats-2 Arm                       96 ( 1.3%)             2            48
 ast-stats-2 FnDecl                   120 ( 1.6%)             5            24
 ast-stats-2 InlineAsm                120 ( 1.6%)             1           120
@@ -81,13 +81,13 @@ ast-stats-2 - Expr                      96 ( 1.3%)             3
 ast-stats-2 Block                    192 ( 2.6%)             6            32
 ast-stats-2 FieldDef                 208 ( 2.8%)             2           104
 ast-stats-2 Variant                  208 ( 2.8%)             2           104
-ast-stats-2 AssocItem                352 ( 4.8%)             4            88
-ast-stats-2 - Fn                       176 ( 2.4%)             2
-ast-stats-2 - Type                     176 ( 2.4%)             2
+ast-stats-2 AssocItem                320 ( 4.3%)             4            80
+ast-stats-2 - Fn                       160 ( 2.2%)             2
+ast-stats-2 - Type                     160 ( 2.2%)             2
 ast-stats-2 GenericBound             352 ( 4.8%)             4            88
 ast-stats-2 - Trait                    352 ( 4.8%)             4
 ast-stats-2 GenericParam             480 ( 6.5%)             5            96
-ast-stats-2 Pat                      504 ( 6.9%)             7            72
+ast-stats-2 Pat                      504 ( 6.8%)             7            72
 ast-stats-2 - Struct                    72 ( 1.0%)             1
 ast-stats-2 - Wild                      72 ( 1.0%)             1
 ast-stats-2 - Ident                    360 ( 4.9%)             5
@@ -96,30 +96,30 @@ ast-stats-2 - InlineAsm                 72 ( 1.0%)             1
 ast-stats-2 - Match                     72 ( 1.0%)             1
 ast-stats-2 - Path                      72 ( 1.0%)             1
 ast-stats-2 - Struct                    72 ( 1.0%)             1
-ast-stats-2 - Lit                      144 ( 2.0%)             2
+ast-stats-2 - Lit                      144 ( 1.9%)             2
 ast-stats-2 - Block                    216 ( 2.9%)             3
-ast-stats-2 PathSegment              864 (11.8%)            36            24
-ast-stats-2 Ty                       896 (12.2%)            14            64
+ast-stats-2 PathSegment              864 (11.7%)            36            24
+ast-stats-2 Ty                       896 (12.1%)            14            64
 ast-stats-2 - Ptr                       64 ( 0.9%)             1
 ast-stats-2 - Ref                       64 ( 0.9%)             1
 ast-stats-2 - ImplicitSelf             128 ( 1.7%)             2
-ast-stats-2 - Path                     640 ( 8.7%)            10
-ast-stats-2 Item                   1_496 (20.3%)            11           136
-ast-stats-2 - Enum                     136 ( 1.8%)             1
-ast-stats-2 - ExternCrate              136 ( 1.8%)             1
-ast-stats-2 - ForeignMod               136 ( 1.8%)             1
-ast-stats-2 - Impl                     136 ( 1.8%)             1
-ast-stats-2 - Trait                    136 ( 1.8%)             1
-ast-stats-2 - Fn                       272 ( 3.7%)             2
-ast-stats-2 - Use                      544 ( 7.4%)             4
+ast-stats-2 - Path                     640 ( 8.6%)            10
+ast-stats-2 Item                   1_584 (21.4%)            11           144
+ast-stats-2 - Enum                     144 ( 1.9%)             1
+ast-stats-2 - ExternCrate              144 ( 1.9%)             1
+ast-stats-2 - ForeignMod               144 ( 1.9%)             1
+ast-stats-2 - Impl                     144 ( 1.9%)             1
+ast-stats-2 - Trait                    144 ( 1.9%)             1
+ast-stats-2 - Fn                       288 ( 3.9%)             2
+ast-stats-2 - Use                      576 ( 7.8%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_352                   127
+ast-stats-2 Total                  7_400                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
 hir-stats ----------------------------------------------------------------
 hir-stats ForeignItemRef            24 ( 0.3%)             1            24
-hir-stats Lifetime                  24 ( 0.3%)             1            24
+hir-stats Lifetime                  28 ( 0.3%)             1            28
 hir-stats Mod                       32 ( 0.4%)             1            32
 hir-stats ExprField                 40 ( 0.4%)             1            40
 hir-stats TraitItemRef              56 ( 0.6%)             2            28
@@ -155,7 +155,7 @@ 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 ( 7.0%)            13
+hir-stats - Path                     624 ( 6.9%)            13
 hir-stats Expr                     768 ( 8.6%)            12            64
 hir-stats - InlineAsm                 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_976                   180
+hir-stats Total                  8_980                   180
 hir-stats
diff --git a/tests/ui/std/channel-stack-overflow-issue-102246.rs b/tests/ui/std/channel-stack-overflow-issue-102246.rs
index 984ebdd553f..7bf6647bdc5 100644
--- a/tests/ui/std/channel-stack-overflow-issue-102246.rs
+++ b/tests/ui/std/channel-stack-overflow-issue-102246.rs
@@ -10,9 +10,16 @@
 // Ref: https://github.com/rust-lang/rust/issues/102246
 
 use std::sync::mpsc::channel;
-use std::thread;
+use std::thread::Builder;
 
 const N: usize = 32_768;
+const SLOTS: usize = 32;
+// Use a stack size that's smaller than N * SLOTS, proving the allocation is on the heap.
+//
+// The test explicitly specifies the stack size, because not all platforms have the same default
+// size.
+const STACK_SIZE: usize = (N*SLOTS) - 1;
+
 struct BigStruct {
     _data: [u8; N],
 }
@@ -20,10 +27,13 @@ struct BigStruct {
 fn main() {
     let (sender, receiver) = channel::<BigStruct>();
 
-    let thread1 = thread::spawn(move || {
+    let thread1 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
         sender.send(BigStruct { _data: [0u8; N] }).unwrap();
-    });
-
+    }).expect("thread1 should spawn successfully");
     thread1.join().unwrap();
-    for _data in receiver.try_iter() {}
+
+    let thread2 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
+        for _data in receiver.try_iter() {}
+    }).expect("thread2 should spawn successfully");
+    thread2.join().unwrap();
 }
diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.rs b/tests/ui/structs/struct-construct-with-call-issue-138931.rs
new file mode 100644
index 00000000000..5d50eb14bff
--- /dev/null
+++ b/tests/ui/structs/struct-construct-with-call-issue-138931.rs
@@ -0,0 +1,25 @@
+struct PersonOnlyName {
+    name: String
+}
+
+struct PersonWithAge {
+    name: String,
+    age: u8,
+    height: u8,
+}
+
+
+
+fn main() {
+    let wilfred = PersonOnlyName("Name1".to_owned());
+    //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonOnlyName` [E0423]
+
+    let bill = PersonWithAge( //~ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423]
+        "Name2".to_owned(),
+        20,
+        180,
+    );
+
+    let person = PersonWithAge("Name3".to_owned());
+    //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423]
+}
diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr
new file mode 100644
index 00000000000..acae01df563
--- /dev/null
+++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr
@@ -0,0 +1,58 @@
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonOnlyName`
+  --> $DIR/struct-construct-with-call-issue-138931.rs:14:19
+   |
+LL | / struct PersonOnlyName {
+LL | |     name: String
+LL | | }
+   | |_- `PersonOnlyName` defined here
+...
+LL |       let wilfred = PersonOnlyName("Name1".to_owned());
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use struct literal syntax instead of calling
+   |
+LL -     let wilfred = PersonOnlyName("Name1".to_owned());
+LL +     let wilfred = PersonOnlyName{name: "Name1".to_owned()};
+   |
+
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge`
+  --> $DIR/struct-construct-with-call-issue-138931.rs:17:16
+   |
+LL | / struct PersonWithAge {
+LL | |     name: String,
+LL | |     age: u8,
+LL | |     height: u8,
+LL | | }
+   | |_- `PersonWithAge` defined here
+...
+LL |       let bill = PersonWithAge(
+   |  ________________^
+LL | |         "Name2".to_owned(),
+LL | |         20,
+LL | |         180,
+LL | |     );
+   | |_____^
+   |
+help: use struct literal syntax instead of calling
+   |
+LL ~     let bill = PersonWithAge{name: "Name2".to_owned(),
+LL ~         age: 20,
+LL ~         height: 180};
+   |
+
+error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge`
+  --> $DIR/struct-construct-with-call-issue-138931.rs:23:18
+   |
+LL | / struct PersonWithAge {
+LL | |     name: String,
+LL | |     age: u8,
+LL | |     height: u8,
+LL | | }
+   | |_- `PersonWithAge` defined here
+...
+LL |       let person = PersonWithAge("Name3".to_owned());
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs
index 7c8231bbb24..4c2336e105e 100644
--- a/tests/ui/suggestions/attribute-typos.rs
+++ b/tests/ui/suggestions/attribute-typos.rs
@@ -4,8 +4,8 @@ fn foo() {}
 #[tests] //~ ERROR cannot find attribute `tests` in this scope
 fn bar() {}
 
-#[rustc_err]
-//~^ ERROR cannot find attribute `rustc_err` in this scope
+#[rustc_dumm]
+//~^ ERROR cannot find attribute `rustc_dumm` in this scope
 //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
 
 fn main() {}
diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr
index b871c9b45a5..a1a01c0abd6 100644
--- a/tests/ui/suggestions/attribute-typos.stderr
+++ b/tests/ui/suggestions/attribute-typos.stderr
@@ -1,14 +1,14 @@
 error: attributes starting with `rustc` are reserved for use by the `rustc` compiler
   --> $DIR/attribute-typos.rs:7:3
    |
-LL | #[rustc_err]
-   |   ^^^^^^^^^
+LL | #[rustc_dumm]
+   |   ^^^^^^^^^^
 
-error: cannot find attribute `rustc_err` in this scope
+error: cannot find attribute `rustc_dumm` in this scope
   --> $DIR/attribute-typos.rs:7:3
    |
-LL | #[rustc_err]
-   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error`
+LL | #[rustc_dumm]
+   |   ^^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_dummy`
 
 error: cannot find attribute `tests` in this scope
   --> $DIR/attribute-typos.rs:4:3
diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs
new file mode 100644
index 00000000000..b7086325d5f
--- /dev/null
+++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs
@@ -0,0 +1,17 @@
+// Verify that the `where` clause suggestion is in the correct place
+// Previously, the suggestion to add `where` clause was placed inside the derive
+// like `#[derive(Clone where Inner<T>: Clone)]`
+// instead of `struct Outer<T>(Inner<T>) where Inner<T>: Clone`
+
+#![crate_type = "lib"]
+
+struct Inner<T>(T);
+//~^ HELP consider annotating `Inner<T>` with `#[derive(Clone)]`
+impl Clone for Inner<()> {
+    fn clone(&self) -> Self { todo!() }
+}
+
+#[derive(Clone)]
+struct Outer<T>(Inner<T>);
+//~^ ERROR the trait bound `Inner<T>: Clone` is not satisfied [E0277]
+//~| HELP consider introducing a `where` clause
diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr
new file mode 100644
index 00000000000..577b090ce1b
--- /dev/null
+++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Inner<T>: Clone` is not satisfied
+  --> $DIR/tuple-struct-where-clause-suggestion-91520.rs:15:17
+   |
+LL | #[derive(Clone)]
+   |          ----- in this derive macro expansion
+LL | struct Outer<T>(Inner<T>);
+   |                 ^^^^^^^^ the trait `Clone` is not implemented for `Inner<T>`
+   |
+help: consider annotating `Inner<T>` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct Inner<T>(T);
+   |
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | struct Outer<T>(Inner<T>) where Inner<T>: Clone;
+   |                           +++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/symbol-mangling-version/bad-value.rs b/tests/ui/symbol-mangling-version/bad-value.rs
index f6fa5c85f33..b0875f3a23c 100644
--- a/tests/ui/symbol-mangling-version/bad-value.rs
+++ b/tests/ui/symbol-mangling-version/bad-value.rs
@@ -4,3 +4,7 @@
 //@ [bad] compile-flags: -Csymbol-mangling-version=bad-value
 
 fn main() {}
+
+//[no-value]~? ERROR codegen option `symbol-mangling-version` requires one of
+//[blank]~? ERROR incorrect value `` for codegen option `symbol-mangling-version`
+//[bad]~? ERROR incorrect value `bad-value` for codegen option `symbol-mangling-version`
diff --git a/tests/ui/symbol-mangling-version/unstable.rs b/tests/ui/symbol-mangling-version/unstable.rs
index d5af8542996..d79320ccccd 100644
--- a/tests/ui/symbol-mangling-version/unstable.rs
+++ b/tests/ui/symbol-mangling-version/unstable.rs
@@ -7,3 +7,6 @@
 //@ [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed
 
 fn main() {}
+
+//[legacy]~? ERROR `-C symbol-mangling-version=legacy` requires `-Z unstable-options`
+//[hashed]~? ERROR `-C symbol-mangling-version=hashed` requires `-Z unstable-options`
diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs
index e34faf5a983..7368ef120fa 100644
--- a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs
+++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs
@@ -7,3 +7,5 @@
 
 #[lang = "sized"]
 pub trait Sized {}
+
+//~? WARN unstable feature specified for `-Ctarget-feature`: `x87`
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index dc8a5304164..05ae49d6b0d 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -98,6 +98,12 @@ LL |
 LL | trait Baz {}
    | ------------ not a function definition
 
+error: cannot use `#[inline(always)]` with `#[target_feature]`
+  --> $DIR/invalid-attribute.rs:69:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+
 error: attribute should be applied to a function definition
   --> $DIR/invalid-attribute.rs:74:1
    |
@@ -163,12 +169,6 @@ error: malformed `target_feature` attribute input
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
 
-error: cannot use `#[inline(always)]` with `#[target_feature]`
-  --> $DIR/invalid-attribute.rs:69:1
-   |
-LL | #[inline(always)]
-   | ^^^^^^^^^^^^^^^^^
-
 error[E0046]: not all trait items implemented, missing: `foo`
   --> $DIR/invalid-attribute.rs:81:1
    |
diff --git a/tests/ui/target-feature/missing-plusminus-2.rs b/tests/ui/target-feature/missing-plusminus-2.rs
index 19f4bc6e724..06291ab23ad 100644
--- a/tests/ui/target-feature/missing-plusminus-2.rs
+++ b/tests/ui/target-feature/missing-plusminus-2.rs
@@ -4,3 +4,5 @@
 
 #![feature(no_core)]
 #![no_core]
+
+//~? WARN unknown feature specified for `-Ctarget-feature`: `rdrand`
diff --git a/tests/ui/target-feature/missing-plusminus.rs b/tests/ui/target-feature/missing-plusminus.rs
index eb3e93c2ef7..e8356e0fa35 100644
--- a/tests/ui/target-feature/missing-plusminus.rs
+++ b/tests/ui/target-feature/missing-plusminus.rs
@@ -1,2 +1,4 @@
 //@ compile-flags: -Ctarget-feature=banana --crate-type=rlib
 //@ build-pass
+
+//~? WARN unknown feature specified for `-Ctarget-feature`: `banana`
diff --git a/tests/ui/target-feature/similar-feature-suggestion.rs b/tests/ui/target-feature/similar-feature-suggestion.rs
index 242d472b794..b82d7e408c7 100644
--- a/tests/ui/target-feature/similar-feature-suggestion.rs
+++ b/tests/ui/target-feature/similar-feature-suggestion.rs
@@ -4,3 +4,5 @@
 
 #![feature(no_core)]
 #![no_core]
+
+//~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd`
diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs
index 17c13826ce9..ce1dc3224a1 100644
--- a/tests/ui/target-feature/tied-features-cli.rs
+++ b/tests/ui/target-feature/tied-features-cli.rs
@@ -18,3 +18,7 @@
 trait Sized {}
 
 fn main() {}
+
+//[one]~? ERROR the target features paca, pacg must all be either enabled or disabled together
+//[two]~? ERROR the target features paca, pacg must all be either enabled or disabled together
+//[three]~? ERROR the target features paca, pacg must all be either enabled or disabled together
diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs
index 0473ca319b8..0a98a7eeccf 100644
--- a/tests/ui/target-feature/tied-features-no-implication-1.rs
+++ b/tests/ui/target-feature/tied-features-no-implication-1.rs
@@ -18,3 +18,5 @@ trait Sized {}
 #[cfg(target_feature = "pacg")]
 pub unsafe fn foo() {
 }
+
+//~? ERROR the target features paca, pacg must all be either enabled or disabled together
diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs
index c74c5ad5d77..f62c4dd938a 100644
--- a/tests/ui/target-feature/unstable-feature.rs
+++ b/tests/ui/target-feature/unstable-feature.rs
@@ -4,3 +4,5 @@
 
 #![feature(no_core)]
 #![no_core]
+
+//~? WARN unstable feature specified for `-Ctarget-feature`: `vaes`
diff --git a/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs b/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs
new file mode 100644
index 00000000000..4bda4ba24c5
--- /dev/null
+++ b/tests/ui/target_modifiers/auxiliary/enabled_reg_struct_return.rs
@@ -0,0 +1,7 @@
+//@ no-prefer-dynamic
+//@ compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return=true
+//@ needs-llvm-components: x86
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
diff --git a/tests/ui/target_modifiers/defaults_check.error.stderr b/tests/ui/target_modifiers/defaults_check.error.stderr
index 4833fe90677..936fbbc94d6 100644
--- a/tests/ui/target_modifiers/defaults_check.error.stderr
+++ b/tests/ui/target_modifiers/defaults_check.error.stderr
@@ -5,8 +5,8 @@ LL | #![feature(no_core)]
    | ^
    |
    = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
-   = note: `-Zreg-struct-return=true` in this crate is incompatible with `-Zreg-struct-return=` in dependency `default_reg_struct_return`
-   = help: set `-Zreg-struct-return=` in this crate or `-Zreg-struct-return=true` in `default_reg_struct_return`
+   = note: `-Zreg-struct-return=true` in this crate is incompatible with unset `-Zreg-struct-return` in dependency `default_reg_struct_return`
+   = help: unset `-Zreg-struct-return` in this crate or set `-Zreg-struct-return=true` in `default_reg_struct_return`
    = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/target_modifiers/incompatible_regparm.rs b/tests/ui/target_modifiers/incompatible_regparm.rs
index befe573b276..395c26fc2c0 100644
--- a/tests/ui/target_modifiers/incompatible_regparm.rs
+++ b/tests/ui/target_modifiers/incompatible_regparm.rs
@@ -14,3 +14,5 @@
 #![no_core]
 
 extern crate wrong_regparm;
+
+//[allow_no_value]~? ERROR codegen option `unsafe-allow-abi-mismatch` requires a comma-separated list of strings
diff --git a/tests/ui/target_modifiers/no_value_bool.error.stderr b/tests/ui/target_modifiers/no_value_bool.error.stderr
new file mode 100644
index 00000000000..0484960dc62
--- /dev/null
+++ b/tests/ui/target_modifiers/no_value_bool.error.stderr
@@ -0,0 +1,13 @@
+error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
+  --> $DIR/no_value_bool.rs:16:1
+   |
+LL | #![feature(no_core)]
+   | ^
+   |
+   = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
+   = note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return`
+   = help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return`
+   = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr b/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr
new file mode 100644
index 00000000000..0484960dc62
--- /dev/null
+++ b/tests/ui/target_modifiers/no_value_bool.error_explicit.stderr
@@ -0,0 +1,13 @@
+error: mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
+  --> $DIR/no_value_bool.rs:16:1
+   |
+LL | #![feature(no_core)]
+   | ^
+   |
+   = help: the `-Zreg-struct-return` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
+   = note: unset `-Zreg-struct-return` in this crate is incompatible with `-Zreg-struct-return=true` in dependency `enabled_reg_struct_return`
+   = help: set `-Zreg-struct-return=true` in this crate or unset `-Zreg-struct-return` in `enabled_reg_struct_return`
+   = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=reg-struct-return` to silence this error
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/target_modifiers/no_value_bool.rs b/tests/ui/target_modifiers/no_value_bool.rs
new file mode 100644
index 00000000000..ceba40afa89
--- /dev/null
+++ b/tests/ui/target_modifiers/no_value_bool.rs
@@ -0,0 +1,22 @@
+// Tests that bool target modifier value (true) in dependency crate is ok linked
+// with the -Zflag specified without value (-Zflag=true is consistent with -Zflag)
+
+//@ aux-build:enabled_reg_struct_return.rs
+//@ compile-flags: --target i686-unknown-linux-gnu -Cpanic=abort
+//@ needs-llvm-components: x86
+
+//@ revisions: ok ok_explicit error error_explicit
+//@[ok] compile-flags: -Zreg-struct-return
+//@[ok_explicit] compile-flags: -Zreg-struct-return=true
+//@[error] compile-flags:
+//@[error_explicit] compile-flags: -Zreg-struct-return=false
+//@[ok] check-pass
+//@[ok_explicit] check-pass
+
+#![feature(no_core)]
+//[error]~^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
+//[error_explicit]~^^ ERROR mixing `-Zreg-struct-return` will cause an ABI mismatch in crate `no_value_bool`
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate enabled_reg_struct_return;
diff --git a/tests/ui/thread-local/spawn-hook-atexit.rs b/tests/ui/thread-local/spawn-hook-atexit.rs
new file mode 100644
index 00000000000..b084e0bb387
--- /dev/null
+++ b/tests/ui/thread-local/spawn-hook-atexit.rs
@@ -0,0 +1,24 @@
+// Regression test for https://github.com/rust-lang/rust/issues/138696
+//@ only-unix
+//@ needs-threads
+//@ run-pass
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+fn main() {
+    std::thread::spawn(|| {
+        unsafe { libc::atexit(spawn_in_atexit) };
+    })
+    .join()
+    .unwrap();
+}
+
+extern "C" fn spawn_in_atexit() {
+    std::thread::spawn(|| {
+        println!("Thread spawned in atexit");
+    })
+    .join()
+    .unwrap();
+}
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.rs b/tests/ui/tool-attributes/duplicate-diagnostic.rs
index 5061bcb9e44..c36179611af 100644
--- a/tests/ui/tool-attributes/duplicate-diagnostic.rs
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.rs
@@ -1,13 +1,14 @@
 //@ aux-build: p1.rs
 //@ aux-build: p2.rs
 
-//@ error-pattern: duplicate diagnostic item in crate `p2`
-//@ error-pattern: note: the diagnostic item is first defined in crate `p1`
-
 #![feature(rustc_attrs)]
 extern crate p1;
 extern crate p2;
 
 #[rustc_diagnostic_item = "Foo"]
 pub struct Foo {} //~ ERROR duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`
+                  //~^ NOTE the diagnostic item is first defined in crate `p2`
 fn main() {}
+
+//~? ERROR duplicate diagnostic item in crate `p2`
+//~? NOTE the diagnostic item is first defined in crate `p1`
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
index 3cd438004c8..16d78d03ae9 100644
--- a/tests/ui/tool-attributes/duplicate-diagnostic.stderr
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
@@ -3,7 +3,7 @@ error: duplicate diagnostic item in crate `p2`: `Foo`
    = note: the diagnostic item is first defined in crate `p1`
 
 error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`
-  --> $DIR/duplicate-diagnostic.rs:12:1
+  --> $DIR/duplicate-diagnostic.rs:9:1
    |
 LL | pub struct Foo {}
    | ^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/feature-gate.gated.stderr b/tests/ui/traits/const-traits/feature-gate.gated.stderr
deleted file mode 100644
index 12f9355e41d..00000000000
--- a/tests/ui/traits/const-traits/feature-gate.gated.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate.rs:22:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs
index c36ec3538c3..921dfb054e3 100644
--- a/tests/ui/traits/const-traits/feature-gate.rs
+++ b/tests/ui/traits/const-traits/feature-gate.rs
@@ -1,8 +1,8 @@
 //@ revisions: stock gated
+//@[gated] check-pass
 // gate-test-const_trait_impl
 
 #![cfg_attr(gated, feature(const_trait_impl))]
-#![feature(rustc_attrs)]
 
 struct S;
 #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
@@ -18,5 +18,4 @@ macro_rules! discard { ($ty:ty) => {} }
 discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental
 discard! { impl const T } //[stock]~ ERROR const trait impls are experimental
 
-#[rustc_error]
-fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
+fn main() {}
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
new file mode 100644
index 00000000000..f4930bf890c
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+   |
+LL |     is_sized::<MaybeSized<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
new file mode 100644
index 00000000000..f4930bf890c
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/incomplete-infer-via-sized-wc.rs:15:5
+   |
+LL |     is_sized::<MaybeSized<_>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.rs b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
new file mode 100644
index 00000000000..9dcddea3551
--- /dev/null
+++ b/tests/ui/traits/incomplete-infer-via-sized-wc.rs
@@ -0,0 +1,19 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MaybeSized<T: ?Sized>(T);
+
+fn is_sized<T: Sized>() -> Box<T> { todo!() }
+
+fn foo<T: ?Sized>()
+where
+    MaybeSized<T>: Sized,
+{
+    is_sized::<MaybeSized<_>>();
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
new file mode 100644
index 00000000000..8a8f7b933b5
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+trait Trait<T>: Sized {}
+impl<T> Trait<T> for T {}
+
+fn is_sized<T: Sized>() {}
+
+fn normal_ref<'a, 'b, T>()
+where
+    &'a u32: Trait<T>,
+{
+    is_sized::<&'b u32>();
+}
+
+struct MyRef<'a, U: ?Sized = ()>(&'a u32, U);
+fn my_ref<'a, 'b, T>()
+where
+    MyRef<'a>: Trait<T>,
+{
+    is_sized::<MyRef<'b>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
new file mode 100644
index 00000000000..dd9393fae85
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr
@@ -0,0 +1,27 @@
+error[E0308]: mismatched types
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+   |
+LL |     (MyType<'a, T>,): Sized,
+   |                       ^^^^^ lifetime mismatch
+   |
+   = note: expected trait `<MyType<'a, T> as Sized>`
+              found trait `<MyType<'static, T> as Sized>`
+note: the lifetime `'a` as defined here...
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+   |
+LL | fn foo<'a, T: ?Sized>()
+   |        ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: lifetime may not live long enough
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+   |
+LL | fn foo<'a, T: ?Sized>()
+   |        -- lifetime `'a` defined here
+...
+LL |     is_sized::<(MyType<'a, T>,)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
new file mode 100644
index 00000000000..05861877d41
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr
@@ -0,0 +1,25 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23
+   |
+LL |     (MyType<'a, T>,): Sized,
+   |                       ^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8
+   |
+LL | fn foo<'a, T: ?Sized>()
+   |        ^^
+   = note: but lifetime parameter must outlive the static lifetime
+
+error: lifetime may not live long enough
+  --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5
+   |
+LL | fn foo<'a, T: ?Sized>()
+   |        -- lifetime `'a` defined here
+...
+LL |     is_sized::<(MyType<'a, T>,)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
new file mode 100644
index 00000000000..ae7a6c9bba3
--- /dev/null
+++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs
@@ -0,0 +1,26 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Exercises change in <https://github.com/rust-lang/rust/pull/138176>.
+
+struct MyType<'a, T: ?Sized>(&'a (), T);
+
+fn is_sized<T>() {}
+
+fn foo<'a, T: ?Sized>()
+where
+    (MyType<'a, T>,): Sized,
+    //[current]~^ ERROR mismatched types
+    //[next]~^^ ERROR lifetime bound not satisfied
+    MyType<'static, T>: Sized,
+{
+    // Preferring the builtin `Sized` impl of tuples
+    // requires proving `MyType<'a, T>: Sized` which
+    // can only be proven by using the where-clause,
+    // adding an unnecessary `'static` constraint.
+    is_sized::<(MyType<'a, T>,)>();
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr
index 272c56301bc..9e8eb1adb11 100644
--- a/tests/ui/traits/mutual-recursion-issue-75860.stderr
+++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr
@@ -2,7 +2,7 @@ error[E0275]: overflow assigning `_` to `Option<_>`
   --> $DIR/mutual-recursion-issue-75860.rs:9:33
    |
 LL |     let left = |o_a: Option<_>| o_a.unwrap();
-   |                                 ^^^
+   |                                 ^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.rs b/tests/ui/traits/next-solver/well-formed-in-relate.rs
new file mode 100644
index 00000000000..eec1ddef228
--- /dev/null
+++ b/tests/ui/traits/next-solver/well-formed-in-relate.rs
@@ -0,0 +1,21 @@
+fn main() {
+    let x;
+    //~^ ERROR type annotations needed for `Map<_, _>`
+    higher_ranked();
+    x = unconstrained_map();
+}
+
+fn higher_ranked() where for<'a> &'a (): Sized {}
+
+struct Map<T, U> where T: Fn() -> U {
+    t: T,
+}
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+fn unconstrained_map<T: Fn() -> U, U>() -> <Map<T, U> as Mirror>::Assoc { todo!() }
diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.stderr b/tests/ui/traits/next-solver/well-formed-in-relate.stderr
new file mode 100644
index 00000000000..5294a072d31
--- /dev/null
+++ b/tests/ui/traits/next-solver/well-formed-in-relate.stderr
@@ -0,0 +1,27 @@
+error[E0283]: type annotations needed for `Map<_, _>`
+  --> $DIR/well-formed-in-relate.rs:2:9
+   |
+LL |     let x;
+   |         ^
+...
+LL |     x = unconstrained_map();
+   |         ------------------- type must be known at this point
+   |
+   = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`:
+           - impl<A, F> Fn<A> for &F
+             where A: Tuple, F: Fn<A>, F: ?Sized;
+           - impl<Args, F, A> Fn<Args> for Box<F, A>
+             where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
+note: required by a bound in `unconstrained_map`
+  --> $DIR/well-formed-in-relate.rs:21:25
+   |
+LL | fn unconstrained_map<T: Fn() -> U, U>() -> <Map<T, U> as Mirror>::Assoc { todo!() }
+   |                         ^^^^^^^^^ required by this bound in `unconstrained_map`
+help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let x: Map<T, U>;
+   |          +++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
new file mode 100644
index 00000000000..f8fa410b7d4
--- /dev/null
+++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
@@ -0,0 +1,24 @@
+//@compile-flags: --edition 2021
+
+fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+    //~^ ERROR expected trait, found builtin type `usize`
+    //~| ERROR expected a type, found a trait [E0782]
+    0
+}
+
+fn create_adder<'a>(x: i32) -> usize + 'a {
+    //~^ ERROR expected trait, found builtin type `usize`
+    //~| ERROR expected a type, found a trait [E0782]
+    move |y| x + y
+}
+
+struct Struct<'a>{
+    x: usize + 'a,
+    //~^ ERROR expected trait, found builtin type `usize`
+    //~| ERROR expected a type, found a trait [E0782]
+}
+
+
+fn main() {
+
+}
diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr
new file mode 100644
index 00000000000..0d1ce85fc28
--- /dev/null
+++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr
@@ -0,0 +1,40 @@
+error[E0404]: expected trait, found builtin type `usize`
+  --> $DIR/suggestion-trait-object-issue-139174.rs:3:36
+   |
+LL | fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+   |                                    ^^^^^ not a trait
+
+error[E0404]: expected trait, found builtin type `usize`
+  --> $DIR/suggestion-trait-object-issue-139174.rs:9:32
+   |
+LL | fn create_adder<'a>(x: i32) -> usize + 'a {
+   |                                ^^^^^ not a trait
+
+error[E0404]: expected trait, found builtin type `usize`
+  --> $DIR/suggestion-trait-object-issue-139174.rs:16:8
+   |
+LL |     x: usize + 'a,
+   |        ^^^^^ not a trait
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/suggestion-trait-object-issue-139174.rs:3:36
+   |
+LL | fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
+   |                                    ^^^^^^^^^^
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/suggestion-trait-object-issue-139174.rs:9:32
+   |
+LL | fn create_adder<'a>(x: i32) -> usize + 'a {
+   |                                ^^^^^^^^^^
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/suggestion-trait-object-issue-139174.rs:16:8
+   |
+LL |     x: usize + 'a,
+   |        ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0404, E0782.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs
index 296bdd7a12d..88a9d07c94c 100644
--- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs
+++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs
@@ -8,5 +8,5 @@
 
 #![feature(rustc_attrs)]
 
-#[rustc_error(delayed_bug_from_inside_query)]
+#[rustc_delayed_bug_from_inside_query]
 fn main() {}
diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
index aec1b89c766..1c8d279c14c 100644
--- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
+++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]
+error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
   --> $DIR/span_delayed_bug.rs:12:1
    |
 LL | fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
index ba97bbf89f8..241eccc5f2b 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
@@ -19,22 +19,5 @@ note: this opaque type is supposed to be constrained
 LL | type Bar = impl std::fmt::Display;
    |            ^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `Bar::{opaque#0}`
-  --> $DIR/const_generic_type.rs:8:31
-   |
-LL |   async fn test<const N: Bar>() {
-   |  _______________________________^
-...  |
-LL | |     let x: u32 = N;
-LL | | }
-   | |_^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/const_generic_type.rs:5:12
-   |
-LL | type Bar = impl std::fmt::Display;
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs
index 5b093be9231..9b38f1449f8 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.rs
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs
@@ -8,7 +8,6 @@ type Bar = impl std::fmt::Display;
 async fn test<const N: Bar>() {
     //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
     //[no_infer]~^^ ERROR item does not constrain
-    //[no_infer]~| ERROR item does not constrain
     #[cfg(infer)]
     let x: u32 = N;
 }
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs
new file mode 100644
index 00000000000..d873af44adf
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.rs
@@ -0,0 +1,11 @@
+#![feature(type_alias_impl_trait)]
+
+extern "C" {
+    fn a() {
+        //~^ ERROR incorrect function inside `extern` block
+        #[define_opaque(String)]
+        fn c() {}
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr
new file mode 100644
index 00000000000..2e944257d8f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid-extern-fn-body.stderr
@@ -0,0 +1,20 @@
+error: incorrect function inside `extern` block
+  --> $DIR/invalid-extern-fn-body.rs:4:8
+   |
+LL |   extern "C" {
+   |   ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |       fn a() {
+   |  ________^___-
+   | |        |
+   | |        cannot have a body
+LL | |
+LL | |         #[define_opaque(String)]
+LL | |         fn c() {}
+LL | |     }
+   | |_____- help: remove the invalid body: `;`
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs
new file mode 100644
index 00000000000..a2de3957c0b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs
@@ -0,0 +1,18 @@
+// We previously didn't taint the borrowck result in this test,
+// causing an ICE later on.
+#![feature(type_alias_impl_trait)]
+trait T {}
+
+type Alias<'a> = impl T;
+
+struct S;
+impl<'a> T for &'a S {}
+
+#[define_opaque(Alias)]
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+    //~^ WARN function cannot return without recursing
+    with_positive(|&n| ());
+    //~^ ERROR cannot move out of a shared reference
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr
new file mode 100644
index 00000000000..956ce3e5936
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr
@@ -0,0 +1,30 @@
+warning: function cannot return without recursing
+  --> $DIR/error-tainting-issue-122904.rs:12:1
+   |
+LL | fn with_positive(fun: impl Fn(Alias<'_>)) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     with_positive(|&n| ());
+   |     ---------------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/error-tainting-issue-122904.rs:14:20
+   |
+LL |     with_positive(|&n| ());
+   |                    ^-
+   |                     |
+   |                     data moved here
+   |                     move occurs because `n` has type `S`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     with_positive(|&n| ());
+LL +     with_positive(|n| ());
+   |
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index 7e010918b29..cbd8150d117 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -22,7 +22,6 @@ where
     for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>,
 {
     //~^ ERROR: expected generic lifetime parameter, found `'any`
-    //~| ERROR item does not constrain
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index 2ca6a199448..2c0be0cbcdc 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -11,21 +11,6 @@ note: this opaque type is supposed to be constrained
 LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `FutNothing::{opaque#0}`
-  --> $DIR/hkl_forbidden4.rs:23:1
-   |
-LL | / {
-...  |
-LL | | }
-   | |_^
-   |
-   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-note: this opaque type is supposed to be constrained
-  --> $DIR/hkl_forbidden4.rs:10:23
-   |
-LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: concrete type differs from previous defining opaque type use
   --> $DIR/hkl_forbidden4.rs:12:1
    |
@@ -54,10 +39,10 @@ LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
 ...
 LL | / {
-...  |
+LL | |
 LL | | }
    | |_^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs
index 7452000b65d..92c8a8f3216 100644
--- a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs
+++ b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs
@@ -6,7 +6,7 @@ trait Foo {
 }
 
 impl Foo for () {
-    type Assoc<'a> = impl Sized; //~ ERROR unconstrained opaque type
+    type Assoc<'a> = impl Sized;
     fn bar<'a: 'a>()
     where
         Self::Assoc<'a>:,
diff --git a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr
index 1274a8b60de..7ce4517fb1e 100644
--- a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr
+++ b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr
@@ -9,14 +9,6 @@ LL |     fn bar<'a: 'a>()
 LL |             let _: Self::Assoc<'a> = x;
    |                    ^^^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/in-assoc-ty-early-bound2.rs:9:22
-   |
-LL |     type Assoc<'a> = impl Sized;
-   |                      ^^^^^^^^^^
-   |
-   = note: `Assoc` must be used in combination with a concrete type within the same impl
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
index 5f44a9aa2df..1a530d27971 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -2,14 +2,15 @@
 #![allow(dead_code)]
 
 type Bug<T, U> = impl Fn(T) -> U + Copy;
+//~^ ERROR cycle detected when computing type of `Bug::{opaque#0}`
 
 #[define_opaque(Bug)]
-//~^ ERROR: only functions and methods can define opaque types
 const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+//~^ ERROR item does not constrain `Bug::{opaque#0}`
 
 #[define_opaque(Bug)]
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
-    |x| x.into() //~ ERROR is not satisfied
+    |x| x.into()
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
index 5739662ff80..3062e55dc49 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -1,25 +1,42 @@
-error: only functions and methods can define opaque types
-  --> $DIR/issue-53092-2.rs:6:1
+error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
+  --> $DIR/issue-53092-2.rs:4:18
    |
-LL | #[define_opaque(Bug)]
-   | ^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092-2.rs:12:5
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of opaque `Bug::{opaque#0}`...
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `CONST_BUG`...
+  --> $DIR/issue-53092-2.rs:8:1
    |
-LL |     |x| x.into()
-   |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `Bug<u8, ()>`...
+   = note: ...which requires normalizing `Bug<u8, ()>`...
+   = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
+note: cycle used when checking that `Bug::{opaque#0}` is well-formed
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: item does not constrain `Bug::{opaque#0}`
+  --> $DIR/issue-53092-2.rs:8:7
    |
-note: required by a bound in `make_bug`
-  --> $DIR/issue-53092-2.rs:11:19
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   |       ^^^^^^^^^
    |
-LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
-   |                   ^^^^^^^ required by this bound in `make_bug`
-help: consider restricting type parameter `U` with trait `From`
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-53092-2.rs:4:18
    |
-LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
-   |              +++++++++++++++++++++++
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs
index c24f1bf44fa..60e455a6a07 100644
--- a/tests/ui/type-alias-impl-trait/issue-53096.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53096.rs
@@ -1,4 +1,5 @@
-#![feature(rustc_attrs)]
+//@ check-pass
+
 #![feature(type_alias_impl_trait)]
 
 pub type Foo = impl Fn() -> usize;
@@ -8,5 +9,4 @@ pub const fn bar() -> Foo {
 }
 const BAZR: Foo = bar();
 
-#[rustc_error]
-fn main() {} //~ ERROR
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr
deleted file mode 100644
index 53490896af7..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-53096.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-53096.rs:12:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs
index 5b8ff6b74de..53280c28ecb 100644
--- a/tests/ui/type-alias-impl-trait/issue-60407.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60407.rs
@@ -1,4 +1,6 @@
-#![feature(type_alias_impl_trait, rustc_attrs)]
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
 
 pub type Debuggable = impl core::fmt::Debug;
 
@@ -9,8 +11,6 @@ pub fn foo() -> Debuggable {
 
 static mut TEST: Option<Debuggable> = None;
 
-#[rustc_error]
 fn main() {
-    //~^ ERROR
     unsafe { TEST = Some(foo()) }
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr
deleted file mode 100644
index f517d5b65fa..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-60407.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-60407.rs:13:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
index b5533eeecba..e21627e14b0 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
@@ -1,19 +1,15 @@
+//@ check-pass
+
 #![feature(type_alias_impl_trait)]
-// Ensures that `const` items can not constrain an opaque `impl Trait`.
 
 use std::fmt::Debug;
 
 pub type Foo = impl Debug;
-//~^ ERROR unconstrained opaque type
 
 #[define_opaque(Foo)]
-//~^ ERROR only functions and methods can define opaque types
 const _FOO: Foo = 5;
-//~^ ERROR mismatched types
 
 #[define_opaque(Foo)]
-//~^ ERROR only functions and methods can define opaque types
-static _BAR: Foo = 22_u32;
-//~^ ERROR mismatched types
+static _BAR: Foo = 22_i32;
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
deleted file mode 100644
index dc15da665f3..00000000000
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
+++ /dev/null
@@ -1,57 +0,0 @@
-error: only functions and methods can define opaque types
-  --> $DIR/type-alias-impl-trait-const.rs:9:1
-   |
-LL | #[define_opaque(Foo)]
-   | ^^^^^^^^^^^^^^^^^^^^^
-
-error: only functions and methods can define opaque types
-  --> $DIR/type-alias-impl-trait-const.rs:14:1
-   |
-LL | #[define_opaque(Foo)]
-   | ^^^^^^^^^^^^^^^^^^^^^
-
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-const.rs:6:16
-   |
-LL | pub type Foo = impl Debug;
-   |                ^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same crate
-
-error[E0308]: mismatched types
-  --> $DIR/type-alias-impl-trait-const.rs:11:19
-   |
-LL | pub type Foo = impl Debug;
-   |                ---------- the expected opaque type
-...
-LL | const _FOO: Foo = 5;
-   |                   ^ expected opaque type, found integer
-   |
-   = note: expected opaque type `Foo`
-                     found type `{integer}`
-note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
-  --> $DIR/type-alias-impl-trait-const.rs:11:7
-   |
-LL | const _FOO: Foo = 5;
-   |       ^^^^
-
-error[E0308]: mismatched types
-  --> $DIR/type-alias-impl-trait-const.rs:16:20
-   |
-LL | pub type Foo = impl Debug;
-   |                ---------- the expected opaque type
-...
-LL | static _BAR: Foo = 22_u32;
-   |                    ^^^^^^ expected opaque type, found `u32`
-   |
-   = note: expected opaque type `Foo`
-                     found type `u32`
-note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
-  --> $DIR/type-alias-impl-trait-const.rs:16:8
-   |
-LL | static _BAR: Foo = 22_u32;
-   |        ^^^^
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
index 19986247d40..53b7667aa9f 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs
@@ -1,9 +1,10 @@
 #![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
 
 type Foo = impl Fn() -> Foo;
 
+#[define_opaque(Foo)]
 fn crash(x: Foo) -> Foo {
+    //~^ ERROR overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
     x
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
index ad96a0eeb87..ee8922b673e 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12
+error[E0275]: overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21
    |
-LL | type Foo = impl Fn() -> Foo;
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash(x: Foo) -> Foo {
+   |                     ^^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
index 761cc83af51..d0c62d29069 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs
@@ -1,13 +1,13 @@
 #![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
 
 pub trait Bar<T> {
     type Item;
 }
 
 type Foo = impl Bar<Foo, Item = Foo>;
-
+#[define_opaque(Foo)]
 fn crash(x: Foo) -> Foo {
+    //~^ ERROR overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
     x
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
index e5bb8163a81..40bd6517c06 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12
+error[E0275]: overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:9:21
    |
-LL | type Foo = impl Bar<Foo, Item = Foo>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash(x: Foo) -> Foo {
+   |                     ^^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
index 52942afd639..de3d23b83a2 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs
@@ -1,9 +1,9 @@
 #![feature(type_alias_impl_trait)]
-//@ known-bug: #109268
 
 type Foo<'a> = impl Fn() -> Foo<'a>;
-
+#[define_opaque(Foo)]
 fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+    //~^ ERROR overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
     x
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
index 157310bf623..f9e26fde1bd 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
@@ -1,10 +1,9 @@
-error: unconstrained opaque type
-  --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16
+error[E0275]: overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
+  --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:5:40
    |
-LL | type Foo<'a> = impl Fn() -> Foo<'a>;
-   |                ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same crate
+LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
+   |                                        ^^^^^^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs
deleted file mode 100644
index ed19b10671a..00000000000
--- a/tests/ui/type/pattern_types/const_block.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(pattern_types)]
-#![feature(pattern_type_macro)]
-#![feature(inline_const_pat)]
-//@ check-pass
-
-use std::pat::pattern_type;
-
-fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-
-fn main() {}
diff --git a/tests/ui/type/pattern_types/literals.rs b/tests/ui/type/pattern_types/literals.rs
index 97a918645f3..7fd630dab3a 100644
--- a/tests/ui/type/pattern_types/literals.rs
+++ b/tests/ui/type/pattern_types/literals.rs
@@ -134,3 +134,6 @@ fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) {
 }
 
 fn main() {}
+
+//~? ERROR pattern type ranges cannot wrap: 1..=0
+//~? ERROR pattern type ranges cannot wrap: 2..=0
diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs
index dda7eb0ae4e..21c1454d6cd 100644
--- a/tests/ui/type/pattern_types/range_patterns.rs
+++ b/tests/ui/type/pattern_types/range_patterns.rs
@@ -40,3 +40,7 @@ type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout
 fn main() {
     let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) };
 }
+
+//~? ERROR pattern type ranges cannot wrap: 1..=0
+//~? ERROR pattern type ranges cannot wrap: 5..=1
+//~? ERROR pattern type ranges cannot wrap: 120..=-120
diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs
index 5a6a688e1b3..c61bb71ac25 100644
--- a/tests/ui/type/pattern_types/validity.rs
+++ b/tests/ui/type/pattern_types/validity.rs
@@ -1,4 +1,6 @@
 //! Check that pattern types have their validity checked
+// Strip out raw byte dumps to make tests platform-independent:
+//@ normalize-stderr: "([[:xdigit:]]{2}\s){4,8}\s+│\s.{4,8}" -> "HEX_DUMP"
 
 #![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
 #![feature(pattern_type_macro)]
diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr
index 5bc18cfba3f..b990ec2d368 100644
--- a/tests/ui/type/pattern_types/validity.stderr
+++ b/tests/ui/type/pattern_types/validity.stderr
@@ -1,22 +1,22 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validity.rs:8:1
+  --> $DIR/validity.rs:10:1
    |
 LL | const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
    |
    = 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: 4, align: 4) {
-               00 00 00 00                                     │ ....
+               HEX_DUMP
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/validity.rs:11:1
+  --> $DIR/validity.rs:13:1
    |
 LL | const BAD_UNINIT: pattern_type!(u32 is 1..) =
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/validity.rs:15:1
+  --> $DIR/validity.rs:17:1
    |
 LL | const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@@ -25,53 +25,53 @@ LL | const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&
    = 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/validity.rs:18:1
+  --> $DIR/validity.rs:20:1
    |
 LL | const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
    |
    = 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) {
-               00 00 00 00 00 00 00 00                         │ ........
+               HEX_DUMP
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validity.rs:24:1
+  --> $DIR/validity.rs:26:1
    |
 LL | const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) }));
    | ^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
    |
    = 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: 4, align: 4) {
-               00 00 00 00                                     │ ....
+               HEX_DUMP
            }
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/validity.rs:27:1
+  --> $DIR/validity.rs:29:1
    |
 LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') =
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validity.rs:31:1
+  --> $DIR/validity.rs:33:1
    |
 LL | const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 97, but expected something in the range 65..=89
    |
    = 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: 4, align: 4) {
-               61 00 00 00                                     │ a...
+               HEX_DUMP
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validity.rs:34:1
+  --> $DIR/validity.rs:36:1
    |
 LL | const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
    |
    = 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: 4, align: 4) {
-               ff ff ff ff                                     │ ....
+               HEX_DUMP
            }
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/unpretty/avoid-crash.rs b/tests/ui/unpretty/avoid-crash.rs
index 7fcabfe6a8d..64fa778bed4 100644
--- a/tests/ui/unpretty/avoid-crash.rs
+++ b/tests/ui/unpretty/avoid-crash.rs
@@ -2,3 +2,5 @@
 //@ compile-flags: -o. -Zunpretty=ast-tree
 
 fn main() {}
+
+//~? ERROR failed to write `.` due to error
diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs
index 763e9496734..b0fdcf97015 100644
--- a/tests/ui/unresolved/unresolved-import.rs
+++ b/tests/ui/unresolved/unresolved-import.rs
@@ -31,6 +31,8 @@ mod food {
 
     mod zug {
         pub mod baz {
+        //~^ NOTE module `food::zug::baz` exists but is inaccessible
+        //~| NOTE not accessible
             pub struct Foobar;
         }
     }
diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr
index c65fe841001..4001695459a 100644
--- a/tests/ui/unresolved/unresolved-import.stderr
+++ b/tests/ui/unresolved/unresolved-import.stderr
@@ -26,6 +26,12 @@ LL | use food::baz;
    |     |     |
    |     |     help: a similar name exists in the module: `bag`
    |     no `baz` in `food`
+   |
+note: module `food::zug::baz` exists but is inaccessible
+  --> $DIR/unresolved-import.rs:33:9
+   |
+LL |         pub mod baz {
+   |         ^^^^^^^^^^^ not accessible
 
 error[E0432]: unresolved import `food::beens`
   --> $DIR/unresolved-import.rs:19:12
@@ -37,13 +43,13 @@ LL | use food::{beens as Foo};
    |            help: a similar name exists in the module: `beans`
 
 error[E0432]: unresolved import `MyEnum`
-  --> $DIR/unresolved-import.rs:44:9
+  --> $DIR/unresolved-import.rs:46:9
    |
 LL |     use MyEnum::*;
    |         ^^^^^^ help: a similar path exists: `self::MyEnum`
 
 error[E0432]: unresolved import `Enum`
-  --> $DIR/unresolved-import.rs:55:9
+  --> $DIR/unresolved-import.rs:57:9
    |
 LL |     use Enum::*;
    |         ^^^^ help: a similar path exists: `self::Enum`
diff --git a/tests/ui/unsafe/const_pat_in_layout_restricted.rs b/tests/ui/unsafe/const_pat_in_layout_restricted.rs
deleted file mode 100644
index 2ba173ee499..00000000000
--- a/tests/ui/unsafe/const_pat_in_layout_restricted.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Check that ref mut patterns within a const pattern don't get considered
-// unsafe because they're within a pattern for a layout constrained stuct.
-//@ check-pass
-
-#![feature(rustc_attrs)]
-#![feature(inline_const_pat)]
-
-#[rustc_layout_scalar_valid_range_start(3)]
-struct Gt2(i32);
-
-fn main() {
-    match unsafe { Gt2(5) } {
-        Gt2(
-            const {
-                || match () {
-                    ref mut y => (),
-                };
-                4
-            },
-        ) => (),
-        _ => (),
-    }
-}
diff --git a/tests/ui/variance/variance-uniquearc.rs b/tests/ui/variance/variance-uniquearc.rs
new file mode 100644
index 00000000000..03589512388
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.rs
@@ -0,0 +1,27 @@
+// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
+// see also the test for UniqueRc` in variance-uniquerc.rs
+//
+// inline comments explain how this code *would* compile if UniqueArc was still covariant
+
+#![feature(unique_rc_arc)]
+
+use std::sync::UniqueArc;
+
+fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+    let r = UniqueArc::new(""); // UniqueArc<&'static str>
+    let w = UniqueArc::downgrade(&r); // Weak<&'static str>
+    let mut r = r; // [IF COVARIANT]: ==>> UniqueArc<&'a str>
+    *r = x; // assign the &'a str
+    let _r = UniqueArc::into_arc(r); // Arc<&'a str>, but we only care to activate the weak
+    let r = w.upgrade().unwrap(); // Arc<&'static str>
+    *r // &'static str, coerces to &'b str
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    let s = String::from("Hello World!");
+    let r = extend_lifetime(&s);
+    println!("{r}");
+    drop(s);
+    println!("{r}");
+}
diff --git a/tests/ui/variance/variance-uniquearc.stderr b/tests/ui/variance/variance-uniquearc.stderr
new file mode 100644
index 00000000000..55076dae732
--- /dev/null
+++ b/tests/ui/variance/variance-uniquearc.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/variance-uniquearc.rs:17:5
+   |
+LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
+   |                    --  -- lifetime `'b` defined here
+   |                    |
+   |                    lifetime `'a` defined here
+...
+LL |     *r // &'static str, coerces to &'b str
+   |     ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/variance/variance-uniquerc.rs b/tests/ui/variance/variance-uniquerc.rs
index 0c395ab06ea..2e9738f66dc 100644
--- a/tests/ui/variance/variance-uniquerc.rs
+++ b/tests/ui/variance/variance-uniquerc.rs
@@ -1,5 +1,5 @@
 // regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
-// we should also test UniqueArc once implemented
+// see also the test for UniqueArc in variance-uniquearc.rs
 //
 // inline comments explain how this code *would* compile if UniqueRc was still covariant
 
diff --git a/triagebot.toml b/triagebot.toml
index 53cdd8b585b..e2b9e321a48 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -174,8 +174,8 @@ label = "O-emscripten"
 
 [ping.relnotes-interest-group]
 message = """\
-Hi relnotes-interest-group, this PR adds release notes. Could you review this PR
-if you have time? Thanks <3
+Hi relnotes-interest-group, this issue/PR could use some help in reviewing /
+adjusting release notes. Could you take a look if available? Thanks <3
 """
 
 [prioritize]
@@ -254,6 +254,16 @@ trigger_files = [
     "compiler/rustc_attr_data_structures",
 ]
 
+[autolabel."F-autodiff"]
+trigger_files = [
+    "src/tools/enzyme",
+    "src/doc/unstable-book/src/compiler-flags/autodiff.md",
+    "compiler/rustc_ast/src/expand/autodiff_attrs.rs",
+    "compiler/rustc_monomorphize/src/partitioning/autodiff.rs",
+    "compiler/rustc_codegen_llvm/src/builder/autodiff.rs",
+    "compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs",
+]
+
 [autolabel."T-rustdoc-frontend"]
 trigger_labels = [
     "A-rustdoc-search",
@@ -307,6 +317,23 @@ exclude_labels = [
     "T-*",
 ]
 
+trigger_labels = [
+    "D-*",
+    "A-diagnostics",
+]
+
+[autolabel."A-diagnostics"]
+
+trigger_labels = [
+    "D-*",
+]
+
+[autolabel."A-lints"]
+
+trigger_labels = [
+    "L-*",
+]
+
 [autolabel."T-libs"]
 trigger_files = [
     "library/alloc",
@@ -564,12 +591,12 @@ trigger_files = [
 ]
 
 [notify-zulip."I-prioritize"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
+zulip_stream = 245100 # #t-compiler/prioritization/alerts
 topic = "#{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* issue #{number} has been requested for prioritization.
 
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#assign-priority-to-unprioritized-issues-with-i-prioritize-label)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization.html)
 - Priority?
 - Regression?
 - Notify people/groups?
@@ -1075,12 +1102,29 @@ cc = ["@jdonszelmann"]
 [mentions."compiler/rustc_attr_data_structures"]
 cc = ["@jdonszelmann"]
 
+[mentions."src/tools/enzyme"]
+cc = ["@ZuseZ4"]
+[mentions."src/doc/unstable-book/src/compiler-flags/autodiff.md"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_ast/src/expand/autodiff_attrs.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_ast/src/expand/typetree.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_builtin_macros/src/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_monomorphize/src/partitioning/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_codegen_llvm/src/builder/autodiff.rs"]
+cc = ["@ZuseZ4"]
+[mentions."compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs"]
+cc = ["@ZuseZ4"]
+
 [assign]
 warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "jyn514",
-    "ChrisDenton",
+    "saethlin",
 ]
 
 [[assign.warn_non_default_branch.exceptions]]
@@ -1098,7 +1142,6 @@ compiler_leads = [
 ]
 compiler = [
     "@BoxyUwU",
-    "@cjgillot",
     "@compiler-errors",
     "@davidtwco",
     "@estebank",
@@ -1116,7 +1159,6 @@ compiler = [
 ]
 libs = [
     "@Mark-Simulacrum",
-    "@Amanieu",
     "@Noratrieb",
     "@workingjubilee",
     "@joboet",
@@ -1148,13 +1190,13 @@ docs = [
     "@ehuss",
     "@GuillaumeGomez",
 ]
-
 codegen = [
+    "@dianqk",
     "@saethlin",
     "@workingjubilee",
 ]
 query-system = [
-    "@cjgillot",
+    "@oli-obk",
 ]
 incremental = [
     "@wesleywiser",